Roxen.git / server / base_server / configuration.pike

version» Context lines:

Roxen.git/server/base_server/configuration.pike:1:   // This file is part of Roxen WebServer.   // Copyright © 1996 - 2004, Roxen IS.   //      // @appears Configuration   //! A site's main configuration    - constant cvs_version = "$Id: configuration.pike,v 1.627 2006/11/14 21:19:16 mast Exp $"; + constant cvs_version = "$Id: configuration.pike,v 1.628 2006/12/05 15:50:04 grubba Exp $";   #include <module.h>   #include <module_constants.h>   #include <roxen.h>   #include <request_trace.h>   #include <timers.h>      #define CATCH(P,X) do{mixed e;if(e=catch{X;})report_error("While "+P+"\n"+describe_backtrace(e));}while(0)      // --- Locale defines ---   //<locale-token project="roxen_start"> LOC_S </locale-token>
Roxen.git/server/base_server/configuration.pike:207:   //! Return all currently active connections.   {    return current_connections;   }      // It's nice to have the name when the rest of __INIT executes.   string name = roxen->bootstrap_info->get();      class DataCache   { -  mapping(string: -  array(string|mapping(string:mixed))|string| -  function(string, RequestID:string)) cache = ([]); +  static typedef array(string|mapping(string:mixed))|string| +  function(string, RequestID:string) EntryType;    -  +  mapping(string:EntryType) cache = ([]); +     int current_size;    int max_size;    int max_file_size;       int hits, misses;       void flush()    {   #ifndef RAM_CACHE_NO_RELOAD_FLUSH    current_size = 0;    cache = ([]);   #endif    }    -  static int low_expire_entry(string key_prefix, array(string) keys) +  // Expire a single entry. +  static void really_low_expire_entry(string key)    { -  +  EntryType e = m_delete(cache, key); +  if (arrayp(e)) { +  current_size -= sizeof(e[0]); +  } +  } +  +  // NOTE: Avoid using this function if possible! O(n) +  static int low_expire_entry(string key_prefix) +  {    if (!key_prefix) return 0;    if (arrayp(cache[key_prefix])) {    // Leaf node. No need to loop. -  current_size -= sizeof(cache[key_prefix][0]); -  m_delete(cache, key_prefix); -  // keys[] = 0; +  really_low_expire_entry(key_prefix);    return 1;    }    // Inner node. Find all its children.    int res = 0; -  foreach(keys; int ind; string key) { +  foreach(indices(cache); int ind; string key) {    if (!key) continue;    if (has_prefix(key, key_prefix)) { -  if (arrayp(cache[key])) { -  current_size -= sizeof(cache[key][0]); -  } -  m_delete(cache, key); -  keys[ind] = 0; +  really_low_expire_entry(key);    res++;    }    }    return res;    }       void expire_entry(string key_prefix, RequestID|void id)    {    if (!id) { -  low_expire_entry(key_prefix, indices(cache)); +  low_expire_entry(key_prefix);    return;    }    string url = key_prefix;    sscanf(url, "%[^\0]", url);    while(1) { -  array(string|mapping(string:mixed))|string| -  function(string, RequestID:string) val; +  EntryType val;    if (arrayp(val = cache[key_prefix])) {    current_size -= sizeof(val[0]);    m_delete(cache, key_prefix);    return;    }    if (!val) {    return;    }       string|array(string) key_frag;
Roxen.git/server/base_server/configuration.pike:285:    key_frag = val(url, id);    }    if (key_frag)    // Avoid spoofing if key_frag happens to contain "\0\0".    key_frag = replace (key_frag, "\0", "\0\1");    else key_frag = "";    key_prefix += "\0\0" + key_frag;    }    }    +  //! Clear ~1/10th of the cache.    static void clear_some_cache()    {    // FIXME: Use random(cache) instead to avoid the indices() call.    array(string) q = indices(cache);    if(!sizeof(q))    {    current_size=0;    return;    } -  +  +  // The following code should be ~O(n * log(n)). +  sort(q);    for(int i = 0; i < sizeof(q)/10; i++) { -  int r; -  i += low_expire_entry(q[r = random(sizeof(q))], q); +  int r = random(sizeof(q)); +  string key_prefix = q[r = random(sizeof(q))]; +  for(;r < sizeof(q); r++,i++) { +  if (!q[r]) break; +  if (!has_prefix(q[r], key_prefix)) break; +  really_low_expire_entry(q[r]);    q[r] = 0;    }    } -  +  }       void set(string url, string data, mapping meta, int expire, RequestID id)    {    if( strlen( data ) > max_file_size ) return;       string key = url;       foreach(id->misc->vary_cb_order || ({}),    string|function(string, RequestID: string) vary_cb) {    array(string|mapping(string:mixed))|string|    function(string, RequestID:string) old = cache[key];    if (old && (old != vary_cb)) {    // FIXME: Warn? -  expire_entry(key); +  low_expire_entry(key);    }    cache[key] = vary_cb;       string|array(string) key_frag;    if (stringp(vary_cb)) {    key_frag = id->request_headers[vary_cb];    } else {    key_frag = vary_cb(url, id);    }    if (key_frag)    // Avoid spoofing if key_frag happens to contain "\0\0".    key_frag = replace (key_frag, "\0", "\0\1");    else key_frag = "";    key += "\0\0" + key_frag;    }       array(string|mapping(string:mixed))|string|    function(string, RequestID:string) old = cache[key];    if (old) {    // FIXME: Warn? -  expire_entry(key); +  low_expire_entry(key);    }       current_size += strlen( data );    cache[key] = ({ data, meta });       // Only the actual cache entry is expired.    // FIXME: This could lead to lots and lots of call outs.. :P -  call_out(low_expire_entry, expire, key, ({ key })); +  call_out(really_low_expire_entry, expire, key);    int n;    while( (current_size > max_size) && (n++<10))    clear_some_cache();    }       array(string|mapping(string:mixed)) get(string url, RequestID id)    {    array(string|mapping(string:mixed))|string|    function(string, RequestID:string) res;    string key = url;