--- deliantra/server/ext/map-tags.ext 2007/09/13 16:16:36 1.7 +++ deliantra/server/ext/map-tags.ext 2009/10/24 00:25:26 1.19 @@ -4,8 +4,8 @@ use JSON::XS; -my $db_mapinfo = cf::sync_job { cf::db_table "tag-mapinfo" }; # info/cache for maps -my $db_target = cf::sync_job { cf::db_table "tag-target" }; # tag => maps +our $db_mapinfo = cf::sync_job { cf::db_table "tag-mapinfo" }; # info/cache for maps +our $db_target = cf::sync_job { cf::db_table "tag-target" }; # tag => maps sub remove_tag_target { my ($txn, $tag, $target) = @_; @@ -42,68 +42,51 @@ my $hash = join ",", 1, (stat _)[7,9], $file; - my $old_tags; - my $txn = $cf::DB_ENV->txn_begin; utf8::encode $key; BDB::db_get $db_mapinfo, $txn, $key, my $data; unless ($!) { - $data = from_json $data; + $data = decode_json $data; return if $data->{hash} eq $hash; - $old_tags = $data->{tags}; - } - $old_tags ||= []; + # remove all old tags unconditionally + remove_tag_target $txn, $_, $key + for @{ $data->{tags} }; + } my $f = new_from_file cf::object::thawer $file or return; my @tags = sort $f->extract_tags; - $data = to_json { hash => $hash, tags => \@tags }; + $data = encode_json { hash => $hash, tags => \@tags }; BDB::db_put $db_mapinfo, $txn, $key, $data; - # 1. remove tags no longer existing - for my $tag (@$old_tags) { - next if grep $_ eq $tag, @tags; - remove_tag_target $txn, $tag, $key; - } - - # 2. add tags that are new - for my $tag (@tags) { - next if grep $_ eq $tag, @$old_tags; - add_tag_target $txn, $tag, $key; - } + # add all tags + add_tag_target $txn, $_, $key + for @tags; # we don't actually care if it succeeds or not, as we # will just retry an hour later BDB::db_txn_finish $txn; -# warn "tag-updated $file (= $key) $hash\n";#d# + warn "tag-updated $file (= $key) <@tags>\n" + if @tags; } sub scan_static { - my ($dir, $map) = @_; + my $maps = cf::map::static_maps; - my ($dirs, $files) = Coro::AIO::aio_scandir $dir, 2 - or return; - - for my $file (@$files) { - my $name = $file; - next unless $name =~ s/\.map$//; - utf8::decode $name; - - scan_map "s$map$name", "$dir/$file"; - } - - &scan_static ("$dir/$_", "$map$_/") - for @$dirs; + scan_map "s$_", "$cf::MAPDIR$_.map" + for @$maps; } sub reload { - my $start = Event::time; + my $guard = cf::lock_acquire "map-tags::reload"; + + my $start = EV::time; # 1. check for maps no longer existing { @@ -114,7 +97,7 @@ BDB::db_c_get $cursor, my $key, my $data, BDB::NEXT; last if $!; - my $data = JSON::XS::from_json $data; + my $data = JSON::XS::decode_json $data; my ($ver, undef, undef, $path) = split /,/, $data->{hash}, 4; push @delkeys, [$key, $data->{tags}] if $ver != 1 || Coro::AIO::aio_stat $path; @@ -168,18 +151,18 @@ # } # } - warn sprintf "map-tag scan (%fs)", Event::time - $start; + warn sprintf "map-tag scan (%fs)", EV::time - $start; } -our $RELOAD_SCHEDULER = Event->timer ( - after => 0, - interval => $SCHEDULE_INTERVAL, - data => cf::WF_AUTOCANCEL, - cb => Coro::unblock_sub { - $Coro::current->prio (Coro::PRIO_MIN); - reload; - }, -); +our $RELOAD_SCHEDULER = cf::periodic $SCHEDULE_INTERVAL, Coro::unblock_sub { + $Coro::current->prio (Coro::PRIO_MIN); + $Coro::current->desc ("map-tag scanner"); + reload; +}; + +cf::post_init { + $RELOAD_SCHEDULER->invoke (0); # force at startup +}; # find all objects with the given tag, or at least try to sub find($) {