/** * Lock the blocks. The blocks are locked in ascending block id order to avoid deadlocks. * * @param isWrite if true, the block should be locked for writing */ public void lock() throws SQLException { if (_isNonLocking) return; if (_isLocked) { throw new IllegalStateException(L.l("blocks are already locked")); } _isLocked = true; if (_thread != Thread.currentThread()) throw new IllegalStateException(); int len = _tableIterators.length; for (int i = 0; i < len; i++) { Block bestBlock = null; long bestId = Long.MAX_VALUE; loop: for (int j = 0; j < len; j++) { TableIterator iter = _tableIterators[j]; if (iter == null) continue; Block block = iter.getBlock(); if (block == null) continue; long id = block.getBlockId(); if (bestId <= id) continue; for (int k = 0; k < i; k++) { if (_blockLocks[k] == block) continue loop; } bestId = id; bestBlock = block; } try { if (bestBlock == null) { } else if (_isWrite) { bestBlock.getWriteLock().tryLock(_xa.getTimeout(), TimeUnit.MILLISECONDS); } else { bestBlock.getReadLock().tryLock(_xa.getTimeout(), TimeUnit.MILLISECONDS); } } catch (Exception e) { throw new IllegalStateException(e); } // assignment must be after obtaining lock because the unlock // requires a lock _blockLocks[i] = bestBlock; } }
/** Returns the following block. */ public boolean nextBlock() throws IOException { byte[] buffer = _buffer; Block block = _block; _block = null; _buffer = null; if (block != null) { block.free(); } _blockId = _table.firstRowBlock(_blockId + Table.BLOCK_SIZE); if (_blockId < 0) { return false; } block = _xa.readBlock(_table, _blockId); buffer = block.getBuffer(); _block = block; _buffer = buffer; _rowOffset = 0; return true; }
public void close() throws SQLException { Thread thread = _thread; _thread = null; unlock(); if (thread != null && thread != Thread.currentThread()) { throw new IllegalStateException(); } DbTransaction xa = _xa; _xa = null; // db/0a10 if (xa != null && xa.isAutoCommit()) xa.commit(); }
/** * Unlock the blocks. The blocks are unlocked in descending order. * * @param isWrite if true, the block should be unlocked for writing */ public void unlock() throws SQLException { if (_isNonLocking) return; if (!_isLocked) { return; } _isLocked = false; if (_thread != null && _thread != Thread.currentThread()) throw new IllegalStateException( String.valueOf(_thread) + " current " + Thread.currentThread()); int len = _blockLocks.length; // need to unlock first since the writeData/commit will wait for // write locks to clear before committing for (int i = len - 1; i >= 0; i--) { Block block = _blockLocks[i]; if (block == null) { } else if (_isWrite) { block.getWriteLock().unlock(); } else { block.getReadLock().unlock(); } } try { _xa.writeData(); } finally { for (int i = len - 1; i >= 0; i--) { Block block = _blockLocks[i]; _blockLocks[i] = null; if (block == null) { } else if (_isWrite) { try { block.commit(); } catch (Exception e) { log.log(Level.FINE, e.toString(), e); } } } } }
/** Sets the next row. */ public void setRow(long rowAddr) throws IOException { long blockId = _table.addressToBlockId(rowAddr); if (blockId != _blockId) { _blockId = blockId; Block block = _block; _block = null; _buffer = null; if (block != null) { block.free(); } _block = _xa.readBlock(_table, _blockId); _buffer = _block.getBuffer(); } _rowOffset = (int) (rowAddr & BlockStore.BLOCK_OFFSET_MASK); }
public void setDirty() throws SQLException { _xa.addUpdateBlock(_block); _block.setDirty(_rowOffset, _rowOffset + _rowLength); }