Check-in [565d4b51c2]
Overview
Comment:Updated to cache file descriptors
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:565d4b51c2cd0fa96ef28afea971a0e52feaaa15
User & Date: rkeene on 2014-02-05 08:49:33
Other Links: manifest | tags
Context
2014-02-05
09:01
Added support for a "no logging" compile-time option (for now) and updated to support sendfile restarts check-in: c7e703e4e5 user: rkeene tags: trunk
08:49
Updated to cache file descriptors check-in: 565d4b51c2 user: rkeene tags: trunk
2014-02-04
12:02
Check sendfile() output and log check-in: 16b1aecd99 user: rkeene tags: trunk
Changes

Modified filed.c from [8a849d733e] to [af10919239].

    21     21   /* Arguments for worker threads */
    22     22   struct filed_worker_thread_args {
    23     23   	int fd;
    24     24   };
    25     25   
    26     26   /* File information */
    27     27   struct filed_fileinfo {
           28  +	pthread_mutex_t mutex;
           29  +	char *path;
    28     30   	int fd;
    29     31   	size_t len;
    30     32   	char *lastmod;
    31     33   	char lastmod_b[64];
    32     34   	char *type;
    33     35   };
    34     36   
           37  +/* Global variables */
           38  +struct filed_fileinfo *filed_fileinfo_fdcache;
           39  +unsigned int filed_fileinfo_fdcache_size = 8192;
           40  +
    35     41   /* Initialize process */
    36         -static void filed_init(void) {
           42  +static int filed_init(void) {
           43  +	unsigned int idx;
           44  +	int mutex_init_ret;
           45  +
    37     46   	mlockall(MCL_CURRENT | MCL_FUTURE);
           47  +
           48  +	filed_fileinfo_fdcache = malloc(sizeof(*filed_fileinfo_fdcache) * filed_fileinfo_fdcache_size);
           49  +	if (filed_fileinfo_fdcache == NULL) {
           50  +		return(1);
           51  +	}
           52  +
           53  +	for (idx = 0; idx < filed_fileinfo_fdcache_size; idx++) {
           54  +		mutex_init_ret = pthread_mutex_init(&filed_fileinfo_fdcache[idx].mutex, NULL);
           55  +		if (mutex_init_ret != 0) {
           56  +			return(1);
           57  +		}
           58  +
           59  +		filed_fileinfo_fdcache[idx].path = strdup("");
           60  +		filed_fileinfo_fdcache[idx].fd = -1;
           61  +		filed_fileinfo_fdcache[idx].lastmod = "";
           62  +		filed_fileinfo_fdcache[idx].type = "";
           63  +	}
           64  +
           65  +	return(0);
    38     66   }
    39     67   
    40     68   /* Listen on a particular address/port */
    41     69   static int filed_listen(const char *address, unsigned int port) {
    42     70   	struct sockaddr_in6 addr;
    43     71   	int pton_ret, bind_ret, listen_ret;
    44     72   	int fd;
................................................................................
    77    105   /* Initialize logging thread */
    78    106   static int filed_logging_thread_init(void) {
    79    107   	/* XXX:TODO: Unimplemented */
    80    108   	return(0);
    81    109   }
    82    110   
    83    111   /* Log a message */
          112  +#define filed_log_msg_debug(x, ...) { fprintf(stderr, x, __VA_ARGS__); fprintf(stderr, "\n"); fflush(stderr); }
    84    113   static void filed_log_msg(const char *buffer) {
    85    114   	/* XXX:TODO: Unimplemented */
    86         -	buffer = buffer;
          115  +	fprintf(stderr, "%s\n", buffer);
          116  +
    87    117   	return;
    88    118   }
    89    119   
    90    120   /* Format time per RFC2616 */
    91    121   static char *filed_format_time(char *buffer, size_t buffer_len, const time_t timeinfo) {
    92    122   	struct tm timeinfo_tm, *timeinfo_tm_p;
    93    123   
................................................................................
    97    127   	}
    98    128   
    99    129   	buffer[buffer_len - 1] = '\0';
   100    130   	buffer_len = strftime(buffer, buffer_len - 1, "%a, %d %b %Y %H:%M:%S GMT", timeinfo_tm_p);
   101    131   
   102    132   	return(buffer);
   103    133   }
          134  +
          135  +/* hash */
          136  +static unsigned int filed_hash(const unsigned char *value, unsigned int modulus) {
          137  +	unsigned char curr;
          138  +	unsigned int retval;
          139  +
          140  +	retval = modulus - 1;
          141  +
          142  +	while ((curr = *value)) {
          143  +		if (curr < 32) {
          144  +			curr = 255 - curr;
          145  +		} else {
          146  +			curr -= 32;
          147  +		}
          148  +
          149  +		retval <<= 5;
          150  +		retval += curr;
          151  +
          152  +		value++;
          153  +	}
          154  +
          155  +	retval = retval % modulus;
          156  +
          157  +	return(retval);
          158  +}
   104    159   
   105    160   /* Open a file and return file information */
   106    161   static struct filed_fileinfo *filed_open_file(const char *path, struct filed_fileinfo *buffer) {
   107         -	/* XXX:TODO: Cache file descriptors */
   108         -
          162  +	struct filed_fileinfo *cache;
          163  +	unsigned int cache_idx;
   109    164   	off_t len;
   110    165   	int fd;
   111    166   
   112         -	fd = open(path, O_RDONLY);
          167  +	cache_idx = filed_hash((const unsigned char *) path, filed_fileinfo_fdcache_size);
          168  +
          169  +	cache = &filed_fileinfo_fdcache[cache_idx];
          170  +
          171  +	filed_log_msg_debug("Locking mutex for idx: %lu", (unsigned long) cache_idx);
          172  +
          173  +	pthread_mutex_lock(&cache->mutex);
          174  +
          175  +	filed_log_msg_debug("Completed locking mutex for idx: %lu", (unsigned long) cache_idx);
          176  +
          177  +	if (strcmp(path, cache->path) != 0) {
          178  +		filed_log_msg_debug("Cache miss for idx: %lu: OLD \"%s\", NEW \"%s\"", (unsigned long) cache_idx, cache->path, path);
          179  +
          180  +		fd = open(path, O_RDONLY);
          181  +		if (fd < 0) {
          182  +			pthread_mutex_unlock(&cache->mutex);
          183  +
          184  +			return(NULL);
          185  +		}
          186  +
          187  +		free(cache->path);
          188  +		if (cache->fd >= 0) {
          189  +			close(cache->fd);
          190  +		}
          191  +
          192  +		len = lseek(fd, 0, SEEK_END);
          193  +		lseek(fd, 0, SEEK_SET);
          194  +
          195  +		cache->fd = fd;
          196  +		cache->len = len;
          197  +		cache->path = strdup(path);
          198  +
          199  +		/* XXX:TODO: Determine */
          200  +		cache->type = "text/plain";
          201  +		cache->lastmod = filed_format_time(cache->lastmod_b, sizeof(cache->lastmod_b), time(NULL) - 30);
          202  +	} else {
          203  +		filed_log_msg_debug("Cache hit for idx: %lu: PATH \"%s\"", (unsigned long) cache_idx, path);
          204  +	}
          205  +
          206  +	/*
          207  +	 * We have to make a duplicate FD, because once we release the cache
          208  +	 * mutex, the file descriptor may be closed
          209  +	 */
          210  +	fd = dup(cache->fd);
   113    211   	if (fd < 0) {
          212  +		pthread_mutex_unlock(&cache->mutex);
          213  +
   114    214   		return(NULL);
   115    215   	}
   116    216   
   117         -	len = lseek(fd, 0, SEEK_END);
   118         -	lseek(fd, 0, SEEK_SET);
   119         -
   120    217   	buffer->fd = fd;
   121         -	buffer->len = len;
          218  +	buffer->len = cache->len;
          219  +	buffer->type = cache->type;
          220  +	memcpy(buffer->lastmod_b, cache->lastmod_b, sizeof(buffer->lastmod_b));
          221  +	buffer->lastmod = buffer->lastmod_b + (cache->lastmod - cache->lastmod_b);
   122    222   
   123         -	/* XXX:TODO: Determine */
   124         -	buffer->type = "text/plain";
   125         -	buffer->lastmod = filed_format_time(buffer->lastmod_b, sizeof(buffer->lastmod_b), time(NULL) - 30);
          223  +	pthread_mutex_unlock(&cache->mutex);
   126    224   
   127    225   	return(buffer);
   128    226   }
   129    227   
   130    228   /* Process an HTTP request and return the path requested */
   131    229   static char *filed_get_http_request(FILE *fp, char *buffer, size_t buffer_len) {
   132    230   	char *method, *path;
................................................................................
   194    292   	);
   195    293   }
   196    294   
   197    295   /* Handle a single request from a client */
   198    296   static void filed_handle_client(int fd) {
   199    297   	struct filed_fileinfo *fileinfo, fileinfo_b;
   200    298   	ssize_t sendfile_ret;
          299  +	off_t sendfile_offset;
   201    300   	char *path, path_b[1010];
   202    301   	char *date_current, date_current_b[64];
   203    302   	FILE *fp;
   204    303   
   205    304   	/* Determine current time */
   206    305   	date_current = filed_format_time(date_current_b, sizeof(date_current_b), time(NULL));
   207    306   
................................................................................
   241    340   		);
   242    341   		fflush(fp);
   243    342   
   244    343   		filed_log_msg("PROCESS_REPLY_COMPLETE FD=... STATUS=200");
   245    344   
   246    345   		filed_log_msg("SEND_START IFD=... OFD=... BYTES=...");
   247    346   
   248         -		sendfile_ret = sendfile(fd, fileinfo->fd, NULL, fileinfo->len);
          347  +		sendfile_offset = 0;
          348  +		sendfile_ret = sendfile(fd, fileinfo->fd, &sendfile_offset, fileinfo->len);
   249    349   		if (sendfile_ret < 0 || ((size_t) sendfile_ret) != fileinfo->len) {
   250    350   			filed_log_msg("SEND_COMPLETE STATUS=ERROR IFD=... OFD=... BYTES=... BYTES_SENT=...");
   251    351   		} else {
   252    352   			filed_log_msg("SEND_COMPLETE STATUS=OK IFD=... OFD=... BYTES=...");
   253    353   		}
   254    354   
   255    355   		close(fileinfo->fd);
................................................................................
   335    435   	return(0);
   336    436   }
   337    437   
   338    438   /* Run process */
   339    439   int main(int argc, char **argv) {
   340    440   	int port = PORT, thread_count = THREAD_COUNT;
   341    441   	const char *bind_addr = BIND_ADDR;
          442  +	int init_ret;
   342    443   	int fd;
   343    444   
   344    445   	/* Ignore */
   345    446   	argc = argc;
   346    447   	argv = argv;
   347    448   
   348    449   	/* Create listening socket */
................................................................................
   353    454   		return(1);
   354    455   	}
   355    456   
   356    457   	/* Become a daemon */
   357    458   	/* XXX:TODO: Become a daemon */
   358    459   
   359    460   	/* Initialize */
   360         -	filed_init();
          461  +	init_ret = filed_init();
          462  +	if (init_ret != 0) {
          463  +		perror("filed_init");
          464  +
          465  +		return(3);
          466  +	}
   361    467   
   362    468   	/* Create logging thread */
   363    469   	/* XXX:TODO: Check for errors */
   364    470   	filed_logging_thread_init();
   365    471   
   366    472   	/* Create worker threads */
   367    473   	/* XXX:TODO: Check for errors */