store.java
来自「RESIN 3.2 最新源码」· Java 代码 · 共 1,996 行 · 第 1/4 页
JAVA
1,996 行
/** * Allocates a new block for a row. * * @return the block id of the allocated block. */ public Block allocateRow() throws IOException { return allocateBlock(ALLOC_ROW); } /** * Return true if the block is a row block. */ public boolean isRowBlock(long blockAddress) { return getAllocation(blockAddress / BLOCK_SIZE) == ALLOC_ROW; } /** * Allocates a new block for a non-row. * * @return the block id of the allocated block. */ public Block allocateBlock() throws IOException { return allocateBlock(ALLOC_USED); } /** * Allocates a new block for a fragment * * @return the block id of the allocated block. */ private Block allocateFragmentBlock() throws IOException { return allocateBlock(ALLOC_FRAGMENT); } /** * Allocates a new block for a mini-fragment * * @return the block id of the allocated block. */ private Block allocateMiniFragmentBlock() throws IOException { return allocateBlock(ALLOC_MINI_FRAG); } /** * Allocates a new block for an index * * @return the block id of the allocated block. */ public Block allocateIndexBlock() throws IOException { return allocateBlock(ALLOC_INDEX); } /** * Return true if the block is an index block. */ public boolean isIndexBlock(long blockAddress) { return getAllocation(blockAddress / BLOCK_SIZE) == ALLOC_INDEX; } /** * Allocates a new block. * * @return the block id of the allocated block. */ private Block allocateBlock(int code) throws IOException { long blockIndex; boolean isFileExtended = false; synchronized (_allocationLock) { long end = _blockCount; if (_allocationTable.length < ALLOC_BYTES_PER_BLOCK * end) end = _allocationTable.length / ALLOC_BYTES_PER_BLOCK; for (blockIndex = 0; blockIndex < end; blockIndex++) { if (getAllocation(blockIndex) == ALLOC_FREE) break; } if (_allocationTable.length <= ALLOC_BYTES_PER_BLOCK * blockIndex) { // expand the allocation table byte []newTable = new byte[_allocationTable.length + ALLOC_CHUNK_SIZE]; System.arraycopy(_allocationTable, 0, newTable, 0, _allocationTable.length); _allocationTable = newTable; // if the allocation table is over 32k, allocate the block for the // extension (each allocation block of 32k allocates 2G) if (blockIndex % (BLOCK_SIZE / ALLOC_BYTES_PER_BLOCK) == 0) { setAllocation(blockIndex, ALLOC_USED); blockIndex++; } } // mark USED before actual code so it's properly initialized setAllocation(blockIndex, ALLOC_USED); if (log.isLoggable(Level.FINE)) log.fine(this + " allocating block " + blockIndex + " " + codeToName(code)); if (_blockCount <= blockIndex) { isFileExtended = true; _blockCount = blockIndex + 1; } } long blockId = blockIndexToBlockId(blockIndex); Block block = _blockManager.getBlock(this, blockId); byte []buffer = block.getBuffer(); for (int i = BLOCK_SIZE - 1; i >= 0; i--) buffer[i] = 0; block.setDirty(0, BLOCK_SIZE); // if extending file, write the contents now if (isFileExtended) { try { block.write(); } catch (IOException e) { log.log(Level.WARNING, e.toString(), e); } } synchronized (_allocationLock) { setAllocation(blockIndex, code); } saveAllocation(); return block; } /** * Check that an allocated block is valid. */ protected void validateBlockId(long blockId) throws IllegalArgumentException, IllegalStateException { RuntimeException e = null; if (isClosed()) e = new IllegalStateException(L.l("store {0} is closing.", this)); else if (getId() <= 0) e = new IllegalStateException(L.l("invalid store {0}.", this)); else if (getId() != (blockId & BLOCK_INDEX_MASK)) { e = new IllegalArgumentException(L.l("block {0} must match store {1}.", blockId & BLOCK_INDEX_MASK, this)); } if (e != null) throw e; } /** * Check that an allocated block is valid. */ protected void assertStoreActive() throws IllegalStateException { RuntimeException e = null; if (isClosed()) e = new IllegalStateException(L.l("store {0} is closing.", this)); else if (getId() <= 0) e = new IllegalStateException(L.l("invalid store {0}.", this)); if (e != null) throw e; } /** * Frees a block. * * @return the block id of the allocated block. */ protected void freeBlock(long blockId) throws IOException { if (blockId == 0) return; synchronized (_allocationLock) { setAllocation(blockIdToIndex(blockId), ALLOC_FREE); } saveAllocation(); } /** * Sets the allocation for a block. */ private final int getAllocation(long blockIndex) { int allocOffset = (int) (ALLOC_BYTES_PER_BLOCK * blockIndex); return _allocationTable[allocOffset] & ALLOC_MASK; } /** * Sets the allocation for a block. */ private void setAllocation(long blockIndex, int code) { int allocOffset = (int) (ALLOC_BYTES_PER_BLOCK * blockIndex); for (int i = 1; i < ALLOC_BYTES_PER_BLOCK; i++) _allocationTable[allocOffset + i] = 0; _allocationTable[allocOffset] = (byte) code; setAllocDirty(allocOffset, allocOffset + ALLOC_BYTES_PER_BLOCK); } /** * Sets the dirty range for the allocation table. */ private void setAllocDirty(int min, int max) { if (min < _allocDirtyMin) _allocDirtyMin = min; if (_allocDirtyMax < max) _allocDirtyMax = max; } /** * Sets the allocation for a block. */ void saveAllocation() throws IOException { // cache doesn't actually need to write this data if (! _isFlushDirtyBlocksOnCommit) return; synchronized (_allocationWriteLock) { int dirtyMin; int dirtyMax; synchronized (_allocationLock) { dirtyMin = _allocDirtyMin; _allocDirtyMin = Integer.MAX_VALUE; dirtyMax = _allocDirtyMax; _allocDirtyMax = 0; } // Write each dirty block to disk. The physical blocks are // broken up each BLOCK_SIZE / ALLOC_BYTES_PER_BLOCK. for (; dirtyMin < dirtyMax; dirtyMin = (dirtyMin + BLOCK_SIZE) - dirtyMin % BLOCK_SIZE) { int block = dirtyMin / (BLOCK_SIZE / ALLOC_BYTES_PER_BLOCK); int offset = dirtyMin % BLOCK_SIZE; int length; if (dirtyMin / BLOCK_SIZE != dirtyMax / BLOCK_SIZE) length = BLOCK_SIZE - offset; else length = dirtyMax - dirtyMin; writeBlock((long) block * BLOCK_SIZE + offset, _allocationTable, offset, length); } } } /** * Reads a fragment. * * @param fragmentAddress the address of the fragment * @param fragmentOffset the offset inside the fragment to start reading * @param buffer the result buffer * @param offset offset into the result buffer * @param length the number of bytes to read * * @return the number of bytes read */ public int readFragment(long fragmentAddress, int fragmentOffset, byte []buffer, int offset, int length) throws IOException { if (fragmentAddress <= 0) { log.warning(this + " illegal fragment read with fragment-address=0"); return 0; } if (FRAGMENT_SIZE - fragmentOffset < length) { // server/13df throw new IllegalArgumentException(L.l("read offset {0} length {1} too long", fragmentOffset, length)); } Block block = readBlock(addressToBlockId(fragmentAddress)); try { int blockOffset = getFragmentOffset(fragmentAddress); byte []blockBuffer = block.getBuffer(); synchronized (blockBuffer) { System.arraycopy(blockBuffer, blockOffset + fragmentOffset, buffer, offset, length); } return length; } finally { block.free(); } } /** * Reads a fragment for a clob. * * @param fragmentAddress the address of the fragment * @param fragmentOffset the offset inside the fragment to start reading * @param buffer the result buffer * @param offset offset into the result buffer * @param length the length of the fragment in characters * * @return the number of characters read */ public int readFragment(long fragmentAddress, int fragmentOffset, char []buffer, int offset, int length) throws IOException { if (FRAGMENT_SIZE - fragmentOffset < 2 * length) { // server/13df throw new IllegalArgumentException(L.l("read offset {0} length {1} too long", fragmentOffset, length)); } Block block = readBlock(addressToBlockId(fragmentAddress)); try { int blockOffset = getFragmentOffset(fragmentAddress); blockOffset += fragmentOffset; byte []blockBuffer = block.getBuffer(); synchronized (blockBuffer) { for (int i = 0; i < length; i++) { int ch1 = blockBuffer[blockOffset] & 0xff; int ch2 = blockBuffer[blockOffset + 1] & 0xff; buffer[offset + i] = (char) ((ch1 << 8) + ch2); blockOffset += 2; } } return length; } finally { block.free(); } } /** * Reads a long value from a fragment. * * @return the long value */ public long readFragmentLong(long fragmentAddress, int fragmentOffset) throws IOException { Block block = readBlock(addressToBlockId(fragmentAddress)); try { int blockOffset = getFragmentOffset(fragmentAddress); byte []blockBuffer = block.getBuffer(); synchronized (blockBuffer) { return readLong(blockBuffer, blockOffset + fragmentOffset); } } finally { block.free(); } } /** * Reads a block. * * @param blockAddress the address of the block * @param blockOffset the offset inside the block to start reading * @param buffer the result buffer * @param offset offset into the result buffer * @param length the number of bytes to read * * @return the number of bytes read */ public int readBlock(long blockAddress, int blockOffset, byte []buffer, int offset, int length) throws IOException { if (BLOCK_SIZE - blockOffset < length) { // server/13df throw new IllegalArgumentException(L.l("read offset {0} length {1} too long", blockOffset, length)); } Block block = readBlock(addressToBlockId(blockAddress)); try { byte []blockBuffer = block.getBuffer(); synchronized (blockBuffer) { System.arraycopy(blockBuffer, blockOffset, buffer, offset, length); } return length; } finally { block.free(); } } /** * Reads a block for a clob. * * @param blockAddress the address of the block * @param blockOffset the offset inside the block to start reading * @param buffer the result buffer * @param offset offset into the result buffer * @param length the length of the block in characters * * @return the number of characters read */ public int readBlock(long blockAddress, int blockOffset, char []buffer, int offset, int length) throws IOException { if (BLOCK_SIZE - blockOffset < 2 * length) { // server/13df throw new IllegalArgumentException(L.l("read offset {0} length {1} too long", blockOffset, length)); } Block block = readBlock(addressToBlockId(blockAddress)); try { byte []blockBuffer = block.getBuffer(); synchronized (blockBuffer) { for (int i = 0; i < length; i++) { int ch1 = blockBuffer[blockOffset] & 0xff; int ch2 = blockBuffer[blockOffset + 1] & 0xff; buffer[offset + i] = (char) ((ch1 << 8) + ch2); blockOffset += 2; } } return length; } finally { block.free(); } } /** * Reads a long value from a block. * * @return the long value */ public long readBlockLong(long blockAddress, int offset) throws IOException { Block block = readBlock(addressToBlockId(blockAddress)); try { byte []blockBuffer = block.getBuffer(); synchronized (blockBuffer) { return readLong(blockBuffer, offset); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?