1 |
root |
1.1 |
#! perl |
2 |
|
|
|
3 |
|
|
# this plug-in prefetches maps. everytime a player enters a map, |
4 |
|
|
# it will asynchronously prefetch files from disk (it will not load them |
5 |
|
|
# into the server, but into the OS cache only). |
6 |
|
|
|
7 |
|
|
use Errno (); |
8 |
|
|
use Time::HiRes; |
9 |
|
|
use Fcntl; |
10 |
|
|
use IO::AIO; |
11 |
|
|
|
12 |
root |
1.2 |
# find all potential exit paths, this is slow, so this info is cached |
13 |
root |
1.1 |
sub find_exits { |
14 |
|
|
my ($map) = @_; |
15 |
|
|
|
16 |
|
|
my %exit; |
17 |
|
|
|
18 |
|
|
for my $x (0 .. $map->width - 1) { |
19 |
|
|
for my $y (0 .. $map->height - 1) { |
20 |
|
|
for (grep $_->type == 66, $map->at ($x, $y)) { |
21 |
|
|
my $path = $_->slaying; |
22 |
|
|
|
23 |
|
|
next if 3 > length $path; |
24 |
|
|
|
25 |
|
|
$path = cf::maps_directory cf::path_combine_and_normalize $map->path, $path; |
26 |
|
|
|
27 |
|
|
$exit{$path}++; |
28 |
|
|
} |
29 |
|
|
} |
30 |
|
|
} |
31 |
|
|
|
32 |
|
|
[keys %exit] |
33 |
|
|
} |
34 |
|
|
|
35 |
root |
1.5 |
my @PREFETCH; |
36 |
root |
1.1 |
my %MAP_TIMEOUT; |
37 |
|
|
|
38 |
root |
1.5 |
sub prefetch; |
39 |
|
|
sub prefetch { |
40 |
|
|
while (my $path = shift @PREFETCH) { |
41 |
|
|
my $NOW = Time::HiRes::time; |
42 |
root |
1.1 |
|
43 |
root |
1.5 |
next if $MAP_TIMEOUT{$path} > $NOW; |
44 |
root |
1.1 |
|
45 |
root |
1.5 |
$MAP_TIMEOUT{$path} = $NOW + 60 + rand 60; |
46 |
root |
1.1 |
|
47 |
|
|
if (my $map = cf::map::has_been_loaded $path) { |
48 |
|
|
next if $map->in_memory == cf::MAP_IN_MEMORY; |
49 |
|
|
|
50 |
|
|
$path = $map->tmppath if $map->in_memory == cf::MAP_SWAPPED; |
51 |
|
|
} |
52 |
|
|
|
53 |
|
|
aio_open $path, O_RDONLY, 0, sub { |
54 |
root |
1.5 |
my $fh = shift |
55 |
root |
1.1 |
or return; |
56 |
|
|
aio_readahead $fh, 0, -s $fh, sub { |
57 |
root |
1.3 |
my $time = Time::HiRes::time - $NOW; |
58 |
root |
1.4 |
warn "LONG PREFETCH $path $time\n" if $time > 0.3; |
59 |
root |
1.5 |
|
60 |
|
|
prefetch; |
61 |
root |
1.1 |
}; |
62 |
|
|
}; |
63 |
root |
1.5 |
|
64 |
|
|
last; |
65 |
root |
1.1 |
} |
66 |
|
|
} |
67 |
|
|
|
68 |
root |
1.5 |
my %MAP_EXITS; |
69 |
|
|
|
70 |
|
|
sub on_mapenter { |
71 |
|
|
my ($ob) = @_; |
72 |
|
|
|
73 |
|
|
my $exit = $MAP_EXITS{$ob->map->path} ||= find_exits $ob->map; |
74 |
|
|
|
75 |
|
|
push @PREFETCH, @$exit; |
76 |
|
|
prefetch; |
77 |
|
|
} |
78 |
|
|
|
79 |
root |
1.1 |
sub on_clock { |
80 |
|
|
# boy how I hate polling |
81 |
|
|
IO::AIO::poll_cb; |
82 |
|
|
} |
83 |
|
|
|
84 |
|
|
|