ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/ext/map-tags.ext
(Generate patch)

Comparing deliantra/server/ext/map-tags.ext (file contents):
Revision 1.7 by root, Thu Sep 13 16:16:36 2007 UTC vs.
Revision 1.20 by root, Sun Oct 25 10:05:20 2009 UTC

2 2
3our $SCHEDULE_INTERVAL = $cf::CFG{extractor_schedule_interval} || 3600; 3our $SCHEDULE_INTERVAL = $cf::CFG{extractor_schedule_interval} || 3600;
4 4
5use JSON::XS; 5use JSON::XS;
6 6
7my $db_mapinfo = cf::sync_job { cf::db_table "tag-mapinfo" }; # info/cache for maps 7our $db_mapinfo = cf::sync_job { cf::db_table "tag-mapinfo" }; # info/cache for maps
8my $db_target = cf::sync_job { cf::db_table "tag-target" }; # tag => maps 8our $db_target = cf::sync_job { cf::db_table "tag-target" }; # tag => maps
9 9
10sub remove_tag_target { 10sub remove_tag_target {
11 my ($txn, $tag, $target) = @_; 11 my ($txn, $tag, $target) = @_;
12 # - U O 12 # - U O
13 13
40 Coro::AIO::aio_stat $file 40 Coro::AIO::aio_stat $file
41 and next; 41 and next;
42 42
43 my $hash = join ",", 1, (stat _)[7,9], $file; 43 my $hash = join ",", 1, (stat _)[7,9], $file;
44 44
45 my $old_tags;
46
47 my $txn = $cf::DB_ENV->txn_begin; 45 my $txn = $cf::DB_ENV->txn_begin;
48 46
49 utf8::encode $key; 47 utf8::encode $key;
50 BDB::db_get $db_mapinfo, $txn, $key, my $data; 48 BDB::db_get $db_mapinfo, $txn, $key, my $data;
51 49
52 unless ($!) { 50 unless ($!) {
53 $data = from_json $data; 51 $data = decode_json $data;
54 return if $data->{hash} eq $hash; 52 return if $data->{hash} eq $hash;
55 $old_tags = $data->{tags}; 53
54 # remove all old tags unconditionally
55 remove_tag_target $txn, $_, $key
56 for @{ $data->{tags} };
56 } 57 }
57
58 $old_tags ||= [];
59 58
60 my $f = new_from_file cf::object::thawer $file 59 my $f = new_from_file cf::object::thawer $file
61 or return; 60 or return;
62 61
63 my @tags = sort $f->extract_tags; 62 my @tags = sort $f->extract_tags;
64 $data = to_json { hash => $hash, tags => \@tags }; 63 $data = encode_json { hash => $hash, tags => \@tags };
65 64
66 BDB::db_put $db_mapinfo, $txn, $key, $data; 65 BDB::db_put $db_mapinfo, $txn, $key, $data;
67 66
68 # 1. remove tags no longer existing 67 # add all tags
69 for my $tag (@$old_tags) {
70 next if grep $_ eq $tag, @tags;
71 remove_tag_target $txn, $tag, $key;
72 }
73
74 # 2. add tags that are new
75 for my $tag (@tags) {
76 next if grep $_ eq $tag, @$old_tags;
77 add_tag_target $txn, $tag, $key; 68 add_tag_target $txn, $_, $key
78 } 69 for @tags;
79 70
80 # we don't actually care if it succeeds or not, as we 71 # we don't actually care if it succeeds or not, as we
81 # will just retry an hour later 72 # will just retry an hour later
82 BDB::db_txn_finish $txn; 73 BDB::db_txn_finish $txn;
83 74
84# warn "tag-updated $file (= $key) $hash\n";#d# 75 warn "tag-updated $file (= $key) <@tags>\n"
76 if @tags;
85} 77}
86 78
87sub scan_static { 79sub scan_static {
88 my ($dir, $map) = @_; 80 my $maps = cf::map::static_maps;
89 81
90 my ($dirs, $files) = Coro::AIO::aio_scandir $dir, 2 82 scan_map "s$_", "$cf::MAPDIR$_.map"
91 or return;
92
93 for my $file (@$files) {
94 my $name = $file;
95 next unless $name =~ s/\.map$//;
96 utf8::decode $name;
97
98 scan_map "s$map$name", "$dir/$file";
99 }
100
101 &scan_static ("$dir/$_", "$map$_/")
102 for @$dirs; 83 for @$maps;
103} 84}
104 85
105sub reload { 86sub reload {
87 my $guard = cf::lock_acquire "map-tags::reload";
88
106 my $start = Event::time; 89 my $start = EV::time;
107 90
108 # 1. check for maps no longer existing 91 # 1. check for maps no longer existing
109 { 92 {
110 my @delkeys; 93 my @delkeys;
111 94
112 my $cursor = $db_mapinfo->cursor; 95 my $cursor = $db_mapinfo->cursor;
113 for (;;) { 96 for (;;) {
114 BDB::db_c_get $cursor, my $key, my $data, BDB::NEXT; 97 BDB::db_c_get $cursor, my $key, my $data, BDB::NEXT;
115 last if $!; 98 last if $!;
116 99
117 my $data = JSON::XS::from_json $data; 100 my $data = JSON::XS::decode_json $data;
118 my ($ver, undef, undef, $path) = split /,/, $data->{hash}, 4; 101 my ($ver, undef, undef, $path) = split /,/, $data->{hash}, 4;
119 push @delkeys, [$key, $data->{tags}] 102 push @delkeys, [$key, $data->{tags}]
120 if $ver != 1 || Coro::AIO::aio_stat $path; 103 if $ver != 1 || Coro::AIO::aio_stat $path;
121 } 104 }
122 BDB::db_c_close $cursor; 105 BDB::db_c_close $cursor;
166# delete $map->{deny_reset}; 149# delete $map->{deny_reset};
167# } 150# }
168# } 151# }
169# } 152# }
170 153
171 warn sprintf "map-tag scan (%fs)", Event::time - $start; 154 warn sprintf "map-tag scan (%fs)", EV::time - $start;
172} 155}
173 156
174our $RELOAD_SCHEDULER = Event->timer ( 157our $RELOAD_SCHEDULER = cf::periodic $SCHEDULE_INTERVAL, Coro::unblock_sub {
175 after => 0,
176 interval => $SCHEDULE_INTERVAL,
177 data => cf::WF_AUTOCANCEL,
178 cb => Coro::unblock_sub {
179 $Coro::current->prio (Coro::PRIO_MIN); 158 $Coro::current->prio (Coro::PRIO_MIN);
159 $Coro::current->desc ("map-tag scanner");
180 reload; 160 reload;
181 }, 161};
182); 162
163cf::post_init {
164 $RELOAD_SCHEDULER->invoke (0); # force at startup
165};
183 166
184# find all objects with the given tag, or at least try to 167# find all objects with the given tag, or at least try to
185sub find($) { 168sub find($) {
186 my ($tag) = @_; 169 my ($tag) = @_;
187 170
193 grep $_, 176 grep $_,
194 map { cf::map::find $_ } 177 map { cf::map::find $_ }
195 grep s/^s//, 178 grep s/^s//,
196 split /\x00/, $data 179 split /\x00/, $data
197} 180}
181
182sub unload {
183 my $guard = cf::lock_acquire "map-tags::reload";
184
185 db_close $db_target;
186 db_close $db_mapinfo;
187}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines