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.456 by root, Tue Sep 30 04:00:35 2008 UTC vs.
Revision 1.457 by root, Wed Oct 1 05:50:19 2008 UTC

130our $JITTER; # average jitter 130our $JITTER; # average jitter
131our $TICK_START; # for load detecting purposes 131our $TICK_START; # for load detecting purposes
132 132
133our @POST_INIT; 133our @POST_INIT;
134 134
135our $REATTACH_ON_RELOAD; # ste to true to force object reattach on reload (slow)
136
135binmode STDOUT; 137binmode STDOUT;
136binmode STDERR; 138binmode STDERR;
137 139
138# read virtual server time, if available 140# read virtual server time, if available
139unless ($RUNTIME || !-e $RUNTIMEFILE) { 141unless ($RUNTIME || !-e $RUNTIMEFILE) {
1189 } 1191 }
1190 1192
1191 aio_rename "$filename~", $filename; 1193 aio_rename "$filename~", $filename;
1192 1194
1193 $filename =~ s%/[^/]+$%%; 1195 $filename =~ s%/[^/]+$%%;
1194 aio_pathsync $filename; 1196 aio_pathsync $filename if $cf::USE_FSYNC;
1195 } else { 1197 } else {
1196 warn "FATAL: $filename~: $!\n"; 1198 warn "FATAL: $filename~: $!\n";
1197 } 1199 }
1198 } else { 1200 } else {
1199 aio_unlink $filename; 1201 aio_unlink $filename;
1292 my ($name, $cb) = @_; 1294 my ($name, $cb) = @_;
1293 1295
1294 $EXTICMD{$name} = $cb; 1296 $EXTICMD{$name} = $cb;
1295} 1297}
1296 1298
1299use File::Glob ();
1300
1297cf::player->attach ( 1301cf::player->attach (
1298 on_command => sub { 1302 on_command => sub {
1299 my ($pl, $name, $params) = @_; 1303 my ($pl, $name, $params) = @_;
1300 1304
1301 my $cb = $COMMAND{$name} 1305 my $cb = $COMMAND{$name}
1332 } 1336 }
1333 1337
1334 cf::override; 1338 cf::override;
1335 }, 1339 },
1336); 1340);
1341
1342# "readahead" all extensions
1343sub cache_extensions {
1344 my $grp = IO::AIO::aio_group;
1345
1346 add $grp IO::AIO::aio_readdir $LIBDIR, sub {
1347 for (grep /\.ext$/, @{$_[0]}) {
1348 add $grp IO::AIO::aio_load "$LIBDIR/$_", my $data;
1349 }
1350 };
1351
1352 $grp
1353}
1337 1354
1338sub load_extensions { 1355sub load_extensions {
1339 cf::sync_job { 1356 cf::sync_job {
1340 my %todo; 1357 my %todo;
1341 1358
3558} 3575}
3559 3576
3560sub emergency_save() { 3577sub emergency_save() {
3561 my $freeze_guard = cf::freeze_mainloop; 3578 my $freeze_guard = cf::freeze_mainloop;
3562 3579
3563 warn "enter emergency perl save\n"; 3580 warn "emergency_perl_save: enter\n";
3564 3581
3565 cf::sync_job { 3582 cf::sync_job {
3583 # this is a trade-off: we want to be very quick here, so
3584 # save all maps without fsync, and later call a global sync
3585 # (which in turn might be very very slow)
3586 local $USE_FSYNC = 0;
3587
3566 # use a peculiar iteration method to avoid tripping on perl 3588 # use a peculiar iteration method to avoid tripping on perl
3567 # refcount bugs in for. also avoids problems with players 3589 # refcount bugs in for. also avoids problems with players
3568 # and maps saved/destroyed asynchronously. 3590 # and maps saved/destroyed asynchronously.
3569 warn "begin emergency player save\n"; 3591 warn "emergency_perl_save: begin player save\n";
3570 for my $login (keys %cf::PLAYER) { 3592 for my $login (keys %cf::PLAYER) {
3571 my $pl = $cf::PLAYER{$login} or next; 3593 my $pl = $cf::PLAYER{$login} or next;
3572 $pl->valid or next; 3594 $pl->valid or next;
3573 delete $pl->{unclean_save}; # not strictly necessary, but cannot hurt 3595 delete $pl->{unclean_save}; # not strictly necessary, but cannot hurt
3574 $pl->save; 3596 $pl->save;
3575 } 3597 }
3576 warn "end emergency player save\n"; 3598 warn "emergency_perl_save: end player save\n";
3577 3599
3578 warn "begin emergency map save\n"; 3600 warn "emergency_perl_save: begin map save\n";
3579 for my $path (keys %cf::MAP) { 3601 for my $path (keys %cf::MAP) {
3580 my $map = $cf::MAP{$path} or next; 3602 my $map = $cf::MAP{$path} or next;
3581 $map->valid or next; 3603 $map->valid or next;
3582 $map->save; 3604 $map->save;
3583 } 3605 }
3584 warn "end emergency map save\n"; 3606 warn "emergency_perl_save: end map save\n";
3585 3607
3586 warn "begin emergency database checkpoint\n"; 3608 warn "emergency_perl_save: begin database checkpoint\n";
3587 BDB::db_env_txn_checkpoint $DB_ENV; 3609 BDB::db_env_txn_checkpoint $DB_ENV;
3588 warn "end emergency database checkpoint\n"; 3610 warn "emergency_perl_save: end database checkpoint\n";
3589 3611
3590 warn "begin write uuid\n"; 3612 warn "emergency_perl_save: begin write uuid\n";
3591 write_uuid_sync 1; 3613 write_uuid_sync 1;
3592 warn "end write uuid\n"; 3614 warn "emergency_perl_save: end write uuid\n";
3593 }; 3615 };
3594 3616
3617 warn "emergency_perl_save: starting sync()\n";
3618 IO::AIO::aio_sync sub {
3619 warn "emergency_perl_save: finished sync()\n";
3620 };
3621
3595 warn "leave emergency perl save\n"; 3622 warn "emergency_perl_save: leave\n";
3596} 3623}
3597 3624
3598sub post_cleanup { 3625sub post_cleanup {
3599 my ($make_core) = @_; 3626 my ($make_core) = @_;
3600 3627
3637 warn "can only reload from main coroutine"; 3664 warn "can only reload from main coroutine";
3638 return; 3665 return;
3639 } 3666 }
3640 3667
3641 return if $RELOAD++; 3668 return if $RELOAD++;
3669
3670 my $t1 = EV::time;
3642 3671
3643 while ($RELOAD) { 3672 while ($RELOAD) {
3644 warn "reloading..."; 3673 warn "reloading...";
3645 3674
3646 warn "entering sync_job"; 3675 warn "entering sync_job";
3725 cf::reload_config; 3754 cf::reload_config;
3726 3755
3727 warn "loading extensions"; 3756 warn "loading extensions";
3728 cf::load_extensions; 3757 cf::load_extensions;
3729 3758
3759 if ($REATTACH_ON_RELOAD) {
3730 warn "reattaching attachments to objects/players"; 3760 warn "reattaching attachments to objects/players";
3731 _global_reattach; # objects, sockets 3761 _global_reattach; # objects, sockets
3732 warn "reattaching attachments to maps"; 3762 warn "reattaching attachments to maps";
3733 reattach $_ for values %MAP; 3763 reattach $_ for values %MAP;
3734 warn "reattaching attachments to players"; 3764 warn "reattaching attachments to players";
3735 reattach $_ for values %PLAYER; 3765 reattach $_ for values %PLAYER;
3766 }
3736 3767
3737 warn "running post_load"; 3768 warn "running post_init jobs";
3738 (pop @POST_INIT)->(1) while @POST_INIT; 3769 (pop @POST_INIT)->(1) while @POST_INIT;
3739 3770
3740 warn "leaving sync_job"; 3771 warn "leaving sync_job";
3741 3772
3742 1 3773 1
3746 }; 3777 };
3747 3778
3748 warn "reloaded"; 3779 warn "reloaded";
3749 --$RELOAD; 3780 --$RELOAD;
3750 } 3781 }
3782
3783 $t1 = EV::time - $t1;
3784 warn "reload completed in ${t1}s\n";
3751}; 3785};
3752 3786
3753our $RELOAD_WATCHER; # used only during reload 3787our $RELOAD_WATCHER; # used only during reload
3754 3788
3755sub reload_perl() { 3789sub reload_perl() {
3756 # doing reload synchronously and two reloads happen back-to-back, 3790 # doing reload synchronously and two reloads happen back-to-back,
3757 # coro crashes during coro_state_free->destroy here. 3791 # coro crashes during coro_state_free->destroy here.
3758 3792
3793 $RELOAD_WATCHER ||= cf::async {
3794 Coro::AIO::aio_wait cache_extensions;
3795
3759 $RELOAD_WATCHER ||= EV::timer $TICK * 1.5, 0, sub { 3796 $RELOAD_WATCHER = EV::timer $TICK * 1.5, 0, sub {
3760 do_reload_perl; 3797 do_reload_perl;
3761 undef $RELOAD_WATCHER; 3798 undef $RELOAD_WATCHER;
3799 };
3762 }; 3800 };
3763} 3801}
3764 3802
3765register_command "reload" => sub { 3803register_command "reload" => sub {
3766 my ($who, $arg) = @_; 3804 my ($who, $arg) = @_;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines