⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cache.c

📁 resinweb服务器源文件
💻 C
字号:
/* * Copyright (c) 1998-2001 Caucho Technology -- all rights reserved * * Caucho Technology permits redistribution, modification and use * of this file in source and binary form ("the Software") under the * Caucho Developer Source License ("the License").  The following * conditions must be met: * * 1. Each copy or derived work of the Software must preserve the copyright *    notice and this notice unmodified. * * 2. Redistributions of the Software in source or binary form must include  *    an unmodified copy of the License, normally in a plain ASCII text * * 3. The names "Resin" or "Caucho" are trademarks of Caucho Technology and *    may not be used to endorse products derived from this software. *    "Resin" or "Caucho" may not appear in the names of products derived *    from this software. * * 4. Caucho Technology requests that attribution be given to Resin *    in any manner possible.  We suggest using the "Resin Powered" *    button or creating a "powered by Resin(tm)" link to *    http://www.caucho.com for each page served by Resin. * * This Software is provided "AS IS," without a warranty of any kind.  * ALL EXPRESS OR IMPLIED REPRESENTATIONS AND WARRANTIES, INCLUDING ANY * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * * CAUCHO TECHNOLOGY AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES * SUFFERED BY LICENSEE OR ANY THIRD PARTY AS A RESULT OF USING OR * DISTRIBUTING SOFTWARE. IN NO EVENT WILL CAUCHO OR ITS LICENSORS BE LIABLE * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE SOFTWARE, EVEN IF HE HAS BEEN ADVISED OF THE POSSIBILITY * OF SUCH DAMAGES.       * * @author Scott Ferguson */#include <linux/kernel.h>#include <linux/proc_fs.h>#include <linux/ctype.h>#include <linux/fs.h>#include <linux/smp_lock.h>#include <asm/uaccess.h>#include <net/ip.h>#include "hardcore.h"typedef struct entry_t {  char buf[256];  char *url;  int use_count;  int expires;  struct file *file;  int length;  char is_live;  char is_dead;} entry_t;#define CACHE_SIZE 128static int g_count;static struct entry_t g_cache[CACHE_SIZE];static struct dentry *lookup_create(struct nameidata *nd, int is_dir){	struct dentry *dentry;	down(&nd->dentry->d_inode->i_sem);	dentry = ERR_PTR(-EEXIST);	if (nd->last_type != LAST_NORM)		goto fail;	dentry = lookup_hash(&nd->last, nd->dentry);	if (IS_ERR(dentry))		goto fail;	if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)		goto enoent;	return dentry;enoent:	dput(dentry);	dentry = ERR_PTR(-ENOENT);fail:	return dentry;}intcache_mkdir(const char *pathname, int mode){  int error = 0;  struct dentry *dir;  struct nameidata nd;    lock_kernel();  if (path_init(pathname, LOOKUP_PARENT, &nd))    error = path_walk(pathname, &nd);  if (error)    goto out;  dir = lookup_create(&nd, 1);  error = PTR_ERR(dir);  if (!IS_ERR(dir)) {    error = vfs_mkdir(nd.dentry->d_inode, dir, mode);    dput(dir);  }  up(&nd.dentry->d_inode->i_sem);  path_release(&nd);out:  unlock_kernel();  return error;}/** * Callback from the readdir routine for removing all the files in the * cache directory. * * @param vdir our parameter storing the directory file struct * @param name the name of the listed file * @param namlen the length of the name * @param offset ?? * @param ino inode of the file */static intremove_file(void *vdir, const char *name, int namlen,            off_t offset, ino_t ino){  struct file *dir = (struct file *) vdir;  struct dentry *file;  struct inode *inode = dir->f_dentry->d_inode;  struct qstr qstr;  if (name[0] == '.')    return 0;    qstr.name = name;  qstr.len = namlen;  qstr.hash = full_name_hash(name, namlen);  LOG(("remove %s\n", name));    file = d_lookup(dir->f_dentry, &qstr);  if (file && inode)    vfs_unlink(inode, file);  if (file)    dput(file);    return 0;}static entry_t *cache_get(char *url){  int hash = 37;  int ch;  int i;  for (i = 0; (ch = url[i]); i++)    hash = 65521 * hash + ch * 29;  hash &= 0x7fffffff;  for (i = 5; i > 0; i--) {    hash %= CACHE_SIZE;    if (! g_cache[hash].url)      return &g_cache[hash];    else if (! strcmp(g_cache[hash].url, url))      return &g_cache[hash];    hash++;  }  return 0;}/** * Remove a cache entry */static voidcache_remove(entry_t *cache){  LOG(("cache remove %s\n", cache->url));    cache->is_live = 0;  cache->url = 0;    /*   * Don't remove because we'll reuse it.  cache->file = 0;  if (file) {    // XXX: unlink, too    filp_close(file, current->files);  }  */}/** * Remove a cache entry */static voidcache_truncate(entry_t *cache){  struct file *file = cache->file;  struct inode *inode = file->f_dentry->d_inode;  LOG(("cache truncate %s %p\n", cache->url ? cache->url : "null", inode));    cache->is_live = 0;  cache->url = 0;  if (inode)    inode->i_op->truncate(inode);    LOG(("post truncate\n"));}intcache_start(browser_t *browser){  char buf[256];  struct file *file = 0;  struct nameidata nd;  int flag;  int err;  entry_t *cache = cache_get(browser->url);  LOG(("cache start %s %p\n", browser->url, cache));  // If already have an entry, don't cache  // XXX: really need to do an LRU here  if (! cache)    return 0;  else if (! cache->url && cache->file) {    // Truncate and return the cache    cache_truncate(cache);        cache->file->f_pos = 0;    cache->is_live = 0;    cache->url = cache->buf;    strcpy(cache->url, browser->url);    browser->cache = cache;    cache->length = 0;          return 1;  }  else if (! cache->url) {  }  else if (cache->expires < browser->now) {    // Truncate and return the cache    cache_truncate(cache);        cache->file->f_pos = 0;    cache->is_live = 0;    cache->url = cache->buf;    strcpy(cache->url, browser->url);    browser->cache = cache;    cache->length = 0;          return 1;  }  else    return 0;  sprintf(buf, "/usr/tmp/caucho/cache/t%d.tmp", g_count++);    flag = O_CREAT|0x3;    // err = open_namei(buf, flag, 0664, &nd);  err = -1;  if (err < 0) {    LOG(("can't open 0\n"));    return 0;  }    file = dentry_open(nd.dentry, nd.mnt, flag);  if (! file) {    LOG(("can't open\n"));    return 0;  }      cache->is_live = 0;  cache->url = cache->buf;  strcpy(cache->url, browser->url);  browser->cache = cache;  cache->file = file;  cache->length = 0;        LOG(("caching %s!\n", cache->url));      return 1;}/** * Writes data to the cache. */voidcache_write(browser_t *browser, char *data, int len){  mm_segment_t oldfs;  int write_len;  struct file *file = browser->cache->file;    LOG(("writing\n"));    oldfs = get_fs(); set_fs(KERNEL_DS);  write_len = file->f_op->write(file, data, len, &file->f_pos);  set_fs(oldfs);  LOG(("write %d -> %d\n", len, write_len));}/** * Kill the caching on this file because of some error during * the request. */voidcache_kill(browser_t *browser){  entry_t *cache = browser->cache;  struct file *file = cache->file;  LOG(("kill %s\n", browser->url));    cache->file = 0;  cache->url = 0;  cache->is_live = 0;  browser->cache = 0;    filp_close(file, current->files);  // XXX: needs unlink too}/** * Finish loading of a cache. */voidcache_finish(browser_t *browser){  entry_t *cache = browser->cache;  struct file *file;  if (! cache)    return;  browser->cache = 0;    file = cache->file;    cache->length = file->f_pos;  cache->expires = browser->expires;  cache->is_live = 1;    LOG(("finished %s %p %d %p\n",       cache->url, file, cache->length, browser));}/** * Writes a string to the buffer. */static intcse_write(char *buf, int off, char *str){  while (*str)    buf[off++] = *str++;  return off;}intcache_lookup(browser_t *browser){  entry_t *cache = cache_get(browser->url);  if (! cache) {    LOG(("no cache lookup %s\n", browser->url));    return 0;  }  else if (! cache->is_live) {    LOG(("not live %s %x\n", browser->url, cache->url));    return 0;  }  else if (browser->now < cache->expires) {    int len = 0;    char *buf = browser->cout_buf;        LOG(("cache lookup %s\n", browser->url));      browser->cache = cache;    browser->state = RHC_CACHE_WRITE;    browser->cache_offset = 0;    len = cse_write(buf, len, "HTTP/1.0 200 OK\r\n");    len = cse_write(buf, len, "Connection: close\r\n");    len = cse_write(buf, len, "Server: ResinHardCore/1.3\r\n");    len += sprintf(buf + len, "Content-Length: %d\r\nDate: ", cache->length);    len += format_now(buf + len);    len = cse_write(buf, len, "\r\n\r\n");    browser->cout_length = len;    cache->use_count++;        if (cache_read(browser))      browser_wake(browser);        return 1;  }  else {    cache_remove(cache);        return 0;  }}intcache_read(browser_t *browser){  entry_t *cache = browser->cache;  struct file *file = cache->file;  int len;  mm_segment_t oldfs;  loff_t offset = browser->cache_offset;  char *buf;  oldfs = get_fs(); set_fs(KERNEL_DS);  buf = browser->cout_buf + browser->cout_length;  len = 4096 - browser->cout_length;  if (len > cache->length - browser->cache_offset)    len =  cache->length - browser->cache_offset;  len = file->f_op->read(file, buf, len, &offset);  set_fs(oldfs);    if (len > 0) {    LOG(("cache read %d live %d\n", len, cache->is_live));    browser->cache_offset += len;    if (browser->cache_offset >= cache->length) {      browser->write_state = RHC_BROWSER_QUIT;      browser->cache = 0;    }    else      browser->write_state = browser->state;        browser->state = RHC_BROWSER_WRITE;          browser->iov[0].iov_base = browser->cout_buf;    browser->iov[0].iov_len = browser->cout_length + len;    browser->iov_index = 1;    browser->cout_length = 0;        return browser_write_iov(browser) > 0;  }  else {    // done?    LOG(("browser done len:%d live:%d?\n", len, cache->is_live));    browser->cache = 0;    browser->state = RHC_BROWSER_QUIT;    return 1;  }}static voidcache_clear(){  struct file *dir = filp_open("/usr/tmp/caucho/cache", O_RDONLY, 0777);  int error;  if (! dir)    return;  down(&dir->f_dentry->d_inode->i_sem);  error = dir->f_op->readdir(dir, dir, remove_file);  up(&dir->f_dentry->d_inode->i_sem);  filp_close(dir, current->files);}intcache_init(){  LOG(("cache init\n"));  lock_kernel();  cache_mkdir("/usr/tmp/caucho", 0777);  cache_mkdir("/usr/tmp/caucho/cache", 0777);  cache_clear();  unlock_kernel();  return 1;}/** * Cleanup the cache module on module shutdown. */voidcache_cleanup(){  int i;    for (i = 0; i < CACHE_SIZE; i++) {    entry_t *cache = &g_cache[i];    struct file *file = cache->file;    // XXX: unlink?    if (file)      filp_close(file, current->files);  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -