# $File: //depot/libOurNet/BBS/lib/OurNet/BBS/MAPLE2/BoardGroup.pm $ $Author: autrijus $
# $Revision: #7 $ $Change: 4012 $ $DateTime: 2003/01/29 11:06:24 $

package OurNet::BBS::MAPLE2::BoardGroup;

use open IN => ':raw', OUT => ':raw';

use strict;
no warnings 'deprecated';
use fields qw/bbsroot shmkey maxboard shmid shm mtime _ego _hash/;
use OurNet::BBS::ShmScalar;

use OurNet::BBS::Base (
    '$packstring'    => 'Z13Z49Z39Z11LZ3CLL',
    '$namestring'    => 'Z13',
    '$packsize'      => 128,
    '@packlist'      => [
        qw/id title bm pad bupdate pad2 bvote vtime level/
    ],
    '$BRD'           => '.BOARDS',
    '$PATH_BRD'      => 'boards',
    '$PATH_GEM'      => 'man/boards',
);

sub shminit {
    my $self = shift;

    if ($^O ne 'MSWin32' and
        $self->{shmid} = shmget($self->{shmkey}, $self->{maxboard} * $packsize + 16, 0)) {
        tie $self->{shm}{touchtime}, 'OurNet::BBS::ShmScalar',
	    $self->{shmid}, $self->{maxboard}*$packsize +  4, 4, 'L';
        tie $self->{shm}{number}, 'OurNet::BBS::ShmScalar',
            $self->{shmid}, $self->{maxboard}*$packsize +  8, 4, 'L';
        tie $self->{shm}{busystate}, 'OurNet::BBS::ShmScalar',
            $self->{shmid}, $self->{maxboard}*$packsize + 12, 4, 'L';
    }
}

# Fetch key: id savemode author date title filemode body
sub refresh_meta {
    my ($self, $key) = @_;

    my $file = "$self->{bbsroot}/$BRD";
    my $board;

    $self->shminit unless ($self->{shmid} || !$self->{shmkey});

    if ($key) {
        $self->{_hash}{$key} ||= $self->module('Board')->new({
            bbsroot => $self->{bbsroot},
            board   => $key,
            shmid   => $self->{shmid},
            shm     => $self->{shm},
        });

	print $self->{_hash}{$key}->shmid if $OurNet::BBS::DEBUG;
        return;
    }

    return if $self->filestamp($file);

    open(my $DIR, "<$file") or die "can't read DIR file $file $!";

    foreach (0 .. int((stat($file))[7] / $packsize)-1) {
        read $DIR, $board, $packsize;

	CORE::unpack($namestring, $board) =~ /^([^\0].*)$/ or next;
 	$board = $1; # untaint

        $self->{_hash}{$board} ||= $self->module('Board')->new({
            bbsroot => $self->{bbsroot},
            board   => $board,
            shmid   => $self->{shmid},
            shm     => $self->{shm},
            recno   => $_,
        });
    }

    close $DIR;
}

sub EXISTS {
    my ($self, $key) = @_;
    $self = $self->ego;
    return 1 if exists ($self->{_hash}{$key});

    my $file = "$self->{bbsroot}/$BRD";
    return 0 if $self->filestamp($file, 'mtime', 1);

    open(my $DIR, "<$file") or die "can't read DIR file $file: $!";

    my $board;
    foreach (0 .. int((stat($file))[7] / $packsize)-1) {
        read $DIR, $board, $packsize;
	return 1 if CORE::unpack($namestring, $key) eq $key;
    }

    close $DIR;
    return 0;
}

sub STORE {
    my ($self, $key, $value) = @_;
    $self = $self->ego;

    die "Need key for STORE" unless $key;

    $self->shminit unless ($self->{shmid} || !$self->{shmkey});
    %{$self->module('Board')->new({
	bbsroot => $self->{bbsroot},
	board   => $key,
	shmid   => $self->{shmid},
	shm     => $self->{shm},
    })} = (%{$value}, bstamp => CORE::time);

    return 1;
}

1;