SyncBase.c

Go to the documentation of this file.
00001 /**
00002  * @file sync/SyncBase.c
00003  *  
00004  * Part of CCNx Sync.
00005  */
00006 /*
00007  * Copyright (C) 2011-2012 Palo Alto Research Center, Inc.
00008  *
00009  * This work is free software; you can redistribute it and/or modify it under
00010  * the terms of the GNU General Public License version 2 as published by the
00011  * Free Software Foundation.
00012  * This work is distributed in the hope that it will be useful, but WITHOUT ANY
00013  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
00015  * for more details. You should have received a copy of the GNU General Public
00016  * License along with this program; if not, write to the
00017  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019  */
00020 
00021 #include "SyncMacros.h"
00022 #include "SyncActions.h"
00023 #include "SyncBase.h"
00024 #include "SyncPrivate.h"
00025 #include "SyncUtil.h"
00026 #include <stdlib.h>
00027 #include <stdio.h>
00028 #include <string.h>
00029 #include <ccn/uri.h>
00030 #include <ccnr/ccnr_msg.h>
00031 #include <ccnr/ccnr_private.h>
00032 #include <ccnr/ccnr_sync.h>
00033 
00034 // Error support
00035 
00036 extern void
00037 SyncSetErrInner(struct SyncBaseStruct *base,
00038                 enum SyncErrCode code,
00039                 char * file, int line) {
00040     struct SyncErrStruct *err = NEW_STRUCT(1, SyncErrStruct);
00041     err->code = code;
00042     err->file = file;
00043     err->line = line;
00044     struct SyncErrStruct *lag = base->errList;
00045     while (lag != NULL) {
00046         struct SyncErrStruct *next = lag->next;
00047         if (next == NULL) break;
00048         lag = next;
00049     }
00050     if (lag != NULL) lag->next = err;
00051     else base->errList = err;
00052 }
00053 
00054 extern void
00055 SyncClearErr(struct SyncBaseStruct *base) {
00056     for (;;) {
00057         struct SyncErrStruct *err = base->errList;
00058         if (err == NULL) break;
00059         base->errList = err->next;
00060         free(err);
00061     }
00062 }
00063 
00064 
00065 
00066 // Basic object support
00067 
00068 extern struct SyncBaseStruct *
00069 SyncNewBase(struct ccnr_handle *ccnr,
00070             struct ccn *ccn,
00071             struct ccn_schedule *sched) {
00072     int64_t now = SyncCurrentTime();
00073     struct SyncBaseStruct *base = NEW_STRUCT(1, SyncBaseStruct);
00074     base->client_handle = ccnr;
00075     base->ccn = ccn;
00076     base->sched = sched;
00077     struct SyncPrivate *priv = NEW_STRUCT(1, SyncPrivate);
00078     base->priv = priv;
00079     priv->topoAccum = SyncAllocNameAccum(4);
00080     priv->prefixAccum = SyncAllocNameAccum(4);
00081     priv->sliceCmdPrefix = ccn_charbuf_create();
00082     priv->localHostPrefix = ccn_charbuf_create();
00083     priv->comps = ccn_indexbuf_create();
00084     priv->stableTarget = CCNR_NULL_HWM;
00085     priv->stableStored = CCNR_NULL_HWM;
00086     priv->lastStable = now;
00087     priv->lastCacheClean = now;
00088     ccn_name_from_uri(priv->localHostPrefix, "/%C1.M.S.localhost");
00089     ccn_name_from_uri(priv->sliceCmdPrefix, "/%C1.M.S.localhost/%C1.S.cs");
00090     return base;
00091 }
00092 
00093 #ifndef SYNCLIBRARY
00094 static int
00095 getEnvLimited(char *key, int lo, int hi, int def) {
00096     char *s = getenv(key);
00097     if (s != NULL && s[0] != 0) {
00098         int x = strtol(s, NULL, 10);
00099         if (x >= lo && x <= hi) return x;
00100     }
00101     return def;
00102 }
00103 extern void
00104 SyncInit(struct SyncBaseStruct *bp) {
00105     if (bp != NULL) {
00106         struct ccnr_handle *ccnr = bp->client_handle;
00107         char *here = "Sync.SyncInit";
00108         
00109         if (ccnr != NULL) {
00110             // called when there is a Repo that is ready for Sync activity
00111             // TBD: read sync state and restart at the saved commit point
00112             struct SyncPrivate *priv = bp->priv;
00113             bp->debug = ccnr->syncdebug;
00114             
00115             int enable = getEnvLimited("CCNS_ENABLE", 0, 1, 1);
00116 
00117             if (enable <= 0) return;
00118             
00119             char *debugStr = getenv("CCNS_DEBUG");
00120             
00121             // enable/disable storing of sync tree nodes
00122             // default is to store
00123             priv->useRepoStore = getEnvLimited("CCNS_REPO_STORE", 0, 1, 1);
00124             
00125             // enable/disable stable recovery point
00126             // default is to disable recovery, but to calculate stable points
00127             priv->stableEnabled = getEnvLimited("CCNS_STABLE_ENABLED", 0, 1, 1);
00128             
00129             // get faux error percent
00130             priv->fauxErrorTrigger = getEnvLimited("CCNS_FAUX_ERROR",
00131                                                    0, 99, 0);
00132             
00133             // get private flags for SyncActions
00134             priv->syncActionsPrivate = getEnvLimited("CCNS_ACTIONS_PRIVATE",
00135                                                      0, 255, 3);
00136             
00137             // heartbeat rate
00138             priv->heartbeatMicros = getEnvLimited("CCNS_HEARTBEAT_MICROS",
00139                                                   10000, 10*1000000, 200000);
00140             
00141             // root advise lifetime
00142             priv->rootAdviseFresh = getEnvLimited("CCNS_ROOT_ADVISE_FRESH",
00143                                                   1, 30, 4);
00144             
00145             // root advise lifetime
00146             priv->rootAdviseLifetime = getEnvLimited("CCNS_ROOT_ADVISE_LIFETIME",
00147                                                      1, 30, 20);
00148             
00149             // root advise lifetime
00150             priv->fetchLifetime = getEnvLimited("CCNS_NODE_FETCH_LIFETIME",
00151                                                 1, 30, 4);
00152 
00153             // max node or content fetches busy per root
00154             priv->maxFetchBusy = getEnvLimited("CCNS_MAX_FETCH_BUSY",
00155                                                1, 100, 6);
00156 
00157             // max number of compares busy
00158             priv->maxComparesBusy = getEnvLimited("CCNS_MAX_COMPARES_BUSY",
00159                                                   1, 100, 4);
00160             
00161             // # of bytes permitted for RootAdvise delta mode
00162             priv->deltasLimit = getEnvLimited("CCNS_DELTAS_LIMIT",
00163                                               0, 8000, 0);
00164             
00165             // # of bytes permitted for RootAdvise delta mode
00166             priv->syncScope = getEnvLimited("CCNS_SYNC_SCOPE",
00167                                               0, 2, 2);
00168             
00169             
00170             if (bp->debug >= CCNL_INFO) {
00171                 char temp[1024];
00172                 int pos = 0;
00173                 pos += snprintf(temp+pos, sizeof(temp)-pos,
00174                                 "CCNS_ENABLE=%d",
00175                                 enable);
00176                 pos += snprintf(temp+pos, sizeof(temp)-pos,
00177                                 ",CCNS_DEBUG=%s",
00178                                 debugStr);
00179                 pos += snprintf(temp+pos, sizeof(temp)-pos,
00180                                 ",CCNS_REPO_STORE=%d",
00181                                 priv->useRepoStore);
00182                 pos += snprintf(temp+pos, sizeof(temp)-pos,
00183                                 ",CCNS_STABLE_ENABLED=%d",
00184                                 priv->stableEnabled);
00185                 pos += snprintf(temp+pos, sizeof(temp)-pos,
00186                                 ",CCNS_FAUX_ERROR=%d",
00187                                 priv->fauxErrorTrigger);
00188                 pos += snprintf(temp+pos, sizeof(temp)-pos,
00189                                 ",CCNS_ACTIONS_PRIVATE=%d",
00190                                 priv->syncActionsPrivate);
00191                 pos += snprintf(temp+pos, sizeof(temp)-pos,
00192                                 ",CCNS_HEARTBEAT_MICROS=%d",
00193                                 priv->heartbeatMicros);
00194                 pos += snprintf(temp+pos, sizeof(temp)-pos,
00195                                 ",CCNS_ROOT_ADVISE_FRESH=%d",
00196                                 priv->rootAdviseFresh);
00197                 pos += snprintf(temp+pos, sizeof(temp)-pos,
00198                                 ",CCNS_ROOT_ADVISE_LIFETIME=%d",
00199                                 priv->rootAdviseLifetime);
00200                 pos += snprintf(temp+pos, sizeof(temp)-pos,
00201                                 ",CCNS_NODE_FETCH_LIFETIME=%d",
00202                                 priv->fetchLifetime);
00203                 pos += snprintf(temp+pos, sizeof(temp)-pos,
00204                                 ",CCNS_MAX_FETCH_BUSY=%d",
00205                                 priv->maxFetchBusy);
00206                 pos += snprintf(temp+pos, sizeof(temp)-pos,
00207                                 ",CCNS_MAX_COMPARES_BUSY=%d",
00208                                 priv->maxComparesBusy);
00209                 pos += snprintf(temp+pos, sizeof(temp)-pos,
00210                                 ",CCNS_DELTAS_LIMIT=%d",
00211                                 priv->deltasLimit);
00212                 pos += snprintf(temp+pos, sizeof(temp)-pos,
00213                                 ",CCNS_SYNC_SCOPE=%d",
00214                                 priv->syncScope);
00215                 pos += snprintf(temp+pos, sizeof(temp)-pos,
00216                                 ",defer_verification=%d",
00217                                 ccn_defer_verification(bp->ccn, -1));
00218                 ccnr_msg(ccnr, "%s, %s", here, temp);
00219             }
00220             
00221             SyncStartHeartbeat(bp);
00222         }
00223     }
00224 }
00225 #endif
00226 
00227 extern void
00228 SyncFreeBase(struct SyncBaseStruct **bp) {
00229     if (bp != NULL) {
00230         struct SyncBaseStruct *base = *bp;
00231         *bp = NULL;
00232         if (base != NULL) {
00233             struct SyncPrivate *priv = base->priv;
00234             // free the errList
00235             SyncClearErr(base);
00236             // free the roots
00237             while (priv->rootHead != NULL) {
00238                 if (SyncRemRoot(priv->rootHead) != NULL) break;
00239             }
00240             // free the name accums
00241             if (priv->topoAccum != NULL)
00242                 SyncFreeNameAccumAndNames(priv->topoAccum);
00243             if (priv->prefixAccum != NULL)
00244                 SyncFreeNameAccumAndNames(priv->prefixAccum);
00245             if (priv->comps != NULL)
00246                 ccn_indexbuf_destroy(&priv->comps);
00247             ccn_charbuf_destroy(&priv->sliceCmdPrefix);
00248             free(priv);
00249             free(base);
00250         }
00251     }
00252 }
00253 
00254 // Enumeration support
00255 extern int
00256 SyncNotifyContent(struct SyncBaseStruct *base,
00257                   int enumeration,
00258                   ccnr_accession item,
00259                   struct ccn_charbuf *name) {
00260     // here for any updates, whether from time-based enumeration
00261     // or from prefix-based enumeration
00262     char *here = "Sync.SyncNotifyContent";
00263     
00264     if (base != NULL && base->client_handle != NULL) {
00265         struct SyncPrivate *priv = base->priv;
00266         int debug = base->debug;
00267         
00268         if (name == NULL) {
00269             // end of an enumeration
00270             if (enumeration == 0) {
00271                 if (debug >= CCNL_WARNING)
00272                     ccnr_msg(base->client_handle, "%s, end of time-based enum?", here);
00273             } else if (enumeration == priv->sliceEnum) {
00274                 priv->sliceEnum = 0;
00275                 if (debug >= CCNL_INFO)
00276                     ccnr_msg(base->client_handle, "%s, all slice names seen", here);
00277             } else if (enumeration == priv->sliceBusy) {
00278                 priv->sliceBusy = 0;
00279                 struct SyncRootStruct *root = priv->rootHead;
00280                 while (root != NULL) {
00281                     struct SyncRootPrivate *rp = root->priv;
00282                     if (enumeration == rp->sliceBusy) {
00283                         rp->sliceBusy = 0;
00284                         if (debug >= CCNL_INFO)
00285                             SyncNoteSimple(root, here, "slice enum done");
00286                         break;
00287                     }
00288                     root = root->next;
00289                 }
00290                 // may need a new enumeration started
00291                 root = priv->rootHead;
00292                 while (root != NULL) {
00293                     struct SyncRootPrivate *rp = root->priv;
00294                     if (rp->sliceBusy < 0) {
00295                         SyncStartSliceEnum(root);
00296                         break;
00297                     }
00298                     root = root->next;
00299                 }  
00300             } else {
00301                 if (debug >= CCNL_WARNING)
00302                     ccnr_msg(base->client_handle, "%s, end of what enum?", here);
00303             }
00304             return -1;
00305         }
00306         
00307         if (debug >= CCNL_FINE) {
00308             struct ccn_charbuf *uri = SyncUriForName(name);
00309             ccnr_msg(base->client_handle,
00310                      "%s, enum %d, %s!",
00311                      here, enumeration, ccn_charbuf_as_string(uri));
00312             ccn_charbuf_destroy(&uri);
00313         }
00314         
00315         struct ccn_indexbuf *comps = priv->comps;
00316         int splitRes = ccn_name_split(name, comps);
00317         if (splitRes < 0) {
00318             // really hould not happen!  but it does not hurt to log and ignore it
00319             if (debug >= CCNL_SEVERE)
00320                 ccnr_msg(base->client_handle, "%s, invalid name!", here);
00321             return 0;
00322         }
00323         
00324         unsigned char *comp0 = NULL;
00325         size_t size0 = 0;
00326         unsigned char *comp1 = NULL;
00327         size_t size1 = 0;
00328         ccn_name_comp_get(name->buf, comps, 0, 
00329                           (const unsigned char **) &comp0, &size0);
00330         ccn_name_comp_get(name->buf, comps, 1,
00331                           (const unsigned char **) &comp1, &size1);
00332         ccnr_accession mark = item;
00333         if (SyncPrefixMatch(priv->localHostPrefix, name, 0)) {
00334             // to the local host, don't update the stable target
00335             mark = CCNR_NULL_ACCESSION;
00336             if (SyncPrefixMatch(priv->sliceCmdPrefix, name, 0))
00337                 // this is a new slice
00338                 SyncHandleSlice(base, name);
00339         }
00340         if (mark != CCNR_NULL_ACCESSION)
00341             priv->stableTarget = ccnr_hwm_update(base->client_handle, priv->stableTarget, mark);
00342         
00343         // add the name to any applicable roots
00344         SyncAddName(base, name, item);
00345         return 0;
00346     }
00347     return -1;
00348 }
00349 
00350 extern void
00351 SyncShutdown(struct SyncBaseStruct *bp) {
00352     char *here = "Sync.SyncShutdown";
00353     int debug = bp->debug;
00354     if (debug >= CCNL_INFO)
00355         ccnr_msg(bp->client_handle, "%s", here);
00356     // TBD: shutdown the hearbeat
00357     // TBD: unregister the prefixes
00358 }
00359 
00360 
Generated on Tue Aug 21 14:54:19 2012 for Content-Centric Networking in C by  doxygen 1.6.3