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 void strip_path(FF_PKT *ff_pkt);
37 void unstrip_path(FF_PKT *ff_pkt);
38 bool encode_and_send_attributes(JCR *jcr, FF_PKT *ff_pkt, int &data_stream);
39 typedef struct PrivateCurFile {
43 char *fname; /* not stored with tchdb mode */
49 bool accurate_add_file(JCR *jcr, char *fname, char *lstat)
54 decode_stat(lstat, &statp, &LinkFIc); /* decode catalog stat */
55 elt.ctime = statp.st_ctime;
56 elt.mtime = statp.st_mtime;
60 if (!tchdbputasync(jcr->file_list,
61 fname, strlen(fname)+1,
62 &elt, sizeof(CurFile)))
64 /* TODO: check error */
68 /* we store CurFile, fname and ctime/mtime in the same chunk */
69 item = (CurFile *)jcr->file_list->hash_malloc(sizeof(CurFile)+strlen(fname)+1);
70 memcpy(item, &elt, sizeof(CurFile));
71 item->fname = (char *)item+sizeof(CurFile);
72 strcpy(item->fname, fname);
73 jcr->file_list->insert(item->fname, item);
76 Dmsg2(500, "add fname=%s lstat=%s\n", fname, lstat);
80 bool accurate_mark_file_as_seen(JCR *jcr, CurFile *elt)
86 if (!tchdbputasync(jcr->file_list,
87 elt->fname, strlen(elt->fname)+1,
88 elt, sizeof(CurFile)))
90 ret = false; /* TODO: add error message */
93 CurFile *temp = (CurFile *)jcr->file_list->lookup(elt->fname);
99 bool accurate_lookup(JCR *jcr, char *fname, CurFile *ret)
105 if (tchdbget3(jcr->file_list,
106 fname, strlen(fname)+1,
107 ret, sizeof(CurFile)) != -1)
114 CurFile *temp = (CurFile *)jcr->file_list->lookup(fname);
116 memcpy(ret, temp, sizeof(CurFile));
124 bool accurate_init(JCR *jcr, int nbfile)
127 jcr->file_list = tchdbnew();
128 tchdbsetcache(jcr->file_list, 300000);
129 tchdbtune(jcr->file_list,
130 nbfile, /* nb bucket 0.5n to 4n */
131 7, /* size of element 2^x */
133 0); /* options like compression */
134 /* TODO: make accurate file unique */
135 if(!tchdbopen(jcr->file_list, "/tmp/casket.hdb", HDBOWRITER | HDBOCREAT)){
136 /* TODO: handle error creation */
137 //ecode = tchdbecode(hdb);
138 //fprintf(stderr, "open error: %s\n", tchdberrmsg(ecode));
143 jcr->file_list = (htable *)malloc(sizeof(htable));
144 jcr->file_list->init(elt, &elt->link, nbfile);
151 * This function is called for each file seen in fileset.
152 * We check in file_list hash if fname have been backuped
153 * the last time. After we can compare Lstat field.
154 * Full Lstat usage have been removed on 6612
156 bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt)
162 if (!jcr->accurate || jcr->JobLevel == L_FULL) {
168 if (S_ISDIR(ff_pkt->statp.st_mode)) {
169 fname = ff_pkt->link;
171 fname = ff_pkt->fname;
174 if (!accurate_lookup(jcr, fname, &elt)) {
175 Dmsg1(2, "accurate %s (not found)\n", fname);
180 if (elt.seen) { /* file has been seen ? */
181 Dmsg1(2, "accurate %s (already seen)\n", fname);
185 if (elt.mtime != ff_pkt->statp.st_mtime) {
186 Jmsg(jcr, M_SAVED, 0, _("%s st_mtime differs\n"), fname);
188 } else if (elt.ctime != ff_pkt->statp.st_ctime) {
189 Jmsg(jcr, M_SAVED, 0, _("%s st_ctime differs\n"), fname);
194 Dmsg4(1, "%i = %i\t%i = %i\n", elt.mtime, ff_pkt->statp.st_mtime,
195 elt.ctime, ff_pkt->statp.st_ctime);
198 accurate_mark_file_as_seen(jcr, &elt);
199 Dmsg2(500, "accurate %s = %i\n", fname, stat);
202 unstrip_path(ff_pkt);
207 * TODO: use bigbuffer from htable
209 int accurate_cmd(JCR *jcr)
211 BSOCK *dir = jcr->dir_bsock;
215 if (!jcr->accurate || job_canceled(jcr) || jcr->JobLevel==L_FULL) {
219 if (sscanf(dir->msg, "accurate files=%ld", &nb) != 1) {
220 dir->fsend(_("2991 Bad accurate command\n"));
223 Dmsg2(2, "nb=%d msg=%s\n", nb, dir->msg);
225 accurate_init(jcr, nb);
228 * buffer = sizeof(CurFile) + dirmsg
229 * dirmsg = fname + \0 + lstat
231 /* get current files */
232 while (dir->recv() >= 0) {
233 Dmsg1(2, "accurate_cmd fname=%s\n", dir->msg);
234 len = strlen(dir->msg) + 1;
235 if (len < dir->msglen) {
236 accurate_add_file(jcr, dir->msg, dir->msg + len);
241 extern void *start_heap;
243 char b1[50], b2[50], b3[50], b4[50], b5[50];
244 Dmsg5(1," Heap: heap=%s smbytes=%s max_bytes=%s bufs=%s max_bufs=%s\n",
245 edit_uint64_with_commas((char *)sbrk(0)-(char *)start_heap, b1),
246 edit_uint64_with_commas(sm_bytes, b2),
247 edit_uint64_with_commas(sm_max_bytes, b3),
248 edit_uint64_with_commas(sm_buffers, b4),
249 edit_uint64_with_commas(sm_max_buffers, b5));
256 bool accurate_send_deleted_list(JCR *jcr)
260 int stream = STREAM_UNIX_ATTRIBUTES;
262 if (!jcr->accurate || jcr->JobLevel == L_FULL) {
266 if (jcr->file_list == NULL) {
270 ff_pkt = init_find_files();
271 ff_pkt->type = FT_DELETED;
277 /* traverse records */
278 tchdbiterinit(jcr->file_list);
279 while((key = tchdbiternext2(jcr->file_list)) != NULL){
280 tchdbget3(jcr->file_list, key, strlen(key), elt, sizeof(CurFile));
282 ff_pkt->statp.st_mtime = elt->mtime;
283 ff_pkt->statp.st_ctime = elt->ctime;
284 encode_and_send_attributes(jcr, ff_pkt, stream);
288 foreach_htable (elt, jcr->file_list) {
289 if (!elt->seen) { /* already seen */
290 Dmsg2(1, "deleted fname=%s seen=%i\n", elt->fname, elt->seen);
291 ff_pkt->fname = elt->fname;
292 ff_pkt->statp.st_mtime = elt->mtime;
293 ff_pkt->statp.st_ctime = elt->ctime;
294 encode_and_send_attributes(jcr, ff_pkt, stream);
300 term_find_files(ff_pkt);
302 /* TODO: clean htable when this function is not reached ? */
303 if (jcr->file_list) {
305 if(!tchdbclose(jcr->file_list)){
306 // ecode = tchdbecode(hdb);
307 // fprintf(stderr, "close error: %s\n", tchdberrmsg(ecode));
310 /* delete the object */
311 tchdbdel(jcr->file_list);
312 unlink("/tmp/casket.hdb");
314 jcr->file_list->destroy();
315 free(jcr->file_list);
317 jcr->file_list = NULL;