Mercurial > hg > orthanc-stone
comparison UnitTestsSources/TestStrategy.cpp @ 708:51976977d2d3
reorganization
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 20 May 2019 11:20:01 +0200 |
parents | 14557e550920 |
children | 2d8ab34c8c91 |
comparison
equal
deleted
inserted
replaced
707:d1feb89ea742 | 708:51976977d2d3 |
---|---|
19 **/ | 19 **/ |
20 | 20 |
21 | 21 |
22 #include "gtest/gtest.h" | 22 #include "gtest/gtest.h" |
23 | 23 |
24 #include "../Framework/Loaders/BasicFetchingStrategy.h" | |
25 #include "../Framework/Loaders/BasicFetchingItemsSorter.h" | |
26 | |
24 #include <Core/OrthancException.h> | 27 #include <Core/OrthancException.h> |
25 | |
26 #include <boost/noncopyable.hpp> | |
27 #include <vector> | |
28 | |
29 namespace OrthancStone | |
30 { | |
31 class IFetchingStrategy : public boost::noncopyable | |
32 { | |
33 public: | |
34 virtual ~IFetchingStrategy() | |
35 { | |
36 } | |
37 | |
38 virtual unsigned int GetItemsCount() const = 0; | |
39 | |
40 virtual unsigned int GetMaxQuality() const = 0; | |
41 | |
42 virtual bool GetNext(unsigned int& item, | |
43 unsigned int& quality) = 0; | |
44 | |
45 virtual void SetCurrent(unsigned int item) = 0; | |
46 | |
47 // Ask the strategy to re-schedule the item with the lowest | |
48 // priority in the fetching order. This allows to know which item | |
49 // should be dropped from a cache. | |
50 virtual void RecycleFurthest(unsigned int& item) = 0; | |
51 }; | |
52 | |
53 | |
54 class IFetchingItemsSorter : public boost::noncopyable | |
55 { | |
56 public: | |
57 virtual ~IFetchingItemsSorter() | |
58 { | |
59 } | |
60 | |
61 virtual unsigned int GetItemsCount() const = 0; | |
62 | |
63 // Sort a set of items given the current item | |
64 virtual void Sort(std::vector<unsigned int>& target, | |
65 unsigned int current) = 0; | |
66 }; | |
67 | |
68 | |
69 | |
70 class BasicFetchingItemsSorter : public IFetchingItemsSorter | |
71 { | |
72 private: | |
73 unsigned int itemsCount_; | |
74 | |
75 public: | |
76 BasicFetchingItemsSorter(unsigned int itemsCount) : | |
77 itemsCount_(itemsCount) | |
78 { | |
79 if (itemsCount == 0) | |
80 { | |
81 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
82 } | |
83 } | |
84 | |
85 virtual unsigned int GetItemsCount() const | |
86 { | |
87 return itemsCount_; | |
88 } | |
89 | |
90 virtual void Sort(std::vector<unsigned int>& target, | |
91 unsigned int current) | |
92 { | |
93 if (current >= itemsCount_) | |
94 { | |
95 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
96 } | |
97 | |
98 target.clear(); | |
99 target.reserve(itemsCount_); | |
100 target.push_back(current); | |
101 | |
102 const unsigned int countBelow = current; | |
103 const unsigned int countAbove = (itemsCount_ - 1) - current; | |
104 const unsigned int n = std::min(countBelow, countAbove); | |
105 | |
106 for (unsigned int i = 1; i <= n; i++) | |
107 { | |
108 assert(current + i < itemsCount_ && | |
109 current >= i); | |
110 target.push_back(current + i); | |
111 target.push_back(current - i); | |
112 } | |
113 | |
114 for (unsigned int i = current - n; i > 0; i--) | |
115 { | |
116 target.push_back(i - 1); | |
117 } | |
118 | |
119 for (unsigned int i = current + n + 1; i < itemsCount_; i++) | |
120 { | |
121 target.push_back(i); | |
122 } | |
123 | |
124 assert(target.size() == itemsCount_); | |
125 } | |
126 }; | |
127 | |
128 | |
129 class BasicFetchingStrategy : public IFetchingStrategy | |
130 { | |
131 private: | |
132 class ContentItem | |
133 { | |
134 private: | |
135 unsigned int item_; | |
136 unsigned int quality_; | |
137 | |
138 public: | |
139 ContentItem(unsigned int item, | |
140 unsigned int quality) : | |
141 item_(item), | |
142 quality_(quality) | |
143 { | |
144 } | |
145 | |
146 unsigned int GetItem() const | |
147 { | |
148 return item_; | |
149 } | |
150 | |
151 unsigned int GetQuality() const | |
152 { | |
153 return quality_; | |
154 } | |
155 }; | |
156 | |
157 std::auto_ptr<IFetchingItemsSorter> sorter_; | |
158 std::vector<unsigned int> nextQuality_; | |
159 unsigned int maxQuality_; | |
160 std::vector<ContentItem> content_; | |
161 size_t position_; | |
162 unsigned int blockSize_; | |
163 | |
164 void Schedule(unsigned int item, | |
165 unsigned int quality) | |
166 { | |
167 assert(item < GetItemsCount() && | |
168 quality <= maxQuality_); | |
169 | |
170 if (nextQuality_[item] <= quality) | |
171 { | |
172 content_.push_back(ContentItem(item, quality)); | |
173 } | |
174 } | |
175 | |
176 public: | |
177 BasicFetchingStrategy(IFetchingItemsSorter* sorter, // Takes ownership | |
178 unsigned int maxQuality) : | |
179 sorter_(sorter), | |
180 maxQuality_(maxQuality), | |
181 position_(0), | |
182 blockSize_(2) | |
183 { | |
184 if (sorter == NULL) | |
185 { | |
186 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | |
187 } | |
188 | |
189 nextQuality_.resize(sorter_->GetItemsCount(), 0), // Does not change along calls to "SetCurrent()" | |
190 | |
191 SetCurrent(0); | |
192 } | |
193 | |
194 virtual unsigned int GetItemsCount() const | |
195 { | |
196 return sorter_->GetItemsCount(); | |
197 } | |
198 | |
199 virtual unsigned int GetMaxQuality() const | |
200 { | |
201 return maxQuality_; | |
202 } | |
203 | |
204 void SetBlockSize(unsigned int size) | |
205 { | |
206 if (size <= 0) | |
207 { | |
208 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
209 } | |
210 | |
211 blockSize_ = size; | |
212 } | |
213 | |
214 virtual bool GetNext(unsigned int& item, | |
215 unsigned int& quality) | |
216 { | |
217 if (position_ >= content_.size()) | |
218 { | |
219 return false; | |
220 } | |
221 else | |
222 { | |
223 item = content_[position_].GetItem(); | |
224 quality = content_[position_].GetQuality(); | |
225 | |
226 assert(nextQuality_[item] <= quality); | |
227 nextQuality_[item] = quality + 1; | |
228 | |
229 position_ ++; | |
230 return true; | |
231 } | |
232 } | |
233 | |
234 virtual void SetCurrent(unsigned int item) | |
235 { | |
236 // TODO - This function is O(N) complexity where "N" is the | |
237 // number of items times the max quality. Could use a LRU index. | |
238 | |
239 position_ = 0; | |
240 | |
241 std::vector<unsigned int> v; | |
242 sorter_->Sort(v, item); | |
243 | |
244 assert(v.size() == GetItemsCount()); | |
245 | |
246 if (v.size() == 0) | |
247 { | |
248 return; | |
249 } | |
250 | |
251 content_.clear(); | |
252 content_.reserve(v.size() * maxQuality_); | |
253 | |
254 Schedule(v.front(), maxQuality_); | |
255 | |
256 for (unsigned int q = 0; q <= maxQuality_; q++) | |
257 { | |
258 unsigned int start = 1 + q * blockSize_; | |
259 unsigned int end = start + blockSize_; | |
260 | |
261 if (q == maxQuality_ || | |
262 end > v.size()) | |
263 { | |
264 end = v.size(); | |
265 } | |
266 | |
267 unsigned int a = 0; | |
268 if (maxQuality_ >= q + 1) | |
269 { | |
270 a = maxQuality_ - q - 1; | |
271 } | |
272 | |
273 for (unsigned int j = a; j <= maxQuality_; j++) | |
274 { | |
275 for (unsigned int i = start; i < end; i++) | |
276 { | |
277 Schedule(v[i], j); | |
278 } | |
279 } | |
280 } | |
281 } | |
282 | |
283 // Ask the strategy to re-schedule the item with the lowest | |
284 // priority in the fetching order. This allows to know which item | |
285 // should be dropped from a cache. | |
286 virtual void RecycleFurthest(unsigned int& item) | |
287 { | |
288 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | |
289 } | |
290 }; | |
291 } | |
292 | |
293 | 28 |
294 | 29 |
295 namespace | 30 namespace |
296 { | 31 { |
297 class StrategyTester : public boost::noncopyable | 32 class StrategyTester : public boost::noncopyable |