reftable/generic: adapt interface to allow reuse of iterators
Refactor the interfaces exposed by `struct reftable_table` and `struct reftable_iterator` such that they support iterator reuse. This is done by separating initialization of the iterator and seeking on it. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
		 Patrick Steinhardt
					Patrick Steinhardt
				
			
				
					committed by
					
						 Junio C Hamano
						Junio C Hamano
					
				
			
			
				
	
			
			
			 Junio C Hamano
						Junio C Hamano
					
				
			
						parent
						
							5bf96e0c39
						
					
				
				
					commit
					d76f0d3f57
				
			| @ -20,8 +20,20 @@ void table_init_iter(struct reftable_table *tab, | ||||
| 	tab->ops->init_iter(tab->table_arg, it, typ); | ||||
| } | ||||
|  | ||||
| int reftable_table_seek_ref(struct reftable_table *tab, | ||||
| 			    struct reftable_iterator *it, const char *name) | ||||
| void reftable_table_init_ref_iter(struct reftable_table *tab, | ||||
| 				  struct reftable_iterator *it) | ||||
| { | ||||
| 	table_init_iter(tab, it, BLOCK_TYPE_REF); | ||||
| } | ||||
|  | ||||
| void reftable_table_init_log_iter(struct reftable_table *tab, | ||||
| 				  struct reftable_iterator *it) | ||||
| { | ||||
| 	table_init_iter(tab, it, BLOCK_TYPE_LOG); | ||||
| } | ||||
|  | ||||
| int reftable_iterator_seek_ref(struct reftable_iterator *it, | ||||
| 			       const char *name) | ||||
| { | ||||
| 	struct reftable_record want = { | ||||
| 		.type = BLOCK_TYPE_REF, | ||||
| @ -29,29 +41,37 @@ int reftable_table_seek_ref(struct reftable_table *tab, | ||||
| 			.refname = (char *)name, | ||||
| 		}, | ||||
| 	}; | ||||
| 	table_init_iter(tab, it, BLOCK_TYPE_REF); | ||||
| 	return it->ops->seek(it->iter_arg, &want); | ||||
| } | ||||
|  | ||||
| int reftable_table_seek_log(struct reftable_table *tab, | ||||
| 			    struct reftable_iterator *it, const char *name) | ||||
| int reftable_iterator_seek_log_at(struct reftable_iterator *it, | ||||
| 				  const char *name, uint64_t update_index) | ||||
| { | ||||
| 	struct reftable_record want = { | ||||
| 		.type = BLOCK_TYPE_LOG, | ||||
| 		.u.log = { | ||||
| 			.refname = (char *)name, | ||||
| 			.update_index = ~((uint64_t)0), | ||||
| 			.update_index = update_index, | ||||
| 		}, | ||||
| 	}; | ||||
| 	table_init_iter(tab, it, BLOCK_TYPE_LOG); | ||||
| 	return it->ops->seek(it->iter_arg, &want); | ||||
| } | ||||
|  | ||||
| int reftable_iterator_seek_log(struct reftable_iterator *it, | ||||
| 			       const char *name) | ||||
| { | ||||
| 	return reftable_iterator_seek_log_at(it, name, ~((uint64_t) 0)); | ||||
| } | ||||
|  | ||||
| int reftable_table_read_ref(struct reftable_table *tab, const char *name, | ||||
| 			    struct reftable_ref_record *ref) | ||||
| { | ||||
| 	struct reftable_iterator it = { NULL }; | ||||
| 	int err = reftable_table_seek_ref(tab, &it, name); | ||||
| 	int err; | ||||
|  | ||||
| 	reftable_table_init_ref_iter(tab, &it); | ||||
|  | ||||
| 	err = reftable_iterator_seek_ref(&it, name); | ||||
| 	if (err) | ||||
| 		goto done; | ||||
|  | ||||
| @ -76,10 +96,13 @@ int reftable_table_print(struct reftable_table *tab) { | ||||
| 	struct reftable_ref_record ref = { NULL }; | ||||
| 	struct reftable_log_record log = { NULL }; | ||||
| 	uint32_t hash_id = reftable_table_hash_id(tab); | ||||
| 	int err = reftable_table_seek_ref(tab, &it, ""); | ||||
| 	if (err < 0) { | ||||
| 	int err; | ||||
|  | ||||
| 	reftable_table_init_ref_iter(tab, &it); | ||||
|  | ||||
| 	err = reftable_iterator_seek_ref(&it, ""); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	} | ||||
|  | ||||
| 	while (1) { | ||||
| 		err = reftable_iterator_next_ref(&it, &ref); | ||||
| @ -94,10 +117,12 @@ int reftable_table_print(struct reftable_table *tab) { | ||||
| 	reftable_iterator_destroy(&it); | ||||
| 	reftable_ref_record_release(&ref); | ||||
|  | ||||
| 	err = reftable_table_seek_log(tab, &it, ""); | ||||
| 	if (err < 0) { | ||||
| 	reftable_table_init_log_iter(tab, &it); | ||||
|  | ||||
| 	err = reftable_iterator_seek_log(&it, ""); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 	} | ||||
|  | ||||
| 	while (1) { | ||||
| 		err = reftable_iterator_next_log(&it, &log); | ||||
| 		if (err > 0) { | ||||
|  | ||||
| @ -45,11 +45,11 @@ static int filtering_ref_iterator_next(void *iter_arg, | ||||
| 		if (fri->double_check) { | ||||
| 			struct reftable_iterator it = { NULL }; | ||||
|  | ||||
| 			err = reftable_table_seek_ref(&fri->tab, &it, | ||||
| 						      ref->refname); | ||||
| 			if (err == 0) { | ||||
| 			reftable_table_init_ref_iter(&fri->tab, &it); | ||||
|  | ||||
| 			err = reftable_iterator_seek_ref(&it, ref->refname); | ||||
| 			if (err == 0) | ||||
| 				err = reftable_iterator_next_ref(&it, ref); | ||||
| 			} | ||||
|  | ||||
| 			reftable_iterator_destroy(&it); | ||||
|  | ||||
|  | ||||
| @ -21,11 +21,11 @@ struct reftable_table { | ||||
| 	void *table_arg; | ||||
| }; | ||||
|  | ||||
| int reftable_table_seek_log(struct reftable_table *tab, | ||||
| 			    struct reftable_iterator *it, const char *name); | ||||
| void reftable_table_init_ref_iter(struct reftable_table *tab, | ||||
| 				  struct reftable_iterator *it); | ||||
|  | ||||
| int reftable_table_seek_ref(struct reftable_table *tab, | ||||
| 			    struct reftable_iterator *it, const char *name); | ||||
| void reftable_table_init_log_iter(struct reftable_table *tab, | ||||
| 				  struct reftable_iterator *it); | ||||
|  | ||||
| /* returns the hash ID from a generic reftable_table */ | ||||
| uint32_t reftable_table_hash_id(struct reftable_table *tab); | ||||
|  | ||||
| @ -21,12 +21,33 @@ struct reftable_iterator { | ||||
| 	void *iter_arg; | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * Position the iterator at the ref record with given name such that the next | ||||
|  * call to `next_ref()` would yield the record. | ||||
|  */ | ||||
| int reftable_iterator_seek_ref(struct reftable_iterator *it, | ||||
| 			       const char *name); | ||||
|  | ||||
| /* reads the next reftable_ref_record. Returns < 0 for error, 0 for OK and > 0: | ||||
|  * end of iteration. | ||||
|  */ | ||||
| int reftable_iterator_next_ref(struct reftable_iterator *it, | ||||
| 			       struct reftable_ref_record *ref); | ||||
|  | ||||
| /* | ||||
|  * Position the iterator at the log record with given name and update index | ||||
|  * such that the next call to `next_log()` would yield the record. | ||||
|  */ | ||||
| int reftable_iterator_seek_log_at(struct reftable_iterator *it, | ||||
| 				  const char *name, uint64_t update_index); | ||||
|  | ||||
| /* | ||||
|  * Position the iterator at the newest log record with given name such that the | ||||
|  * next call to `next_log()` would yield the record. | ||||
|  */ | ||||
| int reftable_iterator_seek_log(struct reftable_iterator *it, | ||||
| 			       const char *name); | ||||
|  | ||||
| /* reads the next reftable_log_record. Returns < 0 for error, 0 for OK and > 0: | ||||
|  * end of iteration. | ||||
|  */ | ||||
|  | ||||
		Reference in New Issue
	
	Block a user