ccn_fetch_test.c

Go to the documentation of this file.
00001 /**
00002  * @file ccn_fetch_test.c
00003  * @brief Provides a test platform for ccn_fetch.
00004  *
00005  * Copyright (C) 2011 Palo Alto Research Center, Inc.
00006  *
00007  * This library is free software; you can redistribute it and/or modify it
00008  * under the terms of the GNU Lesser General Public License version 2.1
00009  * as published by the Free Software Foundation.
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00013  * Lesser General Public License for more details. You should have received
00014  * a copy of the GNU Lesser General Public License along with this library;
00015  * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
00016  * Fifth Floor, Boston, MA 02110-1301 USA.
00017  */
00018 
00019 #include <ccn/fetch.h>
00020 
00021 #include <ccn/ccn.h>
00022 #include <ccn/uri.h>
00023 
00024 #include <sys/select.h>
00025 #include <sys/socket.h>
00026 #include <sys/time.h>
00027 #include <sys/types.h>
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <errno.h>
00031 #include <string.h>
00032 #include <strings.h>
00033 #include <time.h>
00034 #include <unistd.h>
00035 
00036 #include <sys/time.h>
00037 
00038 #define LOCAL_BUF_MAX 20000
00039 
00040 typedef struct ccn_charbuf *MyCharbuf;
00041 typedef char *string;
00042 
00043 struct MyParms {
00044         struct ccn_fetch *f;
00045         int ccnFD;
00046         string src;
00047         string dst;
00048         FILE *debug;
00049         int resolveVersion;
00050         int appendOut;
00051         int assumeFixed;
00052         int maxSegs;
00053 };
00054 
00055 static uint64_t
00056 GetCurrentTime(void) {
00057         const uint64_t M = 1000*1000;
00058         struct timeval now;
00059     gettimeofday(&now, 0);
00060         return now.tv_sec*M+now.tv_usec;
00061 }
00062 
00063 static double
00064 DeltaTime(uint64_t mt1, uint64_t mt2) {
00065         int64_t dmt = mt2-mt1;
00066         return dmt*1.0e-6;
00067 }
00068 
00069 #define MinMilliSleep 2
00070 static void
00071 MilliSleep(uint64_t n) {
00072         if (n >= MinMilliSleep) {
00073                 const uint64_t M = 1000*1000;
00074                 const uint64_t G = 1000*M;
00075                 n = n * M;
00076                 struct timespec ts;
00077                 ts.tv_sec = n / G;
00078                 ts.tv_nsec = n % G;
00079                 nanosleep(&ts, NULL);
00080         }
00081 }
00082 #define MyAlloc(NNN, TTT) (TTT *) calloc(NNN, sizeof(TTT))
00083 
00084 static int
00085 retErr(string msg) {
00086         fprintf(stderr, "** error: %s\n", msg);
00087         fflush(stderr);
00088         return -1;
00089 }
00090 
00091 typedef struct TestElemStruct *TestElem;
00092 struct TestElemStruct {
00093         FILE *out;
00094         string fileName;
00095         struct ccn_fetch_stream *fs;
00096         string buf;
00097         int bufMax;
00098         int bufLen;
00099         intmax_t accum;
00100         uint64_t startTime;
00101 };
00102 
00103 static TestElem
00104 NewElem(struct MyParms *p) {
00105         string name = p->src;
00106         int bufMax = LOCAL_BUF_MAX;
00107         TestElem e = MyAlloc(1, struct TestElemStruct);
00108         e->startTime = GetCurrentTime();
00109         MyCharbuf cbName = ccn_charbuf_create();
00110         int res = ccn_name_from_uri(cbName, name);
00111         if (res < 0) {
00112                 fprintf(stderr, "** open of %s failed!\n", name);
00113         } else {
00114                 e->fs = ccn_fetch_open(p->f, cbName,
00115                                                            name,
00116                                                            NULL,
00117                                                            p->maxSegs,
00118                                                            p->resolveVersion,
00119                                                            p->assumeFixed);
00120                 if (e->fs == NULL) {
00121                         fprintf(stderr, "** open of %s failed!\n", name);
00122                 } else {
00123                         fprintf(stderr, "-- opened %s\n", name);
00124                         if (p->dst != NULL) {
00125                                 e->fileName = p->dst;
00126                                 FILE *out = fopen(e->fileName,
00127                                                                   ((p->appendOut > 0) ? "a" : "w"));
00128                                 e->out = out;
00129                         } else {
00130                                 e->fileName = "stdout";
00131                                 e->out = stdout;
00132                         }
00133                         e->buf = MyAlloc(bufMax+4, char);
00134                         e->bufMax = bufMax;
00135                 }
00136         }
00137         ccn_charbuf_destroy(&cbName);
00138         return e;
00139 }
00140 
00141 static TestElem
00142 ElemDone(TestElem e) {
00143         if (e->fs != NULL)
00144                 e->fs = ccn_fetch_close(e->fs);
00145         if (e->out != NULL && e->out != stdout)
00146                 fclose(e->out);
00147         double dt = DeltaTime(e->startTime, GetCurrentTime());
00148         if (e->accum > 0)
00149                 fprintf(stderr,
00150                                 "-- Moved %jd bytes to %s in %4.3f secs (%4.3f MB/sec)\n",
00151                                 e->accum, e->fileName, dt, e->accum * 1.0e-6 / dt);
00152         if (e->buf != NULL) free(e->buf);
00153         free(e);
00154         return NULL;
00155 }
00156 
00157 static int
00158 runTest(struct MyParms *p) {
00159         int res = 0;
00160         string msg = NULL;
00161         struct SelectDataStruct {
00162                 int fdLen;
00163                 fd_set readFDS;
00164                 fd_set writeFDS;
00165                 fd_set errorFDS;
00166                 struct timeval selectTimeout;
00167         } sds;
00168         int timeoutUsecs = 100;
00169         sds.selectTimeout.tv_sec = (timeoutUsecs / 1000000);
00170         sds.selectTimeout.tv_usec = (timeoutUsecs % 1000000);
00171         
00172         // initialize the test files
00173         TestElem e = NewElem(p);
00174         if (e->fs == NULL) {
00175                 // could not open the file
00176                 res = -1;
00177         } else {
00178                 for (;;) {
00179                         FD_ZERO(&sds.readFDS);
00180                         FD_ZERO(&sds.writeFDS);
00181                         FD_ZERO(&sds.errorFDS);
00182                         sds.fdLen = p->ccnFD+1;
00183                         FD_SET(p->ccnFD, &sds.readFDS);
00184                         FD_SET(p->ccnFD, &sds.writeFDS);
00185                         FD_SET(p->ccnFD, &sds.errorFDS);
00186                         int res = select(sds.fdLen,
00187                                                          &sds.readFDS,
00188                                                          &sds.writeFDS,
00189                                                          &sds.errorFDS,
00190                                                          &sds.selectTimeout
00191                                                          );
00192                         if (res != 0) ccn_fetch_poll(p->f);
00193                         intmax_t nb = ccn_fetch_read(e->fs, e->buf, e->bufMax);
00194                         if (nb == CCN_FETCH_READ_END) {
00195                                 // end of this test
00196                                 break;
00197                         } else if (nb > 0) {
00198                                 // there is data to be written
00199                                 fwrite(e->buf, sizeof(char), nb, e->out);
00200                                 e->accum = e->accum + nb;
00201                         } else if (nb == CCN_FETCH_READ_NONE) {
00202                                 // we just don't know enough right now
00203                                 MilliSleep(5);
00204                         } else if (nb == CCN_FETCH_READ_TIMEOUT) {
00205                                 // timeouts are treated as transient (maybe not true)
00206                                 ccn_reset_timeout(e->fs);
00207                                 MilliSleep(5);
00208                         } else {
00209                                 // random failure
00210                                 msg = "read failed";
00211                         }
00212                 }
00213                 
00214         }
00215         e = ElemDone(e);
00216         MilliSleep(5);
00217 
00218         // cleanup
00219         if (msg != NULL) {
00220                 return retErr(msg);
00221         }
00222         return res;
00223 
00224 }
00225 
00226 static char *help = "usage: ccn_fetch_test {switch | ccnName}*\n\
00227     -help     help\n\
00228     -out XXX  sets output file to XXX (default: stdout)\n\
00229     -mb NNN   ses NNN as max number of buffers to use (default: 4)\n\
00230     -d        enables debug output (default: none)\n\
00231     -f        use fixed-size segments (default: variable)\n\
00232     -nv       no resolve version (default: CCN_V_HIGH)\n";
00233 
00234 int
00235 main(int argc, string *argv) {
00236         
00237         struct ccn *h = ccn_create();
00238         int connRes = ccn_connect(h, NULL);
00239         if (connRes < 0) {
00240                 return retErr("ccn_connect failed");
00241         }
00242         struct ccn_fetch *f = ccn_fetch_new(h);
00243         int ccnFD = ccn_get_connection_fd(h);
00244         int needHelp = ((argc < 2) ? 1 : 0);
00245         
00246         struct MyParms p = {0};
00247         
00248         p.resolveVersion = CCN_V_HIGH;
00249         p.f = f;
00250         p.ccnFD = ccnFD;
00251         p.maxSegs = 4;
00252         
00253         int i = 1;
00254         while (i < argc) {
00255                 string arg = argv[i++];
00256                 if (arg[0] == '-') {
00257                         if (strcasecmp(arg, "-out") == 0) {
00258                                 p.appendOut = 0;
00259                                 p.dst = NULL;
00260                                 if (i < argc) p.dst = argv[i++];
00261                         } else if (strcasecmp(arg, "-d") == 0) {
00262                                 p.debug = stderr;
00263                         } else if (strcasecmp(arg, "-f") == 0) {
00264                                 p.assumeFixed = 1;
00265                         } else if (strcasecmp(arg, "-help") == 0) {
00266                                 needHelp++;
00267                                 break;
00268                         } else if (strcasecmp(arg, "-nv") == 0) {
00269                                 p.resolveVersion = 0;
00270                         } else if (strcasecmp(arg, "-mb") == 0) {
00271                                 if (i < argc) p.maxSegs = atoi(argv[i++]);
00272                         } else {
00273                                 fprintf(stderr, "-- Unsupported switch: %s\n", arg);
00274                                 needHelp++;
00275                                 break;
00276                         }
00277                 } else {
00278                         if (p.debug != NULL)
00279                                 ccn_fetch_set_debug(f, p.debug, ccn_fetch_flags_NoteAll);
00280                         p.src = arg;
00281                         runTest(&p);
00282                         p.appendOut = 1;
00283                 }
00284         }
00285 
00286         f = ccn_fetch_destroy(f);
00287         ccn_disconnect(h);
00288         ccn_destroy(&h);
00289         if (needHelp) {
00290                 fprintf(stderr, help, NULL);
00291         }
00292         return 0;
00293 }
00294 

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