store.java
来自「RESIN 3.2 最新源码」· Java 代码 · 共 1,996 行 · 第 1/4 页
JAVA
1,996 行
{ while (true) { synchronized (_allocationLock) { byte []allocationTable = _allocationTable; for (int i = 0; i < allocationTable.length; i += ALLOC_BYTES_PER_BLOCK) { int fragMask = allocationTable[i + 1] & 0xff; if (allocationTable[i] == ALLOC_MINI_FRAG && fragMask != 0xff) { allocationTable[i + 1] = (byte) 0xff; setAllocDirty(i + 1, i + 2); _miniFragmentUseCount++; long fragmentAddress = BLOCK_SIZE * ((long) i / ALLOC_BYTES_PER_BLOCK); return fragmentAddress; } } } // if no fragment, allocate a new one. Block block = allocateMiniFragmentBlock(); block.free(); } } /** * Deletes a miniFragment. */ public void deleteMiniFragment(StoreTransaction xa, long fragmentAddress) throws IOException { Block block = readBlock(fragmentAddress); try { int fragIndex = (int) (fragmentAddress & BLOCK_OFFSET_MASK); int offset = fragIndex / 8 + MINI_FRAG_ALLOC_OFFSET; int mask = 1 << (fragIndex % 8); byte []blockBuffer = block.getBuffer(); synchronized (blockBuffer) { blockBuffer[offset] &= ~mask; block.setDirty(offset, offset + 1); int i = (int) (ALLOC_BYTES_PER_BLOCK * (fragmentAddress / BLOCK_SIZE)); int j = (int) (fragmentAddress & 0xff); synchronized (_allocationLock) { int fragMask = _allocationTable[i + 1] & 0xff; //System.out.println((fragmentAddress / BLOCK_SIZE) + ":" + j + " DELETE"); if (_allocationTable[i] != ALLOC_MINI_FRAG) System.out.println("BAD ENTRY: " + fragMask); _allocationTable[i + 1] = 0; _miniFragmentUseCount--; setAllocDirty(i + 1, i + 2); } } } finally { block.free(); } } /** * Writes a miniFragment. * * @param xa the owning transaction * @param fragmentAddress the fragment to write * @param fragmentOffset the offset into the fragment * @param buffer the write buffer * @param offset offset into the write buffer * @param length the number of bytes to write * * @return the fragment id */ public void writeMiniFragment(StoreTransaction xa, long fragmentAddress, int fragmentOffset, byte []buffer, int offset, int length) throws IOException { if (MINI_FRAG_SIZE - fragmentOffset < length) throw new IllegalArgumentException(L.l("write offset {0} length {1} too long", fragmentOffset, length)); Block block = xa.readBlock(this, addressToBlockId(fragmentAddress)); try { xa.addUpdateBlock(block); int blockOffset = getMiniFragmentOffset(fragmentAddress); byte []blockBuffer = block.getBuffer(); blockOffset += fragmentOffset; synchronized (blockBuffer) { System.arraycopy(buffer, offset, blockBuffer, blockOffset, length); block.setDirty(blockOffset, blockOffset + length); } } finally { block.free(); } } /** * Writes a character based * * @param miniFragmentAddress the fragment to write * @param fragmentOffset the offset into the fragment * @param buffer the write buffer * @param offset offset into the write buffer * @param length the number of bytes to write */ public void writeMiniFragment(StoreTransaction xa, long fragmentAddress, int fragmentOffset, char []buffer, int offset, int length) throws IOException { if (MINI_FRAG_SIZE - fragmentOffset < length) throw new IllegalArgumentException(L.l("write offset {0} length {1} too long", fragmentOffset, length)); Block block = xa.readBlock(this, addressToBlockId(fragmentAddress)); try { block = xa.createAutoCommitWriteBlock(block); int blockOffset = getMiniFragmentOffset(fragmentAddress); byte []blockBuffer = block.getBuffer(); blockOffset += fragmentOffset; synchronized (blockBuffer) { int blockTail = blockOffset; for (int i = 0; i < length; i++) { char ch = buffer[offset + i]; blockBuffer[blockTail] = (byte) (ch >> 8); blockBuffer[blockTail + 1] = (byte) (ch); blockTail += 2; } block.setDirty(blockOffset, blockTail); } } finally { block.free(); } } /** * Writes a long value to a miniFragment. * * @return the long value */ public void writeMiniFragmentLong(StoreTransaction xa, long fragmentAddress, int fragmentOffset, long value) throws IOException { Block block = xa.readBlock(this, addressToBlockId(fragmentAddress)); try { xa.addUpdateBlock(block); int blockOffset = getMiniFragmentOffset(fragmentAddress); byte []blockBuffer = block.getBuffer(); int offset = blockOffset + fragmentOffset; synchronized (blockBuffer) { writeLong(blockBuffer, offset, value); block.setDirty(offset, offset + 8); } } finally { block.free(); } } /** * Returns the miniFragment offset for an id. */ private int getMiniFragmentOffset(long fragmentAddress) { int id = (int) (fragmentAddress & BLOCK_OFFSET_MASK); return (int) (MINI_FRAG_SIZE * id); } /** * Reads a block into the buffer. */ public void readBlock(long blockId, byte []buffer, int offset, int length) throws IOException { synchronized (_fileLock) { RandomAccessWrapper wrapper = openRowFile(); RandomAccessStream is = wrapper.getFile(); long blockAddress = blockId & BLOCK_MASK; try { if (blockAddress < 0 || _fileSize < blockAddress + length) { throw new IllegalStateException(L.l("block at {0} is invalid for file {1} (length {2})", Long.toHexString(blockAddress), _path, Long.toHexString(_fileSize))); } //System.out.println("READ: " + (blockAddress >> 16) + ":" + (blockAddress & 0xffff)); int readLen = is.read(blockAddress, buffer, offset, length); if (readLen < 0) { for (int i = 0; i < BLOCK_SIZE; i++) buffer[i] = 0; } freeRowFile(wrapper); wrapper = null; } finally { if (wrapper != null) wrapper.close(); } } } /** * Saves the buffer to the database. */ public void writeBlock(long blockAddress, byte []buffer, int offset, int length) throws IOException { synchronized (_fileLock) { RandomAccessWrapper wrapper = openRowFile(); RandomAccessStream os = wrapper.getFile(); try { os.write(blockAddress, buffer, offset, length); freeRowFile(wrapper); wrapper = null; if (_fileSize < blockAddress + length) { _fileSize = blockAddress + length; } } finally { if (wrapper != null) wrapper.close(); } } } /** * Opens the underlying file to the database. */ private RandomAccessWrapper openRowFile() throws IOException { RandomAccessStream file = null; RandomAccessWrapper wrapper = null; synchronized (this) { SoftReference<RandomAccessWrapper> ref = _cachedRowFile; _cachedRowFile = null; if (ref != null) { wrapper = ref.get(); } } if (wrapper != null) file = wrapper.getFile(); if (file == null) { file = _path.openRandomAccess(); wrapper = new RandomAccessWrapper(file); } return wrapper; } private void freeRowFile(RandomAccessWrapper wrapper) throws IOException { synchronized (this) { if (_cachedRowFile == null) { _cachedRowFile = new SoftReference<RandomAccessWrapper>(wrapper); return; } } wrapper.close(); } /** * Writes the short. */ private static void writeShort(byte []buffer, int offset, int v) { buffer[offset + 0] = (byte) (v >> 8); buffer[offset + 1] = (byte) (v); } /** * Reads a short. */ private static int readShort(byte []buffer, int offset) { return (((buffer[offset + 0] & 0xff) << 8) | ((buffer[offset + 1] & 0xff))); } /** * Flush the store. */ public void flush() { if (_lifecycle.isActive()) { if (_blockManager != null) { _blockManager.flush(this); } } } /** * True if destroyed. */ public boolean isClosed() { return _lifecycle.isDestroyed(); } /** * Closes the store. */ public void close() { if (! _lifecycle.toDestroy()) return; log.finer(this + " closing"); if (_blockManager != null) { _blockManager.freeStore(this); _blockManager.freeStoreId(_id); } long id = _id; _id = 0; _path = null; RandomAccessWrapper wrapper = null; SoftReference<RandomAccessWrapper> ref = _cachedRowFile; _cachedRowFile = null; if (ref != null) wrapper = ref.get(); if (wrapper != null) { try { wrapper.close(); } catch (Throwable e) { } } } // debugging stuff. /** * Returns a copy of the allocation table. */ public byte []getAllocationTable() { byte []table = new byte[_allocationTable.length]; System.arraycopy(_allocationTable, 0, table, 0, table.length); return table; } private static IllegalStateException stateError(String msg) { IllegalStateException e = new IllegalStateException(msg); e.fillInStackTrace(); log.log(Level.WARNING, e.toString(), e); return e; } /** * Reads the long. */ public static long readLong(byte []buffer, int offset) { return (((buffer[offset + 0] & 0xffL) << 56) + ((buffer[offset + 1] & 0xffL) << 48) + ((buffer[offset + 2] & 0xffL) << 40) + ((buffer[offset + 3] & 0xffL) << 32) + ((buffer[offset + 4] & 0xffL) << 24) + ((buffer[offset + 5] & 0xffL) << 16) + ((buffer[offset + 6] & 0xffL) << 8) + ((buffer[offset + 7] & 0xffL))); } /** * Writes the long. */ public static void writeLong(byte []buffer, int offset, long v) { buffer[offset + 0] = (byte) (v >> 56); buffer[offset + 1] = (byte) (v >> 48); buffer[offset + 2] = (byte) (v >> 40); buffer[offset + 3] = (byte) (v >> 32); buffer[offset + 4] = (byte) (v >> 24); buffer[offset + 5] = (byte) (v >> 16); buffer[offset + 6] = (byte) (v >> 8); buffer[offset + 7] = (byte) (v); } /** * Debug names for the allocation. */ public static String codeToName(int code) { switch (code) { case ALLOC_FREE: return "free"; case ALLOC_ROW: return "row"; case ALLOC_USED: return "used"; case ALLOC_FRAGMENT: return "fragment"; case ALLOC_MINI_FRAG: return "mini-fragment"; case ALLOC_INDEX: return "index"; default: return String.valueOf(code); } } public String toString() { return "Store[" + _id + "]"; } static class RandomAccessWrapper { private RandomAccessStream _file; RandomAccessWrapper(RandomAccessStream file) { _file = file; } RandomAccessStream getFile() { return _file; } void close() throws IOException { RandomAccessStream file = _file; _file = null; if (file != null) file.close(); } protected void finalize() throws Throwable { super.finalize(); close(); } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?