Roxen.git/
server/
base_server/
roxen.pike
Branch:
Tag:
Non-build tags
All tags
No tags
1999-05-18
1999-05-18 03:55:09 by Per Hedbor <ph@opera.com>
69a869f74a2d7167ef4780ce926189f5d18f1427 (
241
lines) (+
237
/-
4
)
[
Show
|
Annotate
]
Branch:
5.2
Added ImageCache
Rev: server/base_server/roxen.pike:1.279
1:
/*
-
* $Id: roxen.pike,v 1.
278
1999/05/
17
06
:
45
:
06
neotron
Exp $
+
* $Id: roxen.pike,v 1.
279
1999/05/
18
03
:
55
:
09
per
Exp $
* * The Roxen Challenger main program. *
7:
*/ // ABS and suicide systems contributed freely by Francesco Chemolli
-
constant cvs_version="$Id: roxen.pike,v 1.
278
1999/05/
17
06
:
45
:
06
neotron
Exp $";
+
constant cvs_version="$Id: roxen.pike,v 1.
279
1999/05/
18
03
:
55
:
09
per
Exp $";
object backend_thread; object argcache;
1881:
int syslog_disabled() { return QUERY(LogA)!="syslog"; } private int ident_disabled_p() { return QUERY(default_ident); }
+
class ImageCache
+
{
+
string name;
+
string dir;
+
function draw_function;
+
mapping data_cache = ([]); // not normally used.
+
mapping meta_cache = ([]);
-
+
+
static mapping meta_cache_insert( string i, mapping what )
+
{
+
return meta_cache[i] = what;
+
}
+
+
static string data_cache_insert( string i, string what )
+
{
+
return data_cache[i] = what;
+
}
+
+
+
static void draw( string name, RequestID id )
+
{
+
mapping args = argcache->lookup( name );
+
mixed reply = draw_function( args, id );
+
+
mapping meta;
+
string data;
+
+
+
if( objectp( reply ) || (mappingp(reply) && reply->img) )
+
{
+
int quant = (int)args->quant;
+
string format = lower_case(args->format || "gif");
+
string dither = args->dither;
+
Image.Colortable ct;
+
object alpha;
+
+
if( format == "jpg" ) format = "jpeg";
+
+
if(mappingp(reply))
+
{
+
alpha = reply->alpha;
+
reply = reply->img;
+
}
+
if( quant || (format=="gif") )
+
{
+
ct = Image.Colortable( reply, quant||id->misc->defquant||16 );
+
if( dither )
+
if( ct[dither] )
+
ct[dither]();
+
else
+
ct->ordered();
+
}
+
+
if( !Image[upper_case( format )] || !Image[upper_case( format )]->encode )
+
error("Image format "+format+" unknown\n");
+
+
mapping enc_args = ([]);
+
if( ct )
+
enc_args->colortable = ct;
+
if( alpha )
+
enc_args->alpha = alpha;
+
+
switch(format)
+
{
+
case "gif":
+
data = Image.GIF.encode_trans( reply, ct, alpha );
+
break;
+
case "png":
+
if( ct )
+
enc_args->palette = ct;
+
m_delete( enc_args, "colortable" );
+
default:
+
data = Image[upper_case( format )]->encode( reply, enc_args );
+
}
+
+
meta = ([
+
"xsize":reply->xsize(),
+
"ysize":reply->ysize(),
+
"type":"image/"+format,
+
]);
+
}
+
else if( mappingp(reply) )
+
{
+
meta = reply->meta;
+
data = reply->data;
+
if( !meta || !data )
+
error("Invalid reply mapping.\n"
+
"Should be ([ \"meta\": ([metadata]), \"data\":\"data\" ])\n");
+
}
+
store_meta( name, meta );
+
store_data( name, data );
+
}
+
+
+
static void store_meta( string id, mapping meta )
+
{
+
meta_cache_insert( id, meta );
+
+
string data = encode_value( meta );
+
Stdio.File f = Stdio.File( dir+id+".i", "wct" );
+
if(!f)
+
{
+
report_error( "Failed to open image cache persistant cache file "+
+
dir+id+".i: "+strerror( errno() )+ "\n" );
+
return;
+
}
+
f->write( data );
+
}
+
+
static void store_data( string id, string data )
+
{
+
Stdio.File f = Stdio.File( dir+id, "wct" );
+
if(!f)
+
{
+
data_cache_insert( id, data );
+
report_error( "Failed to open image cache persistant cache file "+
+
dir+id+": "+strerror( errno() )+ "\n" );
+
return;
+
}
+
f->write( data );
+
}
+
+
+
static mapping restore_meta( string id )
+
{
+
Stdio.File f;
+
if( meta_cache[ id ] )
+
return meta_cache[ id ];
+
f = Stdio.File( );
+
if( !f->open(dir+id+".i", "r" ) )
+
return 0;
+
return meta_cache_insert( id, decode_value( f->read() ) );
+
}
+
+
static mapping restore( string id )
+
{
+
string|object(Stdio.File) f;
+
mapping m;
+
if( data_cache[ id ] )
+
f = data_cache[ id ];
+
else
+
f = Stdio.File( );
+
+
if(!f->open(dir+id, "r" ))
+
return 0;
+
+
m = restore_meta( id );
+
+
if(!m)
+
return 0;
+
+
if( stringp( f ) )
+
return http_string_answer( f, m->type||("image/gif") );
+
return roxenp()->http_file_answer( f, m->type||("image/gif") );
+
}
+
+
+
string data( string|mapping args, RequestID id, int|void nodraw )
+
{
+
string na = store( args, id );
+
mixed res;
+
+
if(!( res = restore( na )) )
+
{
+
if(nodraw)
+
return 0;
+
draw( na, id );
+
res = restore( na );
+
}
+
if( res->file )
+
return res->file->read();
+
return res->data;
+
}
+
+
mapping http_file_answer( string|mapping data, RequestID id, int|void nodraw )
+
{
+
string na = store( data,id );
+
mixed res;
+
+
if(!( res = restore( na )) )
+
{
+
if(nodraw)
+
return 0;
+
draw( na, id );
+
res = restore( na );
+
}
+
return res;
+
}
+
+
mapping metadata( string|mapping data, RequestID id, int|void nodraw )
+
{
+
string na = store( data,id );
+
if(!restore_meta( na ))
+
{
+
if(nodraw)
+
return 0;
+
draw( na, id );
+
return restore_meta( na );
+
}
+
}
+
+
string store( string|mapping data, RequestID id )
+
{
+
string ci;
+
if( mappingp( data ) )
+
ci = argcache->store( data );
+
else
+
ci = data;
+
return ci;
+
}
+
+
void set_draw_function( function to )
+
{
+
draw_function = to;
+
}
+
+
void create( string id, function draw_func, string|void d )
+
{
+
if(!d) d = roxenp()->QUERY(argument_cache_dir);
+
if( d[-1] != '/' )
+
d+="/";
+
d += id+"/";
+
+
mkdirhier( d+"foo");
+
+
dir = d;
+
name = id;
+
draw_function = draw_func;
+
}
+
}
+
+
class ArgCache { static string name;
2271:
{ string data; object file, img;
-
-
if(id->misc->_load_image_called < 5) {
+
if(id->misc->_load_image_called < 5)
+
{
// We were recursing very badly with the demo module here... id->misc->_load_image_called++; if(!(data=id->conf->try_get_file(f, id))) {