1 /* Copyright (C) 2014 InfiniDB, Inc.
2
3 This program is free software; you can redistribute it and/or
4 modify it under the terms of the GNU General Public License
5 as published by the Free Software Foundation; version 2 of
6 the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16 MA 02110-1301, USA. */
17
18 //
19 // C++ Implementation: bcTest
20 //
21 // Description: A simple Test driver for the Disk Block Buffer Cache
22 //
23 // Author: Jason Rodriguez <jrodriguez@calpont.com>, (C) 2007
24 //
25 //
26
27 #include <vector>
28 #include <string>
29 #include <iomanip>
30 #include <iostream>
31 #include <sys/time.h>
32 #include <unistd.h>
33 #include <boost/thread/thread.hpp>
34
35 #include "blockrequestprocessor.h"
36 #include "blockcacheclient.h"
37 #include "stats.h"
38 #include "brm.h"
39 #include "logger.h"
40 #include "iomanager.h"
41
42 using namespace BRM;
43 using namespace dbbc;
44 using namespace std;
45 using namespace logging;
46 using namespace primitiveprocessor;
47
48 Stats* gPMStatsPtr = NULL;
49 bool gPMProfOn = false;
50 uint32_t gSession = 0;
51 uint32_t lastRangeListIdx = 0;
52
timespec_sub(const struct timespec & tv1,const struct timespec & tv2,double & tm)53 void timespec_sub(const struct timespec& tv1,
54 const struct timespec& tv2,
55 double& tm)
56 {
57 tm = (double)(tv2.tv_sec - tv1.tv_sec) + 1.e-9 * (tv2.tv_nsec - tv1.tv_nsec);
58 }
59
60 namespace primitiveprocessor
61 {
62 Logger ml;
63 }
64
65
66 class BCTest
67 {
68
69 public:
70
71 struct OidRanges
72 {
73 OID_t oid;
74 HWM_t hwm;
75 LBIDRange_v ranges;
OidRangesBCTest::OidRanges76 OidRanges(const OID_t o, const HWM_t h, const LBIDRange_v r)
77 {
78 oid = o;
79 hwm = h;
80 ranges = r;
81 }
82 }; //struct OidRanges
83
84 BCTest(const int cacheSz = 64 * 1024, int readThr = 2, int readAhead = 1024);
85
86 typedef OidRanges OidRanges_t;
87 typedef vector<OidRanges_t>OidRangesList_t;
88 OidRangesList_t OidRangesList;
89
90 DBRM dbrm;
91 uint32_t extentSize;
92 BRM::OID_t maxOid;
93
94 int fCacheSz;
95 int fReadThr;
96 int fReadAhead;
97 uint32_t maxBlocksAvailable;
98 uint32_t fExtentSize;
99
100 void setUp();
101 int LoadOid(const OidRanges_t& o, uint32_t& loadCount);
102 void LoadLbid(const BRM::LBID_t lbid, const BRM::VER_t ver);
103 int ReadOidRanges(const OidRanges_t& v);
104 void ReadOidLbids(const BRM::LBID_t lbid, const BRM::VER_t ver);
105
106 BlockRequestProcessor BRP;
107
108 }; // class BCTest
109
110
BCTest(int cacheSz,int readThr,int readAhead)111 BCTest::BCTest(int cacheSz, int readThr, int readAhead) :
112 fCacheSz(cacheSz),
113 fReadThr(readThr),
114 fReadAhead(readAhead),
115 BRP(fCacheSz, fReadThr, fReadAhead)
116 {
117 setUp();
118 } // ctor
119
120 //
setUp()121 void BCTest::setUp()
122 {
123 LBIDRange_v r;
124 HWM_t hwm;
125 OID_t oid = 1000;
126 extentSize = dbrm.getExtentSize();
127 maxBlocksAvailable = 0;
128 int i = 0;
129 fExtentSize = dbrm.getExtentSize();
130
131 while ( oid < 5000 )
132 {
133 int ret = 0;
134 ret = dbrm.lookup(oid, r);
135
136 if (ret == 0 && r.size() > 0)
137 {
138 dbrm.getHWM(oid, hwm);
139 maxBlocksAvailable += (r.size() * extentSize);
140 OidRanges_t oid_range(oid, hwm, r);
141 OidRangesList.push_back(oid_range);
142 //cout << "Setup i: " << i++ << " o: " << oid
143 // << " r: " << ret << " s: " << r.size()
144 // << " m: " << maxBlocksAvailable
145 // << endl;
146 hwm = 0;
147 r.clear();
148 }
149
150 oid++;
151 }
152
153 //cout << "\t" << OidRangesList.size() << " oid ranges loaded " << endl << endl;
154 i = 0;
155 } // setUp()
156
LoadOid(const OidRanges_t & o,uint32_t & loadCount)157 int BCTest::LoadOid(const OidRanges_t& o, uint32_t& loadCount)
158 {
159 blockCacheClient bc(BRP);
160 uint32_t rCount = 0;
161
162 for (uint32_t i = 0; i < o.ranges.size() ; i++)
163 {
164 const InlineLBIDRange r = {o.ranges[i].start, o.ranges[i].size};
165
166 if (r.size > 0)
167 {
168 bc.check(r, 0, rCount);
169 //cout << "i: " << i << " c: " << rCount << " " << o.ranges[i].size << endl;
170 loadCount += rCount;
171 }
172
173 rCount = 0;
174 } // for
175
176 //cout << "hwm: " << o.hwm << " tot: " << loadCount << " " << o.ranges.size() << endl;
177
178 return loadCount;
179
180 } // LoadOid
181
ReadOidRanges(const OidRanges_t & v)182 int BCTest::ReadOidRanges(const OidRanges_t& v)
183 {
184
185 blockCacheClient bc(BRP);
186 int32_t readBlocks = 0;
187 int32_t missBlocks = 0;
188
189 //int ret;
190 for (uint32_t i = 0; i < v.ranges.size(); i++)
191 {
192 FileBuffer fb(-1, -1);
193 const InlineLBIDRange r = {v.ranges[i].start, v.ranges[i].size};
194
195 for (int j = r.start; readBlocks < fCacheSz && j < r.start + r.size; j++)
196 {
197 //ret=0;
198 //ret=bc.read(j, 0, fb);
199 FileBuffer* ptr = bc.getBlockPtr(j, 0);
200
201 if (ptr)
202 readBlocks++;
203 else
204 missBlocks++;
205 }
206
207 //cout << " -- Read range idx: " << i << " hits: " << readBlocks << " miss: " << missBlocks << " hwm: " << v.hwm << endl;
208 }
209
210 return readBlocks;
211
212 } // ReadRange
213
214 // add one block to block cache
215 //
LoadLbid(const BRM::LBID_t lbid,const BRM::VER_t ver)216 void BCTest::LoadLbid(const BRM::LBID_t lbid, const BRM::VER_t ver)
217 {
218 blockCacheClient bc(BRP);
219 bool b;
220 bc.check(lbid, ver, false, b);
221 } // LoadLbid
222
223 // get one block out of block cache
224 //
ReadOidLbids(const BRM::LBID_t lbid,const BRM::VER_t ver)225 void BCTest::ReadOidLbids(const BRM::LBID_t lbid, const BRM::VER_t ver)
226 {
227 uint8_t d[8192] = {'\0'};
228 blockCacheClient bc(BRP);
229 bc.read(lbid, ver, d);
230 } // ReadLbid
231
232
233 struct loadThr
234 {
loadThr(BCTest & bc,int reps=1)235 loadThr::loadThr(BCTest& bc, int reps = 1) : fBC(bc), fReps(reps) {}
236
operator ()loadThr237 void operator()()
238 {
239 uint32_t loadedBlocks = 0;
240 uint32_t oidBlocks;
241 uint32_t i = 0;
242 uint32_t rc = 0;
243
244 clock_gettime(CLOCK_REALTIME, &tm1);
245
246 for (uint32_t j = 0; j < fReps; j++)
247 for (i = 0; /*loadedBlocks<cacheSize &&*/ i < fBC.OidRangesList.size(); i++)
248 {
249 oidBlocks = 0;
250 rc = fBC.LoadOid(fBC.OidRangesList[i], oidBlocks);
251 /**
252 cout << "."
253 << "-- " << i << " " << fBC.OidRangesList[i].oid
254 << " h: " << fBC.OidRangesList[i].hwm
255 << "/" << oidBlocks
256 << endl;
257 **/
258 loadedBlocks += oidBlocks;
259 }
260
261 clock_gettime(CLOCK_REALTIME, &tm2);
262 double tm3;
263 timespec_sub(tm1, tm2, tm3);
264 lastRangeListIdx = i;
265
266 cout << "loadtest ld: " << loadedBlocks
267 << " sz: " << fBC.fCacheSz
268 //<< " last: " << lastRangeListIdx
269 << " tm: " << right << setw(10) << fixed << tm3
270 << endl;
271
272 } // operator()
273
274 BCTest& fBC;
275 uint32_t fReps;
276 struct timespec tm1;
277 struct timespec tm2;
278
279 };
280
281 struct readThr
282 {
283
readThr(BCTest & bc,int reps=1)284 readThr::readThr(BCTest& bc, int reps = 1) : fBC(bc), fReps(reps) {}
285
operator ()readThr286 void operator()()
287 {
288 uint32_t rc = 0;
289 uint32_t loadedBlocks = 0;
290
291 for (uint32_t k = 0; k < fReps; k++)
292 {
293 for (uint32_t i = 0; i < fBC.OidRangesList.size() ; i++)
294 {
295 rc = fBC.ReadOidRanges(fBC.OidRangesList[i]);
296 cout << ".";
297 //cout << "-- ReadTest " << OidRangesList[i].oid << " h: " << OidRangesList[i].hwm << "/" << rc << endl;
298 loadedBlocks += rc;
299 rc = 0;
300 }
301 }
302
303 cout << "loadtest " << loadedBlocks << " " << rc << endl << endl;
304
305 } // operator()
306
307
308 BCTest& fBC;
309 uint32_t fReps;
310
311 };
312
usage()313 void usage()
314 {
315 cout << "testbc <cacheSz/1024> <reader threads> <read ahead> <client threads> <reps>" << endl;
316 }
317
318 //
main(int argc,char * argv[])319 int main(int argc, char* argv[])
320 {
321
322 int cacheSz = 128; // K number of blocks
323 int thr = 1;
324 int ra = 1024;
325 int clients = 1;
326 int reps = 1;
327
328 if (argc > 1 && atoi(argv[1]) > 0)
329 cacheSz = atoi(argv[1]) * 1024;
330
331 if (argc > 2 && atoi(argv[2]) > 0)
332 thr = atoi(argv[2]);
333
334 if (argc > 3 && atoi(argv[3]) > 0)
335 ra = atoi(argv[3]);
336
337 if (argc > 4 && atoi(argv[4]) > 0)
338 clients = atoi(argv[4]);
339
340 if (argc > 5 && atoi(argv[5]) > 0)
341 reps = atoi(argv[5]);
342
343 BCTest bc(cacheSz, thr, ra);
344
345 cout <<
346 "Cache Size: " << cacheSz <<
347 " read Threads: " << thr <<
348 " read Ahead: " << ra <<
349 " clients: " << clients <<
350 " repetitions: " << reps <<
351 " max Blocks: " << bc.maxBlocksAvailable <<
352 endl;
353
354 // loader test
355 struct loadThr loader1(bc, reps);
356 vector<boost::thread*> v;
357
358 for (int i = 0; i < clients; i++)
359 {
360 boost::thread* th1 = new boost::thread(loader1);
361 v.push_back(th1);
362 }
363
364 for (int i = 0; i < clients; i++)
365 {
366 boost::thread* th1 = v[i];
367 th1->join();
368 delete th1;
369 }
370
371 v.clear();
372
373 // reader test
374
375
376 return 0;
377
378 } // end main
379