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.448 by root, Fri Sep 19 05:30:23 2008 UTC vs.
Revision 1.456 by root, Tue Sep 30 04:00:35 2008 UTC

66$Storable::canonical = 1; # reduce rsync transfers 66$Storable::canonical = 1; # reduce rsync transfers
67Coro::State::cctx_stacksize 256000; # 1-2MB stack, for deep recursions in maze generator 67Coro::State::cctx_stacksize 256000; # 1-2MB stack, for deep recursions in maze generator
68 68
69$Coro::main->prio (Coro::PRIO_MAX); # run main coroutine ("the server") with very high priority 69$Coro::main->prio (Coro::PRIO_MAX); # run main coroutine ("the server") with very high priority
70 70
71{ 71# make sure c-lzf reinitialises itself
72 # very ugly, but ensure we acquire the storable lock
73
74 sub net_mstore {
75 my $guard = Coro::Storable::guard;
76 &Storable::net_mstore
77 }
78
79 sub mretrieve {
80 my $guard = Coro::Storable::guard;
81 &Storable::mretrieve
82 }
83
84 Compress::LZF::set_serializer "Coro::Storable", "cf::net_mstore", "cf::mretrieve"; 72Compress::LZF::set_serializer "Storable", "Storable::net_mstore", "Storable::mretrieve";
85 Compress::LZF::sfreeze_cr { }; # prime Compress::LZF so it does not use require later 73Compress::LZF::sfreeze_cr { }; # prime Compress::LZF so it does not use require later
86}
87 74
88sub WF_AUTOCANCEL () { 1 } # automatically cancel this watcher on reload 75sub WF_AUTOCANCEL () { 1 } # automatically cancel this watcher on reload
89 76
90our %COMMAND = (); 77our %COMMAND = ();
91our %COMMAND_TIME = (); 78our %COMMAND_TIME = ();
94our %EXTCMD = (); 81our %EXTCMD = ();
95our %EXTICMD = (); 82our %EXTICMD = ();
96our %EXT_CORO = (); # coroutines bound to extensions 83our %EXT_CORO = (); # coroutines bound to extensions
97our %EXT_MAP = (); # pluggable maps 84our %EXT_MAP = (); # pluggable maps
98 85
99our $RELOAD; # number of reloads so far 86our $RELOAD; # number of reloads so far, non-zero while in reload
100our @EVENT; 87our @EVENT;
101 88
102our $CONFDIR = confdir; 89our $CONFDIR = confdir;
103our $DATADIR = datadir; 90our $DATADIR = datadir;
104our $LIBDIR = "$DATADIR/ext"; 91our $LIBDIR = "$DATADIR/ext";
141our $LOAD; # a number between 0 (idle) and 1 (too many objects) 128our $LOAD; # a number between 0 (idle) and 1 (too many objects)
142our $LOADAVG; # same thing, but with alpha-smoothing 129our $LOADAVG; # same thing, but with alpha-smoothing
143our $JITTER; # average jitter 130our $JITTER; # average jitter
144our $TICK_START; # for load detecting purposes 131our $TICK_START; # for load detecting purposes
145 132
133our @POST_INIT;
134
146binmode STDOUT; 135binmode STDOUT;
147binmode STDERR; 136binmode STDERR;
148 137
149# read virtual server time, if available 138# read virtual server time, if available
150unless ($RUNTIME || !-e $RUNTIMEFILE) { 139unless ($RUNTIME || !-e $RUNTIMEFILE) {
318our $json_coder = JSON::XS->new->utf8->max_size (1e6); # accept ~1mb max 307our $json_coder = JSON::XS->new->utf8->max_size (1e6); # accept ~1mb max
319 308
320sub encode_json($) { $json_coder->encode ($_[0]) } 309sub encode_json($) { $json_coder->encode ($_[0]) }
321sub decode_json($) { $json_coder->decode ($_[0]) } 310sub decode_json($) { $json_coder->decode ($_[0]) }
322 311
312=item cf::post_init { BLOCK }
313
314Execute the given codeblock, I<after> all extensions have been (re-)loaded,
315but I<before> the server starts ticking again.
316
317The cdoeblock will have a single boolean argument to indicate whether this
318is a reload or not.
319
320=cut
321
322sub post_init(&) {
323 push @POST_INIT, shift;
324}
325
323=item cf::lock_wait $string 326=item cf::lock_wait $string
324 327
325Wait until the given lock is available. See cf::lock_acquire. 328Wait until the given lock is available. See cf::lock_acquire.
326 329
327=item my $lock = cf::lock_acquire $string 330=item my $lock = cf::lock_acquire $string
354 return;#d# 357 return;#d#
355 }#d# 358 }#d#
356 359
357 # wait for lock, if any 360 # wait for lock, if any
358 while ($LOCK{$key}) { 361 while ($LOCK{$key}) {
362 #local $Coro::current->{desc} = "$Coro::current->{desc} <waiting for lock $key>";
359 push @{ $LOCK{$key} }, $Coro::current; 363 push @{ $LOCK{$key} }, $Coro::current;
360 Coro::schedule; 364 Coro::schedule;
361 } 365 }
362} 366}
363 367
1183 } else { 1187 } else {
1184 aio_unlink "$filename.pst"; 1188 aio_unlink "$filename.pst";
1185 } 1189 }
1186 1190
1187 aio_rename "$filename~", $filename; 1191 aio_rename "$filename~", $filename;
1192
1193 $filename =~ s%/[^/]+$%%;
1194 aio_pathsync $filename;
1188 } else { 1195 } else {
1189 warn "FATAL: $filename~: $!\n"; 1196 warn "FATAL: $filename~: $!\n";
1190 } 1197 }
1191 } else { 1198 } else {
1192 aio_unlink $filename; 1199 aio_unlink $filename;
1457 1464
1458sub exists($) { 1465sub exists($) {
1459 my ($login) = @_; 1466 my ($login) = @_;
1460 1467
1461 $cf::PLAYER{$login} 1468 $cf::PLAYER{$login}
1462 or cf::sync_job { !aio_stat path $login } 1469 or !aio_stat path $login
1463} 1470}
1464 1471
1465sub find($) { 1472sub find($) {
1466 return $cf::PLAYER{$_[0]} || do { 1473 return $cf::PLAYER{$_[0]} || do {
1467 my $login = $_[0]; 1474 my $login = $_[0];
2784 id => "infobox", 2791 id => "infobox",
2785 title => "Body Parts", 2792 title => "Body Parts",
2786 reply => undef, 2793 reply => undef,
2787 tooltip => "Shows which body parts you posess and are available", 2794 tooltip => "Shows which body parts you posess and are available",
2788 }, 2795 },
2796 "c/skills" => {
2797 id => "infobox",
2798 title => "Skills",
2799 reply => undef,
2800 tooltip => "Shows your experience per skill and item power",
2801 },
2789 "c/uptime" => { 2802 "c/uptime" => {
2790 id => "infobox", 2803 id => "infobox",
2791 title => "Uptime", 2804 title => "Uptime",
2792 reply => undef, 2805 reply => undef,
2793 tooltip => "How long the server has been running since last restart", 2806 tooltip => "How long the server has been running since last restart",
3347 reload_treasures; 3360 reload_treasures;
3348 3361
3349 warn "finished reloading resource files\n"; 3362 warn "finished reloading resource files\n";
3350} 3363}
3351 3364
3352sub init {
3353 my $guard = freeze_mainloop;
3354
3355 evthread_start IO::AIO::poll_fileno;
3356
3357 reload_resources;
3358}
3359
3360sub reload_config { 3365sub reload_config {
3361 open my $fh, "<:utf8", "$CONFDIR/config" 3366 open my $fh, "<:utf8", "$CONFDIR/config"
3362 or return; 3367 or return;
3363 3368
3364 local $/; 3369 local $/;
3396 seek $fh, 0, 0; 3401 seek $fh, 0, 0;
3397 print $fh $$; 3402 print $fh $$;
3398} 3403}
3399 3404
3400sub main { 3405sub main {
3401 atomic; 3406 cf::init_globals; # initialise logging
3407
3408 LOG llevInfo, "Welcome to Deliantra, v" . VERSION;
3409 LOG llevInfo, "Copyright (C) 2005-2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team.";
3410 LOG llevInfo, "Copyright (C) 1994 Mark Wedel.";
3411 LOG llevInfo, "Copyright (C) 1992 Frank Tore Johansen.";
3412
3413 cf::init_experience;
3414 cf::init_anim;
3415 cf::init_attackmess;
3416 cf::init_dynamic;
3417 cf::init_block;
3418
3419 $Coro::current->prio (Coro::PRIO_MAX); # give the main loop max. priority
3402 3420
3403 # we must not ever block the main coroutine 3421 # we must not ever block the main coroutine
3404 local $Coro::idle = sub { 3422 local $Coro::idle = sub {
3405 Carp::cluck "FATAL: Coro::idle was called, major BUG, use cf::sync_job!\n";#d# 3423 Carp::cluck "FATAL: Coro::idle was called, major BUG, use cf::sync_job!\n";#d#
3406 (async { 3424 (async {
3407 $Coro::current->{desc} = "IDLE BUG HANDLER"; 3425 $Coro::current->{desc} = "IDLE BUG HANDLER";
3408 EV::loop EV::LOOP_ONESHOT; 3426 EV::loop EV::LOOP_ONESHOT;
3409 })->prio (Coro::PRIO_MAX); 3427 })->prio (Coro::PRIO_MAX);
3410 }; 3428 };
3411 3429
3412 { 3430 evthread_start IO::AIO::poll_fileno;
3413 my $guard = freeze_mainloop; 3431
3432 cf::sync_job {
3433 reload_resources;
3414 reload_config; 3434 reload_config;
3415 db_init; 3435 db_init;
3436
3437 cf::load_settings;
3438 cf::load_materials;
3439 cf::init_uuid;
3440 cf::init_signals;
3441 cf::init_commands;
3442 cf::init_skills;
3443
3444 cf::init_beforeplay;
3445
3446 atomic;
3447
3416 load_extensions; 3448 load_extensions;
3417 3449
3418 $Coro::current->prio (Coro::PRIO_MAX); # give the main loop max. priority
3419 }
3420
3421 utime time, time, $RUNTIMEFILE; 3450 utime time, time, $RUNTIMEFILE;
3422 3451
3423 # no (long-running) fork's whatsoever before this point(!) 3452 # no (long-running) fork's whatsoever before this point(!)
3424 POSIX::close delete $ENV{LOCKUTIL_LOCK_FD} if exists $ENV{LOCKUTIL_LOCK_FD}; 3453 POSIX::close delete $ENV{LOCKUTIL_LOCK_FD} if exists $ENV{LOCKUTIL_LOCK_FD};
3454
3455 (pop @POST_INIT)->(0) while @POST_INIT;
3456 };
3425 3457
3426 EV::loop; 3458 EV::loop;
3427} 3459}
3428 3460
3429############################################################################# 3461#############################################################################
3487 my $uuid = "$LOCALDIR/uuid"; 3519 my $uuid = "$LOCALDIR/uuid";
3488 3520
3489 my $fh = aio_open "$uuid~", O_WRONLY | O_CREAT, 0644 3521 my $fh = aio_open "$uuid~", O_WRONLY | O_CREAT, 0644
3490 or return; 3522 or return;
3491 3523
3492 my $value = uuid_str $uuid_skip + uuid_seq uuid_cur; 3524 my $value = uuid_seq uuid_cur;
3525
3526 unless ($value) {
3527 warn "cowardly refusing to write zero uuid value!\n";
3528 return;
3529 }
3530
3531 my $value = uuid_str $value + $uuid_skip;
3493 $uuid_skip = 0; 3532 $uuid_skip = 0;
3494 3533
3495 (aio_write $fh, 0, (length $value), $value, 0) <= 0 3534 (aio_write $fh, 0, (length $value), $value, 0) <= 0
3496 and return; 3535 and return;
3497 3536
3587 my $leaf_symtab = *{$stem_symtab->{$leaf}}{HASH}; 3626 my $leaf_symtab = *{$stem_symtab->{$leaf}}{HASH};
3588 for my $name (keys %$leaf_symtab) { 3627 for my $name (keys %$leaf_symtab) {
3589 _gv_clear *{"$pkg$name"}; 3628 _gv_clear *{"$pkg$name"};
3590# use PApp::Util; PApp::Util::sv_dump *{"$pkg$name"}; 3629# use PApp::Util; PApp::Util::sv_dump *{"$pkg$name"};
3591 } 3630 }
3592 warn "cleared package #$pkg\n";#d# 3631 warn "cleared package $pkg\n";#d#
3593} 3632}
3594
3595our $RELOAD; # how many times to reload
3596 3633
3597sub do_reload_perl() { 3634sub do_reload_perl() {
3598 # can/must only be called in main 3635 # can/must only be called in main
3599 if ($Coro::current != $Coro::main) { 3636 if ($Coro::current != $Coro::main) {
3600 warn "can only reload from main coroutine"; 3637 warn "can only reload from main coroutine";
3695 warn "reattaching attachments to maps"; 3732 warn "reattaching attachments to maps";
3696 reattach $_ for values %MAP; 3733 reattach $_ for values %MAP;
3697 warn "reattaching attachments to players"; 3734 warn "reattaching attachments to players";
3698 reattach $_ for values %PLAYER; 3735 reattach $_ for values %PLAYER;
3699 3736
3737 warn "running post_load";
3738 (pop @POST_INIT)->(1) while @POST_INIT;
3739
3700 warn "leaving sync_job"; 3740 warn "leaving sync_job";
3701 3741
3702 1 3742 1
3703 } or do { 3743 } or do {
3704 warn $@; 3744 warn $@;
3714 3754
3715sub reload_perl() { 3755sub reload_perl() {
3716 # doing reload synchronously and two reloads happen back-to-back, 3756 # doing reload synchronously and two reloads happen back-to-back,
3717 # coro crashes during coro_state_free->destroy here. 3757 # coro crashes during coro_state_free->destroy here.
3718 3758
3719 $RELOAD_WATCHER ||= EV::timer 0, 0, sub { 3759 $RELOAD_WATCHER ||= EV::timer $TICK * 1.5, 0, sub {
3720 do_reload_perl; 3760 do_reload_perl;
3721 undef $RELOAD_WATCHER; 3761 undef $RELOAD_WATCHER;
3722 }; 3762 };
3723} 3763}
3724 3764

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines