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.356 by root, Tue Sep 4 05:43:21 2007 UTC vs.
Revision 1.362 by root, Mon Sep 10 12:44:06 2007 UTC

187 $msg .= "\n" 187 $msg .= "\n"
188 unless $msg =~ /\n$/; 188 unless $msg =~ /\n$/;
189 189
190 $msg =~ s/([\x00-\x08\x0b-\x1f])/sprintf "\\x%02x", ord $1/ge; 190 $msg =~ s/([\x00-\x08\x0b-\x1f])/sprintf "\\x%02x", ord $1/ge;
191 191
192 utf8::encode $msg;
193 LOG llevError, $msg; 192 LOG llevError, $msg;
194 }; 193 };
195} 194}
196 195
197@safe::cf::global::ISA = @cf::global::ISA = 'cf::attachable'; 196@safe::cf::global::ISA = @cf::global::ISA = 'cf::attachable';
285Return true if the lock is currently active, i.e. somebody has locked it. 284Return true if the lock is currently active, i.e. somebody has locked it.
286 285
287=cut 286=cut
288 287
289our %LOCK; 288our %LOCK;
289our %LOCKER;#d#
290 290
291sub lock_wait($) { 291sub lock_wait($) {
292 my ($key) = @_; 292 my ($key) = @_;
293
294 if ($LOCKER{$key} == $Coro::current) {#d#
295 Carp::cluck "lock_wait($key) for already-acquired lock";#d#
296 return;#d#
297 }#d#
293 298
294 # wait for lock, if any 299 # wait for lock, if any
295 while ($LOCK{$key}) { 300 while ($LOCK{$key}) {
296 push @{ $LOCK{$key} }, $Coro::current; 301 push @{ $LOCK{$key} }, $Coro::current;
297 Coro::schedule; 302 Coro::schedule;
303 308
304 # wait, to be sure we are not locked 309 # wait, to be sure we are not locked
305 lock_wait $key; 310 lock_wait $key;
306 311
307 $LOCK{$key} = []; 312 $LOCK{$key} = [];
313 $LOCKER{$key} = $Coro::current;#d#
308 314
309 Coro::guard { 315 Coro::guard {
316 delete $LOCKER{$key};#d#
310 # wake up all waiters, to be on the safe side 317 # wake up all waiters, to be on the safe side
311 $_->ready for @{ delete $LOCK{$key} }; 318 $_->ready for @{ delete $LOCK{$key} };
312 } 319 }
313} 320}
314 321
1009 1016
1010 my $guard = cf::lock_acquire "io"; 1017 my $guard = cf::lock_acquire "io";
1011 1018
1012 sync_job { 1019 sync_job {
1013 if (length $$rdata) { 1020 if (length $$rdata) {
1021 utf8::decode (my $decname = $filename);
1014 warn sprintf "saving %s (%d,%d)\n", 1022 warn sprintf "saving %s (%d,%d)\n",
1015 $filename, length $$rdata, scalar @$objs; 1023 $decname, length $$rdata, scalar @$objs;
1016 1024
1017 if (my $fh = aio_open "$filename~", O_WRONLY | O_CREAT, 0600) { 1025 if (my $fh = aio_open "$filename~", O_WRONLY | O_CREAT, 0600) {
1018 chmod SAVE_MODE, $fh; 1026 chmod SAVE_MODE, $fh;
1019 aio_write $fh, 0, (length $$rdata), $$rdata, 0; 1027 aio_write $fh, 0, (length $$rdata), $$rdata, 0;
1020 aio_fsync $fh if $cf::USE_FSYNC; 1028 aio_fsync $fh if $cf::USE_FSYNC;
1070 1078
1071 undef $guard; 1079 undef $guard;
1072 $av = eval { (Storable::thaw $av)->{objs} }; 1080 $av = eval { (Storable::thaw $av)->{objs} };
1073 } 1081 }
1074 1082
1083 utf8::decode (my $decname = $filename);
1075 warn sprintf "loading %s (%d)\n", 1084 warn sprintf "loading %s (%d,%d)\n",
1076 $filename, length $data, scalar @{$av || []}; 1085 $decname, length $data, scalar @{$av || []};
1077 1086
1078 ($data, $av) 1087 ($data, $av)
1079} 1088}
1080 1089
1081=head2 COMMAND CALLBACKS 1090=head2 COMMAND CALLBACKS
1268use Coro::AIO; 1277use Coro::AIO;
1269 1278
1270=head3 cf::player 1279=head3 cf::player
1271 1280
1272=over 4 1281=over 4
1282
1283=item cf::player::num_playing
1284
1285Returns the official number of playing players, as per the Crossfire metaserver rules.
1286
1287=cut
1288
1289sub num_playing {
1290 scalar grep
1291 $_->ob->map
1292 && !$_->hidden
1293 && !$_->ob->flag (cf::FLAG_WIZ),
1294 cf::player::list
1295}
1273 1296
1274=item cf::player::find $login 1297=item cf::player::find $login
1275 1298
1276Returns the given player object, loading it if necessary (might block). 1299Returns the given player object, loading it if necessary (might block).
1277 1300
1841sub find { 1864sub find {
1842 my ($path, $origin) = @_; 1865 my ($path, $origin) = @_;
1843 1866
1844 $path = normalise $path, $origin && $origin->path; 1867 $path = normalise $path, $origin && $origin->path;
1845 1868
1869 cf::lock_wait "map_data:$path";#d#remove
1846 cf::lock_wait "map_find:$path"; 1870 cf::lock_wait "map_find:$path";
1847 1871
1848 $cf::MAP{$path} || do { 1872 $cf::MAP{$path} || do {
1849 my $guard = cf::lock_acquire "map_find:$path"; 1873 my $guard1 = cf::lock_acquire "map_find:$path";
1874 my $guard2 = cf::lock_acquire "map_data:$path"; # just for the fun of it
1875
1850 my $map = new_from_path cf::map $path 1876 my $map = new_from_path cf::map $path
1851 or return; 1877 or return;
1852 1878
1853 $map->{last_save} = $cf::RUNTIME; 1879 $map->{last_save} = $cf::RUNTIME;
1854 1880
1856 or return; 1882 or return;
1857 1883
1858 if ($map->should_reset) {#d#TODO# disabled, crashy (locking issue?) 1884 if ($map->should_reset) {#d#TODO# disabled, crashy (locking issue?)
1859 # doing this can freeze the server in a sync job, obviously 1885 # doing this can freeze the server in a sync job, obviously
1860 #$cf::WAIT_FOR_TICK->wait; 1886 #$cf::WAIT_FOR_TICK->wait;
1887 undef $guard1;
1888 undef $guard2;
1861 $map->reset; 1889 $map->reset;
1862 undef $guard;
1863 return find $path; 1890 return find $path;
1864 } 1891 }
1865 1892
1866 $cf::MAP{$path} = $map 1893 $cf::MAP{$path} = $map
1867 } 1894 }
1876 local $self->{deny_reset} = 1; # loading can take a long time 1903 local $self->{deny_reset} = 1; # loading can take a long time
1877 1904
1878 my $path = $self->{path}; 1905 my $path = $self->{path};
1879 1906
1880 { 1907 {
1881 my $guard1 = cf::lock_acquire "map_data:$path"; 1908 my $guard = cf::lock_acquire "map_data:$path";
1882 my $guard2 = cf::lock_acquire "map_load:$path";
1883 1909
1910 return unless $self->valid;
1884 return if $self->in_memory != cf::MAP_SWAPPED; 1911 return unless $self->in_memory == cf::MAP_SWAPPED;
1885 1912
1886 $self->in_memory (cf::MAP_LOADING); 1913 $self->in_memory (cf::MAP_LOADING);
1887 1914
1888 $self->alloc; 1915 $self->alloc;
1889 1916
2061 2088
2062 return if $self->players; 2089 return if $self->players;
2063 return if $self->in_memory != cf::MAP_IN_MEMORY; 2090 return if $self->in_memory != cf::MAP_IN_MEMORY;
2064 return if $self->{deny_save}; 2091 return if $self->{deny_save};
2065 2092
2093 $self->in_memory (cf::MAP_SWAPPED);
2094
2095 $self->deactivate;
2096 $_->clear_links_to ($self) for values %cf::MAP;
2066 $self->clear; 2097 $self->clear;
2067 $self->in_memory (cf::MAP_SWAPPED);
2068} 2098}
2069 2099
2070sub reset_at { 2100sub reset_at {
2071 my ($self) = @_; 2101 my ($self) = @_;
2072 2102
2104 if $uniq; 2134 if $uniq;
2105 } 2135 }
2106 2136
2107 delete $cf::MAP{$self->path}; 2137 delete $cf::MAP{$self->path};
2108 2138
2139 $self->deactivate;
2140 $_->clear_links_to ($self) for values %cf::MAP;
2109 $self->clear; 2141 $self->clear;
2110
2111 $_->clear_links_to ($self) for values %cf::MAP;
2112 2142
2113 $self->unlink_save; 2143 $self->unlink_save;
2114 $self->destroy; 2144 $self->destroy;
2115} 2145}
2116 2146

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines