]> git.sur5r.net Git - bacula/bacula/blob - bacula/patches/testing/accurate-db.patch
ebl Update to use a separate db connexion to compute and
[bacula/bacula] / bacula / patches / testing / accurate-db.patch
1 Index: src/filed/accurate.c
2 ===================================================================
3 --- src/filed/accurate.c        (révision 7288)
4 +++ src/filed/accurate.c        (copie de travail)
5 @@ -32,193 +32,295 @@
6  
7  #include "bacula.h"
8  #include "filed.h"
9 +#include "lib/htable.h"
10 +static int dbglvl=500;
11  
12 -static int dbglvl=200;
13 +#ifdef USE_DB
14 +#include <db.h>
15  
16 -typedef struct PrivateCurFile {
17 -#ifndef USE_TCADB
18 -   hlink link;
19 -#endif
20 -   char *fname;                        /* not stored with tchdb mode */
21 -   time_t ctime;
22 -   time_t mtime;
23 -   bool seen;
24 -} CurFile;
25 -
26 -#ifdef USE_TCADB
27 -static void realfree(void *p); /* used by tokyo code */
28 -
29  /*
30 - * Update hash element seen=1
31 + * This backend uses DB Berkeley
32   */
33 -static bool accurate_mark_file_as_seen(JCR *jcr, CurFile *elt)
34 +class AccurateBackendDB : public AccurateBackend
35  {
36 -   bool ret=true;
37 +public:
38 +   ~AccurateBackendDB() { destroy(); }
39 +   bool init(JCR *jcr, int nb_elt);
40 +   void destroy();
41  
42 -   elt->seen = 1;
43 -   if (!tcadbput(jcr->file_list, 
44 -                elt->fname, strlen(elt->fname)+1, 
45 -                elt, sizeof(CurFile)))
46 -   { /* TODO: disabling accurate mode ?  */
47 -      Jmsg(jcr, M_ERROR, 1, _("Can't update accurate hash disk\n"));
48 -      ret = false;
49 +   bool insert(JCR *jcr, char *key, CurFile *item);
50 +   bool lookup(JCR *jcr, char *key, CurFile *item);
51 +
52 +   bool mark_as_seen(JCR *jcr, char *key, CurFile *item);
53 +
54 +   CurFile *first(CurFile *elt);
55 +   CurFile *next();
56 +   void finish();
57 +private:
58 +   DB *db;                      /* DB object */
59 +   DBC *cursorp;                /* DB cursor  */
60 +   DBT dbkey;
61 +   DBT dbdata;
62 +   POOLMEM *hash_name;          /* file name for hash */
63 +};
64 +
65 +void AccurateBackendDB::destroy()
66 +{
67 +   /* cleanup walk cursor if any */
68 +   if (cursorp) {
69 +      cursorp->c_close(cursorp);
70 +      cursorp = NULL;
71     }
72 -
73 -   return ret;
74 +   if (db) {
75 +      db->close(db, DB_NOSYNC);
76 +      db = NULL;
77 +   }
78 +   if (hash_name) {
79 +      unlink(hash_name);        /* remove the hash on disk */
80 +      free_pool_memory(hash_name);
81 +      hash_name = NULL;
82 +   }
83  }
84  
85 -static bool accurate_lookup(JCR *jcr, char *fname, CurFile *ret)
86 +bool AccurateBackendDB::init(JCR *jcr, int nb_elt)
87  {
88 -   bool found=false;
89 -   ret->seen = 0;
90 -   int size;
91 -   CurFile *elt;
92 +   int ret;
93 +   
94 +   Dmsg0(dbglvl, "init DB accurate backend\n");
95  
96 -   elt = (CurFile*)tcadbget(jcr->file_list, 
97 -                           fname, strlen(fname)+1, &size);
98 -   if (elt)
99 +   if ((ret = db_create(&db, NULL, 0)) != 0) {
100 +      Jmsg(jcr, M_ERROR, 1, _("Can't open accurate hash disk ERR=%i\n"), ret);
101 +      return 0;
102 +   }
103 +
104 +   db->set_errfile(db, stderr);
105 +   db->set_errpfx(db, "hash");
106 +
107 +   if ((ret = db->set_cachesize(db, 0, 32 * 1024 * 1024, 0)) != 0) {
108 +      Jmsg(jcr, M_ERROR, 1, _("Can't setup hash disk cache size ERR=%i\n"), ret);
109 +      db->close(db, DB_NOSYNC);
110 +      db=NULL;
111 +   }
112 +
113 +   hash_name  = get_pool_memory(PM_MESSAGE);
114 +   make_unique_filename(&hash_name, jcr->JobId, "accurate");
115 +
116 +   if ((ret = db->open(db,
117 +                       NULL, hash_name, NULL, 
118 +                       DB_BTREE, DB_CREATE, 0600)) != 0)
119     {
120 -      /* TODO: don't malloc/free results */
121 -      found = true;
122 -      elt->fname = fname;
123 -      memcpy(ret, elt, sizeof(CurFile));
124 -      realfree(elt);
125 -//    Dmsg1(dbglvl, "lookup <%s> ok\n", fname);
126 +      db->close(db, DB_NOSYNC);
127 +      db=NULL;
128 +      free_pool_memory(hash_name);
129 +      hash_name = NULL;
130 +      Jmsg(jcr, M_ERROR, 1, _("Can't setup hash disk ERR=%i\n"), ret);
131 +      return 0;
132     }
133 -   return found;
134 +
135 +   return db != NULL;
136  }
137  
138 -/* Create tokyo dbm hash file 
139 - * If something goes wrong, we cancel accurate mode.
140 - */
141 -static bool accurate_init(JCR *jcr, int nbfile)
142 +/* Just update the element->seen to know if we have seen it */
143 +bool AccurateBackendDB::mark_as_seen(JCR *jcr, char *key, CurFile *item)
144  {
145 -   jcr->file_list = tcadbnew();
146 -//
147 -//   tchdbsetcache(jcr->file_list, 300000);
148 -//   tchdbtune(jcr->file_list,
149 -//          nbfile,            /* nb bucket 0.5n to 4n */
150 -//          6,                 /* size of element 2^x */
151 -//          16,
152 -//          0);                /* options like compression */
153 -//
154 -   jcr->hash_name  = get_pool_memory(PM_MESSAGE);
155 -   POOLMEM *temp = get_pool_memory(PM_MESSAGE);
156 +   item->seen = 1;
157 +   return insert(jcr, key, item);
158 +}
159  
160 -   if (nbfile > 500000) {
161 -      make_unique_filename(&jcr->hash_name, jcr->JobId, "accurate");
162 -      pm_strcat(jcr->hash_name, ".tcb");
163 -      Mmsg(temp, "%s#bnum=%i#mode=e#opts=l",
164 -          jcr->hash_name, nbfile*4); 
165 -      Dmsg1(dbglvl, "Doing accurate hash on disk %s\n", jcr->hash_name);
166 -   } else {
167 -      Dmsg0(dbglvl, "Doing accurate hash on memory\n");
168 -      pm_strcpy(jcr->hash_name, "*");
169 -      pm_strcpy(temp, "*");
170 +/* insert/replace */
171 +bool AccurateBackendDB::insert(JCR *jcr, char *key, CurFile *item)
172 +{
173 +   int ret;
174 +   memset(&dbkey, 0, sizeof(DBT));
175 +   memset(&dbdata, 0, sizeof(DBT));
176 +   dbkey.data = key;
177 +   dbkey.size = strlen(key)+1;
178 +   dbdata.data = item;
179 +   dbdata.size = sizeof(CurFile);
180 +   if ((ret = db->put(db, NULL, &dbkey, &dbdata, 0))) {
181 +      Jmsg(jcr, M_ERROR, 1, _("Can't update accurate hash disk ERR=%i\n"), ret);
182 +      return false;
183     }
184 +   return true;
185 +}
186 +
187 +bool AccurateBackendDB::lookup(JCR *jcr, char *key, CurFile *item)
188 +{
189 +   int ret=false;
190 +
191 +   /* Zero out the DBTs before using them. */
192 +   memset(&dbkey, 0, sizeof(DBT));
193 +   memset(&dbdata, 0, sizeof(DBT));
194 +
195 +   dbkey.data = key;
196 +   dbkey.size = strlen(key)+1;
197     
198 -   if(!tcadbopen(jcr->file_list, jcr->hash_name)){
199 -      Jmsg(jcr, M_ERROR, 1, _("Can't open accurate hash disk\n"));
200 -      Jmsg(jcr, M_INFO, 1, _("Disabling accurate mode\n"));
201 -      tcadbdel(jcr->file_list);
202 -      jcr->file_list = NULL;
203 -      jcr->accurate = false;
204 +   dbdata.data = item;
205 +   dbdata.ulen = sizeof(CurFile);
206 +   dbdata.flags = DB_DBT_USERMEM;
207 +
208 +   if (db->get(db, NULL, &dbkey, &dbdata, 0) == 0) {
209 +      ret=true;
210     }
211 -   free_pool_memory(temp);
212 -   return jcr->file_list != NULL;
213 +   item->fname = key;
214 +   return ret;
215  }
216  
217 -/* This function is called at the end of backup
218 - * We walk over all hash disk element, and we check
219 - * for elt.seen.
220 +/*
221 + * We use user memory to copy data
222   */
223 -bool accurate_send_deleted_list(JCR *jcr)
224 +CurFile *AccurateBackendDB::first(CurFile *elt)
225  {
226 -   char *key;
227 +   /* Zero out the DBTs before using them. */
228 +   memset(&dbkey, 0, sizeof(DBT));
229 +   memset(&dbdata, 0, sizeof(DBT));
230 +   dbdata.data = elt;
231 +   dbdata.ulen = sizeof(CurFile);
232 +   dbdata.flags = DB_DBT_USERMEM;
233 +   db->cursor(db, NULL, &cursorp, 0); 
234 +   return next();
235 +}
236 +
237 +CurFile *AccurateBackendDB::next()
238 +{
239     CurFile *elt;
240 -   int size;
241 -   FF_PKT *ff_pkt;
242 -   int stream = STREAM_UNIX_ATTRIBUTES;
243 -
244 -   if (!jcr->accurate || jcr->JobLevel == L_FULL) {
245 -      goto bail_out;
246 +   if (cursorp->c_get(cursorp, &dbkey, &dbdata, DB_NEXT) == 0) {
247 +      /* update fname field with fresh data */
248 +      elt = (CurFile *)dbdata.data;
249 +      elt->fname = (char *)dbkey.data;
250 +      return elt;
251 +   } else {
252 +      return NULL;
253     }
254 +}
255  
256 -   if (jcr->file_list == NULL) {
257 -      goto bail_out;
258 +void AccurateBackendDB::finish()
259 +{
260 +   if (cursorp) {
261 +      cursorp->c_close(cursorp);
262 +      cursorp = NULL;
263     }
264 +}
265  
266 -   ff_pkt = init_find_files();
267 -   ff_pkt->type = FT_DELETED;
268 +#endif /* USE_DB */
269  
270 -   /* traverse records */
271 -   tcadbiterinit(jcr->file_list);
272 -   while((key = tcadbiternext2(jcr->file_list)) != NULL) {
273 -      elt = (CurFile *) tcadbget(jcr->file_list, 
274 -                                key, strlen(key)+1, &size);
275 -      if (elt)
276 -      {
277 -        if (!elt->seen) {      /* already seen */
278 -           ff_pkt->fname = key;
279 -           ff_pkt->statp.st_mtime = elt->mtime;
280 -           ff_pkt->statp.st_ctime = elt->ctime;
281 -           encode_and_send_attributes(jcr, ff_pkt, stream);
282 -        }
283 -        realfree(elt);
284 -      }
285 -      realfree(key);           /* tokyo cabinet have to use real free() */
286 -   }
287 +/****************************************************************/
288  
289 -   term_find_files(ff_pkt);
290 -bail_out:
291 -   /* TODO: clean htable when this function is not reached ? */
292 -   if (jcr->file_list) {
293 -      if(!tcadbclose(jcr->file_list)){
294 -        Jmsg(jcr, M_ERROR, 1, _("Can't close accurate hash disk\n"));
295 -      }
296 +/* 
297 + * This is the htable implementation for accurate mode
298 + */
299 +class AccurateBackendHT : public AccurateBackend
300 +{
301 +public:
302 +   ~AccurateBackendHT() { destroy(); }
303 +   bool init(JCR *jcr, int nb_elt);
304 +   void destroy();
305  
306 -      /* delete the object */
307 -      tcadbdel(jcr->file_list);
308 -      if (!bstrcmp(jcr->hash_name, "*")) {
309 -        unlink(jcr->hash_name);
310 -      }
311 +   bool insert(JCR *jcr, char *key, CurFile *item);
312 +   bool lookup(JCR *jcr, char *key, CurFile *item);
313  
314 -      free_pool_memory(jcr->hash_name);
315 -      jcr->hash_name = NULL;
316 -      jcr->file_list = NULL;
317 +   bool mark_as_seen(JCR *jcr, char *key, CurFile *item);
318 +
319 +   CurFile *first(CurFile *elt);
320 +   CurFile *next();
321 +   void finish();
322 +private:
323 +   htable *db;
324 +};
325 +
326 +typedef struct {
327 +   CurFile elt;
328 +   hlink link;                  /* need this for htable link */
329 +} HTCurFile;
330 +
331 +void AccurateBackendHT::destroy()
332 +{
333 +   if (db) {
334 +      db->destroy();
335 +      free(db);
336 +      db = NULL;
337     }
338 +}
339 +
340 +bool AccurateBackendHT::init(JCR *jcr, int nb_elt)
341 +{
342 +   Dmsg0(dbglvl, "init HT accurate backend\n");
343 +
344 +   HTCurFile *elt=NULL;
345 +   db = (htable *)malloc(sizeof(htable));
346 +   db->init(elt, &elt->link, nb_elt);
347     return true;
348  }
349  
350 -#else  /* HTABLE mode */
351 +bool AccurateBackendHT::insert(JCR *jcr, char *key, CurFile *item)
352 +{
353 +   /* alloc CurFile + hlink + fname */
354 +   HTCurFile *htf = (HTCurFile *)db->hash_malloc(sizeof(HTCurFile)+strlen(key)+1);
355 +   memcpy(&htf->elt, item, sizeof(CurFile));
356  
357 -static bool accurate_mark_file_as_seen(JCR *jcr, CurFile *elt)
358 +   /* store fname at the end of the struct */
359 +   htf->elt.fname = (char *) htf + sizeof(HTCurFile);
360 +
361 +   strcpy(htf->elt.fname, key);
362 +   db->insert(htf->elt.fname, htf); 
363 +   return true;
364 +}
365 +
366 +bool AccurateBackendHT::mark_as_seen(JCR *jcr, char *key, CurFile *item)
367  {
368 -   CurFile *temp = (CurFile *)jcr->file_list->lookup(elt->fname);
369 -   temp->seen = 1;             /* records are in memory */
370 +   HTCurFile *temp = (HTCurFile *)db->lookup(key);
371 +   if (temp) {
372 +      temp->elt.seen = 1;       /* update in memory */
373 +   }
374     return true;
375  }
376  
377 -static bool accurate_lookup(JCR *jcr, char *fname, CurFile *ret)
378 +bool AccurateBackendHT::lookup(JCR *jcr, char *key, CurFile *item)
379  {
380     bool found=false;
381 -   ret->seen = 0;
382  
383 -   CurFile *temp = (CurFile *)jcr->file_list->lookup(fname);
384 +   HTCurFile *temp = (HTCurFile *)db->lookup(key);
385     if (temp) {
386 -      memcpy(ret, temp, sizeof(CurFile));
387 +      memcpy(item, &temp->elt, sizeof(CurFile));
388        found=true;
389 -//    Dmsg1(dbglvl, "lookup <%s> ok\n", fname);
390     }
391 -
392     return found;
393  }
394  
395 +CurFile *AccurateBackendHT::first(CurFile *elt)
396 +{
397 +   HTCurFile *temp = (HTCurFile *)db->first();
398 +   return &temp->elt;
399 +}
400 +
401 +CurFile *AccurateBackendHT::next()
402 +{
403 +   HTCurFile *temp = (HTCurFile *)db->next();
404 +   return &temp->elt;
405 +}
406 +
407 +void AccurateBackendHT::finish()
408 +{
409 +}
410 +
411 +/****************************************************************/
412 +
413 +/* Create hash file 
414 + * For less than 1M files, use htable in memory
415 + */
416  static bool accurate_init(JCR *jcr, int nbfile)
417  {
418 -   CurFile *elt=NULL;
419 -   jcr->file_list = (htable *)malloc(sizeof(htable));
420 -   jcr->file_list->init(elt, &elt->link, nbfile);
421 +#ifdef USE_DB
422 +   if (nbfile > 1000000) {
423 +      jcr->file_list = New(AccurateBackendDB);
424 +   } else {
425 +      jcr->file_list = New(AccurateBackendHT);
426 +   }
427 +#else
428 +   jcr->file_list = New(AccurateBackendHT);
429 +#endif
430 +   jcr->file_list->init(jcr, nbfile);
431 +
432     return true;
433  }
434  
435 @@ -228,7 +330,8 @@
436   */
437  bool accurate_send_deleted_list(JCR *jcr)
438  {
439 -   CurFile *elt;
440 +   CurFile elt;
441 +   CurFile *item;
442     FF_PKT *ff_pkt;
443     int stream = STREAM_UNIX_ATTRIBUTES;
444  
445 @@ -242,31 +345,28 @@
446  
447     ff_pkt = init_find_files();
448     ff_pkt->type = FT_DELETED;
449 -
450 -   foreach_htable (elt, jcr->file_list) {
451 -      if (!elt->seen) { /* already seen */
452 -         Dmsg2(dbglvl, "deleted fname=%s seen=%i\n", elt->fname, elt->seen);
453 -         ff_pkt->fname = elt->fname;
454 -         ff_pkt->statp.st_mtime = elt->mtime;
455 -         ff_pkt->statp.st_ctime = elt->ctime;
456 +   
457 +   for (item = jcr->file_list->first(&elt); item ; item = jcr->file_list->next()) {
458 +      if (!item->seen) { /* already seen */
459 +         Dmsg2(dbglvl, "deleted fname=%s seen=%i\n", item->fname, item->seen);
460 +         ff_pkt->fname = item->fname;
461 +         ff_pkt->statp.st_mtime = item->mtime;
462 +         ff_pkt->statp.st_ctime = item->ctime;
463           encode_and_send_attributes(jcr, ff_pkt, stream);
464        }
465 -//      free(elt->fname);
466     }
467 +   jcr->file_list->finish();
468  
469     term_find_files(ff_pkt);
470  bail_out:
471     /* TODO: clean htable when this function is not reached ? */
472     if (jcr->file_list) {
473 -      jcr->file_list->destroy();
474 -      free(jcr->file_list);
475 +      delete jcr->file_list;
476        jcr->file_list = NULL;
477     }
478     return true;
479  }
480  
481 -#endif /* common code */
482 -
483  static bool accurate_add_file(JCR *jcr, char *fname, char *lstat)
484  {
485     bool ret = true;
486 @@ -278,25 +378,12 @@
487     elt.mtime = statp.st_mtime;
488     elt.seen = 0;
489  
490 -#ifdef USE_TCADB
491 -   if (!tcadbput(jcr->file_list,
492 -                fname, strlen(fname)+1,
493 -                &elt, sizeof(CurFile)))
494 -   {
495 -      Jmsg(jcr, M_ERROR, 1, _("Can't update accurate hash disk ERR=%s\n"));
496 +   if (!jcr->file_list->insert(jcr, fname, &elt)) {
497 +      Jmsg(jcr, M_ERROR, 1, _("Can't update accurate hash ERR=%s\n"));
498        ret = false;
499     }
500 -#else  /* HTABLE */
501 -   CurFile *item;
502 -   /* we store CurFile, fname and ctime/mtime in the same chunk */
503 -   item = (CurFile *)jcr->file_list->hash_malloc(sizeof(CurFile)+strlen(fname)+1);
504 -   memcpy(item, &elt, sizeof(CurFile));
505 -   item->fname  = (char *)item+sizeof(CurFile);
506 -   strcpy(item->fname, fname);
507 -   jcr->file_list->insert(item->fname, item); 
508 -#endif
509  
510 -// Dmsg2(dbglvl, "add fname=<%s> lstat=%s\n", fname, lstat);
511 +   Dmsg2(dbglvl, "add fname=<%s> lstat=%s\n", fname, lstat);
512     return ret;
513  }
514  
515 @@ -324,7 +411,7 @@
516        fname = ff_pkt->fname;
517     } 
518  
519 -   if (!accurate_lookup(jcr, fname, &elt)) {
520 +   if (!jcr->file_list->lookup(jcr, fname, &elt)) {
521        Dmsg1(dbglvl, "accurate %s (not found)\n", fname);
522        stat = true;
523        goto bail_out;
524 @@ -343,7 +430,7 @@
525       stat = true;
526     }
527  
528 -   accurate_mark_file_as_seen(jcr, &elt);
529 +   jcr->file_list->mark_as_seen(jcr, fname, &elt);
530     Dmsg2(dbglvl, "accurate %s = %i\n", fname, stat);
531  
532  bail_out:
533 @@ -379,7 +466,7 @@
534     while (dir->recv() >= 0) {
535        len = strlen(dir->msg) + 1;
536        if (len < dir->msglen) {
537 -        accurate_add_file(jcr, dir->msg, dir->msg + len);
538 +         accurate_add_file(jcr, dir->msg, dir->msg + len);
539        }
540     }
541  
542 @@ -398,17 +485,3 @@
543  
544     return true;
545  }
546 -
547 -#ifdef USE_TCADB
548 -
549 -/*
550 - * Tokyo Cabinet library doesn't use smartalloc by default
551 - * results need to be released with real free()
552 - */
553 -#undef free
554 -void realfree(void *p)
555 -{
556 -   free(p);
557 -}
558 -
559 -#endif
560 Index: src/filed/filed.h
561 ===================================================================
562 --- src/filed/filed.h   (révision 7288)
563 +++ src/filed/filed.h   (copie de travail)
564 @@ -35,11 +35,35 @@
565  
566  
567  #define FILE_DAEMON 1
568 -#ifdef USE_TCADB                     /* hash disk based */
569 -# include <tcadb.h>
570 -#else
571 -# include "lib/htable.h"
572 -#endif
573 +
574 +/* 
575 + * Used to store accurate information
576 + */
577 +typedef struct {
578 +   char *fname;
579 +   time_t ctime;
580 +   time_t mtime;
581 +   bool seen;
582 +} CurFile;
583 +
584 +/* 
585 + * Virtual class for accurate backend (libdb or htable)
586 + */
587 +class AccurateBackend: public SMARTALLOC
588 +{
589 +public:
590 +   AccurateBackend()  : SMARTALLOC()  {}
591 +   virtual ~AccurateBackend() {}
592 +   virtual bool init(JCR *jcr, int nb_elt) = 0;
593 +   virtual bool insert(JCR *jcr, char *key, CurFile *item) = 0;
594 +   virtual bool lookup(JCR *jcr, char *key, CurFile *item) = 0;
595 +   virtual bool mark_as_seen(JCR *jcr, char *key, CurFile *item) = 0;
596 +   virtual CurFile *first(CurFile *elt) = 0;
597 +   virtual CurFile *next()  = 0;
598 +   virtual void finish() = 0;
599 +   virtual void destroy() {}
600 +};
601 +
602  #include "filed_conf.h"
603  #include "fd_plugins.h"
604  #include "findlib/find.h"
605 Index: src/baconfig.h
606 ===================================================================
607 --- src/baconfig.h      (révision 7288)
608 +++ src/baconfig.h      (copie de travail)
609 @@ -113,6 +113,12 @@
610  
611  #endif /* HAVE_WIN32 */
612  
613 +/* Select db backend for accurate mode */
614 +#ifndef USE_TCADB
615 +# ifndef USE_DB
616 +#  define USE_HTABLE
617 +# endif
618 +#endif
619  
620  #ifdef ENABLE_NLS
621     #include <libintl.h>
622 Index: src/jcr.h
623 ===================================================================
624 --- src/jcr.h   (révision 7288)
625 +++ src/jcr.h   (copie de travail)
626 @@ -341,12 +341,7 @@
627     CRYPTO_CTX crypto;                 /* Crypto ctx */
628     DIRRES* director;                  /* Director resource */
629     bool VSS;                          /* VSS used by FD */
630 -#ifdef USE_TCADB
631 -   TCADB *file_list;                  /* Previous file list (accurate mode) */
632 -   POOLMEM *hash_name;
633 -#else
634 -   htable *file_list;                 /* Previous file list (accurate mode) */
635 -#endif
636 +   AccurateBackend *file_list;       /* Accurate backend store */
637  #endif /* FILE_DAEMON */
638  
639