File Coverage

blib/lib/NNML/Group.pm
Criterion Covered Total %
statement 6 108 5.5
branch 0 38 0.0
condition 0 12 0.0
subroutine 2 19 10.5
pod 0 15 0.0
total 8 192 4.1


line stmt bran cond sub pod time code
1             # -*- Mode: Perl -*-
2             # Group.pm --
3             # ITIID : $ITI$ $Header $__Header$
4             # Author : Ulrich Pfeifer
5             # Created On : Sat Sep 28 16:33:51 1996
6             # Last Modified By: Ulrich Pfeifer
7             # Last Modified On: Sat Mar 15 13:44:15 1997
8             # Language : CPerl
9             # Update Count : 58
10             # Status : Unknown, Use with caution!
11             #
12             # (C) Copyright 1996, Universität Dortmund, all rights reserved.
13             #
14              
15             package NNML::Group;
16 1     1   930 use IO::File;
  1         34186  
  1         154  
17 1     1   12 use strict;
  1         2  
  1         1327  
18              
19             sub new {
20 0     0 0   my $type = shift;
21 0           my %parm = @_;
22 0           my $self = {};
23              
24 0           for (qw(name dir min max post ctime)) {
25 0 0         $self->{'_'.$_} = $parm{$_} if exists $parm{$_};
26             }
27 0           $self->{_time} = 0;
28 0           bless $self, $type;
29             }
30              
31 0     0 0   sub max { $_[0]->{_max}};
32 0     0 0   sub min { $_[0]->{_min}};
33 0     0 0   sub name { $_[0]->{_name}};
34 0     0 0   sub post { $_[0]->{_post}};
35 0     0 0   sub ctime { $_[0]->{_ctime}};
36 0     0 0   sub dir { $_[0]->{_dir}};
37              
38             sub add {
39 0     0 0   my ($self, $id) = @_;
40 0           my $ano = ++$self->{_max};
41              
42 0 0         if ($id) {
43 0           $self->{_byid}->{$id} = $ano;
44 0           $self->{_byno}->{$ano} = $id;
45             }
46 0           $ano;
47             }
48              
49             sub article_by_id {
50 0     0 0   my ($self, $msgid) = @_;
51              
52 0           $self->_update;
53 0           $self->{_byid}->{$msgid};
54             }
55              
56             sub article_by_no {
57 0     0 0   my ($self, $ano) = @_;
58              
59 0           $self->_update;
60 0           $self->{_byno}->{$ano};
61             }
62              
63 0     0 0   sub overview {$_[0]->{_dir}. '/.overview'}
64              
65             sub _update {
66 0     0     my $self = shift;
67              
68             # Assume '.overview' has not changed if 'active' was not
69             # modified. The implementation is not correct since a stat() for
70             # active is not forced - but it saves many stat() calls. A stat()
71             # call for 'active' is forced when message id's are used. Therfore
72             # this is quite good.
73              
74 0 0         if (NNML::Active::last_change() > $self->{_time}) {
75 0           my $mtime = (stat($self->overview))[9];
76              
77 0 0         $self->_read_overview if $mtime > $self->{_time};
78             }
79             }
80              
81             sub _read_overview {
82 0     0     my $self = shift;
83 0           $self->{_time} = time;
84 0           $self->{_byid} = {};
85 0           $self->{_byno} = {};
86 0           $self->{_ctime} = (stat($self->overview))[9];
87 0           my $fh = new IO::File "<" . $self->overview;
88 0 0         die "Could not read overview file" unless defined $fh;
89 0           my $line;
90 0           while (defined ($line = <$fh>)) {
91 0           chomp($line);
92 0           my($ano, $subject, $from, $date, $id, $references, $chars, $lines, $xref)
93             = split /\t/, $line;
94 0           $id =~ s/^\s+//; $id =~ s/\s+$//;
  0            
95 0           $self->{_byid}->{$id} = $ano;
96 0           $self->{_byno}->{$ano} = $id;
97             }
98 0           $fh->close;
99             }
100              
101             # This assumes that articles are stored in increasing order.
102             # It deserves tuning (binary search).
103             sub newnews {
104 0     0 0   my ($self, $time) = @_;
105 0           my %result;
106            
107 0           $self->_update;
108 0 0         return () if $self->{_ctime} < $time;
109 0           my $ano;
110 0           my $dir = $self->{_dir}.'/';
111 0           for ($ano=$self->max;$ano>=$self->min;$ano--) {
112 0           my $file = $dir.$ano;
113 0 0         if (-e $file) {
114 0           my $ctime = (stat($file))[9];
115 0 0         if ($ctime >= $time) {
116 0           $result{$self->{_byno}->{$ano}} = $ctime;
117             } else {
118 0           last;
119             }
120             }
121             }
122 0           %result;
123             }
124              
125             sub xover {
126 0     0 0   my ($self,$min,$max) = @_;
127 0           my $result;
128              
129 0   0       $min ||= $self->min;
130 0   0       $max ||= $self->max;
131 0           my $fh = new IO::File "<" . $self->overview;
132 0 0         die "Could not read overview file" unless defined $fh;
133 0           my $line;
134 0           while (defined ($line = <$fh>)) {
135 0 0         if ($line =~ /^(\d+)/) {
136 0 0 0       if ($1 >= $min and $1 <= $max) {
137 0           $result .= $line;
138             }
139             }
140             }
141 0           $fh->close;
142 0           $result;
143             }
144              
145             sub get {
146 0     0 0   my ($self, $ano) = @_;
147 0           my $file = $self->{_dir} . "/$ano";
148 0 0         if (-e $file) {
149 0           my $date = ((stat($file))[10]);
150 0           my $fh = new IO::File "<" . $file;
151 0 0         return unless $fh;
152 0           local($/);
153              
154 0           my ($head, $body) = split /^\r?\n/m, <$fh>, 2;
155 0           return $head, $body, $date;
156             }
157             }
158              
159             sub delete {
160 0     0 0   my ($self, $ano) = @_;
161 0           my $file = $self->{_dir} . "/$ano";
162 0           my ($result, $line);
163            
164 0 0         if (-e $file) {
165 0 0         unlink $file or return;
166             }
167 0           my $overview = $self->overview;
168 0           my $backup = $self->overview . '~';
169 0 0         rename ($overview, $backup) or return;
170 0           my $in = new IO::File "<" . $backup;
171 0           my $out = new IO::File ">" . $overview;
172 0 0 0       return unless $in and $out;
173 0           while (defined ($line = <$in>)) {
174 0 0         if ($line =~ /^(\d+)/) {
175 0 0         if ($1 == $ano) {
176 0           $result++;
177 0           next;
178             }
179             }
180 0           $out->print($line);
181             }
182 0           $in->close;
183 0           $out->close;
184 0           return($result);
185             }
186              
187             1;