2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
36 static int dbglvl=200;
38 typedef struct PrivateCurFile {
42 char *fname; /* not stored with tchdb mode */
49 static void realfree(void *p); /* used by tokyo code */
52 * Update hash element seen=1
54 static bool accurate_mark_file_as_seen(JCR *jcr, CurFile *elt)
59 if (!tchdbputasync(jcr->file_list,
60 elt->fname, strlen(elt->fname)+1,
61 elt, sizeof(CurFile)))
62 { /* TODO: disabling accurate mode ? */
63 Jmsg(jcr, M_ERROR, 1, _("Can't update accurate hash disk ERR=%s\n"),
64 tchdberrmsg(tchdbecode(jcr->file_list)));
71 static bool accurate_lookup(JCR *jcr, char *fname, CurFile *ret)
76 if (tchdbget3(jcr->file_list,
77 fname, strlen(fname)+1,
78 ret, sizeof(CurFile)) != -1)
82 // Dmsg1(dbglvl, "lookup <%s> ok\n", fname);
87 /* Create tokyo dbm hash file
88 * If something goes wrong, we cancel accurate mode.
90 static bool accurate_init(JCR *jcr, int nbfile)
92 jcr->file_list = tchdbnew();
93 tchdbsetcache(jcr->file_list, 300000);
94 tchdbtune(jcr->file_list,
95 nbfile, /* nb bucket 0.5n to 4n */
96 6, /* size of element 2^x */
98 0); /* options like compression */
100 POOLMEM *name = get_pool_memory(PM_MESSAGE);
101 make_unique_filename(&name, jcr->JobId, "accurate");
103 if(!tchdbopen(jcr->file_list, name, HDBOWRITER | HDBOCREAT)){
104 Jmsg(jcr, M_ERROR, 1, _("Can't open accurate hash disk ERR=%s\n"),
105 tchdberrmsg(tchdbecode(jcr->file_list)));
106 Jmsg(jcr, M_INFO, 1, _("Disabling accurate mode\n"));
107 tchdbdel(jcr->file_list);
108 jcr->file_list = NULL;
109 jcr->accurate = false;
111 free_pool_memory(name);
112 return jcr->file_list != NULL;
115 /* This function is called at the end of backup
116 * We walk over all hash disk element, and we check
119 bool accurate_send_deleted_list(JCR *jcr)
124 int stream = STREAM_UNIX_ATTRIBUTES;
126 if (!jcr->accurate || jcr->JobLevel == L_FULL) {
130 if (jcr->file_list == NULL) {
134 ff_pkt = init_find_files();
135 ff_pkt->type = FT_DELETED;
137 /* traverse records */
138 tchdbiterinit(jcr->file_list);
139 while((key = tchdbiternext2(jcr->file_list)) != NULL) {
140 if (tchdbget3(jcr->file_list,
142 &elt, sizeof(CurFile)) != -1)
144 if (!elt.seen) { /* already seen */
146 ff_pkt->statp.st_mtime = elt.mtime;
147 ff_pkt->statp.st_ctime = elt.ctime;
148 encode_and_send_attributes(jcr, ff_pkt, stream);
150 realfree(key); /* tokyo cabinet have to use real free() */
154 term_find_files(ff_pkt);
156 /* TODO: clean htable when this function is not reached ? */
157 if (jcr->file_list) {
158 Dmsg1(dbglvl, "Accurate hash size=%lli\n",tchdbfsiz(jcr->file_list));
159 if(!tchdbclose(jcr->file_list)){
160 Jmsg(jcr, M_ERROR, 1, _("Can't close accurate hash disk ERR=%s\n"),
161 tchdberrmsg(tchdbecode(jcr->file_list)));
164 /* delete the object */
165 tchdbdel(jcr->file_list);
167 POOLMEM *name = get_pool_memory(PM_MESSAGE);
168 make_unique_filename(&name, jcr->JobId, "accurate");
171 free_pool_memory(name);
172 jcr->file_list = NULL;
177 #else /* HTABLE mode */
179 static bool accurate_mark_file_as_seen(JCR *jcr, CurFile *elt)
181 CurFile *temp = (CurFile *)jcr->file_list->lookup(elt->fname);
182 temp->seen = 1; /* records are in memory */
186 static bool accurate_lookup(JCR *jcr, char *fname, CurFile *ret)
191 CurFile *temp = (CurFile *)jcr->file_list->lookup(fname);
193 memcpy(ret, temp, sizeof(CurFile));
195 // Dmsg1(dbglvl, "lookup <%s> ok\n", fname);
201 static bool accurate_init(JCR *jcr, int nbfile)
204 jcr->file_list = (htable *)malloc(sizeof(htable));
205 jcr->file_list->init(elt, &elt->link, nbfile);
209 /* This function is called at the end of backup
210 * We walk over all hash disk element, and we check
213 bool accurate_send_deleted_list(JCR *jcr)
217 int stream = STREAM_UNIX_ATTRIBUTES;
219 if (!jcr->accurate || jcr->JobLevel == L_FULL) {
223 if (jcr->file_list == NULL) {
227 ff_pkt = init_find_files();
228 ff_pkt->type = FT_DELETED;
230 foreach_htable (elt, jcr->file_list) {
231 if (!elt->seen) { /* already seen */
232 Dmsg2(dbglvl, "deleted fname=%s seen=%i\n", elt->fname, elt->seen);
233 ff_pkt->fname = elt->fname;
234 ff_pkt->statp.st_mtime = elt->mtime;
235 ff_pkt->statp.st_ctime = elt->ctime;
236 encode_and_send_attributes(jcr, ff_pkt, stream);
241 term_find_files(ff_pkt);
243 /* TODO: clean htable when this function is not reached ? */
244 if (jcr->file_list) {
245 jcr->file_list->destroy();
246 free(jcr->file_list);
247 jcr->file_list = NULL;
252 #endif /* common code */
254 static bool accurate_add_file(JCR *jcr, char *fname, char *lstat)
260 decode_stat(lstat, &statp, &LinkFIc); /* decode catalog stat */
261 elt.ctime = statp.st_ctime;
262 elt.mtime = statp.st_mtime;
266 if (!tchdbputasync(jcr->file_list,
267 fname, strlen(fname)+1,
268 &elt, sizeof(CurFile)))
270 Jmsg(jcr, M_ERROR, 1, _("Can't update accurate hash disk ERR=%s\n"),
271 tchdberrmsg(tchdbecode(jcr->file_list)));
276 /* we store CurFile, fname and ctime/mtime in the same chunk */
277 item = (CurFile *)jcr->file_list->hash_malloc(sizeof(CurFile)+strlen(fname)+1);
278 memcpy(item, &elt, sizeof(CurFile));
279 item->fname = (char *)item+sizeof(CurFile);
280 strcpy(item->fname, fname);
281 jcr->file_list->insert(item->fname, item);
284 // Dmsg2(dbglvl, "add fname=<%s> lstat=%s\n", fname, lstat);
289 * This function is called for each file seen in fileset.
290 * We check in file_list hash if fname have been backuped
291 * the last time. After we can compare Lstat field.
292 * Full Lstat usage have been removed on 6612
294 bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt)
300 if (!jcr->accurate || jcr->JobLevel == L_FULL) {
306 if (S_ISDIR(ff_pkt->statp.st_mode)) {
307 fname = ff_pkt->link;
309 fname = ff_pkt->fname;
312 if (!accurate_lookup(jcr, fname, &elt)) {
313 Dmsg1(dbglvl, "accurate %s (not found)\n", fname);
318 if (elt.seen) { /* file has been seen ? */
319 Dmsg1(dbglvl, "accurate %s (already seen)\n", fname);
323 if (elt.mtime != ff_pkt->statp.st_mtime) {
324 Jmsg(jcr, M_SAVED, 0, _("%s st_mtime differs\n"), fname);
326 } else if (elt.ctime != ff_pkt->statp.st_ctime) {
327 Jmsg(jcr, M_SAVED, 0, _("%s st_ctime differs\n"), fname);
331 accurate_mark_file_as_seen(jcr, &elt);
332 Dmsg2(dbglvl, "accurate %s = %i\n", fname, stat);
335 unstrip_path(ff_pkt);
340 * TODO: use bigbuffer from htable
342 int accurate_cmd(JCR *jcr)
344 BSOCK *dir = jcr->dir_bsock;
348 if (!jcr->accurate || job_canceled(jcr) || jcr->JobLevel==L_FULL) {
352 if (sscanf(dir->msg, "accurate files=%ld", &nb) != 1) {
353 dir->fsend(_("2991 Bad accurate command\n"));
357 accurate_init(jcr, nb);
360 * buffer = sizeof(CurFile) + dirmsg
361 * dirmsg = fname + \0 + lstat
363 /* get current files */
364 while (dir->recv() >= 0) {
365 len = strlen(dir->msg) + 1;
366 if (len < dir->msglen) {
367 accurate_add_file(jcr, dir->msg, dir->msg + len);
372 extern void *start_heap;
374 char b1[50], b2[50], b3[50], b4[50], b5[50];
375 Dmsg5(dbglvl," Heap: heap=%s smbytes=%s max_bytes=%s bufs=%s max_bufs=%s\n",
376 edit_uint64_with_commas((char *)sbrk(0)-(char *)start_heap, b1),
377 edit_uint64_with_commas(sm_bytes, b2),
378 edit_uint64_with_commas(sm_max_bytes, b3),
379 edit_uint64_with_commas(sm_buffers, b4),
380 edit_uint64_with_commas(sm_max_buffers, b5));
390 * Tokyo Cabinet library doesn't use smartalloc by default
391 * results need to be release with real free()
394 void realfree(void *p)