// creates a new BloomFilter - access via BloomFilter.createOptimal(...) private BloomFilter( File f, int buckets, int hashFns, boolean force, int seekThreshold, BucketSize countBits, Allocator cacheAllocator, CloseCallback callback) throws IOException { this.closeCallback = callback; this.seekThreshold = seekThreshold; this.metadata = BloomMetadata.createNew(buckets, hashFns, countBits); hash = new RepeatedMurmurHash(hashFns, this.metadata.getBucketCount()); // creating a new filter - so I can just be lazy and start it zero'd cache = cacheAllocator.apply(this.metadata.getTotalLength() - this.metadata.getHeaderLength()); cacheDirty = true; open = true; if (f != null) { if (f.exists()) { if (force) { if (!f.delete()) { throw new IOException("Couldn't delete old file at " + f.getAbsolutePath()); } } else { throw new IllegalArgumentException( "Can't create a new BloomFilter at " + f.getAbsolutePath() + " since it already exists"); } } file = new RandomAccessFile(f, "rw"); this.metadata.writeToFile(file); file.setLength(metadata.getTotalLength()); file.getFD().sync(); unflushedChanges = new ConcurrentSkipListMap<Integer, Byte>(); if (f.length() != metadata.getTotalLength()) { throw new RuntimeException( "Bad size - expected " + metadata.getTotalLength() + " but got " + f.length()); } } else { unflushedChanges = null; // don't bother keeping track of unflushed changes if this is memory only file = null; } }
// Opens an existing bloom filter. Access via BloomFilter.openExisting(...) private BloomFilter( File f, int seekThreshold, Allocator cacheAllocator, CloseCallback closeCallback) throws IOException { assert f.exists() && f.isFile() && f.canRead() && f.canWrite() : "Trying to open a non-existent bloom filter"; this.seekThreshold = seekThreshold; this.closeCallback = closeCallback; file = new RandomAccessFile(f, "rw"); this.metadata = BloomMetadata.readHeader(file); unflushedChanges = new ConcurrentSkipListMap<Integer, Byte>(); // load the cache with the on disk data cache = cacheAllocator.apply(metadata.getTotalLength() - metadata.getHeaderLength()); int readRes = file.read(cache); assert readRes == (metadata.getTotalLength() - metadata.getHeaderLength()) : "I only read " + readRes + " bytes, but was expecting " + (metadata.getTotalLength() - metadata.getHeaderLength()); hash = new RepeatedMurmurHash(metadata.getHashFns(), metadata.getBucketCount()); open = true; }