… | |
… | |
18 | use utf8; |
18 | use utf8; |
19 | |
19 | |
20 | use Carp (); |
20 | use Carp (); |
21 | use Storable (); |
21 | use Storable (); |
22 | use Config; |
22 | use Config; |
23 | use Event (); |
|
|
24 | |
23 | |
25 | use CFPlus; |
24 | use CFPlus; |
26 | |
25 | |
27 | our $DB_HOME = "$Crossfire::VARDIR/cfplus-$BerkeleyDB::db_version-$Config{archname}"; |
26 | our $DB_HOME = "$Crossfire::VARDIR/cfplus-$BerkeleyDB::db_version-$Config{archname}"; |
28 | |
27 | |
… | |
… | |
98 | |
97 | |
99 | package CFPlus::DB::Server; |
98 | package CFPlus::DB::Server; |
100 | |
99 | |
101 | use strict; |
100 | use strict; |
102 | |
101 | |
|
|
102 | use EV (); |
103 | use Fcntl; |
103 | use Fcntl; |
104 | use BerkeleyDB; |
104 | use BerkeleyDB; |
105 | |
105 | |
106 | our $DB_ENV; |
106 | our $DB_ENV; |
107 | our $DB_STATE; |
107 | our $DB_STATE; |
… | |
… | |
149 | our ($fh_r_watcher, $fh_w_watcher); |
149 | our ($fh_r_watcher, $fh_w_watcher); |
150 | our $sync_timer; |
150 | our $sync_timer; |
151 | our $write_buf; |
151 | our $write_buf; |
152 | our $read_buf; |
152 | our $read_buf; |
153 | |
153 | |
154 | our $SYNC = Event->idle (min => 120, max => 180, parked => 1, cb => sub { |
154 | our $SYNC = EV::timer_ns 0, 60, sub { |
|
|
155 | $_[0]->stop; |
155 | CFPlus::DB::Server::req (sync => sub { }); |
156 | CFPlus::DB::Server::req (sync => sub { }); |
156 | $_[0]->w->stop; |
|
|
157 | }); |
157 | }; |
158 | |
158 | |
159 | sub fh_write { |
159 | sub fh_write { |
160 | my $len = syswrite $FH, $write_buf; |
160 | my $len = syswrite $FH, $write_buf; |
161 | |
161 | |
162 | substr $write_buf, 0, $len, ""; |
162 | substr $write_buf, 0, $len, ""; |
… | |
… | |
206 | my $id = ++$ID; |
206 | my $id = ++$ID; |
207 | $write_buf .= pack "N/a*", Storable::freeze [$id, $type, @args]; |
207 | $write_buf .= pack "N/a*", Storable::freeze [$id, $type, @args]; |
208 | $CB{$id} = $cb; |
208 | $CB{$id} = $cb; |
209 | |
209 | |
210 | $fh_w_watcher->start; |
210 | $fh_w_watcher->start; |
211 | $SYNC->start; |
211 | $SYNC->again unless $SYNC->is_active; |
212 | } |
212 | } |
213 | |
213 | |
214 | sub do_sync { |
214 | sub do_sync { |
215 | $DB_ENV->txn_checkpoint (0, 0, 0); |
215 | $DB_ENV->txn_checkpoint (0, 0, 0); |
216 | () |
216 | () |
… | |
… | |
378 | my ($id, $type, @args) = @$req; |
378 | my ($id, $type, @args) = @$req; |
379 | my $cb = CFPlus::DB::Server->can ("do_$type") |
379 | my $cb = CFPlus::DB::Server->can ("do_$type") |
380 | or die "$type: unknown database request type\n"; |
380 | or die "$type: unknown database request type\n"; |
381 | my $res = pack "N/a*", Storable::freeze [$id, $cb->(@args)]; |
381 | my $res = pack "N/a*", Storable::freeze [$id, $cb->(@args)]; |
382 | (syswrite $fh, $res) == length $res |
382 | (syswrite $fh, $res) == length $res |
383 | or die; |
383 | or die "DB::write: $!"; |
384 | } |
384 | } |
385 | }; |
385 | }; |
386 | |
386 | |
387 | my $error = $@; |
387 | my $error = $@; |
388 | |
388 | |
389 | eval { |
389 | eval { |
|
|
390 | $DB_ENV->txn_checkpoint (0, 0, 0); |
|
|
391 | |
390 | undef %DB_TABLE; |
392 | undef %DB_TABLE; |
391 | undef $DB_ENV; |
393 | undef $DB_ENV; |
392 | |
394 | |
393 | Storable::store_fd [die => $error], $fh; |
395 | Storable::store_fd [die => $error], $fh; |
394 | }; |
396 | }; |
… | |
… | |
399 | close $fh; |
401 | close $fh; |
400 | CFPlus::fh_nonblocking $FH, 1; |
402 | CFPlus::fh_nonblocking $FH, 1; |
401 | |
403 | |
402 | $CB{die} = sub { die shift }; |
404 | $CB{die} = sub { die shift }; |
403 | |
405 | |
404 | $fh_r_watcher = Event->io (fd => $FH, poll => 'r', nice => 1, cb => \&fh_read); |
406 | $fh_r_watcher = EV::io $FH, EV::READ , \&fh_read; |
405 | $fh_w_watcher = Event->io (fd => $FH, poll => 'w', nice => -1, parked => 1, cb => \&fh_write); |
407 | $fh_w_watcher = EV::io $FH, EV::WRITE, \&fh_write; |
406 | $SYNC->start; |
408 | $SYNC->again unless $SYNC->is_active; |
407 | } |
409 | } |
408 | |
410 | |
409 | sub stop { |
411 | sub stop { |
410 | close $FH; |
412 | close $FH; |
411 | } |
413 | } |