public Transaction tx() { assertLoaded(); return new Transaction(this); }
/** * Executes a closure and if it does not throw any exceptions, then it commits the transaction. * If the closure throws an Exception, then the transaction is rolled back. * * @param <T> * @param closure - the work to get exectued. * @throws T if the closure throws it * @throws IOException If the commit fails. */ public <T extends Throwable> void execute(Closure<T> closure) throws T, IOException { boolean success = false; try { closure.execute(this); success = true; } finally { if (success) { commit(); } else { rollback(); } } }
/** * Frees up a previously allocated page so that it can be re-allocated again. * * @param pageId the page to free up * @throws IOException * If an disk error occurred. * @throws IllegalStateException * if the PageFile is not loaded */ public void free(long pageId) throws IOException { free(load(pageId, null)); }
protected File getTempFile() { if (txFile == null) { txFile = new File(getPageFile().getDirectory(), IOHelper.toFileSystemSafeName("tx-" + Long.toString(getWriteTransactionId()) + "-" + Long.toString(System.currentTimeMillis()) + ".tmp")); } return txFile; }
next = load(page.getNext(), null); page.makeFree(getWriteTransactionId()); write(page, out.getData());
/** * Rolls back the transaction. */ public void rollback() throws IOException { if( writeTransactionId!=-1 ) { if (tmpFile != null) { tmpFile.close(); pageFile.removeTmpFile(getTempFile()); tmpFile = null; txFile = null; } // Release the pages that were allocated in the transaction... freePages(allocateList); freeList.clear(); allocateList.clear(); writes.clear(); writeTransactionId = -1; } else { freePages(allocateList); } size = 0; }
@Override public void remove() { try { synchronized (indexLock) { tx.execute(new Transaction.Closure<IOException>() { @Override public void execute(Transaction tx) throws IOException { iterator.remove(); } }); } } catch (IOException unexpected) { IllegalStateException e = new IllegalStateException(unexpected); e.initCause(unexpected); throw e; } }
public synchronized void load(Transaction tx) throws IOException { if (loaded.compareAndSet(false, true)) { final Page<Metadata> metadataPage = tx.load(pageId, metadataMarshaller); Page binPage = tx.allocate(metadata.binCapacity); metadata.binPageId = binPage.getPageId(); metadata.page = metadataPage; tx.store(metadataPage, metadataMarshaller, true);
private void recoverFreePages(final long lastRecoveryPage) throws Exception { LOG.info(toString() + ". Recovering pageFile free list due to prior unclean shutdown.."); SequenceSet newFreePages = new SequenceSet(); // need new pageFile instance to get unshared readFile PageFile recoveryPageFile = new PageFile(directory, name); recoveryPageFile.loadForRecovery(nextFreePageId.get()); try { for (Iterator<Page> i = new Transaction(recoveryPageFile).iterator(true); i.hasNext(); ) { Page page = i.next(); if (page.getPageId() >= lastRecoveryPage) { break; } if (page.getType() == Page.PAGE_FREE_TYPE) { newFreePages.add(page.getPageId()); } } } finally { recoveryPageFile.readFile.close(); } LOG.info(toString() + ". Recovered pageFile free list of size: " + newFreePages.rangeSize()); if (!newFreePages.isEmpty()) { // allow flush (with index lock held) to merge eventually recoveredFreeList.lazySet(newFreePages); } }
/** * Allocates a free page that you can write data to. * * @return a newly allocated page. * @throws IOException * If an disk error occurred. * @throws IllegalStateException * if the PageFile is not loaded */ public <T> Page<T> allocate() throws IOException { return allocate(1); }
@SuppressWarnings("unchecked") public void remove() { if (lastPage == null) { throw new IllegalStateException(); } try { free(lastPage); lastPage = null; } catch (IOException e) { throw new RuntimeException(e); } } };
} else { pageFile.tx().execute(new Transaction.Closure<IOException>() { @Override public void execute(Transaction tx) throws IOException { } else { pageFile.tx().execute(new Transaction.Closure<IOException>() { @Override public void execute(Transaction tx) throws IOException { } else { pageFile.tx().execute(new Transaction.Closure<IOException>() { @Override public void execute(Transaction tx) throws IOException { value.messageStoreStatistics = new StoredMessageStoreStatistics(pageFile, dataIn.readLong()); } else { pageFile.tx().execute(tx -> { value.messageStoreStatistics = new StoredMessageStoreStatistics(pageFile, tx.allocate()); value.messageStoreStatistics.load(tx); });
/** * Allows you to iterate through all active Pages in this object. Pages with type Page.FREE_TYPE are * not included in this iteration. * * Pages removed with Iterator.remove() will not actually get removed until the transaction commits. * * @throws IllegalStateException * if the PageFile is not loaded */ public Iterator<Page> iterator() { return (Iterator<Page>)iterator(false); }
@Override synchronized public void clear(Transaction tx) throws IOException { for (Iterator<ListNode<Key,Value>> iterator = listNodeIterator(tx); iterator.hasNext(); ) { ListNode<Key,Value>candidate = iterator.next(); candidate.clear(tx); // break up the transaction tx.commit(); } flushCache(); size.set(0); }
/** * Queues up a page write that should get done when commit() gets called. */ private void write(final Page page, byte[] data) throws IOException { Long key = page.getPageId(); // how much pages we have for this transaction size = writes.size() * pageFile.getPageSize(); PageWrite write; if (size > maxTransactionSize) { if (tmpFile == null) { tmpFile = new RandomAccessFile(getTempFile(), "rw"); } long location = nextLocation; tmpFile.seek(nextLocation); tmpFile.write(data); nextLocation = location + data.length; write = new PageWrite(page, location, data.length, getTempFile()); } else { write = new PageWrite(page, data); } writes.put(key, write); }
next = load(page.getNext(), null); page.makeFree(getWriteTransactionId()); write(page, out.getData());
/** * Commits the transaction to the PageFile as a single 'Unit of Work'. Either all page updates associated * with the transaction are written to disk or none will. */ public void commit() throws IOException { if( writeTransactionId!=-1 ) { if (tmpFile != null) { tmpFile.close(); pageFile.removeTmpFile(getTempFile()); tmpFile = null; txFile = null; } // Actually do the page writes... pageFile.write(writes.entrySet()); // Release the pages that were freed up in the transaction.. freePages(freeList); freeList.clear(); allocateList.clear(); writes.clear(); writeTransactionId = -1; } else { freePages(allocateList); } size = 0; }
/** * Frees up a previously allocated sequence of pages so that it can be re-allocated again. * * @param pageId the initial page of the sequence that will be getting freed * @param count the number of pages in the sequence * * @throws IOException * If an disk error occurred. * @throws IllegalStateException * if the PageFile is not loaded */ public void free(long pageId, int count) throws IOException { free(load(pageId, null), count); }