BucketAllocator(long availableSpace, int[] bucketSizes) throws BucketAllocatorException { this.bucketSizes = bucketSizes == null ? DEFAULT_BUCKET_SIZES : bucketSizes; Arrays.sort(this.bucketSizes); this.bigItemSize = Ints.max(this.bucketSizes); this.bucketCapacity = FEWEST_ITEMS_IN_BUCKET * (long) bigItemSize; buckets = new Bucket[(int) (availableSpace / bucketCapacity)]; if (buckets.length < this.bucketSizes.length) throw new BucketAllocatorException("Bucket allocator size too small (" + buckets.length + "); must have room for at least " + this.bucketSizes.length + " buckets"); bucketSizeInfos = new BucketSizeInfo[this.bucketSizes.length]; for (int i = 0; i < this.bucketSizes.length; ++i) { bucketSizeInfos[i] = new BucketSizeInfo(i); } for (int i = 0; i < buckets.length; ++i) { buckets[i] = new Bucket(bucketCapacity * i); bucketSizeInfos[i < this.bucketSizes.length ? i : this.bucketSizes.length - 1] .instantiateBucket(buckets[i]); } this.totalSize = ((long) buckets.length) * bucketCapacity; if (LOG.isInfoEnabled()) { LOG.info("Cache totalSize=" + this.totalSize + ", buckets=" + this.buckets.length + ", bucket capacity=" + this.bucketCapacity + "=(" + FEWEST_ITEMS_IN_BUCKET + "*" + this.bigItemSize + ")=" + "(FEWEST_ITEMS_IN_BUCKET*(largest configured bucketcache size))"); } }
if (b.sizeIndex() != bucketSizeIndex) { throw new BucketAllocatorException("Inconsistent allocation in bucket map;"); if (!b.isCompletelyFree()) { throw new BucketAllocatorException( "Reconfiguring bucket " + bucketNo + " but it's already allocated; corrupt data"); BucketSizeInfo oldbsi = bucketSizeInfos[b.sizeIndex()]; oldbsi.removeBucket(b); bsi.instantiateBucket(b); buckets[bucketNo].addAllocation(foundOffset); usedSize += buckets[bucketNo].getItemAllocationSize(); bucketSizeInfos[bucketSizeIndex].blockAllocated(b);
@Override public String toString() { StringBuilder sb = new StringBuilder(1024); for (int i = 0; i < buckets.length; ++i) { Bucket b = buckets[i]; if (i > 0) sb.append(", "); sb.append("bucket.").append(i).append(": size=").append(b.getItemAllocationSize()); sb.append(", freeCount=").append(b.freeCount()).append(", used=").append(b.usedCount()); } return sb.toString(); }
Bucket b = buckets[bucketNo]; if (reconfigured[bucketNo]) { if (b.sizeIndex() != bucketSizeIndex) throw new BucketAllocatorException( "Inconsistent allocation in bucket map;"); } else { if (!b.isCompletelyFree()) throw new BucketAllocatorException("Reconfiguring bucket " + bucketNo + " but it's already allocated; corrupt data"); BucketSizeInfo oldbsi = bucketSizeInfos[b.sizeIndex()]; oldbsi.removeBucket(b); bsi.instantiateBucket(b); buckets[bucketNo].addAllocation(foundOffset); usedSize += buckets[bucketNo].getItemAllocationSize(); bucketSizeInfos[bucketSizeIndex].blockAllocated(b);
BucketAllocator(long availableSpace, int[] bucketSizes) throws BucketAllocatorException { this.bucketSizes = bucketSizes == null ? DEFAULT_BUCKET_SIZES : bucketSizes; Arrays.sort(this.bucketSizes); this.bigItemSize = Ints.max(this.bucketSizes); this.bucketCapacity = FEWEST_ITEMS_IN_BUCKET * bigItemSize; buckets = new Bucket[(int) (availableSpace / bucketCapacity)]; if (buckets.length < this.bucketSizes.length) throw new BucketAllocatorException( "Bucket allocator size too small - must have room for at least " + this.bucketSizes.length + " buckets"); bucketSizeInfos = new BucketSizeInfo[this.bucketSizes.length]; for (int i = 0; i < this.bucketSizes.length; ++i) { bucketSizeInfos[i] = new BucketSizeInfo(i); } for (int i = 0; i < buckets.length; ++i) { buckets[i] = new Bucket(bucketCapacity * i); bucketSizeInfos[i < this.bucketSizes.length ? i : this.bucketSizes.length - 1] .instantiateBucket(buckets[i]); } this.totalSize = ((long) buckets.length) * bucketCapacity; }
/** * Find a bucket to allocate a block * @return the offset in the IOEngine */ public long allocateBlock() { Bucket b = null; if (freeBuckets.size() > 0) { // Use up an existing one first... b = (Bucket) freeBuckets.lastKey(); } if (b == null) { b = grabGlobalCompletelyFreeBucket(); if (b != null) instantiateBucket(b); } if (b == null) return -1; long result = b.allocate(); blockAllocated(b); return result; }
/** * Free a block with the offset * @param offset block's offset * @return size freed */ public synchronized int freeBlock(long offset) { int bucketNo = (int) (offset / bucketCapacity); assert bucketNo >= 0 && bucketNo < buckets.length; Bucket targetBucket = buckets[bucketNo]; bucketSizeInfos[targetBucket.sizeIndex()].freeBlock(targetBucket, offset); usedSize -= targetBucket.getItemAllocationSize(); return targetBucket.getItemAllocationSize(); }
void blockAllocated(Bucket b) { if (!b.isCompletelyFree()) completelyFreeBuckets.remove(b); if (!b.hasFreeSpace()) freeBuckets.remove(b); }
private void removeBucket(Bucket b) { assert b.isCompletelyFree(); bucketList.remove(b); freeBuckets.remove(b); completelyFreeBuckets.remove(b); }
public int sizeOfAllocation(long offset) { int bucketNo = (int) (offset / bucketCapacity); assert bucketNo >= 0 && bucketNo < buckets.length; Bucket targetBucket = buckets[bucketNo]; return targetBucket.getItemAllocationSize(); }
public void freeBlock(Bucket b, long offset) { assert bucketList.containsKey(b); // else we shouldn't have anything to free... assert (!completelyFreeBuckets.containsKey(b)); b.free(offset); if (!freeBuckets.containsKey(b)) freeBuckets.put(b, b); if (b.isCompletelyFree()) completelyFreeBuckets.put(b, b); }
private void free(long offset) { offset -= baseOffset; assert offset >= 0; assert offset < itemCount * itemAllocationSize; assert offset % itemAllocationSize == 0; assert usedCount > 0; assert freeCount < itemCount; // Else duplicate free int item = (int) (offset / (long) itemAllocationSize); assert !freeListContains(item); --usedCount; freeList[freeCount++] = item; }
public String toString() { StringBuilder sb = new StringBuilder(1024); for (int i = 0; i < buckets.length; ++i) { Bucket b = buckets[i]; if (i > 0) sb.append(", "); sb.append("bucket.").append(i).append(": size=").append(b.getItemAllocationSize()); sb.append(", freeCount=").append(b.freeCount()).append(", used=").append(b.usedCount()); } return sb.toString(); }
public void instantiateBucket(Bucket b) { assert b.isUninstantiated() || b.isCompletelyFree(); b.reconfigure(sizeIndex, bucketSizes, bucketCapacity); bucketList.put(b, b); freeBuckets.put(b, b); completelyFreeBuckets.put(b, b); }
if (!excludedBuckets.contains(i) && !buckets[i].isUninstantiated() && bucketSizeInfos[buckets[i].sizeIndex()].bucketList.size() != 1) { queue.add(i);
/** * Find a bucket to allocate a block * @return the offset in the IOEngine */ public long allocateBlock() { Bucket b = null; if (freeBuckets.size() > 0) { // Use up an existing one first... b = (Bucket) freeBuckets.lastKey(); } if (b == null) { b = grabGlobalCompletelyFreeBucket(); if (b != null) instantiateBucket(b); } if (b == null) return -1; long result = b.allocate(); blockAllocated(b); return result; }
/** * Free a block with the offset * @param offset block's offset * @return size freed */ public synchronized int freeBlock(long offset) { int bucketNo = (int) (offset / bucketCapacity); assert bucketNo >= 0 && bucketNo < buckets.length; Bucket targetBucket = buckets[bucketNo]; bucketSizeInfos[targetBucket.sizeIndex()].freeBlock(targetBucket, offset); usedSize -= targetBucket.getItemAllocationSize(); return targetBucket.getItemAllocationSize(); }
void blockAllocated(Bucket b) { if (!b.isCompletelyFree()) completelyFreeBuckets.remove(b); if (!b.hasFreeSpace()) freeBuckets.remove(b); }
private void free(long offset) { offset -= baseOffset; assert offset >= 0; assert offset < itemCount * itemAllocationSize; assert offset % itemAllocationSize == 0; assert usedCount > 0; assert freeCount < itemCount; // Else duplicate free int item = (int) (offset / (long) itemAllocationSize); assert !freeListContains(item); --usedCount; freeList[freeCount++] = item; }