|
26 | 26 | #include <assert.h> |
27 | 27 | #include <string.h> |
28 | 28 | #include <git2.h> |
29 | | -#include <git2/odb_backend.h> |
| 29 | +#include <git2/sys/odb_backend.h> |
30 | 30 | #include <hiredis/hiredis.h> |
31 | 31 |
|
32 | 32 | typedef struct { |
33 | | - git_odb_backend parent; |
| 33 | + git_odb_backend parent; |
34 | 34 |
|
35 | | - redisContext *db; |
36 | | -} hiredis_backend; |
| 35 | + const char *prefix; |
| 36 | + const char *repo_path; |
| 37 | + redisContext *db; |
| 38 | +} hiredis_odb_backend; |
37 | 39 |
|
38 | | -int hiredis_backend__read_header(size_t *len_p, git_otype *type_p, git_odb_backend *_backend, const git_oid *oid) |
| 40 | +int hiredis_odb_backend__read_header(size_t *len_p, git_otype *type_p, git_odb_backend *_backend, const git_oid *oid) |
39 | 41 | { |
40 | | - hiredis_backend *backend; |
41 | | - int error; |
42 | | - redisReply *reply; |
43 | | - |
44 | | - assert(len_p && type_p && _backend && oid); |
45 | | - |
46 | | - backend = (hiredis_backend *) _backend; |
47 | | - error = GIT_ERROR; |
48 | | - |
49 | | - reply = redisCommand(backend->db, "HMGET %b %s %s", oid->id, GIT_OID_RAWSZ, |
50 | | - "type", "size"); |
51 | | - |
52 | | - if (reply && reply->type == REDIS_REPLY_ARRAY) { |
53 | | - if (reply->element[0]->type != REDIS_REPLY_NIL && |
54 | | - reply->element[0]->type != REDIS_REPLY_NIL) { |
55 | | - *type_p = (git_otype) atoi(reply->element[0]->str); |
56 | | - *len_p = (size_t) atoi(reply->element[1]->str); |
57 | | - error = GIT_SUCCESS; |
58 | | - } else { |
59 | | - error = GIT_ENOTFOUND; |
60 | | - } |
61 | | - } else { |
62 | | - error = GIT_ERROR; |
63 | | - } |
64 | | - |
65 | | - freeReplyObject(reply); |
66 | | - return error; |
| 42 | + hiredis_odb_backend *backend; |
| 43 | + int error; |
| 44 | + redisReply *reply; |
| 45 | + char *str_id = calloc(GIT_OID_HEXSZ + 1, sizeof(char)); |
| 46 | + |
| 47 | + assert(len_p && type_p && _backend && oid); |
| 48 | + |
| 49 | + backend = (hiredis_odb_backend *) _backend; |
| 50 | + error = GIT_ERROR; |
| 51 | + |
| 52 | + git_oid_tostr(str_id, GIT_OID_HEXSZ, oid); |
| 53 | + |
| 54 | + reply = redisCommand(backend->db, "HMGET %s:%s:odb:%s %s %s", backend->prefix, backend->repo_path, str_id, "type", "size"); |
| 55 | + |
| 56 | + if (reply && reply->type == REDIS_REPLY_ARRAY) { |
| 57 | + if (reply->element[0]->type != REDIS_REPLY_NIL && |
| 58 | + reply->element[0]->type != REDIS_REPLY_NIL) { |
| 59 | + *type_p = (git_otype) atoi(reply->element[0]->str); |
| 60 | + *len_p = (size_t) atoi(reply->element[1]->str); |
| 61 | + error = GIT_OK; |
| 62 | + } else { |
| 63 | + giterr_set_str(GITERR_ODB, "Redis odb storage corrupted"); |
| 64 | + error = GIT_ENOTFOUND; |
| 65 | + } |
| 66 | + } else { |
| 67 | + giterr_set_str(GITERR_ODB, "Redis odb storage error"); |
| 68 | + error = GIT_ERROR; |
| 69 | + } |
| 70 | + |
| 71 | + free(str_id); |
| 72 | + freeReplyObject(reply); |
| 73 | + return error; |
67 | 74 | } |
68 | 75 |
|
69 | | -int hiredis_backend__read(void **data_p, size_t *len_p, git_otype *type_p, git_odb_backend *_backend, const git_oid *oid) |
| 76 | +int hiredis_odb_backend__read(void **data_p, size_t *len_p, git_otype *type_p, git_odb_backend *_backend, const git_oid *oid) |
70 | 77 | { |
71 | | - hiredis_backend *backend; |
72 | | - int error; |
73 | | - redisReply *reply; |
74 | | - |
75 | | - assert(data_p && len_p && type_p && _backend && oid); |
76 | | - |
77 | | - backend = (hiredis_backend *) _backend; |
78 | | - error = GIT_ERROR; |
79 | | - |
80 | | - reply = redisCommand(backend->db, "HMGET %b %s %s %s", oid->id, GIT_OID_RAWSZ, |
81 | | - "type", "size", "data"); |
82 | | - |
83 | | - if (reply && reply->type == REDIS_REPLY_ARRAY) { |
84 | | - if (reply->element[0]->type != REDIS_REPLY_NIL && |
85 | | - reply->element[1]->type != REDIS_REPLY_NIL && |
86 | | - reply->element[2]->type != REDIS_REPLY_NIL) { |
87 | | - *type_p = (git_otype) atoi(reply->element[0]->str); |
88 | | - *len_p = (size_t) atoi(reply->element[1]->str); |
89 | | - *data_p = malloc(*len_p); |
90 | | - if (*data_p == NULL) { |
91 | | - error = GIT_ENOMEM; |
92 | | - } else { |
93 | | - memcpy(*data_p, reply->element[2]->str, *len_p); |
94 | | - error = GIT_SUCCESS; |
95 | | - } |
96 | | - } else { |
97 | | - error = GIT_ENOTFOUND; |
98 | | - } |
99 | | - } else { |
100 | | - error = GIT_ERROR; |
101 | | - } |
102 | | - |
103 | | - freeReplyObject(reply); |
104 | | - return error == GIT_SUCCESS; |
| 78 | + hiredis_odb_backend *backend; |
| 79 | + int error; |
| 80 | + redisReply *reply; |
| 81 | + char *str_id = calloc(GIT_OID_HEXSZ + 1, sizeof(char)); |
| 82 | + |
| 83 | + assert(data_p && len_p && type_p && _backend && oid); |
| 84 | + |
| 85 | + backend = (hiredis_odb_backend *) _backend; |
| 86 | + error = GIT_ERROR; |
| 87 | + |
| 88 | + git_oid_tostr(str_id, GIT_OID_HEXSZ, oid); |
| 89 | + |
| 90 | + reply = redisCommand(backend->db, "HMGET %s:%s:odb:%s %s %s %s", backend->prefix, backend->repo_path, str_id, |
| 91 | + "type", "size", "data"); |
| 92 | + |
| 93 | + if (reply && reply->type == REDIS_REPLY_ARRAY) { |
| 94 | + if (reply->element[0]->type != REDIS_REPLY_NIL && |
| 95 | + reply->element[1]->type != REDIS_REPLY_NIL && |
| 96 | + reply->element[2]->type != REDIS_REPLY_NIL) { |
| 97 | + *type_p = (git_otype) atoi(reply->element[0]->str); |
| 98 | + *len_p = (size_t) atoi(reply->element[1]->str); |
| 99 | + *data_p = malloc(*len_p); |
| 100 | + if (*data_p == NULL) { |
| 101 | + error = GITERR_NOMEMORY; |
| 102 | + } else { |
| 103 | + memcpy(*data_p, reply->element[2]->str, *len_p); |
| 104 | + error = GIT_OK; |
| 105 | + } |
| 106 | + } else { |
| 107 | + giterr_set_str(GITERR_ODB, "Redis odb couldn't find object"); |
| 108 | + error = GIT_ENOTFOUND; |
| 109 | + } |
| 110 | + } else { |
| 111 | + giterr_set_str(GITERR_ODB, "Redis odb storage error"); |
| 112 | + error = GIT_ERROR; |
| 113 | + } |
| 114 | + |
| 115 | + free(str_id); |
| 116 | + freeReplyObject(reply); |
| 117 | + return error; |
105 | 118 | } |
106 | 119 |
|
107 | | -int hiredis_backend__read_prefix(git_oid *out_oid, |
| 120 | +int hiredis_odb_backend__read_prefix(git_oid *out_oid, |
108 | 121 | void **data_p, size_t *len_p, git_otype *type_p, git_odb_backend *_backend, |
109 | | - const git_oid *short_oid, unsigned int len) |
| 122 | + const git_oid *short_oid, size_t len) |
110 | 123 | { |
111 | 124 | if (len >= GIT_OID_HEXSZ) { |
112 | 125 | /* Just match the full identifier */ |
113 | | - int error = hiredis_backend__read(data_p, len_p, type_p, _backend, short_oid); |
114 | | - if (error == GIT_SUCCESS) |
| 126 | + int error = hiredis_odb_backend__read(data_p, len_p, type_p, _backend, short_oid); |
| 127 | + if (error == GIT_OK) |
115 | 128 | git_oid_cpy(out_oid, short_oid); |
116 | 129 |
|
117 | 130 | return error; |
118 | | - } else if (len < GIT_OID_HEXSZ) { |
119 | | - /* TODO */ |
120 | | - return GIT_ENOTIMPLEMENTED; |
121 | 131 | } |
| 132 | + |
| 133 | + /* TODO prefix */ |
| 134 | + giterr_set_str(GITERR_ODB, "Redis odb doesn't not implement oid prefix lookup"); |
| 135 | + return GITERR_INVALID; |
122 | 136 | } |
123 | 137 |
|
124 | | -int hiredis_backend__exists(git_odb_backend *_backend, const git_oid *oid) |
| 138 | +int hiredis_odb_backend__exists(git_odb_backend *_backend, const git_oid *oid) |
125 | 139 | { |
126 | | - hiredis_backend *backend; |
127 | | - int found; |
128 | | - redisReply *reply; |
| 140 | + hiredis_odb_backend *backend; |
| 141 | + int found; |
| 142 | + redisReply *reply; |
| 143 | + char *str_id = calloc(GIT_OID_HEXSZ + 1, sizeof(char)); |
| 144 | + |
| 145 | + assert(_backend && oid); |
129 | 146 |
|
130 | | - assert(_backend && oid); |
| 147 | + backend = (hiredis_odb_backend *) _backend; |
| 148 | + found = 0; |
131 | 149 |
|
132 | | - backend = (hiredis_backend *) _backend; |
133 | | - found = 0; |
| 150 | + git_oid_tostr(str_id, GIT_OID_HEXSZ, oid); |
134 | 151 |
|
135 | | - reply = redisCommand(backend->db, "exists %b", oid->id, GIT_OID_RAWSZ); |
136 | | - if (reply && reply->type != REDIS_REPLY_NIL && reply->type != REDIS_REPLY_ERROR) |
137 | | - found = 1; |
| 152 | + reply = redisCommand(backend->db, "exists %s:%s:odb:%s", backend->prefix, backend->repo_path, str_id); |
| 153 | + if (reply->type == REDIS_REPLY_INTEGER) |
| 154 | + found = reply->integer; |
138 | 155 |
|
139 | | - freeReplyObject(reply); |
140 | | - return found; |
| 156 | + free(str_id); |
| 157 | + freeReplyObject(reply); |
| 158 | + return found; |
141 | 159 | } |
142 | 160 |
|
143 | | -int hiredis_backend__write(git_oid *id, git_odb_backend *_backend, const void *data, size_t len, git_otype type) |
| 161 | +int hiredis_odb_backend__write(git_odb_backend *_backend, const git_oid *oid, const void *data, size_t len, git_otype type) |
144 | 162 | { |
145 | | - hiredis_backend *backend; |
146 | | - int error; |
147 | | - redisReply *reply; |
| 163 | + hiredis_odb_backend *backend; |
| 164 | + int error; |
| 165 | + redisReply *reply; |
| 166 | + char *str_id = calloc(GIT_OID_HEXSZ + 1, sizeof(char)); |
148 | 167 |
|
149 | | - assert(id && _backend && data); |
| 168 | + assert(oid && _backend && data); |
150 | 169 |
|
151 | | - backend = (hiredis_backend *) _backend; |
152 | | - error = GIT_ERROR; |
| 170 | + backend = (hiredis_odb_backend *) _backend; |
| 171 | + error = GIT_ERROR; |
153 | 172 |
|
154 | | - if ((error = git_odb_hash(id, data, len, type)) < 0) |
155 | | - return error; |
| 173 | + git_oid_tostr(str_id, GIT_OID_HEXSZ, oid); |
156 | 174 |
|
157 | | - reply = redisCommand(backend->db, "HMSET %b " |
158 | | - "type %d " |
159 | | - "size %d " |
160 | | - "data %b ", id->id, GIT_OID_RAWSZ, |
161 | | - (int) type, len, data, len); |
| 175 | + reply = redisCommand(backend->db, "HMSET %s:%s:odb:%s " |
| 176 | + "type %d " |
| 177 | + "size %d " |
| 178 | + "data %b ", backend->prefix, backend->repo_path, str_id, |
| 179 | + (int) type, len, data, len); |
| 180 | + free(str_id); |
162 | 181 |
|
163 | | - error = (reply == NULL || reply->type == REDIS_REPLY_ERROR) ? GIT_ERROR : GIT_SUCCESS; |
| 182 | + error = (reply == NULL || reply->type == REDIS_REPLY_ERROR) ? GIT_ERROR : GIT_OK; |
164 | 183 |
|
165 | | - freeReplyObject(reply); |
166 | | - return error; |
| 184 | + freeReplyObject(reply); |
| 185 | + return error; |
167 | 186 | } |
168 | 187 |
|
169 | | -void hiredis_backend__free(git_odb_backend *_backend) |
| 188 | +void hiredis_odb_backend__free(git_odb_backend *_backend) |
170 | 189 | { |
171 | | - hiredis_backend *backend; |
172 | | - assert(_backend); |
173 | | - backend = (hiredis_backend *) _backend; |
| 190 | + hiredis_odb_backend *backend; |
174 | 191 |
|
175 | | - redisFree(backend->db); |
| 192 | + assert(_backend); |
| 193 | + backend = (hiredis_odb_backend *) _backend; |
176 | 194 |
|
177 | | - free(backend); |
| 195 | + redisFree(backend->db); |
| 196 | + |
| 197 | + free(backend); |
178 | 198 | } |
179 | 199 |
|
180 | | -int git_odb_backend_hiredis(git_odb_backend **backend_out, const char *host, int port) |
| 200 | +int git_odb_backend_hiredis(git_odb_backend **backend_out, const char* prefix, const char* path, const char *host, int port) |
181 | 201 | { |
182 | | - hiredis_backend *backend; |
| 202 | + hiredis_odb_backend *backend; |
183 | 203 |
|
184 | | - backend = calloc(1, sizeof (hiredis_backend)); |
185 | | - if (backend == NULL) |
186 | | - return GIT_ENOMEM; |
| 204 | + backend = calloc(1, sizeof (hiredis_odb_backend)); |
| 205 | + if (backend == NULL) |
| 206 | + return GITERR_NOMEMORY; |
187 | 207 |
|
188 | | - backend->db = redisConnect(host, port); |
189 | | - if (backend->db->err) { |
| 208 | + backend->db = redisConnect(host, port); |
| 209 | + if (backend->db->err) { |
190 | 210 | free(backend); |
| 211 | + giterr_set_str(GITERR_REFERENCE, "Redis refdb storage couldn't connect to redis server"); |
191 | 212 | return GIT_ERROR; |
192 | 213 | } |
193 | 214 |
|
194 | | - backend->parent.read = &hiredis_backend__read; |
195 | | - backend->parent.read_prefix = &hiredis_backend__read_prefix; |
196 | | - backend->parent.read_header = &hiredis_backend__read_header; |
197 | | - backend->parent.write = &hiredis_backend__write; |
198 | | - backend->parent.exists = &hiredis_backend__exists; |
199 | | - backend->parent.free = &hiredis_backend__free; |
| 215 | + backend->prefix = prefix; |
| 216 | + backend->repo_path = path; |
200 | 217 |
|
201 | | - *backend_out = (git_odb_backend *) backend; |
| 218 | + backend->parent.version = 1; |
202 | 219 |
|
203 | | - return GIT_SUCCESS; |
204 | | -} |
| 220 | + backend->parent.read = &hiredis_odb_backend__read; |
| 221 | + backend->parent.write = &hiredis_odb_backend__write; |
| 222 | + backend->parent.read_prefix = &hiredis_odb_backend__read_prefix; |
| 223 | + backend->parent.read_header = &hiredis_odb_backend__read_header; |
| 224 | + backend->parent.exists = &hiredis_odb_backend__exists; |
| 225 | + backend->parent.free = &hiredis_odb_backend__free; |
| 226 | + |
| 227 | + backend->parent.writestream = NULL; |
| 228 | + backend->parent.foreach = NULL; |
205 | 229 |
|
| 230 | + *backend_out = (git_odb_backend *) backend; |
| 231 | + |
| 232 | + return GIT_OK; |
| 233 | +} |
0 commit comments