ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/lib/cf.pm
(Generate patch)

Comparing deliantra/server/lib/cf.pm (file contents):
Revision 1.598 by root, Sun Nov 11 02:38:10 2012 UTC vs.
Revision 1.599 by root, Sun Nov 11 04:29:11 2012 UTC

251Configuration for the server, loaded from C</etc/deliantra-server/config>, or 251Configuration for the server, loaded from C</etc/deliantra-server/config>, or
252from wherever your confdir points to. 252from wherever your confdir points to.
253 253
254=item cf::wait_for_tick, cf::wait_for_tick_begin 254=item cf::wait_for_tick, cf::wait_for_tick_begin
255 255
256These are functions that inhibit the current coroutine one tick. cf::wait_for_tick_begin only 256These are functions that inhibit the current coroutine one tick.
257returns directly I<after> the tick processing (and consequently, can only wake one thread 257cf::wait_for_tick_begin only returns directly I<after> the tick
258processing (and consequently, can only wake one thread per tick), while
258per tick), while cf::wait_for_tick wakes up all waiters after tick processing. 259cf::wait_for_tick wakes up all waiters after tick processing.
259 260
260Note that cf::Wait_for_tick will immediately return when the server is not 261Note that cf::wait_for_tick will immediately return when the server is not
261ticking, making it suitable for small pauses in threads that need to run 262ticking, making it suitable for small pauses in threads that need to run
262when the server is paused. If that is not applicable (i.e. you I<really> 263when the server is paused. If that is not applicable (i.e. you I<really>
263want to wait, use C<$cf::WAIT_FOR_TICK>). 264want to wait, use C<$cf::WAIT_FOR_TICK>).
264 265
265=item $cf::WAIT_FOR_TICK 266=item $cf::WAIT_FOR_TICK
3519 3520
3520############################################################################# 3521#############################################################################
3521# the server's init and main functions 3522# the server's init and main functions
3522 3523
3523our %FACEHASH; # hash => idx, #d# HACK for http server 3524our %FACEHASH; # hash => idx, #d# HACK for http server
3525our @FACEDATA; # dynamically-created facedata
3524 3526
3525# internal api, not fianlised 3527# internal api, not fianlised
3526sub set_face { 3528sub set_face {
3527 my ($name, $type, $data) = @_; 3529 my ($name, $type, $data) = @_;
3528 3530
3535 } 3537 }
3536 3538
3537 my $hash = cf::face::mangle_chksum Digest::MD5::md5 $data; 3539 my $hash = cf::face::mangle_chksum Digest::MD5::md5 $data;
3538 3540
3539 cf::face::set_type $idx, $type; 3541 cf::face::set_type $idx, $type;
3540 cf::face::set_data $idx, 0, $data, $hash; 3542 cf::face::set_data $idx, 0, (length $data), 0, $hash;
3541 cf::face::set_meta $idx, $type & 1 ? undef : undef; 3543 cf::face::set_meta $idx, $type & 1 ? undef : undef;
3544
3545 # we need to destroy the SV itself, not just overwrite,
3546 # as a running ix might hold a reference to it.
3547 # delete achieves that.
3548 delete $FACEDATA[$idx];
3549 $FACEDATA[$idx] = $data;
3542 $FACEHASH{$hash} = $idx;#d# 3550 $FACEHASH{$hash} = $idx;#d#
3543 3551
3544 $idx 3552 $idx
3553}
3554
3555our $FACEDATA; # facedata filehandle
3556
3557sub _face_get_data($$$$) {
3558 my ($idx, $size, $fofs, $cb) = @_;
3559
3560 if (defined $FACEDATA[$idx]) {
3561 $cb->($FACEDATA[$idx]);
3562 } elsif ($fofs) {
3563 my $buf;
3564 IO::AIO::aio_read $FACEDATA, $fofs, $size, $buf, 0, sub {
3565 if ($_[0] == $size) {
3566 #cf::debug "read face $idx, $size from $fofs as ", length $buf;#d#
3567 $cb->($buf);
3568 } else {
3569 cf::error "INTERNAL ERROR: unable to read facedata for face $idx ($size, $fofs), ignoring request.";
3570 }
3571 };
3572 } else {
3573 cf::error "requested facedata for unknown face $idx ($size, $fofs), ignoring.";
3574 }
3575}
3576
3577# rather ineffient
3578sub cf::face::get_data($;$) {
3579 my ($idx, $faceset) = @_;
3580
3581 my $size = cf::face::get_size $idx, $faceset;
3582 my $fofs = cf::face::get_fofs $idx, $faceset;
3583
3584 _face_get_data $idx, $size, $fofs, Coro::rouse_cb;
3585 Coro::rouse_wait
3586}
3587
3588sub cf::face::ix {
3589 my ($ns, $idx, $pri, $size, $fofs) = @_;
3590
3591 _face_get_data $idx, $size, $fofs, sub {
3592 $ns->ix_send ($idx, $pri, $_[0]);
3593 };
3545} 3594}
3546 3595
3547sub load_facedata($) { 3596sub load_facedata($) {
3548 my ($path) = @_; 3597 my ($path) = @_;
3549 3598
3550 # HACK to clear player env face cache, we need some signal framework
3551 # for this (global event?)
3552 %ext::player_env::MUSIC_FACE_CACHE = ();
3553
3554 my $enc = JSON::XS->new->utf8->canonical->relaxed; 3599 my $enc = JSON::XS->new->utf8->canonical->relaxed;
3555 3600
3556 trace "loading facedata from $path\n"; 3601 trace "loading facedata from $path\n";
3557 3602
3558 my $facedata = decode_storable load_file $path; 3603 my $facedata = decode_storable load_file "$path/faceinfo";
3559 3604
3560 $facedata->{version} == 2 3605 $facedata->{version} == 2
3561 or cf::cleanup "$path: version mismatch, cannot proceed."; 3606 or cf::cleanup "$path/faceinfo: version mismatch, cannot proceed.";
3562 3607
3563 cf::cede_to_tick; 3608 my $fh = aio_open "$DATADIR/facedata", IO::AIO::O_RDONLY, 0
3609 or cf::cleanup "$path/facedata: $!, cnanot proceed.";
3610
3611 get_slot 1, -100, "load_facedata"; # make sure we get a very big slot
3612
3613 # BEGIN ATOMIC
3614 # from here on, everything must be atomic - no thread switch allowed
3615 my $t1 = EV::time;
3564 3616
3565 { 3617 {
3566 my $faces = delete $facedata->{faceinfo}; 3618 my $faces = $facedata->{faceinfo};
3567 3619
3568 for my $face (sort keys %$faces) { 3620 for my $face (sort keys %$faces) {
3569 my $info = $faces->{$face}; 3621 my $info = $faces->{$face};
3570 my $idx = (cf::face::find $face) || cf::face::alloc $face; 3622 my $idx = (cf::face::find $face) || cf::face::alloc $face;
3571 3623
3572 cf::face::set_visibility $idx, $info->{visibility}; 3624 cf::face::set_visibility $idx, $info->{visibility};
3573 cf::face::set_magicmap $idx, $info->{magicmap}; 3625 cf::face::set_magicmap $idx, $info->{magicmap};
3574 cf::face::set_data $idx, 0, $info->{data32}, $info->{hash32}; 3626 cf::face::set_data $idx, 0, $info->{size32}, $info->{fofs32}, $info->{hash32};
3575 cf::face::set_data $idx, 1, $info->{data64}, $info->{hash64}; 3627 cf::face::set_data $idx, 1, $info->{size64}, $info->{fofs64}, $info->{hash64};
3576 cf::face::set_data $idx, 2, $info->{glyph} , $info->{glyph} ; 3628 #cf::face::set_data $idx, 2, $info->{glyph} , $info->{glyph} ;
3577 $FACEHASH{$info->{hash64}} = $idx;#d# 3629 $FACEHASH{$info->{hash64}} = $idx;#d#
3578
3579 cf::cede_to_tick;
3580 } 3630 }
3581 3631
3582 while (my ($face, $info) = each %$faces) { 3632 while (my ($face, $info) = each %$faces) {
3583 next unless $info->{smooth}; 3633 next unless $info->{smooth};
3584 3634
3589 cf::face::set_smooth $idx, $smooth; 3639 cf::face::set_smooth $idx, $smooth;
3590 cf::face::set_smoothlevel $idx, $info->{smoothlevel}; 3640 cf::face::set_smoothlevel $idx, $info->{smoothlevel};
3591 } else { 3641 } else {
3592 error "smooth face '$info->{smooth}' not found for face '$face'"; 3642 error "smooth face '$info->{smooth}' not found for face '$face'";
3593 } 3643 }
3594
3595 cf::cede_to_tick;
3596 } 3644 }
3597 } 3645 }
3598 3646
3599 { 3647 {
3600 my $anims = delete $facedata->{animinfo}; 3648 my $anims = $facedata->{animinfo};
3601 3649
3602 while (my ($anim, $info) = each %$anims) { 3650 while (my ($anim, $info) = each %$anims) {
3603 cf::anim::set $anim, $info->{frames}, $info->{facings}; 3651 cf::anim::set $anim, $info->{frames}, $info->{facings};
3604 cf::cede_to_tick;
3605 } 3652 }
3606 3653
3607 cf::anim::invalidate_all; # d'oh 3654 cf::anim::invalidate_all; # d'oh
3608 } 3655 }
3609 3656
3610 { 3657 {
3611 my $res = delete $facedata->{resource}; 3658 my $res = $facedata->{resource};
3612 3659
3613 while (my ($name, $info) = each %$res) { 3660 while (my ($name, $info) = each %$res) {
3614 if (defined (my $type = $info->{type})) { 3661 if (defined (my $type = $info->{type})) {
3615 # TODO: different hash - must free and use new index, or cache ixface data queue 3662 # TODO: different hash - must free and use new index, or cache ixface data queue
3616 my $idx = (cf::face::find $name) || cf::face::alloc $name; 3663 my $idx = (cf::face::find $name) || cf::face::alloc $name;
3617 3664
3618 cf::face::set_type $idx, $type; 3665 cf::face::set_type $idx, $type;
3619 cf::face::set_data $idx, 0, $info->{data}, $info->{hash}; 3666 cf::face::set_data $idx, 0, $info->{size}, $info->{fofs}, $info->{hash};
3620 cf::face::set_meta $idx, $type & 1 ? undef : $info->{meta}; # preserve meta unless prepended already 3667 cf::face::set_meta $idx, $type & 1 ? undef : $info->{meta}; # preserve meta unless prepended already
3621 $FACEHASH{$info->{hash}} = $idx;#d# 3668 $FACEHASH{$info->{hash}} = $idx;#d#
3622 } else { 3669 } else {
3623# $RESOURCE{$name} = $info; # unused 3670# $RESOURCE{$name} = $info; # unused
3624 } 3671 }
3625
3626 cf::cede_to_tick;
3627 } 3672 }
3628 } 3673 }
3674
3675 ($fh, $FACEDATA) = ($FACEDATA, $fh);
3676
3677 # HACK to clear player env face cache, we need some signal framework
3678 # for this (global event?)
3679 %ext::player_env::MUSIC_FACE_CACHE = ();
3680
3681 # END ATOMIC
3682
3683 cf::debug "facedata atomic update time ", EV::time - $t1;
3629 3684
3630 cf::global->invoke (EVENT_GLOBAL_RESOURCE_UPDATE); 3685 cf::global->invoke (EVENT_GLOBAL_RESOURCE_UPDATE);
3686
3687 aio_close $fh if $fh; # close old facedata
3631 3688
3632 1 3689 1
3633} 3690}
3634 3691
3635register_exticmd fx_want => sub { 3692register_exticmd fx_want => sub {
3676 if exists $_->{match}; 3733 if exists $_->{match};
3677 } 3734 }
3678} 3735}
3679 3736
3680sub reload_facedata { 3737sub reload_facedata {
3681 load_facedata "$DATADIR/facedata" 3738 load_facedata $DATADIR
3682 or die "unable to load facedata\n"; 3739 or die "unable to load facedata\n";
3683} 3740}
3684 3741
3685sub reload_archetypes { 3742sub reload_archetypes {
3686 load_resource_file "$DATADIR/archetypes" 3743 load_resource_file "$DATADIR/archetypes"

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines