[SCM] The rsync repository. - branch master updated

Rsync CVS commit messages rsync-cvs at lists.samba.org
Sat Jun 13 00:52:53 UTC 2020


The branch, master has been updated
       via  ad9f1571 Add hashtable to delete_in_dir() to fix -x deletions
       via  f8005578 Tweak the hashtable routines to be a little clearer and easier.
      from  13f81f4a Tweak a usage message.

https://git.samba.org/?p=rsync.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit ad9f1571cee2a29232d83fcb13c6924722f492bf
Author: Wayne Davison <wayne at opencoder.net>
Date:   Fri Jun 12 16:52:54 2020 -0700

    Add hashtable to delete_in_dir() to fix -x deletions

commit f800557824bbb616f68451a9d5919b982c146ac8
Author: Wayne Davison <wayne at opencoder.net>
Date:   Fri Jun 12 16:39:29 2020 -0700

    Tweak the hashtable routines to be a little clearer and easier.

-----------------------------------------------------------------------

Summary of changes:
 flist.c     |  8 ++++----
 generator.c | 13 ++++++++++---
 hashtable.c | 29 ++++++++++++++++++++++-------
 hlink.c     | 26 +++++++++++++-------------
 rsync.h     |  3 +++
 xattrs.c    | 17 ++++++-----------
 6 files changed, 58 insertions(+), 38 deletions(-)


Changeset truncated at 500 lines:

diff --git a/flist.c b/flist.c
index dbb0f921..bbc028ba 100644
--- a/flist.c
+++ b/flist.c
@@ -491,9 +491,9 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
 	if (tmp_dev != -1) {
 		if (protocol_version >= 30) {
 			struct ht_int64_node *np = idev_find(tmp_dev, tmp_ino);
-			first_hlink_ndx = (int32)(long)np->data - 1;
+			first_hlink_ndx = (int32)(long)np->data; /* is -1 when new */
 			if (first_hlink_ndx < 0) {
-				np->data = (void*)(long)(first_ndx + ndx + 1);
+				np->data = (void*)(long)(first_ndx + ndx);
 				xflags |= XMIT_HLINK_FIRST;
 			}
 			if (DEBUG_GTE(HLINK, 1)) {
@@ -1101,10 +1101,10 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
 				ino = read_longint(f);
 			}
 			np = idev_find(dev, ino);
-			ndx = (int32)(long)np->data - 1;
+			ndx = (int32)(long)np->data; /* is -1 when new */
 			if (ndx < 0) {
-				ndx = cnt++;
 				np->data = (void*)(long)cnt;
+				ndx = cnt++;
 			}
 			F_HL_GNUM(file) = ndx;
 		}
diff --git a/generator.c b/generator.c
index dba97d85..210e5f31 100644
--- a/generator.c
+++ b/generator.c
@@ -277,6 +277,7 @@ static void do_delayed_deletions(char *delbuf)
 static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
 {
 	static int already_warned = 0;
+	static struct hashtable *dev_tbl;
 	struct file_list *dirlist;
 	char delbuf[MAXPATHLEN];
 	int dlen, i;
@@ -305,10 +306,16 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
 	change_local_filter_dir(fbuf, dlen, F_DEPTH(file));
 
 	if (one_file_system) {
-		if (file->flags & FLAG_TOP_DIR)
+		if (!dev_tbl)
+			dev_tbl = hashtable_create(16, HT_KEY64);
+		if (file->flags & FLAG_TOP_DIR) {
+			hashtable_find(dev_tbl, *fs_dev+1, "");
 			filesystem_dev = *fs_dev;
-		else if (filesystem_dev != *fs_dev)
-			return;
+		} else if (filesystem_dev != *fs_dev) {
+			if (!hashtable_find(dev_tbl, *fs_dev+1, NULL))
+				return;
+			filesystem_dev = *fs_dev; /* it's a prior top-dir dev */
+		}
 	}
 
 	dirlist = get_dirlist(fbuf, dlen, 0);
diff --git a/hashtable.c b/hashtable.c
index 00c057db..52f0fa07 100644
--- a/hashtable.c
+++ b/hashtable.c
@@ -66,9 +66,19 @@ void hashtable_destroy(struct hashtable *tbl)
 	free(tbl);
 }
 
-/* This returns the node for the indicated key, either newly created or
- * already existing.  Returns NULL if not allocating and not found. */
-void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing)
+/* Returns the node that holds the indicated key if it exists. When it does not
+ * exist, it returns either NULL (when data_when_new is NULL), or it returns a
+ * new node with its node->data set to the indicated value.
+ *
+ * If your code doesn't know the data value for a new node in advance (usually
+ * because it doesn't know if a node is new or not) you should pass in a unique
+ * (non-0) value that you can use to check if the returned node is new. You can
+ * then overwrite the data with any value you want (even 0) since it only needs
+ * to be different than whatever data_when_new value you use later on.
+ *
+ * This return is a void* just because it might be pointing at a ht_int32_node
+ * or a ht_int64_node, and that makes the caller's assignment a little easier. */
+void *hashtable_find(struct hashtable *tbl, int64 key, void *data_when_new)
 {
 	int key64 = tbl->key64;
 	struct ht_int32_node *node;
@@ -79,7 +89,7 @@ void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing)
 		exit_cleanup(RERR_MESSAGEIO);
 	}
 
-	if (allocate_if_missing && tbl->entries > HASH_LOAD_LIMIT(tbl->size)) {
+	if (data_when_new && tbl->entries > HASH_LOAD_LIMIT(tbl->size)) {
 		void *old_nodes = tbl->nodes;
 		int size = tbl->size * 2;
 		int i;
@@ -99,8 +109,12 @@ void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing)
 			int64 move_key = HT_KEY(move_node, key64);
 			if (move_key == 0)
 				continue;
-			node = hashtable_find(tbl, move_key, 1);
-			node->data = move_node->data;
+			if (move_node->data)
+				hashtable_find(tbl, move_key, move_node->data);
+			else {
+				node = hashtable_find(tbl, move_key, "");
+				node->data = 0;
+			}
 		}
 
 		free(old_nodes);
@@ -155,7 +169,7 @@ void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing)
 		if (nkey == key)
 			return node;
 		if (nkey == 0) {
-			if (!allocate_if_missing)
+			if (!data_when_new)
 				return NULL;
 			break;
 		}
@@ -167,6 +181,7 @@ void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing)
 		((struct ht_int64_node*)node)->key = key;
 	else
 		node->key = (int32)key;
+	node->data = data_when_new;
 	tbl->entries++;
 	return node;
 }
diff --git a/hlink.c b/hlink.c
index 6c5ea61a..29927166 100644
--- a/hlink.c
+++ b/hlink.c
@@ -48,6 +48,8 @@ extern struct file_list *cur_flist;
  * we can avoid the pool of dev+inode data.  For incremental recursion mode,
  * the receiver will use a ndx hash to remember old pathnames. */
 
+static void *data_when_new = "";
+
 static struct hashtable *dev_tbl;
 
 static struct hashtable *prior_hlinks;
@@ -57,32 +59,30 @@ static struct file_list *hlink_flist;
 void init_hard_links(void)
 {
 	if (am_sender || protocol_version < 30)
-		dev_tbl = hashtable_create(16, 1);
+		dev_tbl = hashtable_create(16, HT_KEY64);
 	else if (inc_recurse)
-		prior_hlinks = hashtable_create(1024, 0);
+		prior_hlinks = hashtable_create(1024, HT_KEY32);
 }
 
 struct ht_int64_node *idev_find(int64 dev, int64 ino)
 {
 	static struct ht_int64_node *dev_node = NULL;
-	struct hashtable *tbl;
 
 	/* Note that some OSes have a dev == 0, so increment to avoid storing a 0. */
 	if (!dev_node || dev_node->key != dev+1) {
 		/* We keep a separate hash table of inodes for every device. */
-		dev_node = hashtable_find(dev_tbl, dev+1, 1);
-		if (!(tbl = dev_node->data)) {
-			tbl = dev_node->data = hashtable_create(512, 1);
+		dev_node = hashtable_find(dev_tbl, dev+1, data_when_new);
+		if (dev_node->data == data_when_new) {
+			dev_node->data = hashtable_create(512, HT_KEY64);
 			if (DEBUG_GTE(HLINK, 3)) {
 				rprintf(FINFO,
 				    "[%s] created hashtable for dev %s\n",
 				    who_am_i(), big_num(dev));
 			}
 		}
-	} else
-		tbl = dev_node->data;
+	}
 
-	return hashtable_find(tbl, ino, 1);
+	return hashtable_find(dev_node->data, ino, (void*)-1L);
 }
 
 void idev_destroy(void)
@@ -125,8 +125,8 @@ static void match_gnums(int32 *ndx_list, int ndx_count)
 		file = hlink_flist->sorted[ndx_list[from]];
 		gnum = F_HL_GNUM(file);
 		if (inc_recurse) {
-			node = hashtable_find(prior_hlinks, gnum, 1);
-			if (!node->data) {
+			node = hashtable_find(prior_hlinks, gnum, data_when_new);
+			if (node->data == data_when_new) {
 				if (!(node->data = new_array0(char, 5)))
 					out_of_memory("match_gnums");
 				assert(gnum >= hlink_flist->ndx_start);
@@ -269,7 +269,7 @@ static char *check_prior(struct file_struct *file, int gnum,
 	}
 
 	if (inc_recurse
-	 && (node = hashtable_find(prior_hlinks, gnum, 0)) != NULL) {
+	 && (node = hashtable_find(prior_hlinks, gnum, NULL)) != NULL) {
 		assert(node->data != NULL);
 		if (CVAL(node->data, 0) != 0) {
 			*prev_ndx_p = -1;
@@ -528,7 +528,7 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
 
 	if (inc_recurse) {
 		int gnum = F_HL_GNUM(file);
-		struct ht_int32_node *node = hashtable_find(prior_hlinks, gnum, 0);
+		struct ht_int32_node *node = hashtable_find(prior_hlinks, gnum, NULL);
 		if (node == NULL) {
 			rprintf(FERROR, "Unable to find a hlink node for %d (%s)\n", gnum, f_name(file, prev_name));
 			exit_cleanup(RERR_MESSAGEIO);
diff --git a/rsync.h b/rsync.h
index 06f6d338..f5350da8 100644
--- a/rsync.h
+++ b/rsync.h
@@ -631,6 +631,9 @@ typedef unsigned int size_t;
 # define SIZEOF_INT64 SIZEOF_OFF_T
 #endif
 
+#define HT_KEY32 0
+#define HT_KEY64 1
+
 struct hashtable {
 	void *nodes;
 	int32 size, entries;
diff --git a/xattrs.c b/xattrs.c
index 2afa3473..9016aa4c 100644
--- a/xattrs.c
+++ b/xattrs.c
@@ -415,7 +415,7 @@ static int find_matching_xattr(const item_list *xalp)
 
 	key = xattr_lookup_hash(xalp);
 
-	node = hashtable_find(rsync_xal_h, key, 0);
+	node = hashtable_find(rsync_xal_h, key, NULL);
 	if (node == NULL)
 		return -1;
 
@@ -478,21 +478,17 @@ static int rsync_xal_store(item_list *xalp)
 	new_list->key = xattr_lookup_hash(&new_list->xa_items);
 
 	if (rsync_xal_h == NULL)
-		rsync_xal_h = hashtable_create(512, 1);
+		rsync_xal_h = hashtable_create(512, HT_KEY64);
 	if (rsync_xal_h == NULL)
 		out_of_memory("rsync_xal_h hashtable_create()");
 
-	node = hashtable_find(rsync_xal_h, new_list->key, 1);
-	if (node == NULL)
-		out_of_memory("rsync_xal_h hashtable_find()");
-
 	new_ref = new0(rsync_xa_list_ref);
 	if (new_ref == NULL)
 		out_of_memory("new0(rsync_xa_list_ref)");
-
 	new_ref->ndx = ndx;
 
-	if (node->data != NULL) {
+	node = hashtable_find(rsync_xal_h, new_list->key, new_ref);
+	if (node->data != (void*)new_ref) {
 		rsync_xa_list_ref *ref = node->data;
 
 		while (ref != NULL) {
@@ -504,8 +500,7 @@ static int rsync_xal_store(item_list *xalp)
 			ref->next = new_ref;
 			break;
 		}
-	} else
-		node->data = new_ref;
+	}
 
 	return ndx;
 }
@@ -926,7 +921,7 @@ void uncache_tmp_xattrs(void)
 			if (rsync_xal_h == NULL)
 				continue;
 
-			node = hashtable_find(rsync_xal_h, xa_list_item->key, 0);
+			node = hashtable_find(rsync_xal_h, xa_list_item->key, NULL);
 			if (node == NULL)
 				continue;
 


-- 
The rsync repository.



More information about the rsync-cvs mailing list