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.111 by root, Mon Jan 1 12:28:47 2007 UTC vs.
Revision 1.112 by root, Mon Jan 1 13:31:47 2007 UTC

197=cut 197=cut
198 198
199sub sync_job(&) { 199sub sync_job(&) {
200 my ($job) = @_; 200 my ($job) = @_;
201 201
202 my $busy = 1;
203 my @res;
204
205 my $coro = Coro::async {
206 @res = eval { $job->() };
207 warn $@ if $@;
208 undef $busy;
209 };
210
211 if ($Coro::current == $Coro::main) { 202 if ($Coro::current == $Coro::main) {
203 # this is the main coro, too bad, we have to block
204 # till the operation succeeds, freezing the server :/
205
212 # TODO: use suspend/resume instead 206 # TODO: use suspend/resume instead
207 # (but this is cancel-safe)
213 local $FREEZE = 1; 208 local $FREEZE = 1;
209
210 my $busy = 1;
211 my @res;
212
213 (Coro::async {
214 @res = eval { $job->() };
215 warn $@ if $@;
216 undef $busy;
214 $coro->prio (Coro::PRIO_MAX); 217 })->prio (Coro::PRIO_MAX);
218
215 while ($busy) { 219 while ($busy) {
216 Coro::cede_notself; 220 Coro::cede_notself;
217 Event::one_event unless Coro::nready; 221 Event::one_event unless Coro::nready;
218 } 222 }
223
224 wantarray ? @res : $res[0]
219 } else { 225 } else {
220 $coro->join; 226 # we are in another coroutine, how wonderful, everything just works
227
228 $job->()
221 } 229 }
222
223 wantarray ? @res : $res[0]
224} 230}
225 231
226=item $coro = cf::coro { BLOCK } 232=item $coro = cf::coro { BLOCK }
227 233
228Creates and returns a new coro. This coro is automcatially being canceled 234Creates and returns a new coro. This coro is automcatially being canceled
252 my $runtime = cf::localdir . "/runtime"; 258 my $runtime = cf::localdir . "/runtime";
253 259
254 my $fh = aio_open "$runtime~", O_WRONLY | O_CREAT, 0644 260 my $fh = aio_open "$runtime~", O_WRONLY | O_CREAT, 0644
255 or return; 261 or return;
256 262
257 my $value = $cf::RUNTIME; 263 my $value = $cf::RUNTIME + 1 + 10; # 10 is the runtime save interval, for a monotonic clock
258 (aio_write $fh, 0, (length $value), $value, 0) <= 0 264 (aio_write $fh, 0, (length $value), $value, 0) <= 0
259 and return; 265 and return;
260 266
261 aio_fsync $fh 267 aio_fsync $fh
262 and return; 268 and return;
1046use Fcntl; 1052use Fcntl;
1047use Coro::AIO; 1053use Coro::AIO;
1048 1054
1049our $MAX_RESET = 7200; 1055our $MAX_RESET = 7200;
1050our $DEFAULT_RESET = 3600; 1056our $DEFAULT_RESET = 3600;
1051$MAX_RESET = 10;#d#
1052$DEFAULT_RESET = 10;#d#
1053 1057
1054sub generate_random_map { 1058sub generate_random_map {
1055 my ($path, $rmp) = @_; 1059 my ($path, $rmp) = @_;
1056 1060
1057 # mit "rum" bekleckern, nicht 1061 # mit "rum" bekleckern, nicht
1090 1094
1091 $map->load_header ($path) 1095 $map->load_header ($path)
1092 or return; 1096 or return;
1093 1097
1094 $map->{load_path} = $path; 1098 $map->{load_path} = $path;
1095 use Data::Dumper; warn Dumper $map;#d#
1096 1099
1097 $map 1100 $map
1098} 1101}
1099 1102
1100sub find_map { 1103sub find_map {
1101 my ($path, $origin) = @_; 1104 my ($path, $origin) = @_;
1102 1105
1103 #warn "find_map<$path,$origin>\n";#d# 1106 #warn "find_map<$path,$origin>\n";#d#
1104 1107
1105 $path = ref $path ? $path : new cf::path $path, $origin && $origin->path; 1108 $path = new cf::path $path, $origin && $origin->path;
1106 my $key = $path->as_string; 1109 my $key = $path->as_string;
1107 1110
1108 $cf::MAP{$key} || do { 1111 $cf::MAP{$key} || do {
1109 # do it the slow way 1112 # do it the slow way
1110 my $map = try_load_header $path->save_path; 1113 my $map = try_load_header $path->save_path;
1132 1135
1133 $map->path ($key); 1136 $map->path ($key);
1134 $map->{path} = $path; 1137 $map->{path} = $path;
1135 $map->last_access ($cf::RUNTIME); 1138 $map->last_access ($cf::RUNTIME);
1136 1139
1137 $map->reset if $map->should_reset; 1140 if ($map->should_reset) {
1141 $map->reset;
1142 $map = find_map $path;
1143 }
1138 1144
1139 $cf::MAP{$key} = $map 1145 $cf::MAP{$key} = $map
1140 } 1146 }
1141} 1147}
1142 1148
1151 1157
1152 $self->alloc; 1158 $self->alloc;
1153 $self->load_objects ($self->{load_path}, 1) 1159 $self->load_objects ($self->{load_path}, 1)
1154 or return; 1160 or return;
1155 1161
1156 $self->set_object_flag (cf::FLAG_OBJ_ORIGINAL, 1) if delete $self->{load_original}; 1162 $self->set_object_flag (cf::FLAG_OBJ_ORIGINAL, 1)
1163 if delete $self->{load_original};
1157 1164
1158 if (my $uniq = $path->uniq_path) { 1165 if (my $uniq = $path->uniq_path) {
1159 utf8::encode $uniq; 1166 utf8::encode $uniq;
1160 if (aio_open $uniq, O_RDONLY, 0) { 1167 if (aio_open $uniq, O_RDONLY, 0) {
1161 $self->clear_unique_items; 1168 $self->clear_unique_items;
1207 1214
1208 $self->{load_path} = $save; 1215 $self->{load_path} = $save;
1209 1216
1210 return if $self->{deny_save}; 1217 return if $self->{deny_save};
1211 1218
1212 warn "saving map ", $self->path;
1213
1214 if ($uniq) { 1219 if ($uniq) {
1215 $self->save_objects ($save, cf::IO_HEADER | cf::IO_OBJECTS); 1220 $self->save_objects ($save, cf::IO_HEADER | cf::IO_OBJECTS);
1216 $self->save_objects ($uniq, cf::IO_UNIQUES); 1221 $self->save_objects ($uniq, cf::IO_UNIQUES);
1217 } else { 1222 } else {
1218 $self->save_objects ($save, cf::IO_HEADER | cf::IO_OBJECTS | cf::IO_UNIQUES); 1223 $self->save_objects ($save, cf::IO_HEADER | cf::IO_OBJECTS | cf::IO_UNIQUES);
1229 $self->save; 1234 $self->save;
1230 $self->clear; 1235 $self->clear;
1231 $self->in_memory (cf::MAP_SWAPPED); 1236 $self->in_memory (cf::MAP_SWAPPED);
1232} 1237}
1233 1238
1239sub reset_at {
1240 my ($self) = @_;
1241
1242 # TODO: safety, remove and allow resettable per-player maps
1243 return 1e100 if $self->{path}{user_rel};
1244 return 1e100 if $self->{deny_reset};
1245
1246 my $time = $self->fixed_resettime ? $self->{instantiate_time} : $self->last_access;
1247 my $to = $self->reset_timeout || $DEFAULT_RESET;
1248 $to = $MAX_RESET if $to > $MAX_RESET;
1249
1250 $time + $to
1251}
1252
1234sub should_reset { 1253sub should_reset {
1235 my ($map) = @_; 1254 my ($self) = @_;
1236 1255
1237 # TODO: safety, remove and allow resettable per-player maps 1256 $self->reset_at <= $cf::RUNTIME
1238 return if $map->{path}{user_rel};#d#
1239 return if $map->{deny_reset};
1240 #return unless $map->reset_timeout;
1241
1242 my $time = $map->fixed_resettime ? $map->{instantiate_time} : $map->last_access;
1243 my $to = $map->reset_timeout || $DEFAULT_RESET;
1244 $to = $MAX_RESET if $to > $MAX_RESET;
1245
1246 $time + $to < $cf::RUNTIME
1247} 1257}
1248 1258
1249sub unlink_save { 1259sub unlink_save {
1250 my ($self) = @_; 1260 my ($self) = @_;
1251 1261

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines