--- deliantra/server/lib/cf.pm 2007/09/13 16:16:01 1.371 +++ deliantra/server/lib/cf.pm 2007/10/12 19:13:26 1.385 @@ -6,13 +6,13 @@ use Symbol; use List::Util; use Socket; -use Storable; use Event; use Opcode; use Safe; use Safe::Hole; +use Storable (); -use Coro 3.64 (); +use Coro 4.1 (); use Coro::State; use Coro::Handle; use Coro::Event; @@ -29,7 +29,7 @@ use Digest::MD5; use Fcntl; use YAML::Syck (); -use IO::AIO 2.32 (); +use IO::AIO 2.51 (); use Time::HiRes; use Compress::LZF; use Digest::MD5 (); @@ -356,6 +356,8 @@ $SLOT_QUEUE->cancel if $SLOT_QUEUE; $SLOT_QUEUE = Coro::async { + $Coro::current->desc ("timeslot manager"); + my $signal = new Coro::Signal; while () { @@ -373,7 +375,7 @@ } if (@SLOT_QUEUE) { - # we do not use wait_For_tick() as it returns immediately when tick is inactive + # we do not use wait_for_tick() as it returns immediately when tick is inactive push @cf::WAIT_FOR_TICK, $signal; $signal->wait; } else { @@ -427,6 +429,8 @@ # this is the main coro, too bad, we have to block # till the operation succeeds, freezing the server :/ + LOG llevError, Carp::longmess "sync job";#d# + # TODO: use suspend/resume instead # (but this is cancel-safe) my $freeze_guard = freeze_mainloop; @@ -435,6 +439,7 @@ my @res; (async { + $Coro::current->desc ("sync job coro"); @res = eval { $job->() }; warn $@ if $@; undef $busy; @@ -968,11 +973,16 @@ sub _can_merge { my ($ob1, $ob2) = @_; - local $Storable::canonical = 1; - my $fob1 = Storable::freeze $ob1; - my $fob2 = Storable::freeze $ob2; + return 1;#d# - $fob1 eq $fob2 + #todo#d# kill yourself and do some recursive checking manually without storable + sync_job { + my $guard = Coro::Storable::guard; + local $Storable::canonical = 1; + my $fob1 = Storable::freeze $ob1; + my $fob2 = Storable::freeze $ob2; + $fob1 eq $fob2 + } } sub reattach { @@ -1028,8 +1038,6 @@ sub object_freezer_save { my ($filename, $rdata, $objs) = @_; - my $guard = cf::lock_acquire "io"; - sync_job { if (length $$rdata) { utf8::decode (my $decname = $filename); @@ -1045,7 +1053,7 @@ if (@$objs) { if (my $fh = aio_open "$filename.pst~", O_WRONLY | O_CREAT, 0600) { chmod SAVE_MODE, $fh; - my $data = Storable::nfreeze { version => 1, objs => $objs }; + my $data = Coro::Storable::blocking_nfreeze { version => 1, objs => $objs }; aio_write $fh, 0, (length $data), $data, 0; aio_fsync $fh if $cf::USE_FSYNC; close $fh; @@ -1064,8 +1072,6 @@ aio_unlink "$filename.pst"; } }; - - undef $guard; } sub object_freezer_as_string { @@ -1081,8 +1087,6 @@ my ($data, $av); - my $guard = cf::lock_acquire "io"; - (aio_load $filename, $data) >= 0 or return; @@ -1090,8 +1094,9 @@ (aio_load "$filename.pst", $av) >= 0 or return; - undef $guard; - $av = eval { (Storable::thaw $av)->{objs} }; + my $st = eval { Coro::Storable::thaw $av } + || eval { my $guard = Coro::Storable::guard; Storable::thaw $av }; #d# compatibility, remove + $av = $st->{objs}; } utf8::decode (my $decname = $filename); @@ -1355,7 +1360,6 @@ my $f = new_from_file cf::object::thawer path $login or return; - $f->next; my $pl = cf::player::load_pl $f or return; local $cf::PLAYER_LOADING{$login} = $pl; @@ -2046,6 +2050,8 @@ $MAP_PREFETCH{$path} |= $load; $MAP_PREFETCHER ||= cf::async { + $Coro::current->{desc} = "map prefetcher"; + while (%MAP_PREFETCH) { while (my ($k, $v) = each %MAP_PREFETCH) { if (my $map = find $k) { @@ -2081,6 +2087,7 @@ local $self->{last_access} = $self->last_access;#d# cf::async { + $Coro::current->{desc} = "map player save"; $_->contr->save for $self->players; }; @@ -2277,10 +2284,7 @@ sub deref { my ($ref) = @_; - # temporary compatibility#TODO#remove - $ref =~ s{^<}{player/<}; - - if ($ref =~ m{^player\/(<1\.\d+>)/(.*)$}) { + if ($ref =~ m{^player\/(<1\.[0-9a-f]+>)/(.*)$}) { my ($uuid, $name) = ($1, $2); my $pl = $cf::PLAYER_LOADING{$name} || cf::player::find $name or return; @@ -2461,6 +2465,8 @@ $self->enter_link; (async { + $Coro::current->{desc} = "player::goto $path $x $y"; + # *tag paths override both path and x|y if ($path =~ /^\*(.*)$/) { if (my @obs = grep $_->map, ext::map_tags::find $1) { @@ -2587,6 +2593,8 @@ if $exit->flag (FLAG_DAMNED); (async { + $Coro::current->{desc} = "enter_exit $slaying $hp $sp"; + $self->deactivate_recursive; # just to be sure unless (eval { $self->goto ($slaying, $hp, $sp); @@ -2633,17 +2641,23 @@ our %CHANNEL = ( "c/identify" => { - id => "identify", + id => "infobox", title => "Identify", reply => undef, tooltip => "Items recently identified", }, "c/examine" => { - id => "examine", + id => "infobox", title => "Examine", reply => undef, tooltip => "Signs and other items you examined", }, + "c/lookat" => { + id => "infobox", + title => "Look", + reply => undef, + tooltip => "What you saw there", + }, ); sub cf::client::send_msg { @@ -2654,9 +2668,15 @@ $color &= cf::NDI_CLIENT_MASK; # just in case... # check predefined channels, for the benefit of C - $channel = $CHANNEL{$channel} if $CHANNEL{$channel}; + if ($CHANNEL{$channel}) { + $channel = $CHANNEL{$channel}; + + $self->ext_msg (channel_info => $channel) + if $self->can_msg; + + $channel = $channel->{id}; - if (ref $channel) { + } elsif (ref $channel) { # send meta info to client, if not yet sent unless (exists $self->{channel}{$channel->{id}}) { $self->{channel}{$channel->{id}} = $channel; @@ -2883,7 +2903,7 @@ The following functions and methods are available within a safe environment: cf::object - contr pay_amount pay_player map x y force_find force_add + contr pay_amount pay_player map x y force_find force_add destroy insert remove name archname title slaying race decrease_ob_nr cf::object::player @@ -2900,7 +2920,7 @@ for ( ["cf::object" => qw(contr pay_amount pay_player map force_find force_add x y insert remove inv name archname title slaying race - decrease_ob_nr)], + decrease_ob_nr destroy)], ["cf::object::player" => qw(player)], ["cf::player" => qw(peaceful)], ["cf::map" => qw(trigger)], @@ -3185,6 +3205,7 @@ local $Coro::idle = sub { Carp::cluck "FATAL: Coro::idle was called, major BUG, use cf::sync_job!\n";#d# (async { + $Coro::current->{desc} = "IDLE BUG HANDLER"; Event::one_event; })->prio (Coro::PRIO_MAX); }; @@ -3266,6 +3287,7 @@ for my $login (keys %cf::PLAYER) { my $pl = $cf::PLAYER{$login} or next; $pl->valid or next; + delete $pl->{unclean_save}; # not strictly necessary, but cannot hurt $pl->save; } warn "end emergency player save\n"; @@ -3438,7 +3460,10 @@ if ($who->flag (FLAG_WIZ)) { $who->message ("reloading server."); - async { reload_perl }; + async { + $Coro::current->{desc} = "perl_reload"; + reload_perl; + }; } }; @@ -3490,6 +3515,7 @@ if ($NOW >= $NEXT_RUNTIME_WRITE) { $NEXT_RUNTIME_WRITE = $NOW + 10; Coro::async_pool { + $Coro::current->{desc} = "runtime saver"; write_runtime or warn "ERROR: unable to write runtime file: $!"; }; @@ -3609,7 +3635,7 @@ data => WF_AUTOCANCEL, fd => IO::AIO::poll_fileno, poll => 'r', - prio => 6, + prio => 0, cb => \&IO::AIO::poll_cb, ); } @@ -3625,6 +3651,8 @@ if ($_log_backtrace < 2) { ++$_log_backtrace; async { + $Coro::current->{desc} = "abt $msg"; + my @bt = fork_call { @addr = map { sprintf "%x", $_ } @addr; my $self = (-f "/proc/$$/exe") ? "/proc/$$/exe" : $^X;