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 typedef struct PrivateCurFile {
40 char *fname; /* not stored with tchdb mode */
46 bool accurate_add_file(JCR *jcr, char *fname, char *lstat)
51 decode_stat(lstat, &statp, &LinkFIc); /* decode catalog stat */
52 elt.ctime = statp.st_ctime;
53 elt.mtime = statp.st_mtime;
57 if (!tchdbputasync(jcr->file_list,
58 fname, strlen(fname)+1,
59 &elt, sizeof(CurFile)))
61 Dmsg1(2, "Can't add <%s> to file_list\n", fname);
62 /* TODO: check error */
66 /* we store CurFile, fname and ctime/mtime in the same chunk */
67 item = (CurFile *)jcr->file_list->hash_malloc(sizeof(CurFile)+strlen(fname)+1);
68 memcpy(item, &elt, sizeof(CurFile));
69 item->fname = (char *)item+sizeof(CurFile);
70 strcpy(item->fname, fname);
71 jcr->file_list->insert(item->fname, item);
74 Dmsg2(2, "add fname=<%s> lstat=%s\n", fname, lstat);
78 bool accurate_mark_file_as_seen(JCR *jcr, CurFile *elt)
85 if (!tchdbputasync(jcr->file_list,
86 elt->fname, strlen(elt->fname)+1,
87 elt, sizeof(CurFile)))
89 Dmsg1(2, "can't update <%s>\n", elt->fname);
90 ret = false; /* TODO: add error message */
94 CurFile *temp = (CurFile *)jcr->file_list->lookup(elt->fname);
100 bool accurate_lookup(JCR *jcr, char *fname, CurFile *ret)
106 if (tchdbget3(jcr->file_list,
107 fname, strlen(fname)+1,
108 ret, sizeof(CurFile)) != -1)
115 CurFile *temp = (CurFile *)jcr->file_list->lookup(fname);
117 memcpy(ret, temp, sizeof(CurFile));
123 Dmsg1(2, "lookup <%s> ok\n", fname);
129 bool accurate_init(JCR *jcr, int nbfile)
132 jcr->file_list = tchdbnew();
133 tchdbsetcache(jcr->file_list, 300000);
134 tchdbtune(jcr->file_list,
135 nbfile, /* nb bucket 0.5n to 4n */
136 7, /* size of element 2^x */
138 0); /* options like compression */
139 /* TODO: make accurate file unique */
141 Mmsg(buf, "/tmp/casket.hdb.%i", jcr->JobId);
142 if(!tchdbopen(jcr->file_list, buf.c_str(), HDBOWRITER | HDBOCREAT)){
143 /* TODO: handle error creation */
144 //ecode = tchdbecode(hdb);
145 //fprintf(stderr, "open error: %s\n", tchdberrmsg(ecode));
150 jcr->file_list = (htable *)malloc(sizeof(htable));
151 jcr->file_list->init(elt, &elt->link, nbfile);
158 * This function is called for each file seen in fileset.
159 * We check in file_list hash if fname have been backuped
160 * the last time. After we can compare Lstat field.
161 * Full Lstat usage have been removed on 6612
163 bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt)
169 if (!jcr->accurate || jcr->JobLevel == L_FULL) {
175 if (S_ISDIR(ff_pkt->statp.st_mode)) {
176 fname = ff_pkt->link;
178 fname = ff_pkt->fname;
181 if (!accurate_lookup(jcr, fname, &elt)) {
182 Dmsg1(2, "accurate %s (not found)\n", fname);
187 if (elt.seen) { /* file has been seen ? */
188 Dmsg1(2, "accurate %s (already seen)\n", fname);
192 if (elt.mtime != ff_pkt->statp.st_mtime) {
193 Jmsg(jcr, M_SAVED, 0, _("%s st_mtime differs\n"), fname);
195 } else if (elt.ctime != ff_pkt->statp.st_ctime) {
196 Jmsg(jcr, M_SAVED, 0, _("%s st_ctime differs\n"), fname);
201 Dmsg4(1, "%i = %i\t%i = %i\n", elt.mtime, ff_pkt->statp.st_mtime,
202 elt.ctime, ff_pkt->statp.st_ctime);
205 accurate_mark_file_as_seen(jcr, &elt);
206 Dmsg2(2, "accurate %s = %i\n", fname, stat);
209 unstrip_path(ff_pkt);
214 * TODO: use bigbuffer from htable
216 int accurate_cmd(JCR *jcr)
218 BSOCK *dir = jcr->dir_bsock;
222 if (!jcr->accurate || job_canceled(jcr) || jcr->JobLevel==L_FULL) {
226 if (sscanf(dir->msg, "accurate files=%ld", &nb) != 1) {
227 dir->fsend(_("2991 Bad accurate command\n"));
230 Dmsg2(2, "nb=%d msg=%s\n", nb, dir->msg);
232 accurate_init(jcr, nb);
235 * buffer = sizeof(CurFile) + dirmsg
236 * dirmsg = fname + \0 + lstat
238 /* get current files */
239 while (dir->recv() >= 0) {
240 Dmsg1(2, "accurate_cmd fname=%s\n", dir->msg);
241 len = strlen(dir->msg) + 1;
242 if (len < dir->msglen) {
243 accurate_add_file(jcr, dir->msg, dir->msg + len);
248 extern void *start_heap;
250 char b1[50], b2[50], b3[50], b4[50], b5[50];
251 Dmsg5(1," Heap: heap=%s smbytes=%s max_bytes=%s bufs=%s max_bufs=%s\n",
252 edit_uint64_with_commas((char *)sbrk(0)-(char *)start_heap, b1),
253 edit_uint64_with_commas(sm_bytes, b2),
254 edit_uint64_with_commas(sm_max_bytes, b3),
255 edit_uint64_with_commas(sm_buffers, b4),
256 edit_uint64_with_commas(sm_max_buffers, b5));
263 bool accurate_send_deleted_list(JCR *jcr)
267 int stream = STREAM_UNIX_ATTRIBUTES;
269 if (!jcr->accurate || jcr->JobLevel == L_FULL) {
273 if (jcr->file_list == NULL) {
277 ff_pkt = init_find_files();
278 ff_pkt->type = FT_DELETED;
284 /* traverse records */
285 tchdbiterinit(jcr->file_list);
286 while((key = tchdbiternext2(jcr->file_list)) != NULL) {
287 if (tchdbget3(jcr->file_list,
289 elt, sizeof(CurFile)) != -1)
293 ff_pkt->statp.st_mtime = elt->mtime;
294 ff_pkt->statp.st_ctime = elt->ctime;
295 encode_and_send_attributes(jcr, ff_pkt, stream);
296 Dmsg1(2, "deleted <%s>\n", key);
300 } else { /* TODO: add error message */
301 Dmsg1(2, "No value for <%s> key\n", key);
305 foreach_htable (elt, jcr->file_list) {
306 if (!elt->seen) { /* already seen */
307 Dmsg2(1, "deleted fname=%s seen=%i\n", elt->fname, elt->seen);
308 ff_pkt->fname = elt->fname;
309 ff_pkt->statp.st_mtime = elt->mtime;
310 ff_pkt->statp.st_ctime = elt->ctime;
311 encode_and_send_attributes(jcr, ff_pkt, stream);
317 term_find_files(ff_pkt);
319 /* TODO: clean htable when this function is not reached ? */
320 if (jcr->file_list) {
322 if(!tchdbclose(jcr->file_list)){
323 // ecode = tchdbecode(hdb);
324 // fprintf(stderr, "close error: %s\n", tchdberrmsg(ecode));
327 /* delete the object */
328 tchdbdel(jcr->file_list);
330 Mmsg(buf, "/tmp/casket.hdb.%i", jcr->JobId);
331 // unlink("/tmp/casket.hdb");
333 jcr->file_list->destroy();
334 free(jcr->file_list);
336 jcr->file_list = NULL;