diff options
author | Vicent Marti <tanoku@gmail.com> | 2013-01-03 23:36:26 +0400 |
---|---|---|
committer | Vicent Marti <tanoku@gmail.com> | 2013-01-10 18:34:56 +0400 |
commit | 4a863c06662053a8530a0dcb24e0a2daa33e05cf (patch) | |
tree | 7cf411ca542687c7bda92d17809be88efd28a2e7 /src/odb.c | |
parent | a22ad9fd1f1f938fb9b8ac77939dda8a3b81a00e (diff) |
Sane refresh logic
All the ODB backends have a specific refresh interface. When reading an
object, first we attempt every single backend: if the read fails, then
we refresh all the backends and retry the read one more time to see if
the object has appeared.
Diffstat (limited to 'src/odb.c')
-rw-r--r-- | src/odb.c | 55 |
1 files changed, 49 insertions, 6 deletions
@@ -609,14 +609,22 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id) { unsigned int i; int error = GIT_ENOTFOUND; + bool refreshed = false; git_rawobj raw; assert(out && db && id); + if (db->backends.length == 0) { + giterr_set(GITERR_ODB, "Failed to lookup object: no backends loaded"); + return GIT_ENOTFOUND; + } + *out = git_cache_get(&db->cache, id); if (*out != NULL) return 0; +attempt_lookup: + for (i = 0; i < db->backends.length && error < 0; ++i) { backend_internal *internal = git_vector_get(&db->backends, i); git_odb_backend *b = internal->backend; @@ -625,9 +633,13 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id) error = b->read(&raw.data, &raw.len, &raw.type, b, id); } - /* TODO: If no backends are configured, this returns GIT_ENOTFOUND but - * will never have called giterr_set(). - */ + if (error == GIT_ENOTFOUND && !refreshed) { + if ((error = git_odb_refresh(db)) < 0) + return error; + + refreshed = true; + goto attempt_lookup; + } if (error && error != GIT_PASSTHROUGH) return error; @@ -644,7 +656,7 @@ int git_odb_read_prefix( git_oid found_full_oid = {{0}}; git_rawobj raw; void *data = NULL; - bool found = false; + bool found = false, refreshed = false; assert(out && db); @@ -660,11 +672,13 @@ int git_odb_read_prefix( return 0; } +attempt_lookup: + for (i = 0; i < db->backends.length; ++i) { backend_internal *internal = git_vector_get(&db->backends, i); git_odb_backend *b = internal->backend; - if (b->read != NULL) { + if (b->read_prefix != NULL) { git_oid full_oid; error = b->read_prefix(&full_oid, &raw.data, &raw.len, &raw.type, b, short_id, len); if (error == GIT_ENOTFOUND || error == GIT_PASSTHROUGH) @@ -675,13 +689,23 @@ int git_odb_read_prefix( git__free(data); data = raw.data; + if (found && git_oid_cmp(&full_oid, &found_full_oid)) return git_odb__error_ambiguous("multiple matches for prefix"); + found_full_oid = full_oid; found = true; } } + if (!found && !refreshed) { + if ((error = git_odb_refresh(db)) < 0) + return error; + + refreshed = true; + goto attempt_lookup; + } + if (!found) return git_odb__error_notfound("no match for prefix", short_id); @@ -820,12 +844,31 @@ int git_odb_write_pack(struct git_odb_writepack **out, git_odb *db, git_transfer return error; } -void * git_odb_backend_malloc(git_odb_backend *backend, size_t len) +void *git_odb_backend_malloc(git_odb_backend *backend, size_t len) { GIT_UNUSED(backend); return git__malloc(len); } +int git_odb_refresh(struct git_odb *db) +{ + unsigned int i; + assert(db); + + for (i = 0; i < db->backends.length; ++i) { + backend_internal *internal = git_vector_get(&db->backends, i); + git_odb_backend *b = internal->backend; + + if (b->refresh != NULL) { + int error = b->refresh(b); + if (error < 0) + return error; + } + } + + return 0; +} + int git_odb__error_notfound(const char *message, const git_oid *oid) { if (oid != NULL) { |