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