… | |
… | |
48 | |
48 | |
49 | utf8::encode $key; |
49 | utf8::encode $key; |
50 | BDB::db_get $db_mapinfo, $txn, $key, my $data; |
50 | BDB::db_get $db_mapinfo, $txn, $key, my $data; |
51 | |
51 | |
52 | unless ($!) { |
52 | unless ($!) { |
53 | $data = from_json $data; |
53 | $data = decode_json $data; |
54 | return if $data->{hash} eq $hash; |
54 | return if $data->{hash} eq $hash; |
55 | $old_tags = $data->{tags}; |
55 | $old_tags = $data->{tags}; |
56 | } |
56 | } |
57 | |
57 | |
58 | $old_tags ||= []; |
58 | $old_tags ||= []; |
59 | |
59 | |
60 | my $f = new_from_file cf::object::thawer $file |
60 | my $f = new_from_file cf::object::thawer $file |
61 | or return; |
61 | or return; |
62 | |
62 | |
63 | my @tags = sort $f->extract_tags; |
63 | my @tags = sort $f->extract_tags; |
64 | $data = to_json { hash => $hash, tags => \@tags }; |
64 | $data = encode_json { hash => $hash, tags => \@tags }; |
65 | |
65 | |
66 | BDB::db_put $db_mapinfo, $txn, $key, $data; |
66 | BDB::db_put $db_mapinfo, $txn, $key, $data; |
67 | |
67 | |
68 | # 1. remove tags no longer existing |
68 | # 1. remove tags no longer existing |
69 | for my $tag (@$old_tags) { |
69 | for my $tag (@$old_tags) { |
… | |
… | |
104 | } |
104 | } |
105 | |
105 | |
106 | sub reload { |
106 | sub reload { |
107 | my $guard = cf::lock_acquire "map-tags::reload"; |
107 | my $guard = cf::lock_acquire "map-tags::reload"; |
108 | |
108 | |
109 | my $start = Event::time; |
109 | my $start = EV::time; |
110 | |
110 | |
111 | # 1. check for maps no longer existing |
111 | # 1. check for maps no longer existing |
112 | { |
112 | { |
113 | my @delkeys; |
113 | my @delkeys; |
114 | |
114 | |
115 | my $cursor = $db_mapinfo->cursor; |
115 | my $cursor = $db_mapinfo->cursor; |
116 | for (;;) { |
116 | for (;;) { |
117 | BDB::db_c_get $cursor, my $key, my $data, BDB::NEXT; |
117 | BDB::db_c_get $cursor, my $key, my $data, BDB::NEXT; |
118 | last if $!; |
118 | last if $!; |
119 | |
119 | |
120 | my $data = JSON::XS::from_json $data; |
120 | my $data = JSON::XS::decode_json $data; |
121 | my ($ver, undef, undef, $path) = split /,/, $data->{hash}, 4; |
121 | my ($ver, undef, undef, $path) = split /,/, $data->{hash}, 4; |
122 | push @delkeys, [$key, $data->{tags}] |
122 | push @delkeys, [$key, $data->{tags}] |
123 | if $ver != 1 || Coro::AIO::aio_stat $path; |
123 | if $ver != 1 || Coro::AIO::aio_stat $path; |
124 | } |
124 | } |
125 | BDB::db_c_close $cursor; |
125 | BDB::db_c_close $cursor; |
… | |
… | |
169 | # delete $map->{deny_reset}; |
169 | # delete $map->{deny_reset}; |
170 | # } |
170 | # } |
171 | # } |
171 | # } |
172 | # } |
172 | # } |
173 | |
173 | |
174 | warn sprintf "map-tag scan (%fs)", Event::time - $start; |
174 | warn sprintf "map-tag scan (%fs)", EV::time - $start; |
175 | } |
175 | } |
176 | |
176 | |
177 | our $RELOAD_SCHEDULER = Event->timer ( |
177 | our $RELOAD_SCHEDULER = cf::periodic $SCHEDULE_INTERVAL, Coro::unblock_sub { |
178 | after => 0, |
|
|
179 | interval => $SCHEDULE_INTERVAL, |
|
|
180 | data => cf::WF_AUTOCANCEL, |
|
|
181 | cb => Coro::unblock_sub { |
|
|
182 | $Coro::current->prio (Coro::PRIO_MIN); |
178 | $Coro::current->prio (Coro::PRIO_MIN); |
183 | $Coro::current->desc ("map-tag scanner"); |
179 | $Coro::current->desc ("map-tag scanner"); |
184 | reload; |
180 | reload; |
185 | }, |
181 | }; |
186 | ); |
182 | |
|
|
183 | cf::async { reload }; # force at startup |
187 | |
184 | |
188 | # find all objects with the given tag, or at least try to |
185 | # find all objects with the given tag, or at least try to |
189 | sub find($) { |
186 | sub find($) { |
190 | my ($tag) = @_; |
187 | my ($tag) = @_; |
191 | |
188 | |