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.2 by root, Tue Sep 11 13:27:53 2007 UTC vs.
Revision 1.17 by root, Fri Oct 23 03:08:34 2009 UTC

1#! perl # mandatory 1#! perl # mandatory
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
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) {
77 add_tag_target $txn, $tag, $key; 77 add_tag_target $txn, $tag, $key;
78 } 78 }
79 79
80 # we don't actually care if it succeeds or not, as we 80 # we don't actually care if it succeeds or not, as we
81 # will just retry an hour later 81 # will just retry an hour later
82 BDB::db_txn_commit $txn; 82 BDB::db_txn_finish $txn;
83 83
84# warn "tag-updated $file (= $key) $hash\n";#d# 84 warn "tag-updated $file (= $key) <@tags>\n"
85 if @tags;
85} 86}
86 87
87sub scan_static { 88sub scan_static {
88 my ($dir, $map) = @_; 89 my $maps = cf::map::static_maps;
89 90
90 my ($dirs, $files) = Coro::AIO::aio_scandir $dir, 2 91 scan_map "s$_", "$cf::MAPDIR$_.map";
91 or return; 92 for @$maps;
93}
92 94
93 for my $file (@$files) { 95sub reload {
94 my $name = $file; 96 my $guard = cf::lock_acquire "map-tags::reload";
95 next unless $name =~ s/\.map$//;
96 utf8::decode $name;
97 97
98 scan_map "s$map$name", "$dir/$file"; 98 my $start = EV::time;
99
100 # 1. check for maps no longer existing
101 {
102 my @delkeys;
103
104 my $cursor = $db_mapinfo->cursor;
105 for (;;) {
106 BDB::db_c_get $cursor, my $key, my $data, BDB::NEXT;
107 last if $!;
108
109 my $data = JSON::XS::decode_json $data;
110 my ($ver, undef, undef, $path) = split /,/, $data->{hash}, 4;
111 push @delkeys, [$key, $data->{tags}]
112 if $ver != 1 || Coro::AIO::aio_stat $path;
113 }
114 BDB::db_c_close $cursor;
115
116 for (@delkeys) {
117 my ($key, $tags) = @$_;
118 my $txn = $cf::DB_ENV->txn_begin;
119 BDB::db_del $db_mapinfo, $txn, $key;
120 for my $tag (@{ $tags || [] }) {
121 remove_tag_target $txn, $tag, $key;
122 }
123 BDB::db_txn_finish $txn;
124 }
99 } 125 }
100 126
101 &scan_static ("$dir/$_", "$map$_/") 127 # 2. scan all static maps
102 for @$dirs; 128 scan_static $cf::MAPDIR, "/";
103}
104 129
105cf::async_ext {
106 $Coro::current->prio (Coro::PRIO_MIN);
107
108 while () {
109 my $start = Event::time;
110
111 # 1. check for maps no longer existing
112
113 # 2. scan all static maps
114 scan_static $cf::MAPDIR, "/";
115
116 # 3. scan all dynamic maps 130 # 3. scan all dynamic maps
117 for my $path (@{ cf::map::tmp_maps or [] }, @{ cf::map::random_maps or [] }) { 131 for my $path (@{ cf::map::tmp_maps or [] }, @{ cf::map::random_maps or [] }) {
118# my $map = cf::map::find $path; 132# my $map = cf::map::find $path;
119# extract_map_tags "t/$map", $path; 133# extract_map_tags "t/$map", $path;
120 } 134 }
121 135
122 # now hunt for all per-player maps 136 # now hunt for all per-player maps
123# scan_dir $cf::PLAYERDIR 137# scan_dir $cf::PLAYERDIR
124# for my $login (@{ cf::player::list_logins or [] }) { 138# for my $login (@{ cf::player::list_logins or [] }) {
125# for my $path (@{ cf::player::maps $login or [] }) { 139# for my $path (@{ cf::player::maps $login or [] }) {
126# cf::cede_to_tick; 140# cf::cede_to_tick;
144# delete $map->{deny_reset}; 158# delete $map->{deny_reset};
145# } 159# }
146# } 160# }
147# } 161# }
148 162
149 warn sprintf "map-tag scan (%fs)", Event::time - $start; 163 warn sprintf "map-tag scan (%fs)", EV::time - $start;
150 Coro::Timer::sleep $SCHEDULE_INTERVAL; 164}
151 } 165
166our $RELOAD_SCHEDULER = cf::periodic $SCHEDULE_INTERVAL, Coro::unblock_sub {
167 $Coro::current->prio (Coro::PRIO_MIN);
168 $Coro::current->desc ("map-tag scanner");
169 reload;
152}; 170};
153 171
172cf::post_init {
173 $RELOAD_SCHEDULER->invoke (0); # force at startup
174};
175
176# find all objects with the given tag, or at least try to
154sub find($) { 177sub find($) {
155 my ($tag) = @_; 178 my ($tag) = @_;
156 179
157 my @res;
158
159 utf8::encode $tag; 180 utf8::encode (my $key = $tag);
160 BDB::db_get $db_target, undef, $tag, my $data; 181 BDB::db_get $db_target, undef, $key, my $data;
161 utf8::decode $data; 182 utf8::decode $data;
162 183
163 for my $map ( 184 map { $_->load; $_->find_tagged_objects ($tag) }
164 grep $_, 185 grep $_,
165 map { cf::map::find $_ } 186 map { cf::map::find $_ }
166 grep s/^s//, 187 grep s/^s//,
167 split /\x00/, $data 188 split /\x00/, $data
168 ) {
169 $map->load;
170
171 warn "tag<$tag>map<$map>\n";#d#
172 }
173
174 @res
175} 189}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines