--- deliantra/Deliantra-Client/DC/DB.pm 2007/08/06 02:11:45 1.15 +++ deliantra/Deliantra-Client/DC/DB.pm 2007/11/16 04:54:25 1.23 @@ -20,7 +20,6 @@ use Carp (); use Storable (); use Config; -use Event (); use CFPlus; @@ -53,6 +52,10 @@ CFPlus::DB::Server::req (unlink => @_); } +sub read_file($$) { + CFPlus::DB::Server::req (read_file => @_); +} + sub write_file($$$) { CFPlus::DB::Server::req (write_file => @_); } @@ -68,17 +71,25 @@ our $tilemap; sub get_tile_id_sync($) { - my ($hash) = @_; + my ($name) = @_; # fetch the full face table first unless ($tilemap) { - CFPlus::DB::Server::req (table => facemap => sub { $tilemap = $_[0] }); + CFPlus::DB::Server::req (table => facemap => sub { + $tilemap = $_[0]; + delete $tilemap->{id}; + my %maptile = reverse %$tilemap;#d# + if ((scalar keys %$tilemap) != (scalar keys %maptile)) {#d# + $tilemap = { };#d# + CFPlus::error "FATAL: facemap is not a 1:1 mapping, please report this and delete your $DB_HOME directory!\n";#d# + }#d# + }); sync; } - $tilemap->{$hash} ||= do { + $tilemap->{$name} ||= do { my $id; - CFPlus::DB::Server::req (get_tile_id => $hash, sub { $id = $_[0] }); + CFPlus::DB::Server::req (get_tile_id => $name, sub { $id = $_[0] }); sync; $id } @@ -88,6 +99,7 @@ use strict; +use EV (); use Fcntl; use BerkeleyDB; @@ -108,7 +120,7 @@ # -ErrPrefix => "DATABASE", -Verbose => 1, -Flags => DB_CREATE | DB_RECOVER | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_TXN | $recover, - -SetFlags => DB_AUTO_COMMIT | DB_LOG_AUTOREMOVE, + -SetFlags => DB_AUTO_COMMIT | DB_LOG_AUTOREMOVE | DB_TXN_WRITE_NOSYNC, or die "unable to create/open database home $DB_HOME: $BerkeleyDB::Error"; 1 @@ -126,7 +138,7 @@ # -Filename => "database", # -Subname => $table, -Property => DB_CHKSUM, - -Flags => DB_CREATE | DB_UPGRADE, + -Flags => DB_AUTO_COMMIT | DB_CREATE | DB_UPGRADE, or die "unable to create/open database table $_[0]: $BerkeleyDB::Error" } } @@ -139,10 +151,10 @@ our $write_buf; our $read_buf; -our $SYNC = Event->idle (min => 5, max => 60, parked => 1, cb => sub { +our $SYNC = EV::timer_ns 0, 60, sub { + $_[0]->stop; CFPlus::DB::Server::req (sync => sub { }); - $_[0]->w->stop; -}); +}; sub fh_write { my $len = syswrite $FH, $write_buf; @@ -196,7 +208,7 @@ $CB{$id} = $cb; $fh_w_watcher->start; - $SYNC->start; + $SYNC->again unless $SYNC->is_active; } sub do_sync { @@ -246,13 +258,13 @@ } sub do_get_tile_id { - my ($hash) = @_; + my ($name) = @_; my $id; my $table = table "facemap"; return $id - if $table->db_get ($hash, $id) == 0; + if $table->db_get ($name, $id) == 0; for (1..100) { my $txn = $DB_ENV->txn_begin; @@ -260,13 +272,14 @@ if ($status == 0 || $status == BerkeleyDB::DB_NOTFOUND) { $id = ($id || 64) + 1; if ($table->db_put (id => $id) == 0 - && $table->db_put ($hash => $id) == 0) { + && $table->db_put ($name => $id) == 0) { $txn->txn_commit; return $id; } } $txn->txn_abort; + select undef, undef, undef, 0.01 * rand; } die "maximum number of transaction retries reached - database problems?"; @@ -276,24 +289,35 @@ unlink $_[0]; } +sub do_read_file { + my ($path) = @_; + + utf8::downgrade $path; + open my $fh, "<:raw", $path + or return; + sysread $fh, my $buf, -s $fh; + + $buf +} + sub do_write_file { - my ($file, $data) = @_; + my ($path, $data) = @_; - utf8::downgrade $file; + utf8::downgrade $path; utf8::downgrade $data; - open my $fh, ">:raw", $file + open my $fh, ">:raw", $path or return; - print $fh $data; + syswrite $fh, $data; close $fh; 1 } sub do_prefetch_file { - my ($file, $size) = @_; + my ($path, $size) = @_; - utf8::downgrade $file; - open my $fh, "<:raw", $file + utf8::downgrade $path; + open my $fh, "<:raw", $path or return; sysread $fh, my $buf, $size; @@ -356,13 +380,15 @@ or die "$type: unknown database request type\n"; my $res = pack "N/a*", Storable::freeze [$id, $cb->(@args)]; (syswrite $fh, $res) == length $res - or die; + or die "DB::write: $!"; } }; my $error = $@; eval { + $DB_ENV->txn_checkpoint (0, 0, 0); + undef %DB_TABLE; undef $DB_ENV; @@ -377,9 +403,9 @@ $CB{die} = sub { die shift }; - $fh_r_watcher = Event->io (fd => $FH, poll => 'r', nice => 1, cb => \&fh_read); - $fh_w_watcher = Event->io (fd => $FH, poll => 'w', nice => -1, parked => 1, cb => \&fh_write); - $SYNC->start; + $fh_r_watcher = EV::io $FH, EV::READ , \&fh_read; + $fh_w_watcher = EV::io $FH, EV::WRITE, \&fh_write; + $SYNC->again unless $SYNC->is_active; } sub stop {