⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 persistentbytemap.java

📁 gcc的组建
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* Copyright (C) 2004, 2005  Free Software Foundation   This file is part of libgcj.This software is copyrighted work licensed under the terms of theLibgcj License.  Please consult the file "LIBGCJ_LICENSE" fordetails.  *//*  A PersistentByteMap maps a byte array to another byte array.  Ituses a file that does not need to be serialized but may bememory-mapped and read in-place.  So, even if there are many instancesof gcj applications running, they can share PersistentByteMaps.The idea is to make searches as fast as possible: opening aPersistentByteMap is cheap and search time doesn't grow with thenumber of entries in the table.  On the other hand, enumerating themap is slow, but that is a relatively uncommon operation.The main use of this class is to provide a way to map theMessageDigest of a class file to the location of a DSO that containsthe compiled version of that class.  It is up the the installer of anapplication to keep the DSO up to date with the jar.  USAGE:        MessageDigest md = MessageDigest.getInstance("MD5");        digest = md.digest(bytes);        PersistentByteMap map           = new PersistentByteMap            (fileName, PersistentByteMap.AccessMode.READ_ONLY);        byte[] soName = map.get(digest);        if (soName)          {            String SharedLibraryName = new String(soName);BUGS/FEATURES:        remove() isn't written yet.        capacity is fixed once the map has been created.        We use linear probing to resolve collisions.  It might be        better to use a scheme that results in fewer probes to        determine that an item isn't found.  However, even when the        table is half full there are only on average 1.5 probes for a        successful search and 2.5 probes for an unsuccessful one.	We don't do any locking at all: adding to a PersistentByteMap	at runtime is possible, but it requires filesystem locks	around get(), put(), and remove().*/package gnu.gcj.runtime;import java.io.*;import java.nio.*;import java.nio.channels.*;import java.util.*;import java.security.MessageDigest;import java.math.BigInteger;public class PersistentByteMap{  private MappedByteBuffer buf;  static private final int MAGIC = 0;  static private final int VERSION = 4;  static private final int CAPACITY = 8;  static private final int TABLE_BASE = 12;  static private final int STRING_BASE = 16;  static private final int STRING_SIZE = 20;  static private final int FILE_SIZE = 24;  static private final int ELEMENTS = 28;    static private final int INT_SIZE = 4;  static private final int TABLE_ENTRY_SIZE = 2 * INT_SIZE;  private int capacity;   // number of entries  private int table_base;   // offset from start of file, in bytes  private int string_base;  // offset from start of file, in bytes  private int string_size;  // size of string table, in bytes  private int file_size;    // size of file, in bytes;  private int elements;     // number of elements in table  private long length;      // the length of the underlying file  private final File name;  // The name of the underlying file  static private final int UNUSED_ENTRY = -1;   static public final int KEYS = 0;  static public final int VALUES = 1;  static public final int ENTRIES = 2;  private HashMap values;   // A map of strings in the string table.  FileChannel fc;           // The underlying file channel.  static final public class AccessMode  {    private final FileChannel.MapMode mapMode;    static    {      READ_ONLY = new AccessMode(FileChannel.MapMode.READ_ONLY);      READ_WRITE = new AccessMode(FileChannel.MapMode.READ_WRITE);      PRIVATE = new AccessMode(FileChannel.MapMode.PRIVATE);    }    public static final AccessMode READ_ONLY;    public static final AccessMode READ_WRITE;     public static final AccessMode PRIVATE;    private AccessMode(FileChannel.MapMode mode)    {      this.mapMode = mode;    }  }  private PersistentByteMap(File name)  {    this.name = name;  }  public PersistentByteMap(String filename, AccessMode mode)    throws IOException   {    this(new File(filename), mode);  }  public PersistentByteMap(File f, AccessMode mode)    throws IOException   {    name = f;    if (mode == AccessMode.READ_ONLY)      {        FileInputStream fis = new FileInputStream(f);        fc = fis.getChannel();      }    else      {        RandomAccessFile fos = new RandomAccessFile(f, "rw");        fc = fos.getChannel();      }    length = fc.size();    buf = fc.map(mode.mapMode, 0, length);    int magic = getWord (MAGIC);    if (magic != 0x67636a64) /* "gcjd" */      throw new IllegalArgumentException(f.getName());    table_base = getWord (TABLE_BASE);    capacity = getWord (CAPACITY);    string_base = getWord (STRING_BASE);    string_size = getWord (STRING_SIZE);    file_size = getWord (FILE_SIZE);    elements = getWord (ELEMENTS);    // FIXME:  Insert a bunch of sanity checks here  }  private void init (PersistentByteMap m, File f, int capacity, int strtabSize)    throws IOException   {    f.createNewFile();    RandomAccessFile raf = new RandomAccessFile(f, "rw");    {              // The user has explicitly provided a size for the table.      // We're going to make that size prime.  This isn't      // strictly necessary but it can't hurt.      //      // We expand the size by 3/2 and round the result because the      // hash table is intolerably slow when more than 2/3 full.            BigInteger size = new BigInteger(Integer.toString(((capacity*3)+1)/2));      BigInteger two = BigInteger.ONE.add(BigInteger.ONE);            if (size.getLowestSetBit() != 0) // A hard way to say isEven()	size = size.add(BigInteger.ONE);          while (! size.isProbablePrime(10))	size = size.add(two);            this.capacity = capacity = size.intValue();    }    table_base = 64;    string_base = table_base + capacity * TABLE_ENTRY_SIZE;    string_size = 0;    file_size = string_base;    elements = 0;    int totalFileSize = string_base + strtabSize;    // Create the file; this rounds up the size of the file to a fixed    // number of 4k pages.    byte[] _4k = new byte[4096];    for (long i = 0; i < totalFileSize; i+= 4096)      raf.write(_4k);            fc = raf.getChannel();    buf = fc.map(FileChannel.MapMode.READ_WRITE, 0, raf.length());    for (int i = 0; i < capacity; i++)      putKeyPos(UNUSED_ENTRY, i);            putWord(0x67636a64, MAGIC);    putWord(0x01, VERSION);    putWord(capacity, CAPACITY);    putWord(table_base, TABLE_BASE);    putWord(string_base, STRING_BASE);    putWord(file_size, FILE_SIZE);    putWord(elements, ELEMENTS);    buf.force();    length = fc.size();    string_size = 0;  }       static public PersistentByteMap   emptyPersistentByteMap(File name, int capacity, int strtabSize)    throws IOException   {    PersistentByteMap m = new PersistentByteMap(name);    m.init(m, name, capacity, strtabSize);    return m;  }       private int getWord (int index)  {    buf.position(index);    byte[] wordBuf = new byte[4];    buf.get(wordBuf);    int result = (int)wordBuf[0]&0xff;    result += ((int)wordBuf[1]&0xff) << 8;    result += ((int)wordBuf[2]&0xff) << 16;    result += ((int)wordBuf[3]&0xff) << 24;    return result;  }  private void putWord (int word, int index)  {    buf.position(index);    byte[] wordBuf = new byte[4];    wordBuf[0] = (byte)(word);    wordBuf[1] = (byte)(word >>> 8);    wordBuf[2] = (byte)(word >>> 16);    wordBuf[3] = (byte)(word >>> 24);    buf.put(wordBuf);  }  public Set entrySet()  {    return null;  }  private int getBucket(int n)  {    return table_base + (2*n * INT_SIZE);  }  private int getKeyPos(int n)  {    return getWord(getBucket(n));  }    private int getValuePos(int n)  {    return getWord(getBucket(n) + INT_SIZE);  }  private void putKeyPos(int index, int n)  {    putWord(index, getBucket(n));  }  private void putValuePos(int index, int n)  {    putWord(index, getBucket(n) + INT_SIZE);  }  private byte[] getBytes(int n)  {    int len = getWord (string_base + n);    int base = string_base + n + INT_SIZE;    byte[] key = new byte[len];    buf.position(base);    buf.get(key, 0, len);    return key;  }  private int hash (byte[] b)  {        // We assume that the message digest is evenly distributed, so we    // only need to use a few bytes of it as the hash function.    long hashIndex       = ((b[0]&0xffL)         + ((b[1]&0xffL)<<8)          + ((b[2]&0xffL)<<16)          + ((b[3]&0xffL)<<24));    long result = hashIndex % (long)capacity;    return (int)result;  }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -