--- deliantra/server/lib/cf.pm 2007/01/14 00:37:14 1.168 +++ deliantra/server/lib/cf.pm 2007/01/14 21:20:51 1.175 @@ -10,7 +10,7 @@ use Safe; use Safe::Hole; -use Coro 3.3 (); +use Coro 3.4 (); use Coro::Event; use Coro::Timer; use Coro::Signal; @@ -505,6 +505,12 @@ my %attachment; +sub cf::attachable::thawer_merge { + # simply override everything except _meta + local $_[0]{_meta}; + %{$_[0]} = %{$_[1]}; +} + sub _attach_cb($$$$) { my ($registry, $event, $prio, $cb) = @_; @@ -686,6 +692,8 @@ # basically do the same as instantiate, without calling instantiate my ($obj) = @_; + bless $obj, ref $obj; # re-bless in case extensions have been reloaded + my $registry = $obj->registry; @$registry = (); @@ -1107,7 +1115,8 @@ use Coro::AIO; use overload - '""' => \&as_string; + '""' => \&as_string, + fallback => 1; our $MAX_RESET = 3600; our $DEFAULT_RESET = 3000; @@ -1144,6 +1153,18 @@ # also paths starting with '/' $EXT_MAP{"cf::map"} = qr{^(?=/)}; +sub thawer_merge { + my ($self, $merge) = @_; + + # we have to keep some variables in memory intact + local $self->{path}; + local $self->{load_path}; + local $self->{deny_save}; + local $self->{deny_reset}; + + $self->SUPER::thawer_merge ($merge); +} + sub normalise { my ($path, $base) = @_; @@ -1249,8 +1270,8 @@ my ($self) = @_; utf8::encode (my $save = $self->save_path); - IO::AIO::aioreq_pri 4; IO::AIO::aio_unlink $save; - IO::AIO::aioreq_pri 4; IO::AIO::aio_unlink "$save.pst"; + IO::AIO::aioreq_pri 4; Coro::AIO::aio_unlink $save; + IO::AIO::aioreq_pri 4; Coro::AIO::aio_unlink "$save.pst"; } sub load_header_from($) { @@ -1321,6 +1342,7 @@ or return; if ($map->should_reset) { + $cf::WAIT_FOR_TICK->wait; $map->reset; undef $guard; $map = find $path @@ -1500,7 +1522,7 @@ my ($self) = @_; # TODO: safety, remove and allow resettable per-player maps - return 1e99 if $self->isa ("ext::map_per_player"); + return 1e99 if $self->isa ("ext::map_per_player");#d# return 1e99 if $self->{deny_reset}; my $time = $self->fixed_resettime ? $self->{instantiate_time} : $self->last_access; @@ -1515,20 +1537,6 @@ $self->reset_at <= $cf::RUNTIME } -sub rename { - my ($self, $new_path) = @_; - - normalise $new_path; - - $self->unlink_save; - - delete $cf::MAP{$self->path}; - $self->{path} = $new_path; $self->path ($self->{path}); - $cf::MAP{$self->path} = $self; - - $self->save; -} - sub reset { my ($self) = @_; @@ -1555,9 +1563,18 @@ sub nuke { my ($self) = @_; + delete $cf::MAP{$self->path}; + + $self->unlink_save; + + bless $self, "cf::map"; + delete $self->{deny_reset}; $self->{deny_save} = 1; $self->reset_timeout (1); - $self->rename ("{nuke}/" . ($nuke_counter++)); + $self->path ($self->{path} = "{nuke}/" . ($nuke_counter++)); + + $cf::MAP{$self->path} = $self; + $self->reset; # polite request, might not happen } @@ -2213,7 +2230,11 @@ # we must not ever block the main coroutine local $Coro::idle = sub { Carp::cluck "FATAL: Coro::idle was called, major BUG, use cf::sync_job!\n";#d# - async { Event::one_event }; + (async { + warn "BP1\n";#d# + Event::one_event; + warn "BP2\n";#d# + })->prio (Coro::PRIO_MAX); }; cfg_load; @@ -2371,13 +2392,21 @@ warn "reloaded"; }; +our $RELOAD_WATCHER; # used only during reload + register_command "reload" => sub { my ($who, $arg) = @_; if ($who->flag (FLAG_WIZ)) { - $who->message ("start of reload."); - reload; - $who->message ("end of reload."); + $who->message ("reloading server."); + + # doing reload synchronously and two reloads happen back-to-back, + # coro crashes during coro_state_free->destroy here. + + $RELOAD_WATCHER ||= Event->timer (after => 0, data => WF_AUTOCANCEL, cb => sub { + reload; + undef $RELOAD_WATCHER; + }); } };