… | |
… | |
130 | our $JITTER; # average jitter |
130 | our $JITTER; # average jitter |
131 | our $TICK_START; # for load detecting purposes |
131 | our $TICK_START; # for load detecting purposes |
132 | |
132 | |
133 | our @POST_INIT; |
133 | our @POST_INIT; |
134 | |
134 | |
|
|
135 | our $REATTACH_ON_RELOAD; # ste to true to force object reattach on reload (slow) |
|
|
136 | |
135 | binmode STDOUT; |
137 | binmode STDOUT; |
136 | binmode STDERR; |
138 | binmode STDERR; |
137 | |
139 | |
138 | # read virtual server time, if available |
140 | # read virtual server time, if available |
139 | unless ($RUNTIME || !-e $RUNTIMEFILE) { |
141 | unless ($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 | |
|
|
1299 | use File::Glob (); |
|
|
1300 | |
1297 | cf::player->attach ( |
1301 | cf::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 |
|
|
1343 | sub 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 | |
1338 | sub load_extensions { |
1355 | sub load_extensions { |
1339 | cf::sync_job { |
1356 | cf::sync_job { |
1340 | my %todo; |
1357 | my %todo; |
1341 | |
1358 | |
… | |
… | |
3558 | } |
3575 | } |
3559 | |
3576 | |
3560 | sub emergency_save() { |
3577 | sub 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 | |
3598 | sub post_cleanup { |
3625 | sub 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 | |
3753 | our $RELOAD_WATCHER; # used only during reload |
3787 | our $RELOAD_WATCHER; # used only during reload |
3754 | |
3788 | |
3755 | sub reload_perl() { |
3789 | sub 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 | |
3765 | register_command "reload" => sub { |
3803 | register_command "reload" => sub { |
3766 | my ($who, $arg) = @_; |
3804 | my ($who, $arg) = @_; |