SyncHashCache.c

Go to the documentation of this file.
00001 /**
00002  * @file sync/SyncHashCache.c
00003  *  
00004  * Part of CCNx Sync.
00005  */
00006 /*
00007  * Copyright (C) 2011-2012 Palo Alto Research Center, Inc.
00008  *
00009  * This library is free software; you can redistribute it and/or modify it
00010  * under the terms of the GNU Lesser General Public License version 2.1
00011  * as published by the Free Software Foundation.
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00015  * Lesser General Public License for more details. You should have received
00016  * a copy of the GNU Lesser General Public License along with this library;
00017  * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
00018  * Fifth Floor, Boston, MA 02110-1301 USA.
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             // probably equal, but we have to check
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             // probably equal, but we have to check
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                 // unchain from main chain
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                 // TBD: error if busy?
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     // causes the cache entry to be saved to the repo
00178     int res = 0;
00179     if (ce == NULL) {
00180         // not an entry
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         // not eligible
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         // TBD: do we want to omit version and segment?
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             // clear the bits
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     // causes the cache entry to fetched from the repo
00211     char *here = "Sync.SyncCacheEntryFetch";
00212     int res = 0;
00213     if (ce == NULL) {
00214         // not an entry
00215         res = -1;
00216     } else if (ce->ncL != NULL) {
00217         // it's already here
00218         res = 0;
00219     } else {
00220         // at this point we try to fetch it from the local repo
00221         // a failure should complain
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             // parse the object
00232             const unsigned char *xp = NULL;
00233             size_t xs = 0;
00234             // get the encoded node
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                     // failed, so back out of the allocations
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 
Generated on Tue Aug 21 14:54:19 2012 for Content-Centric Networking in C by  doxygen 1.6.3