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.416 by root, Fri Apr 11 13:59:06 2008 UTC vs.
Revision 1.426 by root, Thu Apr 24 04:40:31 2008 UTC

427 } 427 }
428 } 428 }
429}; 429};
430 430
431sub get_slot($;$$) { 431sub get_slot($;$$) {
432 return if tick_inhibit || $Coro::current == $Coro::main;
433
432 my ($time, $pri, $name) = @_; 434 my ($time, $pri, $name) = @_;
433 435
434 $time = $TICK * .6 if $time > $TICK * .6; 436 $time = $TICK * .6 if $time > $TICK * .6;
435 my $sig = new Coro::Signal; 437 my $sig = new Coro::Signal;
436 438
1473 1475
1474 return if $pl->{deny_save}; 1476 return if $pl->{deny_save};
1475 1477
1476 aio_mkdir playerdir $pl, 0770; 1478 aio_mkdir playerdir $pl, 0770;
1477 $pl->{last_save} = $cf::RUNTIME; 1479 $pl->{last_save} = $cf::RUNTIME;
1480
1481 cf::get_slot 0.01;
1478 1482
1479 $pl->save_pl ($path); 1483 $pl->save_pl ($path);
1480 cf::cede_to_tick; 1484 cf::cede_to_tick;
1481} 1485}
1482 1486
1775our $MAX_RESET = 3600; 1779our $MAX_RESET = 3600;
1776our $DEFAULT_RESET = 3000; 1780our $DEFAULT_RESET = 3000;
1777 1781
1778sub generate_random_map { 1782sub generate_random_map {
1779 my ($self, $rmp) = @_; 1783 my ($self, $rmp) = @_;
1784
1785 my $lock = cf::lock_acquire "generate_random_map"; # the random map generator is NOT reentrant ATM
1786
1780 # mit "rum" bekleckern, nicht 1787 # mit "rum" bekleckern, nicht
1781 $self->_create_random_map ( 1788 $self->_create_random_map (
1782 $rmp->{wallstyle}, $rmp->{wall_name}, $rmp->{floorstyle}, $rmp->{monsterstyle}, 1789 $rmp->{wallstyle}, $rmp->{wall_name}, $rmp->{floorstyle}, $rmp->{monsterstyle},
1783 $rmp->{treasurestyle}, $rmp->{layoutstyle}, $rmp->{doorstyle}, $rmp->{decorstyle}, 1790 $rmp->{treasurestyle}, $rmp->{layoutstyle}, $rmp->{doorstyle}, $rmp->{decorstyle},
1784 $rmp->{origin_map}, $rmp->{final_map}, $rmp->{exitstyle}, $rmp->{this_map}, 1791 $rmp->{origin_map}, $rmp->{final_map}, $rmp->{exitstyle}, $rmp->{this_map},
1906 1913
1907# the temporary/swap location 1914# the temporary/swap location
1908sub save_path { 1915sub save_path {
1909 my ($self) = @_; 1916 my ($self) = @_;
1910 1917
1911 (my $path = $_[0]{path}) =~ s/\//$PATH_SEP/g; 1918 (my $path = $_[0]{path}) =~ s/\//$PATH_SEP/go;
1912 "$TMPDIR/$path.map" 1919 "$TMPDIR/$path.map"
1913} 1920}
1914 1921
1915# the unique path, undef == no special unique path 1922# the unique path, undef == no special unique path
1916sub uniq_path { 1923sub uniq_path {
1917 my ($self) = @_; 1924 my ($self) = @_;
1918 1925
1919 (my $path = $_[0]{path}) =~ s/\//$PATH_SEP/g; 1926 (my $path = $_[0]{path}) =~ s/\//$PATH_SEP/go;
1920 "$UNIQUEDIR/$path" 1927 "$UNIQUEDIR/$path"
1921} 1928}
1922 1929
1923# and all this just because we cannot iterate over 1930# and all this just because we cannot iterate over
1924# all maps in C++... 1931# all maps in C++...
2110 } 2117 }
2111 2118
2112 $self->{last_save} = $cf::RUNTIME; 2119 $self->{last_save} = $cf::RUNTIME;
2113 $self->last_access ($cf::RUNTIME); 2120 $self->last_access ($cf::RUNTIME);
2114 2121
2115 $self->in_memory (cf::MAP_IN_MEMORY); 2122 $self->in_memory (cf::MAP_ACTIVE);
2116 } 2123 }
2117 2124
2118 $self->post_load; 2125 $self->post_load;
2119} 2126}
2120 2127
2178 my ($path, $origin, $load) = @_; 2185 my ($path, $origin, $load) = @_;
2179 2186
2180 $path = normalise $path, $origin && $origin->{path}; 2187 $path = normalise $path, $origin && $origin->{path};
2181 2188
2182 if (my $map = $cf::MAP{$path}) { 2189 if (my $map = $cf::MAP{$path}) {
2183 return $map if !$load || $map->in_memory == cf::MAP_IN_MEMORY; 2190 return $map if !$load || $map->in_memory == cf::MAP_ACTIVE;
2184 } 2191 }
2185 2192
2186 $MAP_PREFETCH{$path} |= $load; 2193 $MAP_PREFETCH{$path} |= $load;
2187 2194
2188 $MAP_PREFETCHER ||= cf::async { 2195 $MAP_PREFETCHER ||= cf::async {
2225 cf::async { 2232 cf::async {
2226 $Coro::current->{desc} = "map player save"; 2233 $Coro::current->{desc} = "map player save";
2227 $_->contr->save for $self->players; 2234 $_->contr->save for $self->players;
2228 }; 2235 };
2229 2236
2237 cf::get_slot 0.02;
2238
2230 if ($uniq) { 2239 if ($uniq) {
2231 $self->_save_objects ($save, cf::IO_HEADER | cf::IO_OBJECTS); 2240 $self->_save_objects ($save, cf::IO_HEADER | cf::IO_OBJECTS);
2232 $self->_save_objects ($uniq, cf::IO_UNIQUES); 2241 $self->_save_objects ($uniq, cf::IO_UNIQUES);
2233 } else { 2242 } else {
2234 $self->_save_objects ($save, cf::IO_HEADER | cf::IO_OBJECTS | cf::IO_UNIQUES); 2243 $self->_save_objects ($save, cf::IO_HEADER | cf::IO_OBJECTS | cf::IO_UNIQUES);
2242 $self->save; 2251 $self->save;
2243 2252
2244 my $lock = cf::lock_acquire "map_data:$self->{path}"; 2253 my $lock = cf::lock_acquire "map_data:$self->{path}";
2245 2254
2246 return if $self->players; 2255 return if $self->players;
2247 return if $self->in_memory != cf::MAP_IN_MEMORY; 2256 return if $self->in_memory != cf::MAP_ACTIVE;
2248 return if $self->{deny_save}; 2257 return if $self->{deny_save};
2249 2258
2250 $self->in_memory (cf::MAP_SWAPPED); 2259 $self->in_memory (cf::MAP_SWAPPED);
2251 2260
2252 $self->deactivate; 2261 $self->deactivate;
2370 2379
2371sub unique_maps() { 2380sub unique_maps() {
2372 [ 2381 [
2373 map { 2382 map {
2374 utf8::decode $_; 2383 utf8::decode $_;
2375 /\.map$/ 2384 s/\.map$//; # TODO future compatibility hack
2385 /\.pst$/ || !/^$PATH_SEP/o # TODO unique maps apparebntly lack the .map suffix :/
2386 ? ()
2376 ? normalise $_ 2387 : normalise $_
2377 : ()
2378 } @{ aio_readdir $UNIQUEDIR or [] } 2388 } @{ aio_readdir $UNIQUEDIR or [] }
2379 ] 2389 ]
2380} 2390}
2381 2391
2382=back 2392=back
2389 2399
2390=over 4 2400=over 4
2391 2401
2392=item $ob->inv_recursive 2402=item $ob->inv_recursive
2393 2403
2394Returns the inventory of the object _and_ their inventories, recursively. 2404Returns the inventory of the object I<and> their inventories, recursively,
2405but I<not> the object itself.
2395 2406
2396=cut 2407=cut
2397 2408
2398sub inv_recursive_; 2409sub inv_recursive_;
2399sub inv_recursive_ { 2410sub inv_recursive_ {
2404 inv_recursive_ inv $_[0] 2415 inv_recursive_ inv $_[0]
2405} 2416}
2406 2417
2407=item $ref = $ob->ref 2418=item $ref = $ob->ref
2408 2419
2409creates and returns a persistent reference to an objetc that can be stored as a string. 2420Creates and returns a persistent reference to an object that can be stored as a string.
2410 2421
2411=item $ob = cf::object::deref ($refstring) 2422=item $ob = cf::object::deref ($refstring)
2412 2423
2413returns the objetc referenced by refstring. may return undef when it cnanot find the object, 2424returns the objetc referenced by refstring. may return undef when it cnanot find the object,
2414even if the object actually exists. May block. 2425even if the object actually exists. May block.
2688 $rmp->{origin_y} = $exit->y; 2699 $rmp->{origin_y} = $exit->y;
2689 } 2700 }
2690 2701
2691 $rmp->{random_seed} ||= $exit->random_seed; 2702 $rmp->{random_seed} ||= $exit->random_seed;
2692 2703
2693 my $data = cf::encode_json $rmp; 2704 my $data = JSON::XS->new->utf8->pretty->canonical->encode ($rmp);
2694 my $md5 = Digest::MD5::md5_hex $data; 2705 my $md5 = Digest::MD5::md5_hex $data;
2695 my $meta = "$RANDOMDIR/$md5.meta"; 2706 my $meta = "$RANDOMDIR/$md5.meta";
2696 2707
2697 if (my $fh = aio_open "$meta~", O_WRONLY | O_CREAT, 0666) { 2708 if (my $fh = aio_open "$meta~", O_WRONLY | O_CREAT, 0666) {
2698 aio_write $fh, 0, (length $data), $data, 0; 2709 aio_write $fh, 0, (length $data), $data, 0;
2821 id => "infobox", 2832 id => "infobox",
2822 title => "Map Info", 2833 title => "Map Info",
2823 reply => undef, 2834 reply => undef,
2824 tooltip => "Information related to the maps", 2835 tooltip => "Information related to the maps",
2825 }, 2836 },
2837 "c/party" => {
2838 id => "party",
2839 title => "Party",
2840 reply => "gsay ",
2841 tooltip => "Messages and chat related to your party",
2842 },
2826); 2843);
2827 2844
2828sub cf::client::send_msg { 2845sub cf::client::send_msg {
2829 my ($self, $channel, $msg, $color, @extra) = @_; 2846 my ($self, $channel, $msg, $color, @extra) = @_;
2830 2847
3067 3084
3068The following functions and methods are available within a safe environment: 3085The following functions and methods are available within a safe environment:
3069 3086
3070 cf::object 3087 cf::object
3071 contr pay_amount pay_player map x y force_find force_add destroy 3088 contr pay_amount pay_player map x y force_find force_add destroy
3072 insert remove name archname title slaying race decrease_ob_nr 3089 insert remove name archname title slaying race decrease split
3073 3090
3074 cf::object::player 3091 cf::object::player
3075 player 3092 player
3076 3093
3077 cf::player 3094 cf::player
3083=cut 3100=cut
3084 3101
3085for ( 3102for (
3086 ["cf::object" => qw(contr pay_amount pay_player map force_find force_add x y 3103 ["cf::object" => qw(contr pay_amount pay_player map force_find force_add x y
3087 insert remove inv name archname title slaying race 3104 insert remove inv name archname title slaying race
3088 decrease_ob_nr destroy)], 3105 decrease split destroy)],
3089 ["cf::object::player" => qw(player)], 3106 ["cf::object::player" => qw(player)],
3090 ["cf::player" => qw(peaceful)], 3107 ["cf::player" => qw(peaceful)],
3091 ["cf::map" => qw(trigger)], 3108 ["cf::map" => qw(trigger)],
3092) { 3109) {
3093 no strict 'refs'; 3110 no strict 'refs';
3301 while (my ($k, $v) = each %$want) { 3318 while (my ($k, $v) = each %$want) {
3302 $ns->fx_want ($k, $v); 3319 $ns->fx_want ($k, $v);
3303 } 3320 }
3304}; 3321};
3305 3322
3323sub load_resource_file($) {
3324 my $guard = lock_acquire "load_resource_file";
3325
3326 my $status = load_resource_file_ $_[0];
3327 get_slot 0.1, 100;
3328 cf::arch::commit_load;
3329
3330 $status
3331}
3332
3306sub reload_regions { 3333sub reload_regions {
3307 # HACK to clear player env face cache, we need some signal framework 3334 # HACK to clear player env face cache, we need some signal framework
3308 # for this (global event?) 3335 # for this (global event?)
3309 %ext::player_env::MUSIC_FACE_CACHE = (); 3336 %ext::player_env::MUSIC_FACE_CACHE = ();
3310 3337
3323} 3350}
3324 3351
3325sub reload_archetypes { 3352sub reload_archetypes {
3326 load_resource_file "$DATADIR/archetypes" 3353 load_resource_file "$DATADIR/archetypes"
3327 or die "unable to load archetypes\n"; 3354 or die "unable to load archetypes\n";
3328 #d# NEED to laod twice to resolve forward references
3329 # this really needs to be done in an extra post-pass
3330 # (which needs to be synchronous, so solve it differently)
3331 load_resource_file "$DATADIR/archetypes"
3332 or die "unable to load archetypes\n";
3333} 3355}
3334 3356
3335sub reload_treasures { 3357sub reload_treasures {
3336 load_resource_file "$DATADIR/treasures" 3358 load_resource_file "$DATADIR/treasures"
3337 or die "unable to load treasurelists\n"; 3359 or die "unable to load treasurelists\n";
3338} 3360}
3339 3361
3340sub reload_resources { 3362sub reload_resources {
3341 warn "reloading resource files...\n"; 3363 warn "reloading resource files...\n";
3342 3364
3365 reload_facedata;
3366 reload_archetypes;
3343 reload_regions; 3367 reload_regions;
3344 reload_facedata;
3345 #reload_archetypes;#d#
3346 reload_archetypes;
3347 reload_treasures; 3368 reload_treasures;
3348 3369
3349 warn "finished reloading resource files\n"; 3370 warn "finished reloading resource files\n";
3350} 3371}
3351 3372
3352sub init { 3373sub init {
3374 my $guard = freeze_mainloop;
3375
3353 reload_resources; 3376 reload_resources;
3354} 3377}
3355 3378
3356sub reload_config { 3379sub reload_config {
3357 open my $fh, "<:utf8", "$CONFDIR/config" 3380 open my $fh, "<:utf8", "$CONFDIR/config"
3382 $Coro::current->{desc} = "IDLE BUG HANDLER"; 3405 $Coro::current->{desc} = "IDLE BUG HANDLER";
3383 EV::loop EV::LOOP_ONESHOT; 3406 EV::loop EV::LOOP_ONESHOT;
3384 })->prio (Coro::PRIO_MAX); 3407 })->prio (Coro::PRIO_MAX);
3385 }; 3408 };
3386 3409
3410 {
3411 my $guard = freeze_mainloop;
3387 reload_config; 3412 reload_config;
3388 db_init; 3413 db_init;
3389 load_extensions; 3414 load_extensions;
3390 3415
3391 $Coro::current->prio (Coro::PRIO_MAX); # give the main loop max. priority 3416 $Coro::current->prio (Coro::PRIO_MAX); # give the main loop max. priority
3392 evthread_start IO::AIO::poll_fileno; 3417 evthread_start IO::AIO::poll_fileno;
3418 }
3419
3393 EV::loop; 3420 EV::loop;
3394} 3421}
3395 3422
3396############################################################################# 3423#############################################################################
3397# initialisation and cleanup 3424# initialisation and cleanup
3404 cf::cleanup "SIG$signal"; 3431 cf::cleanup "SIG$signal";
3405 }; 3432 };
3406 } 3433 }
3407} 3434}
3408 3435
3409sub write_runtime { 3436sub write_runtime_sync {
3410 my $runtime = "$LOCALDIR/runtime"; 3437 my $runtime = "$LOCALDIR/runtime";
3411 3438
3412 # first touch the runtime file to show we are still running: 3439 # first touch the runtime file to show we are still running:
3413 # the fsync below can take a very very long time. 3440 # the fsync below can take a very very long time.
3414 3441
3542 warn "reloading..."; 3569 warn "reloading...";
3543 3570
3544 warn "entering sync_job"; 3571 warn "entering sync_job";
3545 3572
3546 cf::sync_job { 3573 cf::sync_job {
3547 cf::write_runtime; # external watchdog should not bark 3574 cf::write_runtime_sync; # external watchdog should not bark
3548 cf::emergency_save; 3575 cf::emergency_save;
3549 cf::write_runtime; # external watchdog should not bark 3576 cf::write_runtime_sync; # external watchdog should not bark
3550 3577
3551 warn "syncing database to disk"; 3578 warn "syncing database to disk";
3552 BDB::db_env_txn_checkpoint $DB_ENV; 3579 BDB::db_env_txn_checkpoint $DB_ENV;
3553 3580
3554 # if anything goes wrong in here, we should simply crash as we already saved 3581 # if anything goes wrong in here, we should simply crash as we already saved
3679 3706
3680our @WAIT_FOR_TICK; 3707our @WAIT_FOR_TICK;
3681our @WAIT_FOR_TICK_BEGIN; 3708our @WAIT_FOR_TICK_BEGIN;
3682 3709
3683sub wait_for_tick { 3710sub wait_for_tick {
3684 return if tick_inhibit;
3685 return if $Coro::current == $Coro::main; 3711 return if tick_inhibit || $Coro::current == $Coro::main;
3686 3712
3687 my $signal = new Coro::Signal; 3713 my $signal = new Coro::Signal;
3688 push @WAIT_FOR_TICK, $signal; 3714 push @WAIT_FOR_TICK, $signal;
3689 $signal->wait; 3715 $signal->wait;
3690} 3716}
3691 3717
3692sub wait_for_tick_begin { 3718sub wait_for_tick_begin {
3693 return if tick_inhibit;
3694 return if $Coro::current == $Coro::main; 3719 return if tick_inhibit || $Coro::current == $Coro::main;
3695 3720
3696 my $signal = new Coro::Signal; 3721 my $signal = new Coro::Signal;
3697 push @WAIT_FOR_TICK_BEGIN, $signal; 3722 push @WAIT_FOR_TICK_BEGIN, $signal;
3698 $signal->wait; 3723 $signal->wait;
3699} 3724}
3709 3734
3710 if ($NOW >= $NEXT_RUNTIME_WRITE) { 3735 if ($NOW >= $NEXT_RUNTIME_WRITE) {
3711 $NEXT_RUNTIME_WRITE = List::Util::max $NEXT_RUNTIME_WRITE + 10, $NOW + 5.; 3736 $NEXT_RUNTIME_WRITE = List::Util::max $NEXT_RUNTIME_WRITE + 10, $NOW + 5.;
3712 Coro::async_pool { 3737 Coro::async_pool {
3713 $Coro::current->{desc} = "runtime saver"; 3738 $Coro::current->{desc} = "runtime saver";
3714 write_runtime 3739 write_runtime_sync
3715 or warn "ERROR: unable to write runtime file: $!"; 3740 or warn "ERROR: unable to write runtime file: $!";
3716 }; 3741 };
3717 } 3742 }
3718 3743
3719 if (my $sig = shift @WAIT_FOR_TICK_BEGIN) { 3744 if (my $sig = shift @WAIT_FOR_TICK_BEGIN) {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines