/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.db.procore.cluster; import java.util.Arrays; class AllocationException extends java.lang.RuntimeException { private static final long serialVersionUID = 9025410962959482008L; final Allocator allocator; int size; AllocationException(Allocator allocator, int size) { super("Allocator out of memory with size = " + size); this.allocator = allocator; this.size = size; } void increment(int inc) { this.size += inc; } @Override public synchronized Throwable fillInStackTrace() { return this; } } abstract class Allocator { abstract int getCapacity(); abstract void resizeMemory(int capacity); abstract void backupResize(int capacity, int size, int copySize); abstract void backupFree(); static final int MaxIncrement = 1000000; static final int MinIncrement = 100; private int size; // size of used array elements int getSize() { return size; } void setSize(int size) { assert (0 < size && size <= getCapacity()); this.size = size; } int newElement(int size) { int oldSize = this.size; int newSize = oldSize + size; if (newSize > getCapacity()) { throw new AllocationException(this, size); } this.size = newSize; // System.out.println("newElement: old size=" + oldSize + ", new size=" // + newSize + ", capacity=" + getCapacity()); return oldSize; } // ensures that there is space of esize elements // if esize = 0 then uses default increment void ensureSpace(int esize) { // System.out.println("Ensure space " + esize); int space = getCapacity() - this.size; int increment = (space > 0 && esize > 0) ? (esize - space) : MinIncrement; if (increment <= 0) return; increment = Math.max(increment, MinIncrement); int defaultCapacity = Math.min(getCapacity() << 1, getCapacity() + MaxIncrement); int newCapacity = Math.max(defaultCapacity, getCapacity() + increment); resizeMemory(newCapacity); } } class LongAllocator extends Allocator { LongAllocator releaseMemory() { backup = null; memory = null; return null; } private long[] backup; private long[] memory; static final int ClusterId = 0; static final int HeaderSize = 1; long[] getBackup() { return backup; } long[] getMemory() { return memory; } long getClusterId() { return memory[ClusterId]; } void setClusterId(long a) { memory[ClusterId] = a; } LongAllocator(long[] longs, int size) { assert (null != longs); assert (longs.length >= size); assert (longs.length >= HeaderSize); this.backup = null; this.memory = longs; setSize(size); } int getCapacity() { return memory.length; } void resizeMemory(int capacity) { assert (capacity >= HeaderSize); assert (null == backup); // System.out.println("new longs(1) = " + capacity); long[] t = null; try { t = new long[capacity]; } catch (OutOfMemoryError e) { e.printStackTrace(); throw e; } // memory = Arrays.copyOf(memory, capacity); int copySize = Math.min(capacity, getSize()); System.arraycopy(memory, 0, t, 0, copySize); setSize(copySize); memory = t; } void backupResize(int capacity, int size, int copySize) { assert (capacity >= HeaderSize); assert (capacity >= copySize); assert (capacity >= size); if (size < 0) size = getSize(); else if (size < HeaderSize) size = HeaderSize; assert (size <= capacity); if (copySize < 0) copySize = size; assert (copySize <= size); assert (copySize <= getSize()); assert (null == backup); backup = memory; memory = new long[capacity]; // System.out.println("new longs(2) = " + capacity); setSize(size); // uses memory.length System.arraycopy(backup, 0, memory, 0, copySize); } void backupFree() { backup = null; } void dump() { for (int i = 0; i < getSize(); ++i) System.out.println("longs[" + i + "]=" + memory[i]); System.out.println("longs capacity=" + memory.length); } } class IntAllocator extends Allocator { IntAllocator releaseMemory() { backup = null; memory = null; return null; } int[] backup; int[] memory; static final int ResourceHash = 0; static final int ObjectHash = 1; static final int HeaderSize = 2; int getResourceHash() { if (null == memory) return 0; return memory[ResourceHash]; } int getObjectHash() { if (null == memory) return 0; return memory[ObjectHash]; } void setResourceHash(int a) { memory[ResourceHash] = a; } void setObjectHash(int a) { memory[ObjectHash] = a; } IntAllocator(int[] ints, int size) { this.backup = null; this.memory = ints; setSize(size); } int[] getBackup() { return backup; } int[] getMemory() { return memory; } int getCapacity() { if (null == memory) return 0; return memory.length; } void resizeMemory(int capacity) { assert (capacity >= HeaderSize); assert (null == backup); memory = Arrays.copyOf(memory, capacity); } void backupResize(int capacity, int size, int copySize) { assert (capacity >= HeaderSize); assert (capacity >= copySize); assert (capacity >= size); if (size < 0) size = getSize(); else if (size < HeaderSize) size = HeaderSize; assert (size <= capacity); if (copySize < 0) copySize = size; assert (copySize <= size); assert (copySize <= getSize()); assert (null == backup); backup = memory; memory = new int[capacity]; setSize(size); // uses memory.length System.arraycopy(backup, 0, memory, 0, copySize); } void backupFree() { backup = null; } void dump() { for (int i = 0; i < getSize(); ++i) System.out.println("ints[" + i + "]=" + memory[i]); System.out.println("ints capacity=" + memory.length); } } class ByteAllocator extends Allocator { ByteAllocator releaseMemory() { backup = null; memory = null; return null; } private byte[] backup; private byte[] memory; static final int Reserved = 0; static final int HeaderSize = 1; ByteAllocator(byte[] bytes, int size) { this.backup = null; this.memory = bytes; setSize(size); } byte[] getBackup() { return backup; } byte[] getMemory() { return memory; } int getReserved() { return memory[Reserved]; } void setReserved(byte a) { memory[Reserved] = a; } int getCapacity() { return memory.length; } void resizeMemory(int capacity) { assert (capacity >= HeaderSize); assert (null == backup); memory = Arrays.copyOf(memory, capacity); } void backupResize(int capacity, int size, int copySize) { assert (capacity >= HeaderSize); assert (capacity >= copySize); assert (capacity >= size); if (size < 0) size = getSize(); else if (size < HeaderSize) size = HeaderSize; assert (size <= capacity); if (copySize < 0) copySize = size; assert (copySize <= size); assert (copySize <= getSize()); assert (null == backup); backup = memory; memory = new byte[capacity]; setSize(size); // uses memory.length System.arraycopy(backup, 0, memory, 0, copySize); } void backupFree() { backup = null; } void dump() { for (int i = 0; i < getSize(); ++i) { short t = (short) (memory[i] & 0xFF); System.out.println("bytes[" + i + "]=" + t); } System.out.println("bytes capacity=" + memory.length); } }