2000-08-13
2000-08-13 13:54:22 by Per Hedbor <ph@opera.com>
-
5f6dae46463c32a0ddd4cf73ea696aaadd107f7f
(655 lines)
(+337/-318)
[
Show
| Annotate
]
Branch: 5.2
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( )
{