SyncHashCache.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "SyncBase.h"
00022 #include "SyncHashCache.h"
00023 #include "SyncNode.h"
00024 #include "SyncRoot.h"
00025 #include "SyncUtil.h"
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <strings.h>
00029 #include <ccn/ccn.h>
00030 #include <ccnr/ccnr_msg.h>
00031
00032 static struct SyncHashCacheEntry *
00033 localFreeEntry(struct SyncHashCacheEntry *ce) {
00034 ce->next = NULL;
00035 if (ce->ncL != NULL) SyncNodeDecRC(ce->ncL);
00036 if (ce->ncR != NULL) SyncNodeDecRC(ce->ncR);
00037 if (ce->hash != NULL) ccn_charbuf_destroy(&ce->hash);
00038 free(ce);
00039 return NULL;
00040 }
00041
00042 extern struct SyncHashCacheEntry *
00043 SyncHashLookup(struct SyncHashCacheHead *head,
00044 const unsigned char *xp, ssize_t xs) {
00045 if (xp == NULL || xs <= 0) return NULL;
00046 uint32_t h = SyncSmallHash(xp, xs);
00047 uint32_t hx = h % head->mod;
00048 struct SyncHashCacheEntry *ent = head->ents[hx];
00049 head->probes = head->probes + 1;
00050 while (ent != NULL) {
00051 if (h == ent->small) {
00052
00053 ssize_t cmp = SyncCmpHashesRaw(xp, xs, ent->hash->buf, ent->hash->length);
00054 if (cmp == 0) return ent;
00055 }
00056 ent = ent->next;
00057 }
00058 head->misses = head->misses + 1;
00059 return NULL;
00060 }
00061
00062 extern struct SyncHashCacheEntry *
00063 SyncHashEnter(struct SyncHashCacheHead *head,
00064 const unsigned char *xp, ssize_t xs,
00065 enum SyncHashState set) {
00066 if (xp == NULL || xs <= 0) return NULL;
00067 uint32_t h = SyncSmallHash(xp, xs);
00068 uint32_t hx = h % head->mod;
00069 struct SyncHashCacheEntry *old = head->ents[hx];
00070 struct SyncHashCacheEntry *ent = old;
00071 head->probes = head->probes + 1;
00072 while (ent != NULL) {
00073 if (h == ent->small) {
00074
00075 ssize_t cmp = SyncCmpHashesRaw(xp, xs, ent->hash->buf, ent->hash->length);
00076 if (cmp == 0) {
00077 ent->state |= set;
00078 return ent;
00079 }
00080 }
00081 ent = ent->next;
00082 }
00083 head->misses = head->misses + 1;
00084 if (ent == NULL) {
00085 uintmax_t index = head->lastIndex + 1;
00086 head->lastIndex = index;
00087 head->probes = head->probes + 1;
00088 head->misses = head->misses + 1;
00089 ent = NEW_STRUCT(1, SyncHashCacheEntry);
00090 ent->lastUsed = SyncCurrentTime();
00091 ent->stablePoint = CCNR_NULL_HWM;
00092 ent->head = head;
00093 ent->next = old;
00094 ent->small = h;
00095 ent->hash = ccn_charbuf_create();
00096 ent->index = index;
00097 ccn_charbuf_append(ent->hash, xp, xs);
00098 head->ents[hx] = ent;
00099 head->len++;
00100 }
00101 ent->state |= set;
00102 return ent;
00103 }
00104
00105 extern void
00106 SyncHashRemoveEntry(struct SyncHashCacheHead *head,
00107 struct SyncHashCacheEntry *ce) {
00108 if (ce != NULL) {
00109 uint32_t h = ce->small;
00110 uint32_t hx = h % head->mod;
00111 struct SyncHashCacheEntry *ent = head->ents[hx];
00112 struct SyncHashCacheEntry *lag = NULL;
00113 while (ent != NULL) {
00114 struct SyncHashCacheEntry *next = ent->next;
00115 if (ent == ce) {
00116
00117 if (lag == NULL) head->ents[hx] = next;
00118 else lag->next = next;
00119 break;
00120 }
00121 lag = ent;
00122 ent = next;
00123 }
00124 if (ent == ce)
00125 ce = localFreeEntry(ce);
00126 }
00127 }
00128
00129 extern void
00130 SyncHashClearMarks(struct SyncHashCacheHead *head) {
00131 int hx = 0;
00132 for (hx = 0; hx < head->mod; hx++) {
00133 struct SyncHashCacheEntry *ent = head->ents[hx];
00134 while (ent != NULL) {
00135 enum SyncHashState state = ent->state;
00136 enum SyncHashState bit = state & SyncHashState_marked;
00137 ent->state = state - bit;
00138 ent = ent->next;
00139 }
00140 }
00141 }
00142
00143 extern struct SyncHashCacheHead *
00144 SyncHashCacheCreate(struct SyncRootStruct *root, uint32_t mod) {
00145 struct SyncHashCacheHead *head = NEW_STRUCT(1, SyncHashCacheHead);
00146 if (mod < 4) mod = 4;
00147 head->mod = mod;
00148 head->ents = NEW_ANY(mod, struct SyncHashCacheEntry *);
00149 head->root = root;
00150 return head;
00151 }
00152
00153 extern struct SyncHashCacheHead *
00154 SyncHashCacheFree(struct SyncHashCacheHead *head) {
00155 if (head != NULL) {
00156 size_t i = 0;
00157 size_t lim = head->mod;
00158 while (i < lim) {
00159 struct SyncHashCacheEntry *ent = head->ents[i];
00160 head->ents[i] = NULL;
00161 while (ent != NULL) {
00162
00163 struct SyncHashCacheEntry *next = ent->next;
00164 ent = localFreeEntry(ent);
00165 ent = next;
00166 }
00167 i++;
00168 }
00169 free(head->ents);
00170 free(head);
00171 }
00172 return NULL;
00173 }
00174
00175 extern int
00176 SyncCacheEntryStore(struct SyncHashCacheEntry *ce) {
00177
00178 int res = 0;
00179 if (ce == NULL) {
00180
00181 res = -1;
00182 } else if (ce->ncL == NULL || ce->ncL->cb == NULL
00183 || (ce->state & SyncHashState_stored)
00184 || (ce->state & SyncHashState_storing) == 0 ) {
00185
00186 res = 0;
00187 } else {
00188 struct SyncRootStruct *root = ce->head->root;
00189 struct SyncBaseStruct *base = root->base;
00190 struct ccn_charbuf *name = SyncNameForLocalNode(root, ce->hash);
00191 struct ccn_charbuf *content = ce->ncL->cb;
00192
00193
00194 res |= ccn_create_version(base->ccn, name, CCN_V_NOW, 0, 0);
00195 res |= ccn_name_append_numeric(name, CCN_MARKER_SEQNUM, 0);
00196
00197 res = SyncLocalRepoStore(base, name, content, CCN_SP_FINAL_BLOCK);
00198 if (res > 0) {
00199
00200 ce->state |= SyncHashState_stored;
00201 ce->state = ce->state - SyncHashState_storing;
00202 }
00203 ccn_charbuf_destroy(&name);
00204 }
00205 return res;
00206 }
00207
00208 extern int
00209 SyncCacheEntryFetch(struct SyncHashCacheEntry *ce) {
00210
00211 char *here = "Sync.SyncCacheEntryFetch";
00212 int res = 0;
00213 if (ce == NULL) {
00214
00215 res = -1;
00216 } else if (ce->ncL != NULL) {
00217
00218 res = 0;
00219 } else {
00220
00221
00222 struct SyncRootStruct *root = ce->head->root;
00223 struct SyncBaseStruct *base = root->base;
00224 struct ccn_charbuf *name = SyncNameForLocalNode(root, ce->hash);
00225 struct ccn_charbuf *content = ccn_charbuf_create();
00226 char *why = "no fetch";
00227 struct ccn_parsed_ContentObject pcos;
00228
00229 res = SyncLocalRepoFetch(base, name, content, &pcos);
00230 if (res >= 0) {
00231
00232 const unsigned char *xp = NULL;
00233 size_t xs = 0;
00234
00235 res = ccn_content_get_value(content->buf, content->length,
00236 &pcos, &xp, &xs);
00237 if (res < 0)
00238 why = "ccn_content_get_value failed";
00239 else {
00240 struct ccn_buf_decoder ds;
00241 struct ccn_buf_decoder *d = ccn_buf_decoder_start(&ds, xp, xs);
00242 struct SyncNodeComposite *nc = SyncAllocComposite(root->base);
00243 res |= SyncParseComposite(nc, d);
00244 if (res < 0) {
00245
00246 why = "bad parse";
00247 SyncFreeComposite(nc);
00248 nc = NULL;
00249 } else {
00250 res = 1;
00251 SyncNodeIncRC(nc);
00252 ce->ncL = nc;
00253 ce->state |= SyncHashState_stored;
00254 }
00255 }
00256 if (res < 0)
00257 if (root->base->debug >= CCNL_ERROR)
00258 SyncNoteUri(root, here, why, name);
00259 }
00260 ccn_charbuf_destroy(&name);
00261 ccn_charbuf_destroy(&content);
00262 }
00263 return res;
00264 }
00265
00266