private int scan() { int cnt = 0; for (int i = 0, len = _dataArray.length(); i < len; i++) { if (_dataArray.hasData(i)) cnt++; } return cnt; }
protected boolean putInternal(int index, byte[] key, byte[] value) throws Exception { byte[] existingData = _dataArray.get(index); if (existingData == null || existingData.length == 0) { _dataArray.set(index, _dataHandler.assemble(key, value), nextScn()); _loadCount++; } else { try { _dataArray.set(index, _dataHandler.assemble(key, value, existingData), nextScn()); } catch (Exception e) { _log.warn("Value reset at index=" + index + " key=\"" + new String(key) + "\""); _dataArray.set(index, _dataHandler.assemble(key, value), nextScn()); } } return true; }
private void initLinearHashing() throws Exception { int unitCount = _dataArray.length() / getUnitCapacity(); if (unitCount == 1) { _level = 0; _split = 0; _levelCapacity = getUnitCapacity(); _levelThreshold = (int) (_levelCapacity * _loadThreshold); } else { // Determine level and split _level = 0; int remainder = (unitCount - 1) >> 1; while (remainder > 0) { _level++; remainder = remainder >> 1; } _split = (unitCount - (1 << _level) - 1) * getUnitCapacity(); _levelCapacity = getUnitCapacity() * (1 << _level); _levelThreshold = (int) (_levelCapacity * _loadThreshold); // Need to re-populate the last unit for (int i = 0, cnt = getUnitCapacity(); i < cnt; i++) { split(); } } }
@Override public byte[] get(byte[] key) { byte[] existingData; long hashCode = hash(key); /** * Need SPIN to retrieve data from the underlying array because the index might have changed * with the _split. */ // Map key to an array index int index = getIndex(hashCode); do { // Read existing data at the index existingData = _dataArray.get(index); // Check that key is still mapped to the known index int indexNew = getIndex(hashCode); if (index == indexNew) break; else index = indexNew; } while (true); return existingData == null ? null : _dataHandler.extractByKey(key, existingData); }
protected synchronized void split() throws Exception { // Ensure address capacity _addrArray.expandCapacity(_split + _levelCapacity); // Read data from the _split index byte[] data = _dataArray.get(_split); // Process read data if (data != null && data.length > 0) { ByteBuffer bb = ByteBuffer.wrap(data); int newCapacity = _levelCapacity << 1; int cnt = bb.getInt(); while (cnt > 0) { // Read key int len = bb.getInt(); byte[] key = new byte[len]; bb.get(key); int newIndex = (int) (hash(key) % newCapacity); if (newIndex < 0) newIndex = -newIndex; if (newIndex == _split) /* No need to split */ { // Pass value len = bb.getInt(); bb.position(bb.position() + len); } else { // Read value len = bb.getInt(); byte[] value = new byte[len]; bb.get(value); // Remove at the old index deleteInternal(_split, key); // Update at the new index putInternal(newIndex, key, value); } cnt--; } } _split++; if (_split % _unitCapacity == 0) { _log.info("split " + getStatus()); } if (_split == _levelCapacity) { _split = 0; _level++; _levelCapacity = getUnitCapacity() * (1 << _level); _levelThreshold = (int) (_levelCapacity * _loadThreshold); _log.info(getStatus()); } }
private boolean deleteInternal(int index, byte[] key) throws Exception { try { byte[] existingData = _dataArray.get(index); if (existingData != null) { int newLength = _dataHandler.removeByKey(key, existingData); if (newLength == 0) { // entire data is removed _dataArray.set(index, null, nextScn()); _loadCount--; return true; } else if (newLength < existingData.length) { // partial data is removed _dataArray.set(index, existingData, 0, newLength, nextScn()); return true; } } } catch (Exception e) { _log.warn("Failed to delete key=\"" + new String(key) + "\" : " + e.getMessage()); _dataArray.set(index, null, nextScn()); } // no data is removed return false; }
private boolean putInternalNonColliding(int index, byte[] key, byte[] value) throws Exception { byte[] existingData = _dataArray.get(index); if (existingData == null) { return setInternal(index, key, value); } int collisionCnt = _dataHandler.countCollisions(key, existingData); if (collisionCnt == 0) { return setInternal(index, key, value); } else if (collisionCnt == 1) { return putReplace(index, key, value); } else { return false; } }
private byte[] getInternal(Tier tier, long hashCode) { byte[] existingData; /** * Need SPIN to retrieve data from the underlying array because the index might have changed * with the _split. */ // Map key to an array index int index = tier.getMainIndex(hashCode, _level, _split); do { // Read existing data at the index existingData = _dataArray.get(index); // Check that key is still mapped to the known index int indexNew = tier.getMainIndex(hashCode, _level, _split); if (indexNew == index) break; index = indexNew; } while (true); return existingData; }
protected synchronized void split() throws Exception { // Ensure address capacity _addrArray.expandCapacity(_split + _levelCapacity); // Read data from the _split index byte[] data = _dataArray.get(_split); // Process read data if (data != null && data.length > 0) { // Get split tier Tier tier = getTier(_split); // Wrap data in byte buffer ByteBuffer bb = ByteBuffer.wrap(data); int cnt = bb.getInt(); if (tier.isColliding()) { while (cnt > 0) { // Read key int len = bb.getInt(); byte[] key = new byte[len]; bb.get(key); int newIndex = tier.getSplitIndex(hash(key), _level, _split); if (newIndex == _split) /* No need to split */ { // Pass value len = bb.getInt(); bb.position(bb.position() + len); } else { // Read value len = bb.getInt(); byte[] value = new byte[len]; bb.get(value); // Remove at the old index deleteInternal(_split, key); // Update at the new index putInternal(newIndex, key, value); } cnt--; } } else { // Read key int len = bb.getInt(); byte[] key = new byte[len]; bb.get(key); int newIndex = tier.getSplitIndex(hash(key), _level, _split); if (newIndex != _split) { long scn = nextScn(); _addrArray.set(newIndex, _addrArray.get(_split), scn); _addrArray.set(_split, 0, scn); } } } _split++; if (_split % _unitCapacity == 0) { _log.info("split " + getStatus()); } if (_split == _levelCapacity) { _split = 0; _level++; _levelCapacity = getUnitCapacity() * (1 << _level); _levelThreshold = (int) (_levelCapacity * _loadThreshold); _log.info(getStatus()); } }
public final int getCapacity() { return _dataArray.length(); }
private boolean putReplace(int index, byte[] key, byte[] value) throws Exception { _dataArray.set(index, _dataHandler.assemble(key, value), nextScn()); return true; }
private boolean setInternal(int index, byte[] key, byte[] value) throws Exception { _dataArray.set(index, _dataHandler.assemble(key, value), nextScn()); _loadCount++; return true; }
@Override public synchronized void clear() throws IOException { _dataArray.clear(); _loadCount = 0; }
@Override public void persist() throws IOException { _dataArray.persist(); }
@Override public void sync() throws IOException { _dataArray.sync(); }