ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/lib/cf.pm
(Generate patch)

Comparing deliantra/server/lib/cf.pm (file contents):
Revision 1.106 by root, Sun Dec 31 17:29:22 2006 UTC vs.
Revision 1.109 by root, Sun Dec 31 22:23:12 2006 UTC

15use Coro::Timer; 15use Coro::Timer;
16use Coro::Signal; 16use Coro::Signal;
17use Coro::Semaphore; 17use Coro::Semaphore;
18use Coro::AIO; 18use Coro::AIO;
19 19
20use Digest::MD5;
20use Fcntl; 21use Fcntl;
21use IO::AIO 2.31 (); 22use IO::AIO 2.31 ();
22use YAML::Syck (); 23use YAML::Syck ();
23use Time::HiRes; 24use Time::HiRes;
24 25
49our $RUNTIME; 50our $RUNTIME;
50 51
51our %MAP; # all maps 52our %MAP; # all maps
52our $LINK_MAP; # the special {link} map 53our $LINK_MAP; # the special {link} map
53our $FREEZE; 54our $FREEZE;
55our $RANDOM_MAPS = cf::localdir . "/random";
56our %EXT_CORO;
54 57
55binmode STDOUT; 58binmode STDOUT;
56binmode STDERR; 59binmode STDERR;
57 60
58# read virtual server time, if available 61# read virtual server time, if available
64 67
65mkdir cf::localdir; 68mkdir cf::localdir;
66mkdir cf::localdir . "/" . cf::playerdir; 69mkdir cf::localdir . "/" . cf::playerdir;
67mkdir cf::localdir . "/" . cf::tmpdir; 70mkdir cf::localdir . "/" . cf::tmpdir;
68mkdir cf::localdir . "/" . cf::uniquedir; 71mkdir cf::localdir . "/" . cf::uniquedir;
72mkdir $RANDOM_MAPS;
69 73
70our %EXT_CORO; 74# a special map that is always available
75our $LINK_MAP;
71 76
72############################################################################# 77#############################################################################
73 78
74=head2 GLOBAL VARIABLES 79=head2 GLOBAL VARIABLES
75 80
240 $EXT_CORO{$coro+0} = $coro; 245 $EXT_CORO{$coro+0} = $coro;
241 246
242 $coro 247 $coro
243} 248}
244 249
250sub write_runtime {
251 my $runtime = cf::localdir . "/runtime";
252
253 my $fh = aio_open "$runtime~", O_WRONLY | O_CREAT, 0644
254 or return;
255
256 my $value = $cf::RUNTIME;
257 (aio_write $fh, 0, (length $value), $value, 0) <= 0
258 and return;
259
260 aio_fsync $fh
261 and return;
262
263 close $fh
264 or return;
265
266 aio_rename "$runtime~", $runtime
267 and return;
268
269 1
270}
271
245=back 272=back
246 273
247=cut 274=cut
275
276#############################################################################
277
278package cf::path;
279
280sub new {
281 my ($class, $path, $base) = @_;
282
283 my $self = bless { }, $class;
284
285 if ($path =~ s{^\?random/}{}) {
286 Coro::AIO::aio_load "$cf::RANDOM_MAPS/$path.meta", my $data;
287 $self->{random} = cf::from_json $data;
288 } else {
289 if ($path =~ s{^~([^/]+)?}{}) {
290 $self->{user_rel} = 1;
291
292 if (defined $1) {
293 $self->{user} = $1;
294 } elsif ($base =~ m{^~([^/]+)/}) {
295 $self->{user} = $1;
296 } else {
297 warn "cannot resolve user-relative path without user <$path,$base>\n";
298 }
299 } elsif ($path =~ /^\//) {
300 # already absolute
301 } else {
302 $base =~ s{[^/]+/?$}{};
303 return $class->new ("$base/$path");
304 }
305
306 for ($path) {
307 redo if s{/\.?/}{/};
308 redo if s{/[^/]+/\.\./}{/};
309 }
310 }
311
312 $self->{path} = $path;
313
314 $self
315}
316
317# the name / primary key / in-game path
318sub as_string {
319 my ($self) = @_;
320
321 $self->{user_rel} ? "~$self->{user}$self->{path}"
322 : $self->{random} ? "?random/$self->{path}"
323 : $self->{path}
324}
325
326# the displayed name, this is a one way mapping
327sub visible_name {
328 my ($self) = @_;
329
330# if (my $rmp = $self->{random}) {
331# # todo: be more intelligent about this
332# "?random/$rmp->{origin_map}+$rmp->{origin_x}+$rmp->{origin_y}/$rmp->{dungeon_level}"
333# } else {
334 $self->as_string
335# }
336}
337
338# escape the /'s in the path
339sub _escaped_path {
340 # ∕ is U+2215
341 (my $path = $_[0]{path}) =~ s/\//∕/g;
342 $path
343}
344
345# the original (read-only) location
346sub load_path {
347 my ($self) = @_;
348
349 sprintf "%s/%s/%s", cf::datadir, cf::mapdir, $self->{path}
350}
351
352# the temporary/swap location
353sub save_path {
354 my ($self) = @_;
355
356 $self->{user_rel} ? sprintf "%s/%s/%s/%s", cf::localdir, cf::playerdir, $self->{user}, $self->_escaped_path
357 : $self->{random} ? sprintf "%s/%s", $RANDOM_MAPS, $self->{path}
358 : sprintf "%s/%s/%s", cf::localdir, cf::tmpdir, $self->_escaped_path
359}
360
361# the unique path, might be eq to save_path
362sub uniq_path {
363 my ($self) = @_;
364
365 $self->{user_rel} || $self->{random}
366 ? undef
367 : sprintf "%s/%s/%s", cf::localdir, cf::uniquedir, $self->_escaped_path
368}
369
370# return random map parameters, or undef
371sub random_map_params {
372 my ($self) = @_;
373
374 $self->{random}
375}
376
377# this is somewhat ugly, but style maps do need special treatment
378sub is_style_map {
379 $_[0]{path} =~ m{^/styles/}
380}
381
382package cf;
248 383
249############################################################################# 384#############################################################################
250 385
251=head2 ATTACHABLE OBJECTS 386=head2 ATTACHABLE OBJECTS
252 387
1272 local $/; 1407 local $/;
1273 *CFG = YAML::Syck::Load <$fh>; 1408 *CFG = YAML::Syck::Load <$fh>;
1274} 1409}
1275 1410
1276sub main { 1411sub main {
1412 # we must not ever block the main coroutine
1413 local $Coro::idle = sub {
1414 Carp::cluck "FATAL: Coro::idle was called, major BUG\n";#d#
1415 (Coro::unblock_sub {
1416 Event::one_event;
1417 })->();
1418 };
1419
1277 cfg_load; 1420 cfg_load;
1278 db_load; 1421 db_load;
1279 load_extensions; 1422 load_extensions;
1280 Event::loop; 1423 Event::loop;
1281} 1424}
1282 1425
1283############################################################################# 1426#############################################################################
1284# initialisation 1427# initialisation
1285 1428
1286sub _perl_reload() { 1429sub perl_reload() {
1287 # can/must only be called in main 1430 # can/must only be called in main
1288 if ($Coro::current != $Coro::main) { 1431 if ($Coro::current != $Coro::main) {
1289 warn "can only reload from main coroutine\n"; 1432 warn "can only reload from main coroutine\n";
1290 return; 1433 return;
1291 } 1434 }
1373 } 1516 }
1374 1517
1375 warn "reloaded successfully"; 1518 warn "reloaded successfully";
1376}; 1519};
1377 1520
1378sub perl_reload() { 1521#############################################################################
1379 _perl_reload; 1522
1523unless ($LINK_MAP) {
1524 $LINK_MAP = cf::map::new;
1525
1526 $LINK_MAP->width (41);
1527 $LINK_MAP->height (41);
1528 $LINK_MAP->alloc;
1529 $LINK_MAP->path ("{link}");
1530 $LINK_MAP->{path} = bless { path => "{link}" }, "cf::path";
1531 $LINK_MAP->in_memory (MAP_IN_MEMORY);
1380} 1532}
1381 1533
1382register "<global>", __PACKAGE__; 1534register "<global>", __PACKAGE__;
1383 1535
1384register_command "perl-reload" => sub { 1536register_command "perl-reload" => sub {
1385 my ($who, $arg) = @_; 1537 my ($who, $arg) = @_;
1386 1538
1387 if ($who->flag (FLAG_WIZ)) { 1539 if ($who->flag (FLAG_WIZ)) {
1388 $who->message ("reloading..."); 1540 $who->message ("start of reload.");
1389 _perl_reload; 1541 perl_reload;
1542 $who->message ("end of reload.");
1390 } 1543 }
1391}; 1544};
1392 1545
1393unshift @INC, $LIBDIR; 1546unshift @INC, $LIBDIR;
1394 1547
1413 }, 1566 },
1414); 1567);
1415 1568
1416IO::AIO::max_poll_time $TICK * 0.2; 1569IO::AIO::max_poll_time $TICK * 0.2;
1417 1570
1571Event->io (
1418Event->io (fd => IO::AIO::poll_fileno, 1572 fd => IO::AIO::poll_fileno,
1419 poll => 'r', 1573 poll => 'r',
1420 prio => 5, 1574 prio => 5,
1421 data => WF_AUTOCANCEL, 1575 data => WF_AUTOCANCEL,
1422 cb => \&IO::AIO::poll_cb); 1576 cb => \&IO::AIO::poll_cb,
1577);
1423 1578
1424# we must not ever block the main coroutine 1579Event->timer (
1425$Coro::idle = sub { 1580 data => WF_AUTOCANCEL,
1426 #Carp::cluck "FATAL: Coro::idle was called, major BUG\n";#d# 1581 after => 0,
1427 warn "FATAL: Coro::idle was called, major BUG\n"; 1582 interval => 10,
1583 cb => sub {
1428 (Coro::unblock_sub { 1584 (Coro::unblock_sub {
1429 Event::one_event; 1585 write_runtime
1586 or warn "ERROR: unable to write runtime file: $!";
1430 })->(); 1587 })->();
1431}; 1588 },
1589);
1432 1590
14331 15911
1434 1592

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines