--- deliantra/server/ext/map-tags.ext 2007/09/13 08:35:24 1.5 +++ deliantra/server/ext/map-tags.ext 2008/09/22 05:42:41 1.14 @@ -50,7 +50,7 @@ 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}; } @@ -61,7 +61,7 @@ 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; @@ -79,9 +79,10 @@ # we don't actually care if it succeeds or not, as we # will just retry an hour later - BDB::db_txn_commit $txn; + 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 { @@ -103,9 +104,36 @@ } 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 + { + my @delkeys; + + my $cursor = $db_mapinfo->cursor; + for (;;) { + BDB::db_c_get $cursor, my $key, my $data, BDB::NEXT; + last if $!; + + 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; + } + BDB::db_c_close $cursor; + + for (@delkeys) { + my ($key, $tags) = @$_; + my $txn = $cf::DB_ENV->txn_begin; + BDB::db_del $db_mapinfo, $txn, $key; + for my $tag (@{ $tags || [] }) { + remove_tag_target $txn, $tag, $key; + } + BDB::db_txn_finish $txn; + } + } # 2. scan all static maps scan_static $cf::MAPDIR, "/"; @@ -143,18 +171,16 @@ # } # } - 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; +}; + +$RELOAD_SCHEDULER->invoke (0); # force at startup # find all objects with the given tag, or at least try to sub find($) {