home *** CD-ROM | disk | FTP | other *** search
/ Australian PC Authority 1999 May / may1999.iso / INTERNET / COMMUNIC / NETCAST.Z / marimb10.jar / netscape / netcast / MappedFileCache.class (.txt) < prev    next >
Encoding:
Java Class File  |  1998-02-25  |  9.3 KB  |  438 lines

  1. package netscape.netcast;
  2.  
  3. import java.io.File;
  4. import java.io.FileInputStream;
  5. import java.io.FileOutputStream;
  6. import java.io.IOException;
  7. import java.util.Enumeration;
  8. import marimba.castanet.client.CastanetFile;
  9. import marimba.castanet.util.Checksum;
  10. import marimba.io.FastInputStream;
  11. import marimba.io.FastOutputStream;
  12. import marimba.io.RAFOutputStream;
  13. import marimba.util.Timer;
  14. import marimba.util.TimerClient;
  15. import netscape.security.PrivilegeManager;
  16. import netscape.security.Target;
  17.  
  18. public final class MappedFileCache extends FileCache implements TimerClient {
  19.    static final int FILES_PER_DIRECTORY = 128;
  20.    static final int WRITE_DELAY = 3000;
  21.    static final int ENTRY_SIZE = 20;
  22.    File mapFile;
  23.    // $FF: renamed from: in marimba.io.FastInputStream
  24.    FastInputStream field_0;
  25.    FastOutputStream out;
  26.    byte[] data;
  27.    int len;
  28.    int count;
  29.    int nextFile;
  30.    int currentDirectory;
  31.    boolean dirty;
  32.  
  33.    public MappedFileCache(File dir) {
  34.       super(dir);
  35.       this.mapFile = new File(dir, "cache.map");
  36.       this.load();
  37.    }
  38.  
  39.    synchronized void load() {
  40.       PrivilegeManager privMgr = PrivilegeManager.getPrivilegeManager();
  41.       Target target = null;
  42.       if (privMgr != null) {
  43.          target = Target.findTarget("MarimbaAppContextTarget");
  44.          if (target != null) {
  45.             privMgr.enablePrivilege(target);
  46.          }
  47.       }
  48.  
  49.       this.nextFile = -1;
  50.       if (this.mapFile.exists()) {
  51.          this.len = (int)this.mapFile.length();
  52.          this.data = new byte[this.len + 1000];
  53.  
  54.          try {
  55.             FileInputStream fin = new FileInputStream(this.mapFile);
  56.  
  57.             try {
  58.                fin.read(this.data, 0, this.len);
  59.             } finally {
  60.                fin.close();
  61.             }
  62.  
  63.             this.len -= 4;
  64.             if (this.len % 20 != 0) {
  65.                System.out.println("Database length screw up!");
  66.             }
  67.  
  68.             this.count = this.len / 20;
  69.             this.currentDirectory = this.count / 128;
  70.             this.field_0 = new FastInputStream(this.data);
  71.             this.out = new FastOutputStream(this.data);
  72.             this.field_0.seek((long)this.len);
  73.             this.nextFile = this.field_0.readInt();
  74.          } catch (IOException var9) {
  75.          }
  76.       }
  77.  
  78.       if (this.nextFile == -1) {
  79.          this.len = 0;
  80.          this.count = 0;
  81.          this.currentDirectory = 0;
  82.          this.nextFile = 1;
  83.          this.data = new byte[1000];
  84.          this.field_0 = new FastInputStream(this.data);
  85.          this.out = new FastOutputStream(this.data);
  86.       }
  87.  
  88.    }
  89.  
  90.    synchronized boolean save() {
  91.       if (this.dirty) {
  92.          PrivilegeManager privMgr = PrivilegeManager.getPrivilegeManager();
  93.          Target target = null;
  94.          if (privMgr != null) {
  95.             target = Target.findTarget("MarimbaAppContextTarget");
  96.             if (target != null) {
  97.                privMgr.enablePrivilege(target);
  98.             }
  99.          }
  100.  
  101.          try {
  102.             this.out.seek((long)this.len);
  103.             this.out.writeInt(this.nextFile);
  104.             FileOutputStream out = new FileOutputStream(this.mapFile);
  105.             long time = System.currentTimeMillis();
  106.  
  107.             try {
  108.                out.write(this.data, 0, this.len + 4);
  109.                this.dirty = false;
  110.             } finally {
  111.                out.close();
  112.             }
  113.  
  114.             time = System.currentTimeMillis() - time;
  115.          } catch (IOException var11) {
  116.             return false;
  117.          }
  118.       }
  119.  
  120.       return true;
  121.    }
  122.  
  123.    void modify() {
  124.       this.dirty = true;
  125.       Timer.master.add(this, System.currentTimeMillis() + 3000L, (Object)null);
  126.    }
  127.  
  128.    public long tick(long tm, Object arg) {
  129.       if (!this.save()) {
  130.          System.out.println("[Couldn't save cache map!]");
  131.       }
  132.  
  133.       return -1L;
  134.    }
  135.  
  136.    Checksum getChecksum(int slot) {
  137.       try {
  138.          this.field_0.seek((long)(slot * 20));
  139.          return new Checksum(this.field_0);
  140.       } catch (IOException e) {
  141.          ((Throwable)e).printStackTrace();
  142.          return null;
  143.       }
  144.    }
  145.  
  146.    int getName(int slot) {
  147.       try {
  148.          this.field_0.seek((long)(slot * 20 + 16));
  149.          return this.field_0.readInt();
  150.       } catch (IOException var2) {
  151.          return -1;
  152.       }
  153.    }
  154.  
  155.    int compare(long cs1, long cs2, int slot) {
  156.       int off = slot * 20;
  157.       byte[] data = this.data;
  158.  
  159.       for(int i = 56; i >= 0; i -= 8) {
  160.          long diff = (cs1 >> i & 255L) - (long)(data[off++] & 255);
  161.          if (diff < 0L) {
  162.             return -1;
  163.          }
  164.  
  165.          if (diff > 0L) {
  166.             return 1;
  167.          }
  168.       }
  169.  
  170.       for(int i = 56; i >= 0; i -= 8) {
  171.          long diff = (cs2 >> i & 255L) - (long)(data[off++] & 255);
  172.          if (diff < 0L) {
  173.             return -1;
  174.          }
  175.  
  176.          if (diff > 0L) {
  177.             return 1;
  178.          }
  179.       }
  180.  
  181.       return 0;
  182.    }
  183.  
  184.    int lookup(Checksum cs) {
  185.       int min = 0;
  186.       int max = this.count;
  187.       long cs1 = cs.getChecksum1();
  188.       long cs2 = cs.getChecksum2();
  189.  
  190.       while(min < max) {
  191.          int mid = (min + max) / 2;
  192.          int cmp = this.compare(cs1, cs2, mid);
  193.          switch (cmp) {
  194.             case -1:
  195.                max = mid;
  196.                break;
  197.             case 0:
  198.             default:
  199.                return this.getName(mid);
  200.             case 1:
  201.                min = mid + 1;
  202.          }
  203.       }
  204.  
  205.       return -1;
  206.    }
  207.  
  208.    String makeName(int fno) {
  209.       return Integer.toString(fno / 128, 36) + File.separatorChar + Integer.toString(fno, 36);
  210.    }
  211.  
  212.    int nextFile() {
  213.       this.currentDirectory = this.nextFile / 128;
  214.       return this.nextFile++;
  215.    }
  216.  
  217.    void insert(Checksum cs) {
  218.       this.insert(cs, this.nextFile());
  219.    }
  220.  
  221.    void insert(Checksum cs, int name) {
  222.       PrivilegeManager privMgr = PrivilegeManager.getPrivilegeManager();
  223.       Target target = null;
  224.       if (privMgr != null) {
  225.          target = Target.findTarget("MarimbaAppContextTarget");
  226.          if (target != null) {
  227.             privMgr.enablePrivilege(target);
  228.          }
  229.       }
  230.  
  231.       int min = 0;
  232.       int max = this.count;
  233.       long cs1 = cs.getChecksum1();
  234.       long cs2 = cs.getChecksum2();
  235.  
  236.       while(min < max) {
  237.          int mid = (min + max) / 2;
  238.          int cmp = this.compare(cs1, cs2, mid);
  239.          switch (cmp) {
  240.             case -1:
  241.                max = mid;
  242.                break;
  243.             case 0:
  244.             default:
  245.                System.out.println("Cache error: already in cache");
  246.                break;
  247.             case 1:
  248.                min = mid + 1;
  249.          }
  250.       }
  251.  
  252.       if (this.len + 20 >= this.data.length - 4) {
  253.          byte[] d = new byte[this.data.length * 3 / 2];
  254.          System.arraycopy(this.data, 0, d, 0, this.data.length);
  255.          this.data = d;
  256.          this.field_0 = new FastInputStream(this.data);
  257.          this.out = new FastOutputStream(this.data);
  258.       }
  259.  
  260.       int pos = min * 20;
  261.       if (min < this.count) {
  262.          System.arraycopy(this.data, pos, this.data, pos + 20, this.len - pos);
  263.       }
  264.  
  265.       try {
  266.          this.out.seek((long)pos);
  267.          cs.writeChecksum(this.out);
  268.          this.out.writeInt(name);
  269.          ++this.count;
  270.          this.len += 20;
  271.       } catch (IOException e) {
  272.          ((Throwable)e).printStackTrace();
  273.       }
  274.    }
  275.  
  276.    int remove(Checksum cs) {
  277.       int min = 0;
  278.       int max = this.count;
  279.       long cs1 = cs.getChecksum1();
  280.       long cs2 = cs.getChecksum2();
  281.  
  282.       while(min < max) {
  283.          int mid = (min + max) / 2;
  284.          int cmp = this.compare(cs1, cs2, mid);
  285.          switch (cmp) {
  286.             case -1:
  287.                max = mid;
  288.                break;
  289.             case 0:
  290.             default:
  291.                int name = this.getName(mid);
  292.                --this.count;
  293.                this.len -= 20;
  294.                System.arraycopy(this.data, (mid + 1) * 20, this.data, mid * 20, (this.count - mid) * 20);
  295.                this.modify();
  296.                return name;
  297.             case 1:
  298.                min = mid + 1;
  299.          }
  300.       }
  301.  
  302.       return -1;
  303.    }
  304.  
  305.    public synchronized CastanetFile get(Checksum cs) {
  306.       PrivilegeManager privMgr = PrivilegeManager.getPrivilegeManager();
  307.       Target target = null;
  308.       if (privMgr != null) {
  309.          target = Target.findTarget("MarimbaAppContextTarget");
  310.          if (target != null) {
  311.             privMgr.enablePrivilege(target);
  312.          }
  313.       }
  314.  
  315.       int name = this.lookup(cs);
  316.       if (name != -1) {
  317.          FileCacheFile file = new MappedFileCacheFile(this, super.dir, this.makeName(name), -2L, cs);
  318.          return ((File)file).exists() ? file : null;
  319.       } else {
  320.          return null;
  321.       }
  322.    }
  323.  
  324.    public synchronized CastanetFile getPending(Checksum cs, long length) {
  325.       PrivilegeManager privMgr = PrivilegeManager.getPrivilegeManager();
  326.       Target target = null;
  327.       if (privMgr != null) {
  328.          target = Target.findTarget("MarimbaAppContextTarget");
  329.          if (target != null) {
  330.             privMgr.enablePrivilege(target);
  331.          }
  332.       }
  333.  
  334.       int name = this.lookup(cs);
  335.       if (name == -1) {
  336.          name = this.nextFile();
  337.          this.insert(cs, name);
  338.       }
  339.  
  340.       return new MappedFileCacheFile(this, super.dir, this.makeName(name), length, cs);
  341.    }
  342.  
  343.    public synchronized boolean delete(Checksum cs) {
  344.       PrivilegeManager privMgr = PrivilegeManager.getPrivilegeManager();
  345.       Target target = null;
  346.       if (privMgr != null) {
  347.          target = Target.findTarget("MarimbaAppContextTarget");
  348.          if (target != null) {
  349.             privMgr.enablePrivilege(target);
  350.          }
  351.       }
  352.  
  353.       int name = this.lookup(cs);
  354.       if (name != -1) {
  355.          File file = new File(super.dir, this.makeName(name));
  356.          if (file.delete()) {
  357.             this.remove(cs);
  358.             int dirno = name / 128;
  359.             if (dirno < this.currentDirectory) {
  360.                (new File(file.getParent())).delete();
  361.             }
  362.  
  363.             return true;
  364.          }
  365.       }
  366.  
  367.       return false;
  368.    }
  369.  
  370.    void deleted(MappedFileCacheFile file) {
  371.       this.remove(((FileCacheFile)file).getChecksum());
  372.    }
  373.  
  374.    public synchronized RAFOutputStream create(Checksum cs, long length) {
  375.       PrivilegeManager privMgr = PrivilegeManager.getPrivilegeManager();
  376.       Target target = null;
  377.       if (privMgr != null) {
  378.          target = Target.findTarget("MarimbaAppContextTarget");
  379.          if (target != null) {
  380.             privMgr.enablePrivilege(target);
  381.          }
  382.       }
  383.  
  384.       int name = this.lookup(cs);
  385.       boolean newFile = name == -1;
  386.       if (newFile) {
  387.          name = this.nextFile();
  388.       }
  389.  
  390.       FileCacheFile file = new MappedFileCacheFile(this, super.dir, this.makeName(name), length, cs);
  391.  
  392.       RAFOutputStream raf;
  393.       try {
  394.          raf = new FileCacheOutputStream(file);
  395.       } catch (IOException var12) {
  396.          File parent = new File(((File)file).getParent());
  397.          if (!parent.exists() && !parent.mkdirs()) {
  398.             return null;
  399.          }
  400.  
  401.          try {
  402.             raf = new FileCacheOutputStream(file);
  403.          } catch (IOException var11) {
  404.             return null;
  405.          }
  406.       }
  407.  
  408.       if (newFile) {
  409.          this.insert(cs, name);
  410.       }
  411.  
  412.       return raf;
  413.    }
  414.  
  415.    public Enumeration enumerate() {
  416.       return new MappedFileCacheEnumeration(this);
  417.    }
  418.  
  419.    public int estimateFileCount() {
  420.       return this.count;
  421.    }
  422.  
  423.    public synchronized void close() {
  424.       if (this.dirty && !this.save()) {
  425.          System.out.println("Couldn't close cache!");
  426.       }
  427.  
  428.    }
  429.  
  430.    public synchronized void notifyComplete(Checksum cs) {
  431.       this.modify();
  432.    }
  433.  
  434.    public void sync() {
  435.       this.save();
  436.    }
  437. }
  438.