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 //
24 // Author: Jason Rodriguez <jrodriguez@calpont.com>, (C) 2007
25 //
26 // Copyright: See COPYING file that comes with this distribution
27 //
28 //
29
30 #include <vector>
31 #include <string>
32 #include <iostream>
33 #include <sys/time.h>
34 #include <unistd.h>
35
36 #include "blockcacheclient.h"
37 #include "stats.h"
38 #include "brm.h"
39 using namespace BRM;
40 using namespace dbbc;
41 using namespace std;
42
43 Stats* gPMStatsPtr = NULL;
44 bool gPMProfOn = false;
45 uint32_t gSession = 0;
46
47 int fLoops = 1;
48 int thr_cnt = 1;
49 uint64_t bfoundTot = 0;
50 uint64_t bnfoundTot = 0;
51 uint64_t rfoundTot = 0;
52 uint64_t rnfoundTot = 0;
53 uint64_t rangeOpCountTot = 0;
54 uint64_t blockOpCountTot = 0;
55 uint64_t noOpCountTot = 0;
56
57 struct thr_wait_struct
58 {
59 int predicate;
60 pthread_mutex_t fMutex;
61 pthread_cond_t fCond;
62 vector<LBIDRange_v> range_thr;
63 };
64 typedef thr_wait_struct thr_wait_t;
65
66 const int32_t cacheSize = 175000;
67 BlockRequestProcessor BRP(cacheSize, 4, 16);
68 BRM::VER_t ver = 0xFFFF;
69 u_int64_t totBlocks = 0;
70
thr_client(void * clientArgs)71 void* thr_client(void* clientArgs)
72 {
73 blockCacheClient bc(BRP);
74 uint64_t bfound = 0;
75 uint64_t bnfound = 0;
76 uint64_t rfound = 0;
77 uint64_t rnfound = 0;
78 uint64_t rangeOpCount = 0;
79 uint64_t blockOpCount = 0;
80 uint64_t noOpCount = 0;
81 thr_wait_t* clientWait = (thr_wait_t*)clientArgs;
82 struct timeval tv, tv2;
83 uint32_t randstate = 0;
84 randstate = static_cast<uint32_t>(tv.tv_usec);
85 pthread_mutex_lock(&clientWait->fMutex);
86 clientWait->predicate++;
87 pthread_mutex_unlock(&clientWait->fMutex);
88 vector<LBIDRange_v>& range_thr = clientWait->range_thr;
89
90 gettimeofday(&tv, NULL);
91 int j = 0;
92 int s = 0;
93 uint8_t fb[8192] = {0};
94 LBIDRange_v& r = range_thr[0];
95
96 for (int idx = 0; idx < fLoops; idx++)
97 {
98 for (int jdx = 0; jdx < range_thr.size(); jdx++)
99 {
100 uint32_t lbid = 0;
101 bool b;
102 int ret = 0;
103 r = range_thr[jdx];
104
105 for (int l = 0; l < r.size(); l++)
106 {
107 for (int m = r[l].start; m < r[l].start + r[l].size; m++)
108 {
109 //ret=bc.getBlock(m, ver, &fb, false, b);
110 ret = bc.read(m, ver, &fb);
111
112 if (ret)
113 {
114 bfound++;
115 }
116 else
117 {
118 bnfound++;
119 }
120 }
121 }
122 }
123 }
124
125 gettimeofday(&tv2, NULL);
126 time_t tm = time(0);
127 char t[50];
128 ctime_r(&tm, t);
129 t[strlen(t) - 1] = 0;
130 uint32_t elTime = tv2.tv_sec - tv.tv_sec;
131 uint64_t avgTot = 0;
132 uint64_t rangeAvg = 0;
133 uint64_t blkAvg = 0;
134
135 if (elTime > 0)
136 {
137 avgTot = (bfound + rfound) / elTime;
138 rangeAvg = (rfound) / elTime;
139 blkAvg = (bfound) / elTime;
140 }
141 else
142 {
143 avgTot = bfound + rfound;
144 rangeAvg = rfound;
145 blkAvg = bfound;
146 }
147
148 cout << "thr(" << pthread_self() << ") tm " << t << " " << (tv2.tv_sec - tv.tv_sec) << endl <<
149 "\tBlk: c " << blockOpCount << " pass " << bfound << " fail " << bnfound <<
150 " Blks/Sec Blk " << blkAvg << endl << endl;
151
152 pthread_mutex_lock(&clientWait->fMutex);
153 bfoundTot += bfound;
154 bnfoundTot += bnfound;
155 rfoundTot += rfound;
156 rnfoundTot += rnfound;
157 rangeOpCountTot += rangeOpCount;
158 blockOpCountTot += blockOpCount;
159 noOpCountTot += noOpCount;
160 clientWait->predicate--;
161 pthread_cond_signal(&clientWait->fCond);
162 pthread_mutex_unlock(&clientWait->fMutex);
163
164 return NULL;
165
166 } // end thr_client
167
LoadRange(const LBIDRange_v & v,uint32_t & loadCount)168 void LoadRange(const LBIDRange_v& v, uint32_t& loadCount)
169 {
170 blockCacheClient bc(BRP);
171
172 uint32_t rCount = 0;
173
174 for (uint32_t i = 0; i < v.size() ; i++)
175 {
176 const InlineLBIDRange r = {v[i].start, v[i].size};
177
178 if (r.size <= 1024)
179 {
180 bc.check(r, ver, rCount );
181 loadCount += rCount;
182 }
183
184 rCount = 0;
185
186 }
187
188 }
189
ReadRange(const LBIDRange_v & v)190 void ReadRange(const LBIDRange_v& v)
191 {
192 blockCacheClient bc(BRP);
193 int found = 0;
194 int notfound = 0;
195 int ret = 0;
196
197 for (uint32_t i = 0; i < v.size(); i++)
198 {
199 const InlineLBIDRange r = {v[i].start, v[i].size};
200 FileBuffer fb(-1, -1);
201
202 for (int j = r.start; j < r.start + r.size; j++)
203 {
204 if (r.size > 1024)
205 continue;
206
207 ret = bc.read(j, ver, fb);
208
209 if (ret)
210 found++;
211 else
212 notfound++;
213
214 ret = 0;
215 }
216
217 totBlocks += found;
218 totBlocks += notfound;
219 found = 0;
220 notfound = 0;
221 }
222
223 }
224
LoadLbid(const BRM::LBID_t lbid,const BRM::VER_t ver)225 void LoadLbid(const BRM::LBID_t lbid, const BRM::VER_t ver)
226 {
227 blockCacheClient bc(BRP);
228 bool b;
229 bc.check(lbid, ver, false, b);
230 }
231
ReadLbid(const BRM::LBID_t lbid,const BRM::VER_t ver)232 void ReadLbid(const BRM::LBID_t lbid, const BRM::VER_t ver)
233 {
234 static int found = 0, notfound = 0;
235 uint8_t d[8192];
236 blockCacheClient bc(BRP);
237 //FileBuffer fb(-1, -1);
238 //bc.read(lbid, ver, fb);
239 int ret = bc.read(lbid, ver, d);
240
241 if (ret)
242 found++;
243 else
244 notfound++;
245
246 if ((found + notfound) % 10000 == 0)
247 cout << "found " << found << " notfound " << notfound << endl;
248 }
249
250 //
main(int argc,char * argv[])251 int main(int argc, char* argv[])
252 {
253
254 if (argc >= 2) thr_cnt = atoi(argv[1]);
255
256 if (argc >= 3) fLoops = atoi(argv[2]);
257
258 if (thr_cnt <= 0) thr_cnt = 1;
259
260 if (thr_cnt > 1024) thr_cnt = 1024;
261
262 if (fLoops <= 0) fLoops = 1;
263
264 LBIDRange_v r;
265 vector<LBIDRange_v> ranges;
266 DBRM dbrm;
267 uint32_t hwm, lowfbo, highfbo, fbo, extentSize, lowlbid;
268 struct timeval tv, tv2;
269
270 cout << "Starting " << endl;
271 extentSize = dbrm.getExtentSize();
272 BRM::OID_t oid = 3000;
273 uint32_t totalExt = 0;
274
275 do
276 {
277 int ret = dbrm.lookup(oid, r);
278
279 if (ret == 0 && r.size() > 0)
280 {
281 lowlbid = (r[0].start / extentSize) * extentSize;
282 dbrm.lookup(r[0].start, ver, false, oid, fbo); // need the oid
283 dbrm.getHWM(oid, hwm);
284 lowfbo = fbo - (r[0].start - lowlbid);
285 highfbo = lowfbo + extentSize;
286 r[0].start = lowlbid;
287
288 if (hwm < highfbo)
289 r[0].size = hwm - lowfbo + 1;
290 else
291 r[0].size = extentSize;
292
293 for (uint32_t idx = 0; idx < r.size(); idx++)
294 totalExt += r[idx].size;
295
296 ranges.push_back(r);
297 }
298
299 oid++;
300 }
301 while ( (r.size() > 0 || oid < 900000) );
302
303 cout << ranges.size() << " ranges found" << endl;
304
305 gettimeofday(&tv, NULL);
306 uint32_t blksLoaded = 0;
307 int rangesLoaded = 0;
308
309 for (uint32_t i = 0; i < ranges.size() && blksLoaded < cacheSize; i++)
310 {
311 LoadRange(ranges[i], blksLoaded);
312 rangesLoaded++;
313 }
314
315 cout << endl;
316
317 gettimeofday(&tv2, NULL);
318 cout << "Loaded: " << blksLoaded << " blks " << rangesLoaded << " ranges sec: " << tv2.tv_sec - tv.tv_sec << endl;
319
320 while (ranges.size() > rangesLoaded) ranges.pop_back();
321
322 #ifdef BLAH
323
324 for (uint32_t i = 0; i < ranges; i++)
325 ReadRange(ranges[i]);
326
327 for (uint32_t i = 0; i < ranges.size(); i++)
328 {
329 LBIDRange_v rv = ranges[i];
330
331 for (uint32_t j = 0; j < rv.size(); j++)
332 {
333 const InlineLBIDRange l = {rv[j].start, rv[j].size};
334
335 for (uint32_t k = l.start; k < l.start + l.size; k++)
336 {
337 LoadLbid(k, ver);
338 ReadLbid(k, ver);
339 }
340 }
341 }
342
343 #endif
344
345 pthread_t thr_id[thr_cnt];
346 thr_wait_t thr_wait = {0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, ranges};
347
348 //start threads running
349 cout << "Starting driver threads" << endl;
350 gettimeofday(&tv, NULL);
351 memset(thr_id, 0, thr_cnt * (sizeof(pthread_t)));
352
353 for (int i = 0; i < thr_cnt; i++)
354 {
355 pthread_create(&thr_id[i], NULL, thr_client, &thr_wait);
356 }
357
358 // waiting until all threads have indicated completion
359 pthread_mutex_lock(&thr_wait.fMutex);
360
361 while (thr_wait.predicate > 0)
362 {
363 pthread_cond_wait(&thr_wait.fCond, &thr_wait.fMutex);
364 }
365
366 pthread_mutex_unlock(&thr_wait.fMutex);
367
368 // join threads back to main
369 for (int i = 0; i < thr_cnt; i++)
370 {
371 pthread_join(thr_id[i], NULL);
372 }
373
374 gettimeofday(&tv2, NULL);
375 time_t tm = time(0);
376 char t[50];
377 ctime_r(&tm, t);
378 t[strlen(t) - 1] = 0;
379 uint32_t elTime = tv2.tv_sec - tv.tv_sec;
380 uint64_t total = bfoundTot + rfoundTot;
381 uint64_t avgTot = 0;
382 uint64_t rangeAvg = 0;
383 uint64_t blkAvg = 0;
384
385 if (elTime > 0)
386 {
387 avgTot = (bfoundTot + rfoundTot) / elTime;
388 rangeAvg = (rfoundTot) / elTime;
389 blkAvg = (bfoundTot) / elTime;
390 }
391 else
392 {
393 avgTot = bfoundTot + rfoundTot;
394 rangeAvg = rfoundTot;
395 blkAvg = bfoundTot;
396 }
397
398 cout << "Summary tm " << t << " " << (tv2.tv_sec - tv.tv_sec) << endl <<
399 "\tBlk: c " << blockOpCountTot << " pass " << bfoundTot << " fail " << bnfoundTot <<
400 //"\tRng: c "<< rangeOpCountTot << " pass " << rfoundTot << " fail " << rnfoundTot << endl <<
401 //"\tNoOp: c " << noOpCountTot << " Total " << total << endl <<
402 //"\tblks/sec Blk " << blkAvg << " Rng " << rangeAvg << " Tot " << avgTot << " Thr " << avgTot/thr_cnt << endl << endl;
403 " Blks/Sec Blk " << blkAvg << " Thr " << avgTot / thr_cnt << endl << endl;
404
405
406 return 0;
407
408 } // end main
409