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 /* TODO: check error */
65 /* we store CurFile, fname and ctime/mtime in the same chunk */
66 item = (CurFile *)jcr->file_list->hash_malloc(sizeof(CurFile)+strlen(fname)+1);
67 memcpy(item, &elt, sizeof(CurFile));
68 item->fname = (char *)item+sizeof(CurFile);
69 strcpy(item->fname, fname);
70 jcr->file_list->insert(item->fname, item);
73 Dmsg2(500, "add fname=%s lstat=%s\n", fname, lstat);
77 bool accurate_mark_file_as_seen(JCR *jcr, CurFile *elt)
83 if (!tchdbputasync(jcr->file_list,
84 elt->fname, strlen(elt->fname)+1,
85 elt, sizeof(CurFile)))
87 ret = false; /* TODO: add error message */
90 CurFile *temp = (CurFile *)jcr->file_list->lookup(elt->fname);
96 bool accurate_lookup(JCR *jcr, char *fname, CurFile *ret)
102 if (tchdbget3(jcr->file_list,
103 fname, strlen(fname)+1,
104 ret, sizeof(CurFile)) != -1)
111 CurFile *temp = (CurFile *)jcr->file_list->lookup(fname);
113 memcpy(ret, temp, sizeof(CurFile));
121 bool accurate_init(JCR *jcr, int nbfile)
124 jcr->file_list = tchdbnew();
125 tchdbsetcache(jcr->file_list, 300000);
126 tchdbtune(jcr->file_list,
127 nbfile, /* nb bucket 0.5n to 4n */
128 7, /* size of element 2^x */
130 0); /* options like compression */
131 /* TODO: make accurate file unique */
132 if(!tchdbopen(jcr->file_list, "/tmp/casket.hdb", HDBOWRITER | HDBOCREAT)){
133 /* TODO: handle error creation */
134 //ecode = tchdbecode(hdb);
135 //fprintf(stderr, "open error: %s\n", tchdberrmsg(ecode));
140 jcr->file_list = (htable *)malloc(sizeof(htable));
141 jcr->file_list->init(elt, &elt->link, nbfile);
148 * This function is called for each file seen in fileset.
149 * We check in file_list hash if fname have been backuped
150 * the last time. After we can compare Lstat field.
151 * Full Lstat usage have been removed on 6612
153 bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt)
159 if (!jcr->accurate || jcr->JobLevel == L_FULL) {
165 if (S_ISDIR(ff_pkt->statp.st_mode)) {
166 fname = ff_pkt->link;
168 fname = ff_pkt->fname;
171 if (!accurate_lookup(jcr, fname, &elt)) {
172 Dmsg1(2, "accurate %s (not found)\n", fname);
177 if (elt.seen) { /* file has been seen ? */
178 Dmsg1(2, "accurate %s (already seen)\n", fname);
182 if (elt.mtime != ff_pkt->statp.st_mtime) {
183 Jmsg(jcr, M_SAVED, 0, _("%s st_mtime differs\n"), fname);
185 } else if (elt.ctime != ff_pkt->statp.st_ctime) {
186 Jmsg(jcr, M_SAVED, 0, _("%s st_ctime differs\n"), fname);
191 Dmsg4(1, "%i = %i\t%i = %i\n", elt.mtime, ff_pkt->statp.st_mtime,
192 elt.ctime, ff_pkt->statp.st_ctime);
195 accurate_mark_file_as_seen(jcr, &elt);
196 Dmsg2(500, "accurate %s = %i\n", fname, stat);
199 unstrip_path(ff_pkt);
204 * TODO: use bigbuffer from htable
206 int accurate_cmd(JCR *jcr)
208 BSOCK *dir = jcr->dir_bsock;
212 if (!jcr->accurate || job_canceled(jcr) || jcr->JobLevel==L_FULL) {
216 if (sscanf(dir->msg, "accurate files=%ld", &nb) != 1) {
217 dir->fsend(_("2991 Bad accurate command\n"));
220 Dmsg2(2, "nb=%d msg=%s\n", nb, dir->msg);
222 accurate_init(jcr, nb);
225 * buffer = sizeof(CurFile) + dirmsg
226 * dirmsg = fname + \0 + lstat
228 /* get current files */
229 while (dir->recv() >= 0) {
230 Dmsg1(2, "accurate_cmd fname=%s\n", dir->msg);
231 len = strlen(dir->msg) + 1;
232 if (len < dir->msglen) {
233 accurate_add_file(jcr, dir->msg, dir->msg + len);
238 extern void *start_heap;
240 char b1[50], b2[50], b3[50], b4[50], b5[50];
241 Dmsg5(1," Heap: heap=%s smbytes=%s max_bytes=%s bufs=%s max_bufs=%s\n",
242 edit_uint64_with_commas((char *)sbrk(0)-(char *)start_heap, b1),
243 edit_uint64_with_commas(sm_bytes, b2),
244 edit_uint64_with_commas(sm_max_bytes, b3),
245 edit_uint64_with_commas(sm_buffers, b4),
246 edit_uint64_with_commas(sm_max_buffers, b5));
253 bool accurate_send_deleted_list(JCR *jcr)
257 int stream = STREAM_UNIX_ATTRIBUTES;
259 if (!jcr->accurate || jcr->JobLevel == L_FULL) {
263 if (jcr->file_list == NULL) {
267 ff_pkt = init_find_files();
268 ff_pkt->type = FT_DELETED;
274 /* traverse records */
275 tchdbiterinit(jcr->file_list);
276 while((key = tchdbiternext2(jcr->file_list)) != NULL){
277 tchdbget3(jcr->file_list, key, strlen(key), elt, sizeof(CurFile));
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);
285 foreach_htable (elt, jcr->file_list) {
286 if (!elt->seen) { /* already seen */
287 Dmsg2(1, "deleted fname=%s seen=%i\n", elt->fname, elt->seen);
288 ff_pkt->fname = elt->fname;
289 ff_pkt->statp.st_mtime = elt->mtime;
290 ff_pkt->statp.st_ctime = elt->ctime;
291 encode_and_send_attributes(jcr, ff_pkt, stream);
297 term_find_files(ff_pkt);
299 /* TODO: clean htable when this function is not reached ? */
300 if (jcr->file_list) {
302 if(!tchdbclose(jcr->file_list)){
303 // ecode = tchdbecode(hdb);
304 // fprintf(stderr, "close error: %s\n", tchdberrmsg(ecode));
307 /* delete the object */
308 tchdbdel(jcr->file_list);
309 unlink("/tmp/casket.hdb");
311 jcr->file_list->destroy();
312 free(jcr->file_list);
314 jcr->file_list = NULL;