comparison Common/MoveStorageJob.cpp @ 83:431ab61b5760

/move-storage when HybridMode is enabled
author Alain Mazy <am@osimis.io>
date Thu, 20 Oct 2022 15:14:39 +0200
parents
children 8a9207933297
comparison
equal deleted inserted replaced
82:f30b9acf80f0 83:431ab61b5760
1 /**
2 * Cloud storage plugins for Orthanc
3 * Copyright (C) 2020-2021 Osimis S.A., Belgium
4 *
5 * This program is free software: you can redistribute it and/or
6 * modify it under the terms of the GNU Affero General Public License
7 * as published by the Free Software Foundation, either version 3 of
8 * the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 **/
18
19 #include "MoveStorageJob.h"
20 #include "Logging.h"
21
22
23 MoveStorageJob::MoveStorageJob(const std::string& targetStorage,
24 const std::vector<std::string>& instances,
25 const Json::Value& resourceForJobContent,
26 bool cryptoEnabled)
27 : OrthancPlugins::OrthancJob("MoveStorage"),
28 targetStorage_(targetStorage),
29 instances_(instances),
30 processedInstancesCount_(0),
31 resourceForJobContent_(resourceForJobContent),
32 fileSystemStorage_(NULL),
33 objectStorage_(NULL),
34 cryptoEnabled_(cryptoEnabled)
35 {
36 }
37
38 void MoveStorageJob::SetStorages(IStorage* fileSystemStorage, IStorage* objectStorage)
39 {
40 fileSystemStorage_ = fileSystemStorage;
41 objectStorage_ = objectStorage;
42 }
43
44 static bool MoveAttachment(const std::string& uuid, int type, IStorage* sourceStorage, IStorage* targetStorage, bool cryptoEnabled)
45 {
46 std::vector<char> buffer;
47
48 // read from source storage
49 try
50 {
51 OrthancPlugins::LogInfo("Move attachment: " + sourceStorage->GetNameForLogs() + ": reading attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type));
52 std::unique_ptr<IStorage::IReader> reader(sourceStorage->GetReaderForObject(uuid.c_str(), static_cast<OrthancPluginContentType>(type), cryptoEnabled));
53
54 size_t fileSize = reader->GetSize();
55 buffer.resize(fileSize);
56
57 reader->ReadWhole(buffer.data(), fileSize);
58 }
59 catch (StoragePluginException& ex)
60 {
61 OrthancPlugins::LogInfo("Move attachment: " + sourceStorage->GetNameForLogs() + ": error while reading attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type) + ", this likely means that the file is already on the right storage");
62 return true;
63 }
64
65 // write to target storage
66 if (buffer.size() > 0)
67 {
68 try
69 {
70 std::unique_ptr<IStorage::IWriter> writer(targetStorage->GetWriterForObject(uuid.c_str(), static_cast<OrthancPluginContentType>(type), cryptoEnabled));
71
72 writer->Write(buffer.data(), buffer.size());
73 }
74 catch (StoragePluginException& ex)
75 {
76 OrthancPlugins::LogError("Move attachment: " + targetStorage->GetNameForLogs() + ": error while writing attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type) + ": " + ex.what());
77 return false;
78 }
79 }
80
81 // everything went well so fare, we can delete from source storage
82 if (buffer.size() > 0)
83 {
84 try
85 {
86 sourceStorage->DeleteObject(uuid.c_str(), static_cast<OrthancPluginContentType>(type), cryptoEnabled);
87 }
88 catch (StoragePluginException& ex)
89 {
90 OrthancPlugins::LogError("Move attachment: " + sourceStorage->GetNameForLogs() + ": error while deleting attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type) + ": " + ex.what());
91 return false;
92 }
93 }
94 return true;
95 }
96
97 static bool MoveInstance(const std::string& instanceId, IStorage* sourceStorage, IStorage* targetStorage, bool cryptoEnabled)
98 {
99 LOG(INFO) << "Moving instance from " << sourceStorage->GetNameForLogs() << " to " << targetStorage->GetNameForLogs();
100
101 Json::Value attachmentsList;
102 OrthancPlugins::RestApiGet(attachmentsList, std::string("/instances/") + instanceId + "/attachments?full", false);
103
104 Json::Value::Members attachmentsMembers = attachmentsList.getMemberNames();
105 bool success = true;
106
107 for (size_t i = 0; i < attachmentsMembers.size(); i++)
108 {
109 int attachmentId = attachmentsList[attachmentsMembers[i]].asInt();
110
111 Json::Value attachmentInfo;
112 OrthancPlugins::RestApiGet(attachmentInfo, std::string("/instances/") + instanceId + "/attachments/" + boost::lexical_cast<std::string>(attachmentId) + "/info", false);
113
114 std::string attachmentUuid = attachmentInfo["Uuid"].asString();
115
116 // now we have the uuid and type. We actually don't know where the file is but we'll try to move it anyway to the requested target
117 success &= MoveAttachment(attachmentUuid, attachmentId, sourceStorage, targetStorage, cryptoEnabled);
118 }
119
120 return success;
121 }
122
123 OrthancPluginJobStepStatus MoveStorageJob::Step()
124 {
125 if (processedInstancesCount_ < instances_.size())
126 {
127 IStorage* sourceStorage = (targetStorage_ == "file-system" ? objectStorage_ : fileSystemStorage_);
128 IStorage* targetStorage = (targetStorage_ == "file-system" ? fileSystemStorage_ : objectStorage_);
129
130 if (MoveInstance(instances_[processedInstancesCount_], sourceStorage, targetStorage, cryptoEnabled_))
131 {
132 processedInstancesCount_++;
133 return OrthancPluginJobStepStatus_Continue;
134 }
135 else
136 {
137 return OrthancPluginJobStepStatus_Failure;
138 }
139 }
140
141 return OrthancPluginJobStepStatus_Success;
142 }
143
144 void MoveStorageJob::Stop(OrthancPluginJobStopReason reason)
145 {
146 }
147
148 void MoveStorageJob::Reset()
149 {
150 processedInstancesCount_ = 0;
151 }