home *** CD-ROM | disk | FTP | other *** search
/ PC World 2001 April / PCWorld_2001-04_cd.bin / Software / TemaCD / smartcache / src / cachedir.java < prev    next >
Encoding:
Java Source  |  2001-01-26  |  11.9 KB  |  461 lines

  1. /*
  2.  *  Smart Cache, http proxy cache server
  3.  *  Copyright (C) 1998, 1999 Radim Kolar 
  4.  *
  5.  *    Smart Cache is Open Source Software; you may redistribute it
  6.  *  and/or modify it under the terms of the GNU General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2, or (at your option) any later version.
  9.  *
  10.  *    This program distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13.  *  General Public License for more details.
  14.  *
  15.  *    A copy of the GNU General Public License is available as
  16.  *  /usr/doc/copyright/GPL in the Debian GNU/Linux distribution or on
  17.  *  the World Wide Web at http://www.gnu.org/copyleft/gpl.html. You
  18.  *  can also obtain it by writing to the Free Software Foundation,
  19.  *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20.  */
  21.  
  22. import java.io.*;
  23. import java.util.*;
  24. import java.util.zip.*;
  25. import java.net.*;
  26.  
  27. public final class cachedir{
  28.  
  29.  
  30. public static final String DIRINFO=".cacheinfo";
  31. public static boolean readonly;
  32. static mgr parent;
  33.  
  34. /* private data */
  35. private String localdir;
  36. private Hashtable objects;
  37. public boolean dirty;
  38.  
  39. cachedir(String locdir)
  40. {
  41.  objects=new Hashtable();
  42.  localdir=locdir;
  43.  
  44.  File f=new File(locdir);
  45.  if(f.exists() && !f.isDirectory())
  46.   {
  47.    /* konflikt se jmenem souboru, smazeme ho */ 
  48.    System.out.println("Directory "+locdir+" has the same name as existing file. File removed.");
  49.    f.delete();
  50.   }
  51.  if(!f.exists()) 
  52.                   {
  53.            if(readonly) {localdir=null;return;}
  54.                    f.mkdirs();
  55.                    if(!f.exists()) 
  56.                      { 
  57.                        /* likvidujeme up-dirs, mozna je to konflikt se souborem */
  58.                        File thisdir=new File(localdir.substring(0,localdir.length()-1));
  59.                        while(true)
  60.                        {  
  61.                           String par;
  62.                           thisdir.delete();
  63.                           par=thisdir.getParent();
  64.                           if(par==null) break;
  65.                           thisdir=new File(par);
  66.                        }
  67.                        f.mkdirs();
  68.                        if(!f.exists())
  69.                        {     
  70.                        System.out.println("Cannot create directory "+localdir+" - turning caching off for it.");
  71.                        localdir=null;
  72.                        return;
  73.                        }
  74.                      }
  75.                    
  76.                   }
  77.                   
  78.  dirty=false;
  79.  /* nacteme cachovane objekty */
  80.  
  81.  DataInputStream is=null;
  82.  try{
  83.  is=new DataInputStream( 
  84.                  new BufferedInputStream(
  85.                  new FileInputStream( localdir+DIRINFO ),4096));
  86.                  
  87.  int howmany=is.readInt();
  88.  byte version=2;
  89.  if(howmany==0x53433033) 
  90.   {
  91.    version=3;
  92.    howmany=is.readInt();
  93.   }
  94.  for(int i=0;i<howmany;i++)
  95.   {
  96.    cacheobject o;
  97.    o=new cacheobject(is,this,version);
  98.    objects.put(o.getName(),o);
  99.   }
  100.  is.close(); 
  101.  }
  102.  catch(IOException e) {
  103.                        try{
  104.                          if(is!=null) { System.out.println("ERROR reading "+localdir+DIRINFO+", file corrupted?");
  105.                                         is.close();
  106.                                       }
  107.                           }
  108.                         catch (IOException z) {}  
  109.                        };
  110. } /* konstruktor */
  111.  
  112. final public synchronized void save()
  113. {
  114.  if(localdir==null || readonly==true) { dirty=false;return;}
  115.  if(!dirty) return;
  116.  
  117.  /* smazat ty, ktere neukladame */
  118.  Enumeration en=objects.elements();
  119.  while(en.hasMoreElements())
  120.   {
  121.    cacheobject o=(cacheobject)en.nextElement();
  122.    if(!o.needSave())
  123.                       objects.remove(o.getName());
  124.  
  125.   }
  126.  int howmany;
  127.  howmany=objects.size();
  128.  if(howmany==0) {
  129.                   /* nemusime nic ukladat */ 
  130.                   dirty=false;
  131.                   return;
  132.                  }
  133.  
  134.   try{
  135.  DataOutputStream os=new DataOutputStream(
  136.                      new BufferedOutputStream(
  137.                      new FileOutputStream( localdir+DIRINFO),4096 ));
  138.                      
  139.  os.writeInt(0x53433033); // VERSION 3
  140.  os.writeInt(howmany);
  141.  en=objects.elements();
  142.  while(en.hasMoreElements())
  143.   {
  144.    cacheobject o=(cacheobject)en.nextElement();
  145.    if(o.needSave())
  146.                 o.save(os);
  147.         /*
  148.        else
  149.                  { objects.remove(o.getName());
  150.                    os.close();save();return;}
  151.         */
  152.   }
  153.  os.flush();
  154.  os.close();
  155.  dirty=false;
  156.  }
  157.  catch (FileNotFoundException e) 
  158.     /* nekdo nam smazal hot dir, ze by BFU nebo GC ? */
  159.    {
  160.      dirty=false;
  161.      if(new File(localdir).exists()) 
  162.       { /* .cacheinfo no perm for write */
  163.        System.out.println("No write access to "+localdir+DIRINFO);
  164.        dirty=false; // no retry
  165.        return;
  166.       }
  167.      System.out.println("Lost Directory "+localdir);
  168.      localdir=null;
  169.      objects=new Hashtable();
  170.      return;
  171.     }
  172.  catch (IOException e) 
  173.    {
  174.      System.out.println("**DIRECTORY SAVE ERROR** "+localdir+"  ("+e+")");
  175.      dirty=false; // no retry
  176.    }
  177. }
  178.  
  179. final public boolean cleandir()
  180. {
  181.   if(localdir==null) return false;
  182.   if(objects.size()!=0) return false; /* safe-check */
  183.   boolean rc;
  184.   rc=true;
  185.   
  186.    File thisdir=new File(localdir.substring(0,localdir.length()-1));
  187.    String filez[]=thisdir.list();
  188.    if(filez==null) return true;
  189.    for(int i=0;i<filez.length;i++)
  190.    {
  191.     if(!new File(localdir,filez[i]).delete()) rc=false;
  192.    }
  193.    if(rc) System.err.println("Cleaned empty dir: "+localdir);
  194.      else
  195.        { localdir=null;return false;}
  196.    
  197.    /* likvidujeme up-dirs*/
  198.    while(thisdir.delete())
  199.     {
  200.      String par;
  201.      par=thisdir.getParent();
  202.      if(par==null) break;
  203.      thisdir=new File(par);
  204.     }
  205.     localdir=null;
  206.     return rc;
  207. }
  208.  
  209. final public int countObjects()
  210. {
  211.  return objects.size();
  212. }
  213.  
  214. final public synchronized cacheobject getObject(String name)
  215. {
  216.  cacheobject obj;
  217.  obj=(cacheobject) objects.get(name);
  218.  if(obj!=null) return obj;
  219.  obj=new cacheobject(name,this);
  220.  objects.put(name,obj);
  221.  return obj;
  222. }
  223.  
  224. final synchronized void putObject(cacheobject co)
  225. {
  226.  dirty=true;
  227.  objects.put(co.getName(),co);
  228. }
  229.  
  230. final public boolean equals(Object o)
  231. {
  232.  if(o==null || ! (o instanceof cachedir)) return false;
  233.  cachedir o1=(cachedir)o;
  234.  
  235.  return localdir.equals(o1.getLocalDir());
  236. }
  237.  
  238. final public String getLocalDir()
  239. {
  240.  return localdir;
  241. }
  242.  
  243. final public String toString()
  244. {
  245.  return localdir;
  246. }
  247.  
  248. final public int hashCode()
  249. {
  250.  if(localdir==null) return 0;
  251.  return localdir.hashCode();
  252. final public void compressdir()
  253. {
  254.  // System.out.println("Compressing directory: "+localdir);
  255.  Enumeration en=objects.elements();
  256.  while(en.hasMoreElements())
  257.   {
  258.    cacheobject o;
  259.    o=(cacheobject)en.nextElement();
  260.    o.compress(9);
  261.   }
  262. }
  263.  
  264. final public String[] listLocalNames()
  265. {
  266.  String res[]=new String[objects.size()];
  267.  int i=0; 
  268.  Enumeration en=objects.elements();
  269.  while(en.hasMoreElements())
  270.   {
  271.    cacheobject o=(cacheobject)en.nextElement();
  272.    res[i++]=o.getLocalName();
  273.   }
  274.   return res;
  275. }
  276.  
  277. /* zjisti aktualnost objektu  */
  278. /* smaze neexistujici objekty */
  279. final public boolean checkDir()
  280. {
  281.  Enumeration en=objects.elements();
  282.  while(en.hasMoreElements())
  283.   {
  284.    cacheobject o=(cacheobject)en.nextElement();
  285.    if(!o.isValid()) { objects.remove(o.getName()); 
  286.                       dirty=true;
  287.                       System.out.println(" - Bad .cacheinfo data for "+localdir+o.getLocalName());
  288.                       }
  289.   }
  290.   return !dirty;
  291. }
  292.  
  293. /* smaze referenci na objekt */
  294. final public void remove(cacheobject o)
  295. {
  296.  objects.remove(o.getName());
  297.  // o.delete();
  298.  dirty=true;
  299. }
  300.  
  301. final public Enumeration getObjects()
  302. {
  303.  return objects.elements();
  304. }
  305.  
  306. final public void export_to(cachedir nd,int type,long difftime)
  307. {
  308.  if(nd==null) return;
  309.  if(localdir==null) return;
  310.  long now=System.currentTimeMillis();
  311.  Enumeration e=getObjects();
  312.  while(e.hasMoreElements())
  313.  {
  314.   cacheobject my,out;
  315.   boolean exp;
  316.   exp=false;
  317.   my=(cacheobject)e.nextElement();
  318.   switch(type)
  319.   {
  320.   case garbage.EXPORT_ALL:
  321.              exp=true;
  322.              break;
  323.   case garbage.EXPORT_LRU:             
  324.                      if (now-my.getLRU()<=difftime) { exp=true;}
  325.              break;
  326.   case garbage.EXPORT_DATE:
  327.                      if(now-my.getDate()<=difftime) { exp=true;}
  328.              break;
  329.   case garbage.EXPORT_FILEDATE:
  330.                      if(now-my.getDate()>difftime) break;
  331.              String ln;
  332.              ln=my.getLocalName();
  333.              if(ln==null || ln.equals(cacheobject.RESERVED)) break;
  334.              if(now-new File(localdir+ln).lastModified()<=difftime) exp=true;
  335.              break;
  336.  
  337.  
  338.   } /* switch */
  339.   if(exp==false) continue;
  340.   if(!my.isValid()) 
  341.   {
  342.      System.out.println(" - "+localdir+my.getLocalName());
  343.      continue;
  344.   }
  345.   /* found valid object for export */
  346.   out=nd.getObject(my.getName());
  347.   out.delete(); /* delete old object */
  348.   File exp1,f2;
  349.   exp1=new File(localdir,my.getLocalName());
  350.  
  351.   my.setDirectory(nd); // needed for localname generation
  352.   // generovat nove jmeno
  353.   my.regenName();
  354.   f2=new File(nd.getLocalDir(),my.getLocalName());
  355.   
  356.   if(copyfile(exp1,f2)==false) { continue;}
  357.   // musime udelat touch na date
  358.   my.touch();
  359.   nd.putObject(my);
  360.  } /* elements */
  361. }
  362.  
  363. /* 
  364.   merge current directory with data in new, file will be moved/copied
  365. */
  366.  
  367. final public void merge(cachedir nd)
  368. {
  369.  if(nd==null) return;
  370.  if(localdir==null) return;
  371.  // nd.checkDir();  //already done by garbage.import0
  372.  Enumeration e1=nd.getObjects();
  373.  while(e1.hasMoreElements())
  374.  {
  375.   cacheobject o,o2;
  376.   /*  o - novy objekt */
  377.   /*  o2 - stary objekt v cache */
  378.   o=(cacheobject)e1.nextElement();
  379.   if(o.getLocalName()==null) continue; // transient object
  380.   o2=(cacheobject)objects.get(o.getName());
  381.   // System.out.println("OBJ="+o.getName()+" O2="+o2);
  382.   if(o2!=null)
  383.    {
  384.     if(!o2.isValid())
  385.                 {
  386.           System.out.println(" - "+localdir+o2.getLocalName());
  387.           o2.delete(); // KILL our BAD object
  388.           o2=null;
  389.         }
  390.       else
  391.         if(o2.getDate()>o.getDate()) continue; /* our VALID object is newer */ 
  392.    }
  393.    // import object o into our directory
  394.  
  395.    // step1 - prepare f and f2
  396.    /* f - soubor k importu, f2 - importovat do... */
  397.    File f,f2;
  398.    f=new File(o.getDirectory().getLocalDir(),o.getLocalName());
  399.    o.setDirectory(this); // needed for localname generation
  400.    if(o2!=null)
  401.    {
  402.       o2.delete(); // delete old object
  403.    }
  404.    // generovat nove jmeno
  405.    o.regenName();
  406.    f2=new File(localdir,o.getLocalName());
  407.  
  408.   // System.out.println("f2="+f2); 
  409.   // jmeno vygenerovano
  410.  
  411.   //step2 - presun souboru pod nove jmeno
  412.   if(!f.renameTo(f2))
  413.    {
  414.             /* rename selhalo, kopiruje se */
  415.             if(copyfile(f,f2)==false) { continue;}
  416.         // musime udelat touch na date
  417.         o.touch();
  418.   }
  419.   
  420.   // touch imported OBJ's LRU
  421.   o.touchLRU();
  422.  
  423.   //step3 - vymenit objekt v adresari
  424.   objects.put(o.getName(),o);
  425.   if(cacheobject.auto_compress) o.compress(9);
  426.   
  427.   dirty=true;
  428.  }
  429. } /* merge */
  430.  
  431. private final static boolean copyfile(File f,File f2)
  432. {
  433.   System.out.println("[INFO] Copying "+f+" -> "+f2);
  434.   try
  435.   {
  436.     DataInputStream is=new DataInputStream(new BufferedInputStream(new FileInputStream(f),4096));
  437.     DataOutputStream os=new DataOutputStream(new BufferedOutputStream(
  438.     new FileOutputStream(f2),4096));
  439.  
  440.     byte b[]=new byte[4096];
  441.     while(true)
  442.     {
  443.      int rb;
  444.      rb=is.read(b);
  445.      if(rb==-1) break; /* konec dat! */
  446.      os.write(b,0,rb);
  447.     }
  448.     os.close();
  449.     is.close();
  450.   }
  451.   catch (IOException ioe)
  452.    { 
  453.      System.out.println("[ERROR] Failed copy "+f+" -> "+f2);
  454.      f2.delete(); // try to delete new file...
  455.      return false;
  456.    }
  457.    return true;
  458. }
  459. } /* class */
  460.