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