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