Branch: Tag:

2000-08-13

2000-08-13 13:54:22 by Per Hedbor <ph@opera.com>

Optimizations

Rev: server/base_server/configuration.pike:1.335
Rev: server/base_server/fastpipe.pike:1.6
Rev: server/config_interface/standard/sites/site_content.pike:1.75
Rev: server/protocols/http.pike:1.241

2:   // Modified by Francesco Chemolli to add throttling capabilities.   // Copyright © 1996 - 2000, Roxen IS.    - constant cvs_version = "$Id: http.pike,v 1.240 2000/08/13 04:03:30 per Exp $"; + constant cvs_version = "$Id: http.pike,v 1.241 2000/08/13 13:54:22 per Exp $";   // #define REQUEST_DEBUG   #define MAGIC_ERROR -  + #define RAM_CACHE    -  +    #undef OLD_RXML_COMPAT      #ifdef MAGIC_ERROR
325:    end();    return;    } -  if (!conf || !conf->query("req_throttle")) -  throttle->doit=0; -  if(!pipe) { -  if (throttle->doit || (conf && conf->throttler)) { -  pipe=roxen->slowpipe(); -  } else { -  pipe=roxen->fastpipe(); -  } -  } -  if (throttle->doit) { //we are sure that pipe is really a slowpipe. -  throttle->rate=max(throttle->rate, -  conf->query("req_throttle_min")); //if conf=0 => throttle=0 +  if ( throttle->doit && conf->query("req_throttle") ) +  throttle->doit = 0; +  if( throttle->doit || conf->throttler ) +  pipe=roxen.slowpipe(); +  else +  pipe=roxen.fastpipe(); +  +  if (throttle->doit) +  { +  //we are sure that pipe is really a slowpipe. +  throttle->rate=max(throttle->rate, conf->query("req_throttle_min"));    pipe->throttle(throttle->rate,    (int)(throttle->rate*conf->query("req_throttle_depth_mult")),    0);    THROTTLING_DEBUG("throtting request at "+throttle->rate);    } -  if (conf && conf->throttler) { +  if ( conf->throttler )    pipe->assign_throttler(conf->throttler);   } - } +          void send (string|object what, int|void len)   {    REQUEST_WERR(sprintf("send(%O, %O)\n", what, len)); -  +     if(!what) return;    if(!pipe) setup_pipe(); -  if(!pipe) return; +     if(stringp(what)) pipe->write(what);    else pipe->input(what,len);   }    - void start_sender (function callback, mixed ... args) + void start_sender( )   { -  if (pipe) { +  if (pipe) +  {    MARK_FD("HTTP really handled, piping "+not_query);   #ifdef FD_DEBUG    call_out(timer, 30, _time(1)); // Update FD with time...   #endif -  // FIXME: What about args? -  pipe->set_done_callback( callback ); -  pipe->output(my_fd); +  pipe->set_done_callback( do_log ); +  pipe->output( my_fd );    } else {    MARK_FD("HTTP really handled, pipe done"); -  callback(@args); +  do_log();    }   }   
771:       REQUEST_WERR(sprintf("After simplify_path == not_query:%O", not_query));    -  request_headers = ([]); // FIXME: KEEP-ALIVE? +        misc->pref_languages=PrefLanguages();      #if constant(Roxen.HeaderParser) -  +  request_headers = header_mapping;    foreach( (array)header_mapping, [string linename,contents] )   #else -  +  request_headers = ([]);    if(sizeof(s)) {    // sscanf(s, "%s\r\n\r\n%s", s, data);    // s = replace(s, "\n\t", ", ") - "\r";
794: Inside #if !constant(Roxen.HeaderParser)
  #if !constant(Roxen.HeaderParser)    linename=lower_case(linename);    REQUEST_WERR(sprintf("lower-case :%s", linename)); - #endif -  +     request_headers[linename] = contents; -  if( arrayp( contents ) ) contents *= ", "; + #endif    switch (linename)    {    case "content-length":
1012:   #endif    REQUEST_WERR("HTTP: parse_got(): after header scan");   #ifndef DISABLE_SUPPORTS -  if(!client) { +  if( !sizeof( supports ) ) +  { +  if( !client ) +  {    client = ({ "unknown" });    array s_and_v = find_supports_and_vars("", supports);    supports = s_and_v[0];    client_var = s_and_v[1];    } -  else { +  else +  {    if( !client_var->Fullname )    client_var->Fullname = "unknown";    client_var->fullname=lower_case(client_var->Fullname); -  array s_and_v = find_supports_and_vars(client_var->fullname, supports, client_var); +  array s_and_v=find_supports_and_vars(client_var->fullname, supports, client_var);    supports = s_and_v[0];    client_var = s_and_v[1];    } -  +  }    if ( client_var->charset && client_var->charset != "iso-8859-1" )    {    set_output_charset( client_var->charset );
1076: Inside #if defined(REQUEST_DEBUG)
  #ifdef REQUEST_DEBUG    if (my_fd) MARK_FD("my_fd in HTTP disconnected?");   #endif -  if(do_not_disconnect)return; +  if(do_not_disconnect) +  return;    destruct();   }      void end(string|void s, int|void keepit)   { -  pipe = 0; +    #ifdef PROFILE -  if(conf) -  { +     float elapsed = SECHR(HRTIME()-req_time);    string nid =   #ifdef FILE_PROFILE
1100:    p[0]++;    p[1] += elapsed;    if(elapsed > p[2]) p[2]=elapsed; -  } +    #endif    -  TIMER("end[1]"); -  - #ifdef KEEP_ALIVE -  if(keepit && !file->raw +  if(keepit +  && !file->raw    && (misc->connection == "keep-alive" ||    (prot == "HTTP/1.1" && misc->connection != "close"))    && my_fd)
1115: Inside #if defined(KEEP_ALIVE)
   object o = object_program(this_object())(0, 0, 0);    o->remoteaddr = remoteaddr;    o->supports = supports; +  o->client_var = client_var;    o->host = host; -  o->client = client; +     o->conf = conf; -  +  o->pipe = pipe;    MARK_FD("HTTP kept alive"); -  object fd = my_fd; -  my_fd=0; -  if(s) leftovers += s; -  o->chain(fd,port_obj,leftovers); -  TIMER("end[2]"); -  disconnect(); +  o->chain( my_fd, port_obj, leftovers ); +  my_fd = 0; +  pipe = 0; +  destruct();    return;    } - #endif +     -  +  pipe = 0;    if(objectp(my_fd))    {    MARK_FD("HTTP closed"); -  catch { -  my_fd->set_close_callback(0); -  my_fd->set_read_callback(0); -  my_fd->set_blocking(); -  if(s) my_fd->write(s); +  catch +  {    my_fd->close();    destruct(my_fd);    };    my_fd = 0;    } -  TIMER("end[3]"); -  disconnect(); +  destruct();   }      static void do_timeout()
1157:    // This is an easy reason why: It breaks keep-alive totaly.    // It is not a very good idea to do that, since it might be enabled    // per deafult any century now.. -  end(""); +  end();    } else {    // premature call_out... *¤#!"    call_out(do_timeout, 10);
1402:    if(conf)    {    int len; -  if(pipe) file->len = pipe->bytes_sent(); +  if(pipe) +  file->len = pipe->bytes_sent();    if(conf)    {    if(file->len > 0) conf->sent+=file->len;
1647:    array err;    int tmp;    mapping heads; -  string head_string; +  string head_string="";    if (result)    file = result;       REQUEST_WERR(sprintf("HTTP: send_result(%O)", file));    -  +  +  if(!leftovers) +  leftovers = data||""; +  +  if( !file->from_cache ) +  {    if(!mappingp(file))    { -  +  misc->cacheable = 0;    if(misc->error_code)    file = Roxen.http_low_answer(misc->error_code, errors[misc->error]);    else if(err = catch {
1670:    conf->query("ZNoSuchFile"),   #endif    this_object())); -  }) { +  })    INTERNAL_ERROR(err);    } -  } else { +  else +  {    if((file->file == -1) || file->leave_me)    {    if(do_not_disconnect) {
1746:    else    charset = "";    } -  if(stringp(file->data)) +     file->len = strlen(file->data);    } -  heads["Content-type"] = file["type"]+charset; +  heads["Content-Type"] = file["type"]+charset;    heads["Accept-Ranges"] = "bytes";    heads["Server"] = replace(version(), " ", "·");    heads["Connection"] = (misc->connection=="close" ? "close": "keep-alive"); - // heads["Date"] = Roxen.http_date(time), +     -  if(file->encoding) -  heads["Content-Encoding"] = file->encoding; +  if(file->encoding) heads["Content-Encoding"] = file->encoding;       if(!file->error)    file->error=200;
1783:    array ranges = parse_range_header(file->len);    if(ranges) // No incorrect syntax...    { +  misc->cacheable = 0;    if(sizeof(ranges)) // And we have valid ranges as well.    {    file->error = 206; // 206 Partial Content
1831:    head_string += h+": "+heads[h]+"\r\n";    head_string += "\r\n";   #endif -  if(conf) conf->hsent += strlen(head_string); +  conf->hsent += strlen(head_string);    }    }    REQUEST_WERR(sprintf("Sending result for prot:%O, method:%O file:%O\n",    prot, method, file)); -  +     MARK_FD("HTTP handled");    - #ifdef KEEP_ALIVE -  if(!leftovers) leftovers = data||""; - #endif -  +     TIMER("send_result"); -  if(method != "HEAD" && file->error != 304) +  if( (method!="HEAD") && (file->error!=304) )    // No data for these two...    { -  if(my_fd->query_fd && my_fd->query_fd() >= 0 && -  file->len > 0 && file->len < 4000) + #ifdef RAM_CACHE +  if( (misc->cacheable > 0) )    { -  // Ordinary connection, and a short file. +  if( (file->len + strlen( head_string )) < conf->datacache->max_file_size ) +  { +  string data = head_string + (file->file?file->file->read(file->len): +  (file->data[..file->len-1])); +  conf->datacache->set( raw_url, data, +  (["hs":strlen(head_string)]), +  misc->cacheable ); +  file = ([ "data":data ]); +  head_string = ""; +  } +  } + #endif +  if( file->len > 0 && file->len < 4000 ) +  {    // Just do a blocking write().    my_fd->write(head_string +    (file->file?file->file->read(file->len):
1858:    do_log();    return;    } -  if(head_string) -  send(head_string); -  if(file->data && strlen(file->data)) -  send(file->data, file->len); -  if(file->file) -  send(file->file, file->len); -  } else { -  if(head_string) +  if(strlen(head_string)) send(head_string); +  if(file->data && strlen(file->data)) send(file->data, file->len); +  if(file->file) send(file->file, file->len); +  } +  else    { -  if(my_fd->query_fd && my_fd->query_fd() >= 0 && -  file->len > 0 && file->len < 2000) +  if( strlen( head_string ) < 4000)    { -  // Ordinary connection, and a short file. -  // Just do a blocking write(). +     my_fd->write( head_string );    do_log( );    return;    }    send(head_string); -  } +     file->len = 1; // Keep those alive, please...    } -  start_sender(do_log); +     } -  +  else +  { +  if( strlen( file->data ) < 4000 ) +  { +  conf->hsent += file->hsize; +  my_fd->write( file->data ); +  do_log(); +  return; +  } +  else +  { +  conf->hsent += file->hsize; +  send( file->data ); +  } +  } +  start_sender(); + }         // Execute the request
1995:    end();    return;    } +  misc->cacheable = 30; // FIXME: Make configurable.    -  +     mixed q;    if( q = variables->magic_roxen_automatic_charset_variable )    decode_charset_encoding( Roxen.get_client_charset_decoder( q,this_object() ) );
2006:       if( !conf )    { -  if (misc->host) -  { +     // FIXME: port_obj->name & port_obj->default_port are constant    // consider caching them?    conf =
2017:    (":"+port_obj->default_port):"") +    not_query,    this_object()); +  // else +  // { +  // // No host header. +  // // Fallback to using the first configuration bound to this port. +  // conf = port_obj->mu || +  // (port_obj->mu = port_obj->urls[port_obj->sorted_urls[0]]->conf); +  // misc->defaulted = 1; +  // // Support delayed loading in this case too. +  // if (!conf->inited) { +  // conf->enable_all_modules(); +  // } +  // }    } -  else -  { -  // No host header. -  // Fallback to using the first configuration bound to this port. -  conf = port_obj->mu || -  (port_obj->mu = port_obj->urls[port_obj->sorted_urls[0]]->conf); -  misc->defaulted = 1; -  // Support delayed loading in this case too. -  if (!conf->inited) { -  conf->enable_all_modules(); -  } -  } -  } +        TIMER("conf");   
2048:    y = conf->auth_module->auth(y, this_object());    auth = y;    } +  misc->cacheable = 0;    }      
2061:    misc->proxyauth    = conf->auth_module->auth(misc->proxyauth,this_object() );    } +  misc->cacheable = 0;    }       conf->received += strlen(s);
2071:    my_fd->set_close_callback(0);    my_fd->set_read_callback(0);    processed=1; +  + #ifdef RAM_CACHE +  array cv; +  if( misc->cacheable && (cv = conf->datacache->get( raw_url )) ) +  { +  string d = cv[ 0 ]; +  file = ([ "from_cache":1,"len":strlen(d),"hsize":cv[1]->hs,"data":d, ]); +  send_result(); +  return; +  } + #endif +     TIMER("pre_handle"); -  + #ifdef THREADS    roxen.handle(handle_request); -  + #else +  handle_request(); + #endif    })    {    report_error("Internal server error: " + describe_backtrace(err));    my_fd->close(); -  destruct (my_fd); +  destruct( my_fd );    disconnect();    }   }
2145:      static void create(object f, object c, object cc)   { + // trace(1);    if(f)    { -  + // f->set_blocking();    MARK_FD("HTTP connection");    f->set_read_callback(got_data);    f->set_close_callback(end);
2164:   {    my_fd = f;    port_obj = c; -  do_not_disconnect=-1; -  +  processed = 0;    MARK_FD("Kept alive"); -  if(strlen(le)) -  // More to handle already. -  got_data(0,le); +  time = _time(1); +  +  if( strlen( le ) ) +  got_data( 0,le );    else    {    // If no pipelined data is available, call out...    remove_call_out(do_timeout);    call_out(do_timeout, 150); -  time = _time(1); - // string q = f->read( 8192, 1 ); - // if( q ) got_data( 0, q ); +     }    -  if(!my_fd) +  if( !processed )    { -  if(do_not_disconnect == -1) -  { -  do_not_disconnect=0; -  disconnect(); +  f->set_close_callback( end ); +  f->set_read_callback( got_data );    }   } -  else -  { -  if(do_not_disconnect == -1) -  do_not_disconnect = 0; -  if(!processed) -  { -  f->set_close_callback(end); -  f->set_read_callback(got_data); -  } -  } - } +       string _sprintf( )   {