Roxen.git / server / base_server / configuration.pike

version» Context lines:

Roxen.git/server/base_server/configuration.pike:1:   // A vitual server's main configuration   // Copyright © 1996 - 2000, Roxen IS. -  - constant cvs_version = "$Id: configuration.pike,v 1.379 2000/09/25 06:29:43 per Exp $"; - constant is_configuration = 1; + constant cvs_version = "$Id: configuration.pike,v 1.380 2000/09/25 07:03:11 per Exp $";   #include <module.h>   #include <module_constants.h>   #include <roxen.h>   #include <request_trace.h>    - inherit "basic_defvar"; +     - mapping enabled_modules = ([]); - mapping(string:array(int)) error_log=([]); -  - #ifdef PROFILE - mapping profile_map = ([]); - #endif -  +    #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>   //<locale-token project="roxen_config"> LOC_C </locale-token>   //<locale-token project="roxen_message"> LOC_M </locale-token>   //<locale-token project="roxen_config"> DLOCALE </locale-token>   #define LOC_S(X,Y) _STR_LOCALE("roxen_start",X,Y)   #define LOC_C(X,Y) _STR_LOCALE("roxen_config",X,Y)   #define LOC_M(X,Y) _STR_LOCALE("roxen_message",X,Y)
Roxen.git/server/base_server/configuration.pike:39:   #define THROTTLING_DEBUG(X)   #endif      #ifdef REQUEST_DEBUG   # define REQUEST_WERR(X) werror("CONFIG: "+X+"\n")   #else   # define REQUEST_WERR(X)   #endif      /* A configuration.. */ + inherit Configuration; + inherit "basic_defvar";    -  +    #include "rxml.pike"; -  + constant store = roxen.store; + constant retrieve = roxen.retrieve; + constant remove = roxen.remove;    - object throttler; - function store = roxen->store; - function retrieve = roxen->retrieve; - function remove = roxen->remove; - RoxenModule types_module; - RoxenModule auth_module; - RoxenModule dir_module; - function types_fun; - function auth_fun; -  - string name; - int inited; +    int config_id; -  - int get_config_id() { + int get_config_id() + {    if(config_id) return config_id;    for(int i=sizeof(roxen->configurations); i;)    if(roxen->configurations[--i]->name==name) return config_id=i;   }      string get_doc_for( string region, string variable )   {    RoxenModule module;    if(variable[0] == '_')    return 0;
Roxen.git/server/base_server/configuration.pike:98:    if(strlen(QUERY(name)))    return QUERY(name);    return name;   }      string comment()   {    return QUERY(comment);   }    - class Priority - { -  string _sprintf() -  { -  return "Priority()"; -  } -  -  array (RoxenModule) url_modules = ({ }); -  array (RoxenModule) logger_modules = ({ }); -  array (RoxenModule) location_modules = ({ }); -  array (RoxenModule) filter_modules = ({ }); -  array (RoxenModule) last_modules = ({ }); -  array (RoxenModule) first_modules = ({ }); -  mapping (string:array(RoxenModule)) file_extension_modules = ([ ]); -  mapping (RoxenModule:multiset(string)) provider_modules = ([ ]); -  -  void stop() -  { -  foreach(url_modules, RoxenModule m) -  CATCH("stopping url modules",m->stop && m->stop()); -  foreach(logger_modules, RoxenModule m) -  CATCH("stopping logging modules",m->stop && m->stop()); -  foreach(filter_modules, RoxenModule m) -  CATCH("stopping filter modules",m->stop && m->stop()); -  foreach(location_modules, RoxenModule m) -  CATCH("stopping location modules",m->stop && m->stop()); -  foreach(last_modules, RoxenModule m) -  CATCH("stopping last modules",m->stop && m->stop()); -  foreach(first_modules, RoxenModule m) -  CATCH("stopping first modules",m->stop && m->stop()); -  foreach(indices(provider_modules), RoxenModule m) -  CATCH("stopping provider modules",m->stop && m->stop()); -  } - } -  -  -  +    /* A 'pri' is one of the ten priority objects. Each one holds a list    * of modules for that priority. They are all merged into one list for    * performance reasons later on.    */      array (Priority) allocate_pris()   {    return allocate(10, Priority)();   }    - int requests; - //! The number of requests, for debug and statistics info only. +     - // Protocol specific statistics. - mapping(string:mixed) extra_statistics = ([]); - mapping(string:mixed) misc = ([]); // Even more statistics. -  - int sent; - //! Bytes data sent - int hsent; - //! Bytes headers sent - int received; - //! Bytes data received -  - // Will write a line to the log-file. This will probably be replaced - // entirely by log-modules in the future, since this would be much - // cleaner. - function(string:int) log_function; -  +    // The logging format used. This will probably move to the above   // mentioned module in the future.   private mapping (int:string) log_format = ([]);      // A list of priority objects   private array (Priority) pri = allocate_pris();      public mapping modules = ([]);   //! All enabled modules in this site.   //! The format is "module":{ "copies":([ num:instance, ... ]) }
Roxen.git/server/base_server/configuration.pike:210:    CATCH("stopping priority group",    (pri[i] && pri[i]->stop && pri[i]->stop()));    CATCH("stopping the logger",    log_function && lambda(mixed m){    destruct(m);    }(function_object(log_function)));    foreach( registered_urls, string url )    roxen.unregister_url(url);   }    - public string type_from_filename( string file, int|void to, string|void myext ) + string type_from_filename( string file, int|void to, string|void myext )   {    array(string)|string tmp;    if(!types_fun)    return to?({ "application/octet-stream", 0 }):"application/octet-stream";       string ext=myext || Roxen.extension(file);       if(tmp = types_fun(ext))    {    mixed tmp2,nx;
Roxen.git/server/base_server/configuration.pike:348:    array(RoxenModule) d;    RoxenModule p;    if(d=pri[i]->url_modules)    foreach(d, p)    url_module_cache += ({ p->remap_url });    }    }    return url_module_cache;   }    - mapping api_module_cache = ([]); + static mapping api_module_cache = ([]);   mapping api_functions(void|RequestID id)   {    return api_module_cache+([]);   }      array (function) logger_modules(RequestID id)   {    if(!logger_module_cache)    {    int i;
Roxen.git/server/base_server/configuration.pike:769:    invalidate_cache();    foreach(indices(otomod), RoxenModule m)    if (m && m->clear_memory_caches)    if (mixed err = catch( m->clear_memory_caches() ))    report_error("clear_memory_caches() "+    LOC_M(40, "failed for module %O:\n%s\n"),    otomod[m], describe_backtrace(err));   }      // Returns tuple < image, mime-type > - array(string) draw_saturation_bar(int hue,int brightness, int where) + static array(string) draw_saturation_bar(int hue,int brightness, int where)   {    Image.Image bar=Image.Image(30,256);       for(int i=0;i<128;i++)    {    int j = i*2;    bar->line(0,j,29,j,@hsv_to_rgb(hue,255-j,brightness));    bar->line(0,j+1,29,j+1,@hsv_to_rgb(hue,255-j,brightness));    }   
Roxen.git/server/base_server/configuration.pike:1346:    TRACE_LEAVE("Rewrote result.");    res=res2;    } else    TRACE_LEAVE("");    }       id->misc->internal_get = orig_internal_get;    return res;   }    - public array(string) find_dir(string file, RequestID id, void|int(0..1) verbose) + array(string) find_dir(string file, RequestID id, void|int(0..1) verbose)   {    array dir;    TRACE_ENTER(sprintf("List directory %O.", file), 0);       if(file[0] != '/')    file = "/" + file;      #ifdef URL_MODULES   #ifdef THREADS    object key;
Roxen.git/server/base_server/configuration.pike:1466:    {    TRACE_LEAVE(sprintf("Returning list of %d files.", sizeof(dir)));    return dir;    }    TRACE_LEAVE("Returning 'No such directory'.");    return 0;   }      // Stat a virtual file.    - public array(int)|Stat stat_file(string file, RequestID id) + array(int)|Stat stat_file(string file, RequestID id)   {    string loc;    mixed s, tmp;   #ifdef THREADS    object key;   #endif    TRACE_ENTER(sprintf("Stat file %O.", file), 0);       file=replace(file, "//", "/"); // "//" is really "/" here...   
Roxen.git/server/base_server/configuration.pike:1554:    TRACE_LEAVE("");    TRACE_LEAVE("Stat ok.");    return s;    }    TRACE_LEAVE("");    }    }    TRACE_LEAVE("Returned 'no such file'.");   }    - class StringFile( string data, mixed|void _st ) - { -  int offset; -  -  string _sprintf() -  { -  return "StringFile("+strlen(data)+","+offset+")"; -  } -  -  string read(int nbytes) -  { -  if(!nbytes) -  { -  offset = strlen(data); -  return data; -  } -  string d = data[offset..offset+nbytes-1]; -  offset += strlen(d); -  return d; -  } -  -  array stat() -  { -  if( _st ) return (array)_st; -  return ({ 0, strlen(data), time(), time(), time(), 0, 0, 0 }); -  } -  -  void write(mixed ... args) -  { -  throw( ({ "File not open for write\n", backtrace() }) ); -  } -  -  void seek(int to) -  { -  offset = to; -  } - } -  -  +    // this is not as trivial as it sounds. Consider gtext. :-) - public array open_file(string fname, string mode, RequestID id, void|int internal_get) + array open_file(string fname, string mode, RequestID id, void|int internal_get)   {    object oc = id->conf;    string oq = id->not_query;    function funp;    mapping|int(0..1) file;       id->not_query = fname;       foreach(oc->first_modules(), funp)    if(file = funp( id ))
Roxen.git/server/base_server/configuration.pike:1678:    m_delete(file, "data");    }    id->not_query = oq;    return ({ file->file, file });    }    id->not_query = oq;    return ({ 0, (["error":501, "data":"Not implemented." ]) });   }       - public mapping(string:array(mixed)) find_dir_stat(string file, RequestID id) + mapping(string:array(mixed)) find_dir_stat(string file, RequestID id)   {    string loc;    mapping(string:array(mixed)) dir = ([]);    mixed d, tmp;          file=replace(file, "//", "/");       if(file[0] != '/')    file = "/" + file;
Roxen.git/server/base_server/configuration.pike:1804:    }    TRACE_LEAVE("");    }    if(sizeof(dir))    return dir;   }         // Access a virtual file?    - public array access(string file, RequestID id) + array access(string file, RequestID id)   {    string loc;    array s, tmp;       file=replace(file, "//", "/"); // "//" is really "/" here...       // Map location-modules.    foreach(location_modules(id), tmp)    {    loc = tmp[0];
Roxen.git/server/base_server/configuration.pike:1832: Inside #if defined(MODULE_LEVEL_SECURITY)
  #ifdef MODULE_LEVEL_SECURITY    if(check_security(tmp[1], id)) continue;   #endif    if(s=function_object(tmp[1])->access(file[strlen(loc)..], id))    return s;    }    }    return 0;   }    - public string real_file(string file, RequestID id) + string real_file(string file, RequestID id)   //! Return the _real_ filename of a virtual file, if any.   {    string loc;    string s;    array tmp;    file=replace(file, "//", "/"); // "//" is really "/" here...       if(!id) error("No id passed to real_file");       // Map location-modules.
Roxen.git/server/base_server/configuration.pike:2039:    store(q, o->query(), 0, this_object());    invalidate_cache();    o->start(2, this_object());    invalidate_cache();    return 1;   }      RoxenModule reload_module( string modname )   {    RoxenModule old_module = find_module( modname ); -  ModuleInfo mi = roxen->find_module( (modname/"#")[0] ); +  ModuleInfo mi = roxen.find_module( (modname/"#")[0] );    if( !old_module ) return 0;       save_one( old_module );       master()->refresh_inherit( object_program( old_module ) );    master()->refresh( object_program( old_module ), 1 );       catch( disable_module( modname, 1 ) );       RoxenModule nm;
Roxen.git/server/base_server/configuration.pike:2076:    // that count on that the old module object is gone before the new    // is started.    destruct (old_module);    }       call_start_callbacks( nm, mi, modules[ (modname/"#")[0] ] );       return nm;   }    - class ModuleCopies - { -  mapping copies = ([]); -  mixed `[](mixed q ) -  { -  return copies[q]; -  } -  mixed `[]=(mixed q,mixed w ) -  { -  return copies[q]=w; -  } -  mixed _indices() -  { -  return(indices(copies)); -  } -  mixed _values() -  { -  return(values(copies)); -  } -  string _sprintf( ) { return "ModuleCopies()"; } - } -  +    #ifdef THREADS   Thread.Mutex enable_modules_mutex = Thread.Mutex();   #define MODULE_LOCK \    Thread.MutexKey enable_modules_lock = enable_modules_mutex->lock (2)   #else   #define MODULE_LOCK   #endif      static int enable_module_batch_msgs;   
Roxen.git/server/base_server/configuration.pike:2130:    if( datacache ) datacache->flush();       if( sscanf(modname, "%s#%d", modname, id ) != 2 )    while( modules[ modname ] && modules[ modname ][ id ] )    id++;       int start_time = gethrtime();       if( !moduleinfo )    { -  moduleinfo = roxen->find_module( modname ); +  moduleinfo = roxen.find_module( modname );       if (!moduleinfo)    {    report_warning("Failed to load %s. The module probably "    "doesn't exist in the module path.\n", modname);    got_no_delayed_load = -1;    return 0;    }    }   
Roxen.git/server/base_server/configuration.pike:2510:      int disable_module( string modname, int|void nodest )   {    MODULE_LOCK;    RoxenModule me;    int id, pr;    sscanf(modname, "%s#%d", modname, id );       if( datacache ) datacache->flush();    -  ModuleInfo moduleinfo = roxen->find_module( modname ); +  ModuleInfo moduleinfo = roxen.find_module( modname );    mapping module = modules[ modname ];    string descr = moduleinfo->get_name() + (id ? " copy " + (id + 1) : "");       if(!module)    {    report_error("disable_module(): " +    LOC_M(42, "Failed to disable module:\n"    "No module by that name: \"%s\".\n"), modname);    return 0;    }
Roxen.git/server/base_server/configuration.pike:2617:       m_delete( enabled_modules, modname + "#" + id );    forcibly_added[ modname + "#" + id ] = 0;    store( "EnabledModules",enabled_modules, 1, this_object());       if(!nodest)    destruct(me);    return 1;   }    - RoxenModule|string find_module(string name) + RoxenModule find_module(string name)   //! Return the module corresponding to the name (eg "rxmlparse",   //! "rxmlparse#0" or "filesystem#1") or zero, if there was no such   //! module.   {    int id;    sscanf(name, "%s#%d", name, id);    if(modules[name])    return modules[name]->copies[id];    return 0;   }
Roxen.git/server/base_server/configuration.pike:2801:    }       after_init_hooks = ({});       inited = 1;    if (!modules_already_enabled)    report_notice(LOC_S(4, "All modules for %s enabled in %3.1f seconds") +    "\n\n", query_name(), (gethrtime()-start_time)/1000000.0);   }    -  - // Trivial cache (actually, it's more or less identical to the 200+ - // lines of C in HTTPLoop. But it does not have to bother with the - // fact that more than one thread can be active in it at once. Also, - // it does not have to delay free until all current connections using - // the cache entry is done...) - class DataCache - { -  mapping(string:array(string|mapping(string:mixed))) cache = ([]); -  -  int current_size; -  int max_size; -  int max_file_size; -  -  int hits, misses; -  -  void flush() -  { -  current_size = 0; -  cache = ([]); -  } -  -  static void clear_some_cache() -  { -  array q = indices( cache ); -  if(!sizeof(q)) -  { -  current_size=0; -  return; -  } -  for( int i = 0; i<sizeof( q )/10; i++ ) -  expire_entry( q[random(sizeof(q))] ); -  } -  -  void expire_entry( string url ) -  { -  if( cache[ url ] ) -  { -  current_size -= strlen(cache[url][0]); -  m_delete( cache, url ); -  } -  } -  -  void set( string url, string data, mapping meta, int expire ) -  { -  if( strlen( data ) > max_size ) return; -  call_out( expire_entry, expire, url ); -  current_size += strlen( data ); -  cache[url] = ({ data, meta }); -  int n; -  while( (current_size > max_size) && (n++<10)) -  clear_some_cache(); -  } -  -  array(string|mapping(string:mixed)) get( string url ) -  { -  mixed res; -  if( res = cache[ url ] ) -  hits++; -  else -  misses++; -  return res; -  } -  -  void init_from_variables( ) -  { -  max_size = query( "data_cache_size" ) * 1024; -  max_file_size = query( "data_cache_file_max_size" ) * 1024; -  if( max_size < max_file_size ) -  max_size += max_file_size; -  int n; -  while( (current_size > max_size) && (n++<10)) -  clear_some_cache(); -  } -  -  static void create() -  { -  init_from_variables(); -  } - }; -  +    DataCache datacache;    - void create(string config) + static void create(string config)   {    name=config;       // for now only theese two. In the future there might be more variables.    defvar( "data_cache_size", 2048, DLOCALE(274, "Data Cache:Cache size"),    TYPE_INT,    DLOCALE(275, "The size of the data cache used to speed up requests "    "for commonly requested files, in KBytes"));       defvar( "data_cache_file_max_size", 50, DLOCALE(276, "Data Cache:Max file size"),
Roxen.git/server/base_server/configuration.pike:2983:    "</pre>")    ,0, lambda(){ return !query("Log");});       defvar("NoLog", ({ }),    DLOCALE(32, "Logging: No Logging for"), TYPE_STRING_LIST|VAR_MORE,    DLOCALE(33, "Don't log requests from hosts with an IP number which "    "matches any of the patterns in this list. This also affects "    "the access counter log."),    0, lambda(){ return !query("Log");});    -  defvar("Domain", roxen->get_domain(), DLOCALE(34, "Domain"), TYPE_STRING, +  defvar("Domain", roxen.get_domain(), DLOCALE(34, "Domain"), TYPE_STRING,    DLOCALE(35, "The domain name of the server. The domain name is used "    "to generate default URLs, and to generate email addresses."));       defvar("MyWorldLocation", "http://"+gethostname()+"/",    DLOCALE(36, "Primary Server URL"), TYPE_URL,    DLOCALE(37, "This is the main server URL, where your start page is "    "located. Please note that you also have to configure the "    "'URLs' variable."));       defvar("URLs",
Roxen.git/server/base_server/configuration.pike:3136:    if (query("throttle"))    {    throttler=.throttler();    throttler->throttle(query("throttle_fill_rate"),    query("throttle_bucket_depth"),    query("throttle_min_grant"),    query("throttle_max_grant"));    }   }    - int arent_we_throttling_server () { + static int arent_we_throttling_server () {    return !query("throttle");   } - int arent_we_throttling_request() { + static int arent_we_throttling_request() {    return !query("req_throttle");   } -  - string _sprintf( ) - { -  return "Configuration("+name+")"; - } +