Mercurial > hg > orthanc-transfers
annotate Framework/TransferBucket.cpp @ 35:81262707d68e
sync
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Sat, 12 Jun 2021 09:35:17 +0200 |
parents | 44a0430d7899 |
children | 1e396fb509ca |
rev | line source |
---|---|
0 | 1 /** |
2 * Transfers accelerator plugin for Orthanc | |
33
44a0430d7899
upgrade to year 2021
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
20
diff
changeset
|
3 * Copyright (C) 2018-2021 Osimis S.A., Belgium |
0 | 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 | |
20 #include "TransferBucket.h" | |
21 | |
20 | 22 #include <Logging.h> |
23 #include <OrthancException.h> | |
0 | 24 |
25 | |
26 namespace OrthancPlugins | |
27 { | |
28 TransferBucket::TransferBucket() : | |
29 totalSize_(0), | |
30 extensible_(true) | |
31 { | |
32 } | |
33 | |
34 | |
35 TransferBucket::TransferBucket(const Json::Value& serialized) : | |
36 totalSize_(0), | |
37 extensible_(false) | |
38 { | |
39 if (serialized.type() != Json::arrayValue) | |
40 { | |
41 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
42 } | |
43 | |
44 chunks_.reserve(serialized.size()); | |
45 | |
46 for (Json::Value::ArrayIndex i = 0; i < serialized.size(); i++) | |
47 { | |
48 if (serialized[i].type() != Json::objectValue || | |
49 !serialized[i].isMember(KEY_ID) || | |
50 !serialized[i].isMember(KEY_OFFSET) || | |
51 !serialized[i].isMember(KEY_SIZE) || | |
52 serialized[i][KEY_ID].type() != Json::stringValue || | |
53 serialized[i][KEY_OFFSET].type() != Json::stringValue || | |
54 serialized[i][KEY_SIZE].type() != Json::stringValue) | |
55 { | |
56 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
57 } | |
58 else | |
59 { | |
60 try | |
61 { | |
62 Chunk chunk; | |
63 chunk.instanceId_ = serialized[i][KEY_ID].asString(); | |
64 chunk.offset_ = boost::lexical_cast<size_t>(serialized[i][KEY_OFFSET].asString()); | |
65 chunk.size_ = boost::lexical_cast<size_t>(serialized[i][KEY_SIZE].asString()); | |
66 | |
67 chunks_.push_back(chunk); | |
68 totalSize_ += chunk.size_; | |
69 } | |
70 catch (boost::bad_lexical_cast&) | |
71 { | |
72 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
73 } | |
74 } | |
75 } | |
76 } | |
77 | |
78 | |
79 void TransferBucket::Serialize(Json::Value& target) const | |
80 { | |
81 target = Json::arrayValue; | |
82 | |
83 for (size_t i = 0; i < chunks_.size(); i++) | |
84 { | |
85 Json::Value item = Json::objectValue; | |
86 item[KEY_ID] = chunks_[i].instanceId_; | |
87 item[KEY_OFFSET] = boost::lexical_cast<std::string>(chunks_[i].offset_); | |
88 item[KEY_SIZE] = boost::lexical_cast<std::string>(chunks_[i].size_); | |
89 target.append(item); | |
90 } | |
91 } | |
92 | |
93 void TransferBucket::Clear() | |
94 { | |
95 chunks_.clear(); | |
96 totalSize_ = 0; | |
97 extensible_ = true; | |
98 } | |
99 | |
100 | |
101 void TransferBucket::AddChunk(const DicomInstanceInfo& instance, | |
102 size_t chunkOffset, | |
103 size_t chunkSize) | |
104 { | |
105 if (chunkOffset + chunkSize > instance.GetSize()) | |
106 { | |
107 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
108 } | |
109 | |
110 if (!extensible_) | |
111 { | |
112 LOG(ERROR) << "Cannot add a new chunk after a truncated instance"; | |
113 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
114 } | |
115 | |
116 if (!chunks_.empty() && | |
117 chunkOffset != 0) | |
118 { | |
119 LOG(ERROR) << "Only the first chunk can have non-zero offset in a transfer bucket"; | |
120 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
121 } | |
122 | |
123 if (chunkSize == 0) | |
124 { | |
125 // Ignore empty chunks | |
126 return; | |
127 } | |
128 | |
129 if (!chunks_.empty() && | |
130 chunkSize != instance.GetSize()) | |
131 { | |
132 // Prevents adding new chunk after an incomplete instance | |
133 extensible_ = false; | |
134 } | |
135 | |
136 Chunk chunk; | |
137 chunk.instanceId_ = instance.GetId(); | |
138 chunk.offset_ = chunkOffset; | |
139 chunk.size_ = chunkSize; | |
140 | |
141 chunks_.push_back(chunk); | |
142 totalSize_ += chunkSize; | |
143 } | |
144 | |
145 | |
146 const std::string& TransferBucket::GetChunkInstanceId(size_t index) const | |
147 { | |
148 if (index >= chunks_.size()) | |
149 { | |
150 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
151 } | |
152 else | |
153 { | |
154 return chunks_[index].instanceId_; | |
155 } | |
156 } | |
157 | |
158 | |
159 size_t TransferBucket::GetChunkOffset(size_t index) const | |
160 { | |
161 if (index >= chunks_.size()) | |
162 { | |
163 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
164 } | |
165 else | |
166 { | |
167 return chunks_[index].offset_; | |
168 } | |
169 } | |
170 | |
171 | |
172 size_t TransferBucket::GetChunkSize(size_t index) const | |
173 { | |
174 if (index >= chunks_.size()) | |
175 { | |
176 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
177 } | |
178 else | |
179 { | |
180 return chunks_[index].size_; | |
181 } | |
182 } | |
183 | |
184 | |
185 void TransferBucket::ComputePullUri(std::string& uri, | |
186 BucketCompression compression) const | |
187 { | |
188 if (chunks_.empty()) | |
189 { | |
190 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
191 } | |
192 | |
193 bool first = true; | |
194 uri = std::string(URI_CHUNKS) + "/"; | |
195 | |
196 for (size_t i = 0; i < chunks_.size(); i++) | |
197 { | |
198 if (first) | |
199 { | |
200 first = false; | |
201 } | |
202 else | |
203 { | |
204 uri += "."; | |
205 } | |
206 | |
207 uri += chunks_[i].instanceId_; | |
208 | |
209 assert(i == 0 || chunks_[i].offset_ == 0); | |
210 } | |
211 | |
212 uri += ("?offset=" + boost::lexical_cast<std::string>(chunks_[0].offset_) + | |
213 "&size=" + boost::lexical_cast<std::string>(totalSize_)); | |
214 | |
215 switch (compression) | |
216 { | |
217 case BucketCompression_None: | |
218 uri += "&compression=none"; | |
219 break; | |
220 | |
221 case BucketCompression_Gzip: | |
222 uri += "&compression=gzip"; | |
223 break; | |
224 | |
225 default: | |
226 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
227 } | |
228 } | |
229 } |