--- trunk/IsisDB.pm 2004/12/28 01:41:45 2 +++ trunk/IsisDB.pm 2004/12/29 16:01:41 9 @@ -7,7 +7,7 @@ BEGIN { use Exporter (); use vars qw ($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); - $VERSION = 0.01; + $VERSION = 0.03; @ISA = qw (Exporter); #Give a hoot don't pollute, do not export more than needed by default @EXPORT = qw (); @@ -66,6 +66,7 @@ isisdb => './cds/cds', read_fdt => 1, debug => 1, + include_deleted => 1, ); Options are described below: @@ -86,6 +87,10 @@ Dump a C of debugging output. +=item include_deleted + +Don't skip logically deleted records. + =back It will also set C<$isis-E{'maxmfn'}> which is maximum MFN stored in database. @@ -97,9 +102,11 @@ my $self = {}; bless($self, $class); - $self->{isisdb} = {@_}->{isisdb} || croak "new needs database name as argument!"; + croak "new needs database name (isisdb) as argument!" unless ({@_}->{isisdb}); - $self->{debug} = {@_}->{debug}; + foreach my $v (qw{isisdb debug include_deleted}) { + $self->{$v} = {@_}->{$v}; + } # if you want to read .FDT file use read_fdt argument when creating class! if ({@_}->{read_fdt} && -e $self->{isisdb}.".FDT") { @@ -173,6 +180,8 @@ my $buff = shift || return; my @arr = unpack("ssssssllls", $buff); + print "unpack_cnt: ",join(" ",@arr),"\n" if ($self->{'debug'}); + my $IDTYPE = shift @arr; foreach (@flds) { $self->{$IDTYPE}->{$_} = abs(shift @arr); @@ -191,37 +200,40 @@ print Dumper($self) if ($self->{debug}); + # open files for later + open($self->{'fileXRF'}, $self->{isisdb}.".XRF") || croak "can't open '$self->{isisdb}.XRF': $!"; + + open($self->{'fileMST'}, $self->{isisdb}.".MST") || croak "can't open '$self->{isisdb}.MST': $!"; + $self ? return $self : return undef; } -=head2 GetMFN +=head2 fetch Read record with selected MFN - my $rec = $isis->GetMFN(55); + my $rec = $isis->fetch(55); Returns hash with keys which are field names and values are unpacked values for that field. =cut -sub GetMFN { +sub fetch { my $self = shift; - my $mfn = shift || croak "GetMFN needs MFN as argument!"; - - print "GetMFN: $mfn\n" if ($self->{debug}); + my $mfn = shift || croak "fetch needs MFN as argument!"; - open(fileXRF, $self->{isisdb}.".XRF") || croak "can't open '$self->{isisdb}.XRF': $!"; + print "fetch: $mfn\n" if ($self->{debug}); # XXX check this? my $mfnpos=($mfn+int(($mfn-1)/127))*4; print "seeking to $mfnpos in file '$self->{isisdb}.XRF'\n" if ($self->{debug}); - seek(fileXRF,$mfnpos,0); + seek($self->{'fileXRF'},$mfnpos,0); # read XRFMFB abd XRFMFP - my $pointer=$self->Read32(\*fileXRF); + my $pointer=$self->Read32(\*{$self->{'fileXRF'}}); my $XRFMFB = int($pointer/2048); my $XRFMFP = $pointer - ($XRFMFB*2048); @@ -242,15 +254,11 @@ print "$offset - $offset2 - $offset3 - $offset4\n" if ($self->{debug}); - close(fileXRF); - # Get Record Information - open(fileMST, $self->{isisdb}.".MST") || croak "can't open '$self->{isisdb}.MST': $!"; + seek($self->{'fileMST'},$offset4,0); - seek(fileMST,$offset4,0); - - my $value=$self->Read32(\*fileMST); + my $value=$self->Read32(\*{$self->{'fileMST'}}); if ($value!=$mfn) { print ("Error: The MFN:".$mfn." is not found in MST(".$value.")"); @@ -265,26 +273,37 @@ # $STATUS=$self->Read16($fileMST); my $buff; - read(fileMST, $buff, 14); + read($self->{'fileMST'}, $buff, 14); my ($MFRL,$MFBWB,$MFBWP,$BASE,$NVF,$STATUS) = unpack("slssss", $buff); print "MFRL: $MFRL MFBWB: $MFBWB MFBWP: $MFBWP BASE: $BASE NVF: $NVF STATUS: $STATUS\n" if ($self->{debug}); + # delete old record + delete $self->{record}; + + if (! $self->{'include_deleted'} && $MFRL < 0) { + print "## logically deleted record $mfn, skipping...\n" if ($self->{debug}); + return; + } + # Get Directory Format my @FieldPOS; my @FieldLEN; my @FieldTAG; + read($self->{'fileMST'}, $buff, 6 * $NVF); + + my $fld_len = 0; + for (my $i = 0 ; $i < $NVF ; $i++) { # $TAG=$self->Read16($fileMST); # $POS=$self->Read16($fileMST); # $LEN=$self->Read16($fileMST); - read(fileMST, $buff, 6); - my ($TAG,$POS,$LEN) = unpack("sss", $buff); + my ($TAG,$POS,$LEN) = unpack("sss", substr($buff,$i * 6, 6)); print "TAG: $TAG POS: $POS LEN: $LEN\n" if ($self->{debug}); @@ -301,24 +320,19 @@ push @FieldTAG,$TAG; push @FieldPOS,$POS; push @FieldLEN,$LEN; + + $fld_len += $LEN; } # Get Variable Fields - delete $self->{record}; + read($self->{'fileMST'},$buff,$fld_len); for (my $i = 0 ; $i < $NVF ; $i++) { - my $rec; - read(fileMST,$rec,$FieldLEN[$i]); - push @{$self->{record}->{$FieldTAG[$i]}}, $rec; + push @{$self->{record}->{$FieldTAG[$i]}}, substr($buff,$FieldPOS[$i],$FieldLEN[$i]); } close(fileMST); - # The record is marked for deletion - if ($STATUS==1) { - return -1; - } - print Dumper($self) if ($self->{debug}); return $self->{'record'}; @@ -337,9 +351,7 @@ my $mfn = shift || croak "need MFN"; - my $rec = $self->GetMFN($mfn); - -print STDERR Dumper($rec); + my $rec = $self->fetch($mfn); my $out = "0\t$mfn"; @@ -352,265 +364,6 @@ return $out; } -################# old cruft which is not ported from php to perl - -=begin php - - # Load the dictionary from the $db.L0x files. - # Not usefull Yet - - sub LoadDictionary() - { - $fileL01=fopen($self->{isisdb}.".L01","r"); - rewind($fileL01); - - do - { - - $POS=$self->Read32($fileL01); - $OCK=$self->Read16($fileL01); - $IT=$self->Read16($fileL01); - $PS=$self->Read32($fileL01); -print "
PS:".$PS." ".$self->{ORDF}->{1}." "; - for ($i=0;$i<$OCK;$i++) - { - $KEY=fread($fileL01,10); - - print $KEY." ### "; - - $INFO1=$self->Read32($fileL01); - $INFO2=$self->Read32($fileL01); - - #L01Key->{$key}=array($INFO1,$INFO2); - } - - rewind($fileL01); - $offset=($PS-1)*(12+$self->{ORDF}->{1}*18*2); - fseek($fileL01,$offset); - - } While (!feof($fileL01)); - - fclose($fileL01); - } - - # self function search through the tree and returns an array of pointers to IFP - # The function must be recursive - - sub SearchTree($search,$fileNB,$PUNT) - { - $offset=(($PUNT-1)*(8+2*$self->{ORDN}->{1}*14)); - - rewind($fileNB1); - - fseek($fileNB,$offset); - - $POS=$self->Read32($fileNB); - $OCK=$self->Read16($fileNB); - $IT=$self->Read16($fileNB); - -#print "
".$POS." - ".$OCK." - ".$IT; - - $OLDPUNT=$POS; - $j=0; - for ($i=0;$i<$OCK;$i++) - { - $KEY=fread($fileNB,10); - - $PUNT=$self->Read32($fileNB); - -#print " ## ".chop($KEY)."(".$PUNT."-".$OLDPUNT.") ## "; - - If (strcmp($search,chop($KEY))<0) - { - break; - } - $OLDPUNT=$PUNT; - } -#print $OLDPUNT; - Return $OLDPUNT; - } - - # Search ISIS for record containing search - # Return a sorted array of MFN - - sub Search($search) - { - - $search=strtoupper($search); -#print "Searching....".$search." - ".$self->{POSRX}->{1}."
"; - # first search .x01 - - - # Search in .N01 - - - $fileN01=fopen($self->{isisdb}.".N01","r"); - $offset=(($self->{POSRX}->{1}-1)*(8+2*$self->{ORDN}->{1}*14)); - - do - { - rewind($fileN01); - - fseek($fileN01,$offset); - - $POS=$self->Read32($fileN01); - $OCK=$self->Read16($fileN01); - $IT=$self->Read16($fileN01); - -#print "
".$POS." - ".$OCK." - ".$IT; - - $OLDPUNT=$POS; - for ($i=0;$i<$OCK;$i++) - { - $KEY=fread($fileN01,10); - - $PUNT=$self->Read32($fileN01); - -#print " ## ".chop($KEY)."(".$PUNT."-".$OLDPUNT.") ## "; - - If (strcmp($search,chop($KEY))<0) - { - break; - } - $OLDPUNT=$PUNT; - } - $offset=(($OLDPUNT-1)*(8+2*$self->{ORDN}->{1}*14)); - } while ($OLDPUNT>0); -#print $OLDPUNT; - - - fclose($fileN01); - - # Now look for records in .L01 file - $fileL01=fopen($self->{isisdb}.".L01","r"); - rewind($fileL01); - - $offset=(-$OLDPUNT-1)*(12+$self->{ORDF}->{1}*18*2); - fseek($fileL01,$offset); - - $POS=$self->Read32($fileL01); - $OCK=$self->Read16($fileL01); - $IT=$self->Read16($fileL01); - $PS=$self->Read32($fileL01); -#print "
POS:".$POS." ".$self->{ORDF}->{1}." "; - for ($i=0;$i<$OCK;$i++) - { - $KEY=fread($fileL01,10); - -#print $KEY." ### "; - - $INFO1=$self->Read32($fileL01); - $INFO2=$self->Read32($fileL01); - - If (strcmp($search,chop($KEY))==0) - { - break; - } - } - - fclose($fileL01); - -#print $INFO1."--".$INFO2; - - # Now look in .IFP for the MFN - $fileIFP=fopen($self->{isisdb}.".IFP","r"); - rewind($fileIFP); - $offset=($INFO1-1)*512+($INFO2*4); - fseek($fileIFP,$offset); - - $IFPBLK=$self->Read32($fileIFP); - - $IFPNXTB=$self->Read32($fileIFP); - $IFPNXTP=$self->Read32($fileIFP); - $IFPTOTP=$self->Read32($fileIFP); - $IFPSEGP=$self->Read32($fileIFP); - $IFPSEGC=$self->Read32($fileIFP); - - -#print "
IFP:".$IFPBLK." # ".$IFPNXTB." - ".$IFPNXTP." - ".$IFPTOTP." - ".$IFPSEGP." - ".$IFPSEGC; - - rewind($fileIFP); - $offset=($INFO1-1)*512+24+($INFO2*4); - fseek($fileIFP,$offset); - - $j=24+($INFO2*4); - $k=0; - $l=1; - $OLDPMFN=""; - for ($i=0;$i<$IFPSEGP;$i++) - { - $B1=$self->Read8($fileIFP); - $B2=$self->Read8($fileIFP); - $B3=$self->Read8($fileIFP); - $B4=$self->Read8($fileIFP); - $B5=$self->Read8($fileIFP); - $B6=$self->Read8($fileIFP); - $B7=$self->Read8($fileIFP); - $B8=$self->Read8($fileIFP); - - $PMFN=$B1*65536+$B2*256+$B3; - $PTAG=$B4*256+$B5; - $POCC=$B6; - $PCNT=$B7*256+$B8; - - if ($OLDPMFN!=$PMFN) - { - if ($PMFN!=0) - { - $self->{MFNArray}->{$l}=$PMFN; - $OLDPMFN=$PMFN; - $l+=1; - } - } - - $j=$j+8; -#print "
".$PMFN."-".$PTAG." - ".$POCC." - ".$PCNT; -#print "@@".$j."@@@@"; - if ($j>=504) - { - if ($IFPNXTB==0 && $IFPNXTP==0) - { - $k=$k+1; - rewind($fileIFP); - $offset=($INFO1-1+$k)*512; - fseek($fileIFP,$offset); - $B=$self->Read32($fileIFP); -#print "
-".$B."-
"; - $j=0; - } else - { - rewind($fileIFP); - $offset=($IFPNXTB-1)*512; - fseek($fileIFP,$offset); - - $OLDIFPNXTB=$IFPNXTB; - $OLDIFPNXTP=$IFPNXTP; - - $IFPBLK=$self->Read32($fileIFP); - - $IFPNXTB=$self->Read32($fileIFP); - $IFPNXTP=$self->Read32($fileIFP); - $IFPTOTP=$self->Read32($fileIFP); - $IFPSEGP=$self->Read32($fileIFP); - $IFPSEGC=$self->Read32($fileIFP); - - rewind($fileIFP); - $offset=($OLDIFPNXTB-1)*512+24+($OLDIFPNXTP*4); - fseek($fileIFP,$offset); - - $j=24+($OLDIFPNXTP*4); - $k=0; - $j=0; - } - } - - } - fclose($fileIFP); - return $l-1; - } - -=cut - # # XXX porting from php left-over: # @@ -620,110 +373,17 @@ # Probably direct usage is better! # -sub GetFieldName { - my $self = shift; - return $self->{FieldName}; -} - -sub GetTagName { +sub TagName { my $self = shift; return $self->{TagName}; } -sub GetFieldTag { - my $self = shift; - return $self->{FieldTAG}; -} - -sub GetNextMFN { +sub NextMFN { my $self = shift; return $self->{NXTMFN}; } -sub GetMFNArray { - my $self = shift; - return $self->{MFNArray}; -} -=begin php - - sub Read32($fileNB) - { - $B1=ord(fread($fileNB,1)); - $B2=ord(fread($fileNB,1)); - $B3=ord(fread($fileNB,1)); - $B4=ord(fread($fileNB,1)); - - if ($B4<=128) - { - $value=$B1+$B2*256+$B3*65536+$B4*16777216; - } else - { - $value=$self->Not8($B1)+$self->Not8($B2)*256+$self->Not8($B3)*65536+$self->Not8($B4)*16777216; - $value=-($value+1); - } -# print "(".$B1.",".$B2.",".$B3.",".$B4.":".$value.")"; - - return $value; - } - - sub Read24($fileNB) - { - $B1=ord(fread($fileNB,1)); - $B2=ord(fread($fileNB,1)); - $B3=ord(fread($fileNB,1)); - - $value=$B1+$B2*256+$B3*65536; - -# print "(".$B1.",".$B2.",".$B3.":".$value.")"; - - return $value; - } - - sub Read16($fileNB) - { - $B1=ord(fread($fileNB,1)); - $B2=ord(fread($fileNB,1)); - - $value=$B1+$B2*256; -# print "(".$B1.",".$B2.":".$value.")"; - - return $value; - } - - sub Read8($fileNB) - { - $B1=ord(fread($fileNB,1)); - - $value=$B1; -# print "(".$value.")"; - - return $value; - } - - sub Not8($value) - { - $value=decbin($value); - if (strlen($value)<8) - { - $buffer=""; - for($i=0;$i<(8-strlen($value));$i++) - { - $buffer.="0"; - } - $value=$buffer.$value; - } - $value=ereg_replace("0","3",$value); - $value=ereg_replace("1","0",$value); - $value=ereg_replace("3","1",$value); - $value=bindec($value); - return $value; - } -} - -=cut - 1; -__END__ =head1 BUGS