00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
00173 TestElem e = NewElem(p);
00174 if (e->fs == NULL) {
00175
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
00196 break;
00197 } else if (nb > 0) {
00198
00199 fwrite(e->buf, sizeof(char), nb, e->out);
00200 e->accum = e->accum + nb;
00201 } else if (nb == CCN_FETCH_READ_NONE) {
00202
00203 MilliSleep(5);
00204 } else if (nb == CCN_FETCH_READ_TIMEOUT) {
00205
00206 ccn_reset_timeout(e->fs);
00207 MilliSleep(5);
00208 } else {
00209
00210 msg = "read failed";
00211 }
00212 }
00213
00214 }
00215 e = ElemDone(e);
00216 MilliSleep(5);
00217
00218
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