From: Kern Sibbald Date: Fri, 18 Jun 2004 10:07:42 +0000 (+0000) Subject: Finish new restore tree code X-Git-Tag: Release-1.35.1~103 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=d5a03aa493e551547a8d6c56371a15417c5f5a5e;p=bacula%2Fbacula Finish new restore tree code git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1426 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/platforms/freebsd/Makefile.in b/bacula/platforms/freebsd/Makefile.in index c070eed6c2..960a8676d8 100644 --- a/bacula/platforms/freebsd/Makefile.in +++ b/bacula/platforms/freebsd/Makefile.in @@ -49,8 +49,8 @@ install-autostart-sd: rm -f /etc/rc.local.$$today; \ cp -p /etc/rc.local /etc/rc.local.$$today; \ ( echo "Start the Bacula Storage daemon. Do not remove the 'TAG_BACULA_SD' text"; \ - echo "if [ -x /etc/rc.bacula-fd ]; then # TAG_BACULA_SD"; \ - echo " /etc/rc.bacula-fd start # TAG_BACULA_SD"; \ + echo "if [ -x /etc/rc.bacula-sd ]; then # TAG_BACULA_SD"; \ + echo " /etc/rc.bacula-sd start # TAG_BACULA_SD"; \ echo "fi # TAG_BACULA_SD"; \ ) >> /etc/rc.local; \ echo ""; \ @@ -137,4 +137,3 @@ distclean: clean devclean: clean @rm -f Makefile bacula-*.spec - diff --git a/bacula/src/cats/sql.c b/bacula/src/cats/sql.c index e80caec2a1..7b3ebd4db8 100644 --- a/bacula/src/cats/sql.c +++ b/bacula/src/cats/sql.c @@ -162,7 +162,7 @@ UpdateDB(const char *file, int line, JCR *jcr, B_DB *mdb, char *cmd) m_msg(file, line, &mdb->errmsg, _("Update problem: affected_rows=%s\n"), edit_uint64(mdb->num_rows, ed1)); if (verbose) { - j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd); +// j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd); } return 0; } diff --git a/bacula/src/dird/sql_cmds.c b/bacula/src/dird/sql_cmds.c index 042d3764bd..247cf50924 100644 --- a/bacula/src/dird/sql_cmds.c +++ b/bacula/src/dird/sql_cmds.c @@ -144,6 +144,8 @@ const char *select_restore_del = /* ======= ua_restore.c */ +const char *uar_count_files = + "SELECT JobFiles FROM Job WHERE JobId=%u"; /* List last 20 Jobs */ const char *uar_list_jobs = diff --git a/bacula/src/dird/ua.h b/bacula/src/dird/ua.h index 92ce51e5c9..82818f9a47 100644 --- a/bacula/src/dird/ua.h +++ b/bacula/src/dird/ua.h @@ -34,32 +34,36 @@ struct UAContext { JCR *jcr; B_DB *db; CAT *catalog; - CONRES *cons; /* console resource */ - POOLMEM *cmd; /* return command/name buffer */ - POOLMEM *args; /* command line arguments */ - char *argk[MAX_CMD_ARGS]; /* argument keywords */ - char *argv[MAX_CMD_ARGS]; /* argument values */ - int argc; /* number of arguments */ - char **prompt; /* list of prompts */ - int max_prompts; /* max size of list */ - int num_prompts; /* current number in list */ - bool auto_display_messages; /* if set, display messages */ + CONRES *cons; /* console resource */ + POOLMEM *cmd; /* return command/name buffer */ + POOLMEM *args; /* command line arguments */ + char *argk[MAX_CMD_ARGS]; /* argument keywords */ + char *argv[MAX_CMD_ARGS]; /* argument values */ + int argc; /* number of arguments */ + char **prompt; /* list of prompts */ + int max_prompts; /* max size of list */ + int num_prompts; /* current number in list */ + bool auto_display_messages; /* if set, display messages */ bool user_notified_msg_pending; /* set when user notified */ - bool automount; /* if set, mount after label */ - bool quit; /* if set, quit */ - bool verbose; /* set for normal UA verbosity */ - uint32_t pint32_val; /* positive integer */ - int32_t int32_val; /* positive/negative */ -}; + bool automount; /* if set, mount after label */ + bool quit; /* if set, quit */ + bool verbose; /* set for normal UA verbosity */ + uint32_t pint32_val; /* positive integer */ + int32_t int32_val; /* positive/negative */ +}; /* Context for insert_tree_handler() */ struct TREE_CTX { - TREE_ROOT *root; /* root */ - TREE_NODE *node; /* current node */ - TREE_NODE *avail_node; /* unused node last insert */ - int cnt; /* count for user feedback */ - bool all; /* if set mark all as default */ + TREE_ROOT *root; /* root */ + TREE_NODE *node; /* current node */ + TREE_NODE *avail_node; /* unused node last insert */ + int cnt; /* count for user feedback */ + bool all; /* if set mark all as default */ UAContext *ua; + uint32_t FileEstimate; /* estimate of number of files */ + uint32_t FileCount; /* current count of files */ + uint32_t LastCount; /* last count of files */ + uint32_t DeltaCount; /* trigger for printing */ }; #endif diff --git a/bacula/src/dird/ua_restore.c b/bacula/src/dird/ua_restore.c index c976e84540..8d5347dbc3 100644 --- a/bacula/src/dird/ua_restore.c +++ b/bacula/src/dird/ua_restore.c @@ -48,6 +48,7 @@ extern char *uar_create_temp1, *uar_last_full, *uar_full; extern char *uar_inc, *uar_list_temp, *uar_sel_jobid_temp; extern char *uar_sel_all_temp1, *uar_sel_fileset, *uar_mediatype; extern char *uar_jobid_fileindex, *uar_dif, *uar_sel_all_temp; +extern char *uar_count_files; struct NAME_LIST { @@ -108,6 +109,7 @@ static int insert_file_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *fi static void insert_one_file(UAContext *ua, RESTORE_CTX *rx, char *date); static int get_client_name(UAContext *ua, RESTORE_CTX *rx); static int get_date(UAContext *ua, char *date, int date_len); +static int count_handler(void *ctx, int num_fields, char **row); /* * Restore files @@ -716,6 +718,20 @@ static bool build_directory_tree(UAContext *ua, RESTORE_CTX *rx) * appear more than once, however, we only insert it once. */ int items = 0; + p = rx->JobIds; + tree.FileEstimate = 0; + if (get_next_jobid_from_list(&p, &JobId) > 0) { + /* Use first JobId as estimate of the number of files to restore */ + Mmsg(&rx->query, uar_count_files, JobId); + if (!db_sql_query(ua->db, rx->query, count_handler, (void *)rx)) { + bsendmsg(ua, "%s\n", db_strerror(ua->db)); + } + if (rx->found) { + /* Add about 25% more than this job for over estimate */ + tree.FileEstimate = rx->JobId + (rx->JobId >> 2); + tree.DeltaCount = rx->JobId/50; /* print 50 ticks */ + } + } for (p=rx->JobIds; get_next_jobid_from_list(&p, &JobId) > 0; ) { if (JobId == last_JobId) { @@ -739,8 +755,10 @@ static bool build_directory_tree(UAContext *ua, RESTORE_CTX *rx) bsendmsg(ua, "%s", db_strerror(ua->db)); } } - bsendmsg(ua, "%d Job%s inserted into the tree%s.\n", - items, items==1?"":"s", tree.all?" and marked for extraction":""); + char ec1[50]; + bsendmsg(ua, "\n%d Job%s, %s files inserted into the tree%s.\n", + items, items==1?"":"s", edit_uint64_with_commas(tree.FileCount, ec1), + tree.all?" and marked for extraction":""); /* Check MediaType and select storage that corresponds */ get_storage_from_mediatype(ua, &rx->name_list, rx); @@ -944,6 +962,14 @@ static int get_next_jobid_from_list(char **p, uint32_t *JobId) return 1; } +static int count_handler(void *ctx, int num_fields, char **row) +{ + RESTORE_CTX *rx = (RESTORE_CTX *)ctx; + rx->JobId = atoi(row[0]); + rx->found = true; + return 0; +} + /* * Callback handler to get JobId and FileIndex for files */ diff --git a/bacula/src/dird/ua_tree.c b/bacula/src/dird/ua_tree.c index 52de814f4e..8198717b69 100644 --- a/bacula/src/dird/ua_tree.c +++ b/bacula/src/dird/ua_tree.c @@ -66,11 +66,11 @@ static struct cmdstruct commands[] = { { N_("help"), helpcmd, _("print help")}, { N_("ls"), lscmd, _("list current directory -- wildcards allowed")}, { N_("lsmark"), lsmarkcmd, _("list the marked files in and below the cd")}, - { N_("mark"), markcmd, _("mark file to be restored")}, - { N_("markdir"), markdircmd, _("mark directory entry to be restored -- nonrecursive")}, + { N_("mark"), markcmd, _("mark dir/file to be restored -- recursively in dirs")}, + { N_("markdir"), markdircmd, _("mark directory name to be restored (no files)")}, { N_("pwd"), pwdcmd, _("print current working directory")}, - { N_("unmark"), unmarkcmd, _("unmark file to be restored")}, - { N_("unmarkdir"), unmarkdircmd, _("unmark directory -- no recursion")}, + { N_("unmark"), unmarkcmd, _("unmark dir/file to be restored -- recursively in dir")}, + { N_("unmarkdir"), unmarkdircmd, _("unmark directory name only -- no recursion")}, { N_("quit"), quitcmd, _("quit")}, { N_("?"), helpcmd, _("print help")}, }; @@ -168,8 +168,7 @@ int insert_tree_handler(void *ctx, int num_fields, char **row) type = TN_FILE; } hard_link = (decode_LinkFI(row[4], &statp) != 0); - node = insert_tree_node(row[0], row[1], NULL, tree->root, NULL); - /* Note, if node already exists, save new one for next time */ + node = insert_tree_node(row[0], row[1], type, tree->root, NULL); JobId = (JobId_t)str_to_int64(row[3]); FileIndex = atoi(row[2]); /* @@ -202,6 +201,13 @@ int insert_tree_handler(void *ctx, int num_fields, char **row) } } } + if (node->inserted) { + tree->FileCount++; + if (tree->DeltaCount > 0 && (tree->FileCount-tree->LastCount) > tree->DeltaCount) { + bsendmsg(tree->ua, "+"); + tree->LastCount = tree->FileCount; + } + } tree->cnt++; return 0; } @@ -284,6 +290,7 @@ static int markcmd(UAContext *ua, TREE_CTX *tree) { TREE_NODE *node; int count = 0; + char ec1[50]; if (ua->argc < 2 || !tree_node_has_child(tree->node)) { bsendmsg(ua, _("No files marked.\n")); @@ -299,7 +306,8 @@ static int markcmd(UAContext *ua, TREE_CTX *tree) if (count == 0) { bsendmsg(ua, _("No files marked.\n")); } else { - bsendmsg(ua, _("%d file%s marked.\n"), count, count==0?"":"s"); + bsendmsg(ua, _("%s file%s marked.\n"), + edit_uint64_with_commas(count, ec1), count==0?"":"s"); } return 1; } @@ -308,6 +316,7 @@ static int markdircmd(UAContext *ua, TREE_CTX *tree) { TREE_NODE *node; int count = 0; + char ec1[50]; if (ua->argc < 2 || !tree_node_has_child(tree->node)) { bsendmsg(ua, _("No files marked.\n")); @@ -326,7 +335,8 @@ static int markdircmd(UAContext *ua, TREE_CTX *tree) if (count == 0) { bsendmsg(ua, _("No directories marked.\n")); } else { - bsendmsg(ua, _("%d director%s marked.\n"), count, count==1?"y":"ies"); + bsendmsg(ua, _("%s director%s marked.\n"), + edit_uint64_with_commas(count, ec1), count==1?"y":"ies"); } return 1; } @@ -335,6 +345,7 @@ static int markdircmd(UAContext *ua, TREE_CTX *tree) static int countcmd(UAContext *ua, TREE_CTX *tree) { int total, num_extract; + char ec1[50]; total = num_extract = 0; for (TREE_NODE *node=first_tree_node(tree->root); node; node=next_tree_node(node)) { @@ -345,7 +356,8 @@ static int countcmd(UAContext *ua, TREE_CTX *tree) } } } - bsendmsg(ua, "%d total files/dirs. %d marked to be restored.\n", total, num_extract); + bsendmsg(ua, "%s total files/dirs. %d marked to be restored.\n", total, + edit_uint64_with_commas(num_extract, ec1)); return 1; } diff --git a/bacula/src/gnome2-console/console.c b/bacula/src/gnome2-console/console.c index 963b96b58e..391fcbb51c 100644 --- a/bacula/src/gnome2-console/console.c +++ b/bacula/src/gnome2-console/console.c @@ -330,7 +330,7 @@ static void fill_combo(GtkWidget *dialog, const char *combo_name, GList *options GtkWidget *combo; combo = lookup_widget(dialog, combo_name); - if (combo) { + if (combo && options) { gtk_combo_set_popdown_strings(GTK_COMBO(combo), options); } return; @@ -361,7 +361,9 @@ int connect_to_director(gpointer data) dir_dialog = create_SelectDirectorDialog(); combo = lookup_widget(dir_dialog, "combo1"); dir_select = lookup_widget(dir_dialog, "dirselect"); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), dirs); + if (dirs) { + gtk_combo_set_popdown_strings(GTK_COMBO(combo), dirs); + } gtk_widget_show(dir_dialog); gtk_main(); diff --git a/bacula/src/lib/tree.c b/bacula/src/lib/tree.c index d4fb6402e5..b8fed2297a 100755 --- a/bacula/src/lib/tree.c +++ b/bacula/src/lib/tree.c @@ -31,7 +31,7 @@ /* Forward referenced subroutines */ static TREE_NODE *search_and_insert_tree_node(char *fname, int type, - TREE_NODE *node, TREE_ROOT *root, TREE_NODE *parent); + TREE_ROOT *root, TREE_NODE *parent); static char *tree_alloc(TREE_ROOT *root, int size); /* @@ -96,7 +96,7 @@ TREE_ROOT *new_tree(int count) /* * Create a new tree node. */ -static TREE_NODE *new_tree_node(TREE_ROOT *root, int type) +static TREE_NODE *new_tree_node(TREE_ROOT *root) { TREE_NODE *node; int size = sizeof(TREE_NODE); @@ -105,6 +105,19 @@ static TREE_NODE *new_tree_node(TREE_ROOT *root, int type) return node; } +#ifdef USE_DLIST +/* + * This routine can be called to release the + * previously allocated tree node. + */ +static void free_tree_node(TREE_ROOT *root) +{ + int asize = BALIGN(sizeof(TREE_NODE)); + root->mem->rem += asize; + root->mem->mem -= asize; +} +#endif + /* @@ -158,11 +171,12 @@ void free_tree(TREE_ROOT *root) * called when building a tree. * */ -TREE_NODE *insert_tree_node(char *path, char *fname, TREE_NODE *node, +TREE_NODE *insert_tree_node(char *path, char *fname, int type, TREE_ROOT *root, TREE_NODE *parent) { char *p, *q; int path_len = strlen(path); + TREE_NODE *node; Dmsg1(100, "insert_tree_node: %s\n", path); /* @@ -207,12 +221,12 @@ TREE_NODE *insert_tree_node(char *path, char *fname, TREE_NODE *node, fname = path; if (!parent) { parent = (TREE_NODE *)root; - node->type = TN_DIR_NLS; + type = TN_DIR_NLS; } Dmsg1(100, "No / found: %s\n", path); } - node = search_and_insert_tree_node(fname, 0, node, root, parent); + node = search_and_insert_tree_node(fname, 0, root, parent); if (q) { /* if trailing slash on entry */ *q = '/'; /* restore it */ } @@ -248,16 +262,59 @@ TREE_NODE *make_tree_path(char *path, TREE_ROOT *root) parent = (TREE_NODE *)root; type = TN_DIR_NLS; } - node = search_and_insert_tree_node(fname, type, NULL, root, parent); + node = search_and_insert_tree_node(fname, type, root, parent); return node; } +#ifdef USE_DLIST +static int node_compare(void *item1, void *item2) +{ + TREE_NODE *tn1 = (TREE_NODE *)item1; + TREE_NODE *tn2 = (TREE_NODE *)item2; + if (tn1->fname[0] > tn2->fname[0]) { + return 1; + } else if (tn1->fname[0] < tn2->fname[0]) { + return -1; + } + return strcmp(tn1->fname, tn2->fname); +} +#endif + /* * See if the fname already exists. If not insert a new node for it. */ static TREE_NODE *search_and_insert_tree_node(char *fname, int type, - TREE_NODE *node, TREE_ROOT *root, TREE_NODE *parent) + TREE_ROOT *root, TREE_NODE *parent) { +#ifdef USE_DLIST + TREE_NODE *node, *found_node; + node = new_tree_node(root); + node->fname = fname; + found_node = (TREE_NODE *)parent->child.binary_insert(node, node_compare); + if (found_node != node) { /* already in list */ + free_tree_node(root); /* free node allocated above */ + found_node->inserted = false; + return found_node; + } + /* It was not found, but is now inserted */ + node->fname_len = strlen(fname); + node->fname = tree_alloc(root, node->fname_len + 1); + strcpy(node->fname, fname); + node->parent = parent; + node->type = type; + + /* Maintain a linear chain of nodes */ + if (!root->first) { + root->first = node; + root->last = node; + } else { + root->last->next = node; + root->last = node; + } + node->inserted = true; /* inserted into tree */ + return node; + +#else TREE_NODE *sibling, *last_sibling = NULL; uint16_t fname_len = strlen(fname); int cmp; @@ -272,7 +329,7 @@ static TREE_NODE *search_and_insert_tree_node(char *fname, int type, if (cmp < 0) { /* Insert before current sibling */ if (!node) { - node = new_tree_node(root, type); + node = new_tree_node(root); } node->sibling_ = sibling; if (sibling == first_child(parent)) { /* if sibling was at head of list */ @@ -291,13 +348,14 @@ static TREE_NODE *search_and_insert_tree_node(char *fname, int type, * At this point, the fname is not found. We must add it */ if (!node) { - node = new_tree_node(root, type); + node = new_tree_node(root); } Dmsg1(000, "append_tree_node: %s\n", fname); node->fname_len = fname_len; node->fname = tree_alloc(root, node->fname_len + 1); strcpy(node->fname, fname); node->parent = parent; + node->type = type; if (!tree_node_has_child(parent)) { parent->child_ = node; } else { @@ -314,6 +372,7 @@ static TREE_NODE *search_and_insert_tree_node(char *fname, int type, } node->inserted = true; /* inserted into tree */ return node; +#endif } #ifdef SLOW_WAY @@ -520,7 +579,7 @@ void FillDirectoryTree(char *path, TREE_ROOT *root, TREE_NODE *parent) } Dmsg2(100, "Doing: %d %s\n", type, pathbuf); - node = new_tree_node(root, type); + node = new_tree_node(root); node->FileIndex = ++FileIndex; parent = insert_tree_node(pathbuf, node, root, parent); if (S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)) { diff --git a/bacula/src/lib/tree.h b/bacula/src/lib/tree.h index dd81675648..2d712b406a 100644 --- a/bacula/src/lib/tree.h +++ b/bacula/src/lib/tree.h @@ -25,20 +25,86 @@ */ struct s_mem { - struct s_mem *next; /* next buffer */ - int rem; /* remaining bytes */ - char *mem; /* memory pointer */ - char first[1]; /* first byte */ + struct s_mem *next; /* next buffer */ + int rem; /* remaining bytes */ + char *mem; /* memory pointer */ + char first[1]; /* first byte */ }; +#define USE_DLIST +#ifdef USE_DLIST +#define foreach_child(var, list) \ + for((var)=NULL; (*((TREE_NODE **)&(var))=(TREE_NODE*)(list->child.next(var))); ) + +#define tree_node_has_child(node) \ + ((node)->child.size() > 0) + +#define first_child(node) \ + ((TREE_NODE *)(node->child.first()) + + +/* + * Keep this node as small as possible because + * there is one for each file. + */ +struct s_tree_node { + /* KEEP sibling as the first member to avoid having to + * do initialization of child */ + dlink sibling; + dlist child; + char *fname; /* file name */ + int32_t FileIndex; /* file index */ + uint32_t JobId; /* JobId */ + uint16_t fname_len; /* filename length */ + int type: 8; /* node type */ + unsigned int extract: 1; /* extract item */ + unsigned int extract_dir: 1; /* extract dir entry only */ + unsigned int hard_link: 1; /* set if have hard link */ + unsigned int soft_link: 1; /* set if is soft link */ + unsigned int inserted: 1; /* set when newly inserted */ + struct s_tree_node *parent; + struct s_tree_node *next; /* next hash of FileIndex */ +}; +typedef struct s_tree_node TREE_NODE; + +struct s_tree_root { + /* KEEP sibling as the first member to avoid having to + * do initialization of child */ + dlink sibling; + dlist child; + char *fname; /* file name */ + int32_t FileIndex; /* file index */ + uint32_t JobId; /* JobId */ + uint16_t fname_len; /* filename length */ + unsigned int type: 8; /* node type */ + unsigned int extract: 1; /* extract item */ + unsigned int extract_dir: 1; /* extract dir entry only */ + unsigned int have_link: 1; /* set if have hard link */ + unsigned int inserted: 1; /* set when newly inserted */ + struct s_tree_node *parent; + struct s_tree_node *next; /* next hash of FileIndex */ + + /* The above ^^^ must be identical to a TREE_NODE structure */ + struct s_tree_node *first; /* first entry in the tree */ + struct s_tree_node *last; /* last entry in tree */ + struct s_mem *mem; /* tree memory */ + uint32_t total_size; /* total bytes allocated */ + uint32_t blocks; /* total mallocs */ + int cached_path_len; /* length of cached path */ + char *cached_path; /* cached current path */ + TREE_NODE *cached_parent; /* cached parent for above path */ +}; +typedef struct s_tree_root TREE_ROOT; + +#else #define foreach_child(cld, node) \ - for(cld=(node)->child_; cld; cld=cld->sibling_) + for(cld=(node)->child_; cld; cld=cld->sibling_) #define tree_node_has_child(node) \ - ((node)->child_ != NULL) + ((node)->child_ != NULL) #define first_child(node) \ - ((node)->child_) + ((node)->child_) /* @@ -46,67 +112,73 @@ struct s_mem { * there is one for each file. */ struct s_tree_node { - char *fname; /* file name */ - int32_t FileIndex; /* file index */ - uint32_t JobId; /* JobId */ - uint16_t fname_len; /* filename length */ - int type: 8; /* node type */ - unsigned int extract: 1; /* extract item */ + char *fname; /* file name */ + int32_t FileIndex; /* file index */ + uint32_t JobId; /* JobId */ + uint16_t fname_len; /* filename length */ + int type: 8; /* node type */ + unsigned int extract: 1; /* extract item */ unsigned int extract_dir: 1; /* extract dir entry only */ - unsigned int hard_link: 1; /* set if have hard link */ - unsigned int soft_link: 1; /* set if is soft link */ - unsigned int inserted: 1; /* set when newly inserted */ + unsigned int hard_link: 1; /* set if have hard link */ + unsigned int soft_link: 1; /* set if is soft link */ + unsigned int inserted: 1; /* set when newly inserted */ struct s_tree_node *parent; struct s_tree_node *sibling_; - struct s_tree_node *next; /* next hash of FileIndex */ + struct s_tree_node *next; /* next hash of FileIndex */ struct s_tree_node *child_; }; typedef struct s_tree_node TREE_NODE; struct s_tree_root { - char *fname; /* file name */ - int32_t FileIndex; /* file index */ - uint32_t JobId; /* JobId */ - uint16_t fname_len; /* filename length */ - unsigned int type: 8; /* node type */ - unsigned int extract: 1; /* extract item */ + char *fname; /* file name */ + int32_t FileIndex; /* file index */ + uint32_t JobId; /* JobId */ + uint16_t fname_len; /* filename length */ + unsigned int type: 8; /* node type */ + unsigned int extract: 1; /* extract item */ unsigned int extract_dir: 1; /* extract dir entry only */ - unsigned int have_link: 1; /* set if have hard link */ - unsigned int inserted: 1; /* set when newly inserted */ + unsigned int have_link: 1; /* set if have hard link */ + unsigned int inserted: 1; /* set when newly inserted */ struct s_tree_node *parent; struct s_tree_node *sibling_; - struct s_tree_node *next; /* next hash of FileIndex */ + struct s_tree_node *next; /* next hash of FileIndex */ struct s_tree_node *child_; /* The above ^^^ must be identical to a TREE_NODE structure */ - struct s_tree_node *first; /* first entry in the tree */ - struct s_tree_node *last; /* last entry in tree */ - struct s_mem *mem; /* tree memory */ - uint32_t total_size; /* total bytes allocated */ - uint32_t blocks; /* total mallocs */ - int cached_path_len; /* length of cached path */ - char *cached_path; /* cached current path */ - TREE_NODE *cached_parent; /* cached parent for above path */ + struct s_tree_node *first; /* first entry in the tree */ + struct s_tree_node *last; /* last entry in tree */ + struct s_mem *mem; /* tree memory */ + uint32_t total_size; /* total bytes allocated */ + uint32_t blocks; /* total mallocs */ + int cached_path_len; /* length of cached path */ + char *cached_path; /* cached current path */ + TREE_NODE *cached_parent; /* cached parent for above path */ }; typedef struct s_tree_root TREE_ROOT; +#endif /* type values */ -#define TN_ROOT 1 /* root node */ -#define TN_NEWDIR 2 /* created directory to fill path */ -#define TN_DIR 3 /* directory entry */ -#define TN_DIR_NLS 4 /* directory -- no leading slash -- win32 */ -#define TN_FILE 5 /* file entry */ +#define TN_ROOT 1 /* root node */ +#define TN_NEWDIR 2 /* created directory to fill path */ +#define TN_DIR 3 /* directory entry */ +#define TN_DIR_NLS 4 /* directory -- no leading slash -- win32 */ +#define TN_FILE 5 /* file entry */ /* External interface */ TREE_ROOT *new_tree(int count); -TREE_NODE *insert_tree_node(char *path, char *fname, TREE_NODE *node, - TREE_ROOT *root, TREE_NODE *parent); +TREE_NODE *insert_tree_node(char *path, char *fname, int type, + TREE_ROOT *root, TREE_NODE *parent); TREE_NODE *make_tree_path(char *path, TREE_ROOT *root); TREE_NODE *tree_cwd(char *path, TREE_ROOT *root, TREE_NODE *node); TREE_NODE *tree_relcwd(char *path, TREE_ROOT *root, TREE_NODE *node); void free_tree(TREE_ROOT *root); int tree_getpath(TREE_NODE *node, char *buf, int buf_size); +/* + * Use the following for traversing the whole tree. It will be + * traversed in the order the entries were inserted into the + * tree. + */ #ifdef SLOW_WAY TREE_NODE *first_tree_node(TREE_ROOT *root); TREE_NODE *next_tree_node(TREE_NODE *node); diff --git a/bacula/src/version.h b/bacula/src/version.h index 074b9a0eb6..5e3765645d 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -2,8 +2,8 @@ #undef VERSION #define VERSION "1.35.0" #define VSTRING "1" -#define BDATE "16 June 2004" -#define LSMDATE "16Jun04" +#define BDATE "18 June 2004" +#define LSMDATE "18Jun04" /* Debug flags */ #undef DEBUG