SyncHashCache.c

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

Generated on Thu Feb 16 00:44:01 2012 for Content-Centric Networking in C by  doxygen 1.5.6