ccnfilewatch.c

Go to the documentation of this file.
00001 /**
00002  * @file ccnfilewatch.c
00003  * 
00004  * Utility program to record a file's size
00005  *
00006  */
00007 
00008 /*
00009  * Copyright (C) 2011 Palo Alto Research Center, Inc.
00010  *
00011  * This work is free software; you can redistribute it and/or modify it under
00012  * the terms of the GNU General Public License version 2 as published by the
00013  * Free Software Foundation.
00014  * This work is distributed in the hope that it will be useful, but WITHOUT ANY
00015  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
00016  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
00017  * for more details. You should have received a copy of the GNU General Public
00018  * License along with this program; if not, write to the
00019  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020  * Boston, MA 02110-1301, USA.
00021  */
00022 
00023 #include <errno.h>
00024 #include <fcntl.h>
00025 #include <inttypes.h>
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <time.h>
00030 #include <unistd.h>
00031 #include <sys/poll.h>
00032 #include <sys/stat.h>
00033 #include <sys/time.h>
00034 
00035 static int
00036 usage(const char *progname) {
00037     fprintf(stderr, "%s" " wrong args\n", progname);
00038     exit(1);
00039 }
00040 
00041 static int
00042 statchanged(struct stat *prev, struct stat *curr)
00043 {
00044     if (curr->st_size != prev->st_size)
00045         return(1);
00046     if (curr->st_mtime != prev->st_mtime)
00047         return(1);
00048     return(0);
00049 }
00050 
00051 static void
00052 printstat(FILE *out, struct stat *s)
00053 {
00054     struct timeval now;
00055     time_t sec;
00056     unsigned usec;
00057     
00058     gettimeofday(&now, NULL);
00059     sec = s->st_mtime;
00060     usec = 0;
00061     if (now.tv_sec <= s->st_mtime + 1) {
00062         /* If more file systems kept hi-res mtime, we could use that here. */
00063         sec = now.tv_sec;
00064         usec = now.tv_usec;
00065     }
00066     fprintf(out, "%lu.%06u d=%u,i=%lu %ju\n",
00067             (unsigned long)sec,
00068             usec,
00069             (unsigned)s->st_dev,
00070             (unsigned long)s->st_ino,
00071             (uintmax_t)(s->st_size)
00072             );
00073 }
00074 
00075 /**
00076  * Monitor the size of the named file, recording its growth
00077  *
00078  * This is used for repository tests.  We want to measure the point at which
00079  * the repository file is a stable size.
00080  *
00081  * @param path is the name of the file to monitor
00082  * @param out is where to write the logged data
00083  * @param minsize is the minimum expected final size
00084  * @param maxsize is threshold beyond which we stop monitoring
00085  * @param maxsec is a limit, in seconds, on how long to monitor
00086  * @param msecstable is a time in milliseconds to consider file size stable
00087  * @param msecpoll is the delay, in milliseconds, between polls.
00088  *
00089  * @returns 0 if stability was obtained within given parameters,
00090  *         -1 if system call failed or invaild arguments (see errno),
00091  *         -2 if maxsize exceeded,
00092  *         -3 if maxsec exceeded,
00093  *         -4 if the file is unlinked.
00094  */
00095 #define FW_NBUF 4
00096 int
00097 ccn_filewatch(const char *path,
00098               FILE *out,
00099               off_t minsize,
00100               off_t maxsize,
00101               time_t maxsec,
00102               int msecstable,
00103               int msecpoll)
00104 {
00105     int fd = -1;
00106     int res = 0;
00107     unsigned i = 0;
00108     const unsigned int nbuf = FW_NBUF;
00109     struct stat stats[FW_NBUF];
00110     struct stat *curr = NULL;
00111     struct stat *prev = NULL;
00112     struct stat statname = {0};
00113     struct pollfd dummy[1];
00114     time_t elapsed = 0;
00115     unsigned elapsedms = 0;
00116     unsigned stablems = 0;
00117     
00118     memset(stats, 0, sizeof(stats));
00119     memset(dummy, 0, sizeof(dummy));
00120     errno = EINVAL;
00121     if (msecpoll < 1)
00122         return(-1);
00123     if (msecstable < 1)
00124         return(-1);
00125     fd = open(path, O_RDONLY, 0);
00126     if (fd < 0)
00127         return(-1);
00128     for (i = 0;;) {
00129         curr = &(stats[i % nbuf]);
00130         res = fstat(fd, curr);
00131         if (res == -1)
00132             break;
00133         if (prev == NULL || statchanged(prev, curr)) {
00134             printstat(out, curr);
00135             prev = curr;
00136             stablems = 0;
00137             if (maxsize != 0 && curr->st_size > maxsize) {
00138                 res = -2;
00139                 break;
00140             }
00141             i++;
00142         }
00143         else {
00144             stablems += msecpoll;
00145             if (stablems >= msecstable && curr->st_size >= minsize) {
00146                 res = 0;
00147                 break;
00148             }
00149         }
00150         res = poll(dummy, 0, msecpoll);
00151         if (res != 0) abort();
00152         elapsedms += msecpoll;
00153         if (elapsed + elapsedms / 1000 > maxsec) {
00154             res = -3;
00155             break;
00156         }
00157         if (elapsedms >= 3000) {
00158             elapsed += elapsedms / 1000;
00159             elapsedms %= 1000;
00160             res = stat(path, &statname);
00161             if (res < 0 ||
00162                 statname.st_dev != curr->st_dev ||
00163                 statname.st_ino != curr->st_ino) {
00164                 res = -4;
00165                 break;
00166             }
00167             fflush(out);
00168         }
00169     }
00170     close(fd);
00171     fflush(out);
00172     return(res);
00173 }
00174 
00175 int
00176 main(int argc, char** argv)
00177 {
00178     int opt = 0;
00179     int res = 0;
00180     const char *path = NULL;
00181     FILE *out = stdout;
00182     off_t minsize = 1;
00183     off_t maxsize = 0; /* unlimited */
00184     time_t maxsec = 600;
00185     int msecstable = 5000;
00186     int msecpoll = 100;
00187 
00188     while ((opt = getopt(argc, argv, "h")) != -1) {
00189         switch (opt) {
00190             case 'a':
00191                 break;
00192             case 'h':
00193             default:
00194                 usage(argv[0]);
00195         }
00196     }
00197     if (argv[optind] == NULL || argv[optind + 1] != NULL)
00198         usage(argv[0]);
00199     path = argv[optind];
00200     res = ccn_filewatch(path,
00201                         out,
00202                         minsize,
00203                         maxsize,
00204                         maxsec,
00205                         msecstable,
00206                         msecpoll);
00207     if (res == -1)
00208         perror(path);
00209     exit(-res);
00210 }

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