/[classpath]/inetlib/source/gnu/inet/nntp/FileNewsrc.java
ViewVC logotype

Diff of /inetlib/source/gnu/inet/nntp/FileNewsrc.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1 by dog, Sun Oct 19 08:51:37 2003 UTC revision 1.2 by dog, Sun Oct 19 16:16:50 2003 UTC
# Line 47  import java.util.Map; Line 47  import java.util.Map;
47   * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>   * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
48   * @version $Revision$ $Date$   * @version $Revision$ $Date$
49   */   */
50  public class FileNewsrc  public class FileNewsrc implements Newsrc
   implements Newsrc  
51  {  {
52    
53    private static final String NEWSRC_ENCODING = "US-ASCII";    private static final String NEWSRC_ENCODING = "US-ASCII";
54            
55    protected File file;    protected File file;
56    
57    protected List subs = null;    protected List subs = null;
# Line 60  public class FileNewsrc Line 59  public class FileNewsrc
59    protected Map lines = null;    protected Map lines = null;
60    protected boolean dirty;    protected boolean dirty;
61    protected boolean debug;    protected boolean debug;
62            
63    /**    /**
64     * Constructs a FileNewsrc for the specified url.     * Constructs a FileNewsrc for the specified url.
65     */     */
66    public FileNewsrc(File file, boolean debug)    public FileNewsrc(File file, boolean debug)
67    {    {
68      this.file = file;      this.file = file;
69      this.debug = debug;      this.debug = debug;
70    }    }
71      
72    public void close()    public void close()
73    {    {
74      if (!dirty)      if (!dirty)
75        return;        return;
# Line 83  public class FileNewsrc Line 82  public class FileNewsrc
82    void load()    void load()
83    {    {
84      long fs = file.length();      long fs = file.length();
85      long max = (long)Integer.MAX_VALUE;      long max = (long) Integer.MAX_VALUE;
86      int bs = (int)(fs>max ? max : fs);      int bs = (int) (fs > max ? max : fs);
87        
88      groups = new LinkedList();      groups = new LinkedList();
89      lines = new HashMap(bs/20);      lines = new HashMap(bs / 20);
90      subs = new LinkedList();      subs = new LinkedList();
91    
92      // Load      // Load
93      try      try
94      {      {
95        long t1 = System.currentTimeMillis();        long t1 = System.currentTimeMillis();
96        //long rcount = 0;        //long rcount = 0;
97        if (debug)        if (debug)
98          System.err.println("DEBUG: nntp: newsrc loading "+file.getPath());          System.err.println("DEBUG: nntp: newsrc loading " + file.getPath());
99          
100        FileInputStream fr = new FileInputStream(file);        FileInputStream fr = new FileInputStream(file);
101        InputStreamReader ir = new InputStreamReader(fr, NEWSRC_ENCODING);        InputStreamReader ir = new InputStreamReader(fr, NEWSRC_ENCODING);
102        BufferedReader reader = new BufferedReader(ir, bs);        BufferedReader reader = new BufferedReader(ir, bs);
# Line 105  public class FileNewsrc Line 104  public class FileNewsrc
104        String line = reader.readLine();        String line = reader.readLine();
105        //long tt2 = System.currentTimeMillis();        //long tt2 = System.currentTimeMillis();
106        //rcount += (tt2-tt1);        //rcount += (tt2-tt1);
107        while (line!=null)        while (line != null)
108        {        {
109          int cp = line.indexOf(':');          int cp = line.indexOf(':');
110          if (cp>-1)          if (cp > -1)
111          {          {
112            // Subscribed newsgroup            // Subscribed newsgroup
113            String name = line.substring(0, cp);            String name = line.substring(0, cp);
114            groups.add(name);            groups.add(name);
115            subs.add(name);            subs.add(name);
116            cp++;            cp++;
117            if (cp<line.length())            if (cp < line.length())
118            {            {
119              String tail = line.substring(cp).trim();              String tail = line.substring(cp).trim();
120              if (tail.length()>0)              if (tail.length() > 0)
121                lines.put(name, tail);                lines.put(name, tail);
122            }            }
123          }          }
124          else          else
125          {          {
126            int pp = line.indexOf('!');            int pp = line.indexOf('!');
127            if (pp>-1)            if (pp > -1)
128            {            {
129              // Unsubscribed newsgroup              // Unsubscribed newsgroup
130              String name = line.substring(0, pp);              String name = line.substring(0, pp);
131              groups.add(name);              groups.add(name);
132              pp++;              pp++;
133              if (pp<line.length())              if (pp < line.length())
134              {              {
135                String tail = line.substring(pp).trim();                String tail = line.substring(pp).trim();
136                if (tail.length()>0)                if (tail.length() > 0)
137                  lines.put(name, tail);                  lines.put(name, tail);
138              }              }
139            }            }
# Line 148  public class FileNewsrc Line 147  public class FileNewsrc
147        reader.close();        reader.close();
148    
149        long t2 = System.currentTimeMillis();        long t2 = System.currentTimeMillis();
150          
151        //System.err.println("rcount="+rcount);        //System.err.println("rcount="+rcount);
152        //System.err.println("total="+(t2-t1));        //System.err.println("total="+(t2-t1));
153          
154        if (debug)        if (debug)
155          System.err.println("DEBUG: nntp: newsrc load: "+          System.err.println("DEBUG: nntp: newsrc load: " +
156              groups.size()+" groups in "+(t2-t1)+"ms");                             groups.size() + " groups in " + (t2 - t1) + "ms");
157      }      }
158      catch (FileNotFoundException e)      catch(FileNotFoundException e)
159      {      {
160      }      }
161      catch (IOException e)      catch(IOException e)
162      {      {
163        System.err.println("WARNING: nntp: unable to read newsrc file");        System.err.println("WARNING: nntp: unable to read newsrc file");
164        if (debug)        if (debug)
165          e.printStackTrace(System.err);          e.printStackTrace(System.err);
166      }      }
167      catch (SecurityException e)      catch(SecurityException e)
168      {      {
169        System.err.println("WARNING: nntp: no read permission on newsrc file");        System.err.println("WARNING: nntp: no read permission on newsrc file");
170      }      }
171      dirty = false;      dirty = false;
172    }    }
173                            
174    /**    /**
175     * Save the file.     * Save the file.
176     */     */
177    void save()    void save()
178    {    {
179      try      try
180      {      {
181        long t1 = System.currentTimeMillis();        long t1 = System.currentTimeMillis();
182        if (debug)        if (debug)
183          System.err.println("DEBUG: nntp: newsrc saving "+file.getPath());          System.err.println("DEBUG: nntp: newsrc saving " + file.getPath());
184    
185        int bs = (groups.size()*20); // guess an average line length        int bs = (groups.size() * 20);    // guess an average line length
186        FileOutputStream fw = new FileOutputStream(file);        FileOutputStream fw = new FileOutputStream(file);
187        BufferedOutputStream writer = new BufferedOutputStream(fw, bs);        BufferedOutputStream writer = new BufferedOutputStream(fw, bs);
188        for (Iterator i = groups.iterator(); i.hasNext(); )        for (Iterator i = groups.iterator(); i.hasNext();)
189        {        {
190          String group = (String)i.next();          String group = (String) i.next();
191          StringBuffer buffer = new StringBuffer(group);          StringBuffer buffer = new StringBuffer(group);
192          if (subs.contains(group))          if (subs.contains(group))
193            buffer.append(':');            buffer.append(':');
# Line 196  public class FileNewsrc Line 195  public class FileNewsrc
195            buffer.append('!');            buffer.append('!');
196          Object r = lines.get(group);          Object r = lines.get(group);
197          if (r instanceof String)          if (r instanceof String)
198            buffer.append((String)r);            buffer.append((String) r);
199          else          else
200          {          {
201            RangeList ranges = (RangeList)r;            RangeList ranges = (RangeList) r;
202            if (ranges!=null)            if (ranges != null)
203              buffer.append(ranges.toString());              buffer.append(ranges.toString());
204          }          }
205          buffer.append('\n');          buffer.append('\n');
206    
207          byte[] bytes = buffer.toString().getBytes(NEWSRC_ENCODING);          byte[]bytes = buffer.toString().getBytes(NEWSRC_ENCODING);
208          writer.write(bytes);          writer.write(bytes);
209        }        }
210        writer.flush();        writer.flush();
# Line 213  public class FileNewsrc Line 212  public class FileNewsrc
212    
213        long t2 = System.currentTimeMillis();        long t2 = System.currentTimeMillis();
214        if (debug)        if (debug)
215          System.err.println("DEBUG: nntp: newsrc save: "+          System.err.println("DEBUG: nntp: newsrc save: " +
216             groups.size()+" groups in "+(t2-t1)+"ms");                             groups.size() + " groups in " + (t2 - t1) + "ms");
217      }      }
218      catch (IOException e)      catch(IOException e)
219      {      {
220        System.err.println("WARNING: nntp: unable to save newsrc file");        System.err.println("WARNING: nntp: unable to save newsrc file");
221        if (debug)        if (debug)
# Line 224  public class FileNewsrc Line 223  public class FileNewsrc
223      }      }
224      dirty = false;      dirty = false;
225    }    }
226            
227    /**    /**
228     * Returns an iterator over the names of the currently subscribed     * Returns an iterator over the names of the currently subscribed
229     * newsgroups.     * newsgroups.
230     */     */
231    public Iterator list()    public Iterator list()
232    {    {
233      if (subs==null)      if (subs == null)
234        load();        load();
235      return subs.iterator();      return subs.iterator();
236    }    }
237            
238    public boolean isSubscribed(String newsgroup)    public boolean isSubscribed(String newsgroup)
239    {    {
240      if (subs==null)      if (subs == null)
241        load();        load();
242      return (subs.contains(newsgroup));      return (subs.contains(newsgroup));
243    }    }
244            
245    public void setSubscribed(String newsgroup, boolean flag)    public void setSubscribed(String newsgroup, boolean flag)
246    {    {
247      if (subs==null)      if (subs == null)
248        load();        load();
249      boolean subscribed = subs.contains(newsgroup);      boolean subscribed = subs.contains(newsgroup);
250      if (flag && !subscribed)      if (flag && !subscribed)
# Line 259  public class FileNewsrc Line 258  public class FileNewsrc
258        dirty = true;        dirty = true;
259      }      }
260    }    }
261            
262    public boolean isSeen(String newsgroup, int article)    public boolean isSeen(String newsgroup, int article)
263    {    {
264      if (subs==null)      if (subs == null)
265        load();        load();
266      Object value = lines.get(newsgroup);      Object value = lines.get(newsgroup);
267      if (value instanceof String)      if (value instanceof String)
268        value = new RangeList((String)value);        value = new RangeList((String) value);
269      RangeList ranges = (RangeList)value;      RangeList ranges = (RangeList) value;
270      if (ranges!=null)      if (ranges != null)
271        return ranges.isSeen(article);        return ranges.isSeen(article);
272      return false;      return false;
273    }    }
274                    
275    public void setSeen(String newsgroup, int article, boolean flag)    public void setSeen(String newsgroup, int article, boolean flag)
276    {    {
277      if (subs==null)      if (subs == null)
278        load();        load();
279      Object value = lines.get(newsgroup);      Object value = lines.get(newsgroup);
280      if (value instanceof String)      if (value instanceof String)
281        value = new RangeList((String)value);        value = new RangeList((String) value);
282      RangeList ranges = (RangeList)value;      RangeList ranges = (RangeList) value;
283      if (ranges==null)      if (ranges == null)
284      {      {
285        ranges = new RangeList();        ranges = new RangeList();
286        lines.put(newsgroup, ranges);        lines.put(newsgroup, ranges);
287      }      }
288      if (ranges.isSeen(article)!=flag)      if (ranges.isSeen(article) != flag)
289      {      {
290        ranges.setSeen(article, flag);        ranges.setSeen(article, flag);
291        dirty = true;        dirty = true;
292      }      }
293    }    }
294            
295    /**    /**
296     * A RangeList holds a series of ranges that are ordered and     * A RangeList holds a series of ranges that are ordered and
297     * non-overlapping.     * non-overlapping.
298     */     */
299    static class RangeList    static class RangeList
300    {    {
301        
302      List seen;      List seen;
303              
304      RangeList()        RangeList()
305      {      {
306        seen = new LinkedList();        seen = new LinkedList();
307      }      }
308        
309      RangeList(String line)      RangeList(String line)
310      {      {
311        this();        this();
312        try        try
313        {        {
314          // Parse the line at comma delimiters.          // Parse the line at comma delimiters.
315          int start = 0;          int start = 0;
316          int end = line.indexOf(',');          int end = line.indexOf(',');
317          while (end>start)          while (end > start)
318          {          {
319            String token = line.substring(start, end);            String token = line.substring(start, end);
320            addToken(token);            addToken(token);
321            start = end+1;            start = end + 1;
322            end = line.indexOf(',', start);            end = line.indexOf(',', start);
323          }          }
324          addToken(line.substring(start));          addToken(line.substring(start));
325        }        }
326        catch (NumberFormatException e)        catch(NumberFormatException e)
327        {        {
328          System.err.println("ERROR: nntp: bad newsrc format: "+line);          System.err.println("ERROR: nntp: bad newsrc format: " + line);
329        }        }
330      }      }
331    
332      /*      /*
333       * Used during initial parse.       * Used during initial parse.
334       */       */
335      private void addToken(String token)      private void addToken(String token) throws NumberFormatException
       throws NumberFormatException  
336      {      {
337        int hp = token.indexOf('-');        int hp = token.indexOf('-');
338        if (hp>-1)        if (hp > -1)
339        {        {
340          // Range          // Range
341          String fs = token.substring(0, hp);          String fs = token.substring(0, hp);
342          String ts = token.substring(hp+1);          String ts = token.substring(hp + 1);
343          int from = Integer.parseInt(fs);          int from = Integer.parseInt(fs);
344          int to = Integer.parseInt(ts);          int to = Integer.parseInt(ts);
345          if (from>-1 && to>-1)          if (from > -1 && to > -1)
346            insert(from, to);              insert(from, to);
347        }        }
348        else        else
349        {        {
350          // Single number          // Single number
351          int number = Integer.parseInt(token);          int number = Integer.parseInt(token);
352          if (number>-1)          if (number > -1)
353            insert(number);            insert(number);
354        }        }
355      }      }
356      
357      /**      /**
358       * Indicates whether the specified article is seen.       * Indicates whether the specified article is seen.
359       */       */
360      public boolean isSeen(int num)      public boolean isSeen(int num)
361      {      {
362        int len = seen.size();        int len = seen.size();
363        Range[] r = new Range[len];        Range[]r = new Range[len];
364        seen.toArray(r);        seen.toArray(r);
365        for (int i=0; i<len; i++)        for (int i = 0; i < len; i++)
366        {        {
367          if (r[i].contains(num))          if (r[i].contains(num))
368            return true;            return true;
369        }        }
370        return false;        return false;
371      }      }
372        
373      /**      /**
374       * Sets whether the specified article is seen.       * Sets whether the specified article is seen.
375       */       */
376      public void setSeen(int num, boolean flag)      public void setSeen(int num, boolean flag)
377      {      {
378        if (flag)        if (flag)
379          insert(num);          insert(num);
380        else        else
381          remove(num);          remove(num);
382      }      }
383              
384      /*      /*
385       * Find the index within seen to insert the specified article.       * Find the index within seen to insert the specified article.
386       * The range object at the returned index may already contain num.       * The range object at the returned index may already contain num.
387       */       */
388      int indexOf(int num)      int indexOf(int num)
389      {      {
390        int len = seen.size();        int len = seen.size();
391        Range[] r = new Range[len];        Range[]r = new Range[len];
392        seen.toArray(r);        seen.toArray(r);
393        for (int i=0; i<len; i++)        for (int i = 0; i < len; i++)
394        {        {
395          if (r[i].contains(num))          if (r[i].contains(num))
396            return i;            return i;
397          if (r[i].from>num)          if (r[i].from > num)
398            return i;            return i;
399          if (r[i].to==num-1)          if (r[i].to == num - 1)
400            return i;            return i;
401        }        }
402        return len;        return len;
403      }      }
404        
405      void insert(int start, int end)      void insert(int start, int end)
406      {      {
407        Range range = new Range(start, end);        Range range = new Range(start, end);
408        int i1 = indexOf(range.from);        int i1 = indexOf(range.from);
409        // range is at end        // range is at end
410        if (i1==seen.size())        if (i1 == seen.size())
411        {        {
412          seen.add(range);          seen.add(range);
413          return;          return;
414        }        }
415        Range r1 = (Range)seen.get(i1);        Range r1 = (Range) seen.get(i1);
416        // range is before r1        // range is before r1
417        if (range.to<r1.from)        if (range.to < r1.from)
418        {        {
419          seen.add(i1, range);          seen.add(i1, range);
420          return;          return;
421        }        }
422        // range is a subset of r1        // range is a subset of r1
423        if (r1.from<=range.from && r1.to>=range.to)        if (r1.from <= range.from && r1.to >= range.to)
424          return;          return;
425        // range is a superset of r1        // range is a superset of r1
426        int i2 = indexOf(range.to);        int i2 = indexOf(range.to);
427        Range r2 = (Range)seen.get(i2);        Range r2 = (Range) seen.get(i2);
428        System.err.println("r2 "+r2+" i2 "+i2);        System.err.println("r2 " + r2 + " i2 " + i2);
429        // remove all ranges between        // remove all ranges between
430        for (int i=i2; i>=i1; i--)        for (int i = i2; i >= i1; i--)
431          seen.remove(i);          seen.remove(i);
432        // merge        // merge
433        int f = (range.from<r1.from) ? range.from : r1.from;        int f = (range.from < r1.from) ? range.from : r1.from;
434        int t = (range.to>r2.to) ? range.to : r2.to;        int t = (range.to > r2.to) ? range.to : r2.to;
435        range = new Range(f, t);        range = new Range(f, t);
436        seen.add(i1, range);        seen.add(i1, range);
437      }      }
438              
439      void insert(int num)      void insert(int num)
440      {      {
441        insert(num, num);        insert(num, num);
442      }      }
443              
444      void remove(int num)      void remove(int num)
445      {      {
446        int i = indexOf(num);        int i = indexOf(num);
447        Range r = (Range)seen.get(i);        Range r = (Range) seen.get(i);
448        seen.remove(i);        seen.remove(i);
449        // num == r        // num == r
450        if ((r.from==r.to) && (r.to==num))        if ((r.from == r.to) && (r.to == num))
451          return;          return;
452        // split r        // split r
453        if (r.to>num)        if (r.to > num)
454        {        {
455          Range r2 = new Range(num+1, r.to);          Range r2 = new Range(num + 1, r.to);
456          seen.add(i, r2);          seen.add(i, r2);
457        }        }
458        if (r.from<num)        if (r.from < num)
459        {        {
460          Range r2 = new Range(r.from, num-1);          Range r2 = new Range(r.from, num - 1);
461          seen.add(i, r2);          seen.add(i, r2);
462        }        }
463      }      }
464              
465      public String toString()      public String toString()
466      {      {
467        StringBuffer buf = new StringBuffer();        StringBuffer buf = new StringBuffer();
468        int len = seen.size();        int len = seen.size();
469        for (int i=0; i<len; i++)        for (int i = 0; i < len; i++)
470        {        {
471          Range range = (Range)seen.get(i);          Range range = (Range) seen.get(i);
472          if (i>0)          if (i > 0)
473            buf.append(',');            buf.append(',');
474          buf.append(range.toString());          buf.append(range.toString());
475        }        }
476        return buf.toString();        return buf.toString();
477      }      }
478        
479    }    }
480            
481    /**    /**
482     * A range is either a single integer or a range between two integers.     * A range is either a single integer or a range between two integers.
483     */     */
# Line 487  public class FileNewsrc Line 485  public class FileNewsrc
485    {    {
486      int from;      int from;
487      int to;      int to;
488              
489      public Range(int i)      public Range(int i)
490      {      {
491        from = to = i;            from = to = i;
492      }      }
493              
494      public Range(int f, int t)      public Range(int f, int t)
495      {      {
496        if (f>t)        if (f > t)
497        {        {
498          from = t;          from = t;
499          to = f;          to = f;
500        }        }
501        else        else
502        {        {
503          from = f;          from = f;
504          to = t;          to = t;
505        }        }
506      }      }
507              
508      public boolean contains(int num)      public boolean contains(int num)
509      {      {
510        return (num>=from && num<=to);        return (num >= from && num <= to);
511      }      }
512              
513      public String toString()      public String toString()
514      {      {
515        StringBuffer buf = new StringBuffer();        StringBuffer buf = new StringBuffer();
516        buf.append(from);        buf.append(from);
# Line 520  public class FileNewsrc Line 518  public class FileNewsrc
518          buf.append("-").append(to);          buf.append("-").append(to);
519        return buf.toString();        return buf.toString();
520      }      }
521        
522    }    }
523            
524  }  }

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26