@NotNull List<String> getAllStoreNames() { checkIsFinished(); return getMetaTree().getAllStoreNames(); }
void downgradeTransaction(@NotNull final TransactionBase txn) { downgradeTransaction(txn.getCreatingThread(), txn.getAcquiredPermits()); txn.setAcquiredPermits(1); }
@NotNull @Override List<String> getAllStoreNames() { List<String> result = super.getAllStoreNames(); if (createdStores.isEmpty()) return result; if (result.isEmpty()) { result = new ArrayList<>(); } result.addAll(createdStores.keySet()); Collections.sort(result); return result; }
void releaseTransaction(@NotNull final TransactionBase txn) { releaseTransaction(txn.getCreatingThread(), txn.getAcquiredPermits()); }
void acquireTransaction(@NotNull final TransactionBase txn, @NotNull final Environment env) { final Thread creatingThread = txn.getCreatingThread(); int acquiredPermits; if (txn.isExclusive()) { if (txn.isGCTransaction()) { final int gcTransactionAcquireTimeout = env.getEnvironmentConfig().getGcTransactionAcquireTimeout(); acquiredPermits = tryAcquireExclusiveTransaction(creatingThread, gcTransactionAcquireTimeout); if (acquiredPermits == 0) { throw new TransactionAcquireTimeoutException(gcTransactionAcquireTimeout); } } else { acquiredPermits = acquireExclusiveTransaction(creatingThread); } if (acquiredPermits == 1) { txn.setExclusive(false); } } else { acquiredPermits = acquireTransaction(creatingThread); } txn.setAcquiredPermits(acquiredPermits); }
@Override public void beforeSettingChanged(@NotNull String key, @NotNull Object value, @NotNull Map<String, Object> context) { if (key.equals(EnvironmentConfig.ENV_IS_READONLY)) { if (log.getConfig().getReaderWriterProvider().isReadonly()) { throw new InvalidSettingException("Can't modify read-only state in run time since DataReaderWriterProvider is read-only"); } if (Boolean.TRUE.equals(value)) { suspendGC(); final TransactionBase txn = beginTransaction(); try { if (!txn.isReadonly()) { gc.getUtilizationProfile().forceSave(txn); txn.setCommitHook(new Runnable() { @Override public void run() { EnvironmentConfig.suppressConfigChangeListenersForThread(); ec.setEnvIsReadonly(true); EnvironmentConfig.resumeConfigChangeListenersForThread(); } }); ((ReadWriteTransaction) txn).forceFlush(); } } finally { txn.abort(); } } } }
/** * Constructor for creating new snapshot transaction. */ ReadonlyTransaction(@NotNull final TransactionBase origin) { super(origin.getEnvironment(), false); beginHook = null; setMetaTree(origin.getMetaTree()); final EnvironmentImpl env = getEnvironment(); env.acquireTransaction(this); env.registerTransaction(this); env.getStatistics().getStatisticsItem(READONLY_TRANSACTIONS).incTotal(); }
@Override public void run() { final EnvironmentImpl env = getEnvironment(); setMetaTree(env.getMetaTreeInternal()); env.registerTransaction(TransactionBase.this); if (beginHook != null) { beginHook.run(); } } };
private void checkTreeCursor() { if (treeCursor == null) { treeCursor = txn.getTree(store).openCursor(); } if (txnHighAddress != txn.getHighAddress()) { throw new ExodusException("Cursor holds an obsolete database snapshot. Check if txn.flush() or txn.commit() is called."); } } }
void setMetaTree(@NotNull final MetaTreeImpl metaTree) { checkIsFinished(); this.metaTree = metaTree; }
private void setCurrentTransaction(@NotNull final TransactionBase result) { final Thread thread = result.getCreatingThread(); Deque<TransactionBase> stack = threadTxns.get(thread); if (stack == null) { stack = new ArrayDeque<>(4); threadTxns.put(thread, stack); } stack.push(result); }
long getRoot() { return getMetaTree().root; }
CursorImpl(@NotNull final StoreImpl store, @NotNull final TransactionBase txn) { this.store = store; this.txn = txn; this.txnHighAddress = txn.getHighAddress(); treeCursor = null; isClosed = false; }
MetaTreeImpl holdNewestSnapshotBy(@NotNull final TransactionBase txn, final boolean acquireTxn) { if (acquireTxn) { acquireTransaction(txn); } final Runnable beginHook = txn.getBeginHook(); metaReadLock.lock(); try { if (beginHook != null) { beginHook.run(); } return metaTree; } finally { metaReadLock.unlock(); } }
void add(@NotNull final TransactionBase txn) { final Snapshot snapshot = new Snapshot(txn, txn.getRoot()); for (; ; ) { final MinMaxAwareSnapshotSet prevSet = snapshots.get(); final PersistentHashSet<Snapshot> newSet = prevSet.set.getClone(); if (!newSet.contains(snapshot)) { final PersistentHashSet.MutablePersistentHashSet<Snapshot> mutableSet = newSet.beginWrite(); mutableSet.add(snapshot); mutableSet.endWrite(); } final Snapshot prevMin = prevSet.min; final Snapshot prevMax = prevSet.max; final Snapshot newMin = prevMin != null && prevMin.root > snapshot.root ? snapshot : prevMin; final Snapshot newMax = prevMax != null && prevMax.root < snapshot.root ? snapshot : prevMax; if (this.snapshots.compareAndSet(prevSet, new MinMaxAwareSnapshotSet(newSet, newMin, newMax))) { break; } } }
ReadWriteTransaction(@NotNull final TransactionBase origin, @Nullable final Runnable beginHook) { super(origin.getEnvironment(), false); mutableTrees = new TreeMap<>(); removedStores = new LongHashMap<>(); createdStores = new HashMapDecorator<>(); final EnvironmentImpl env = getEnvironment(); this.beginHook = getWrappedBeginHook(beginHook); replayCount = 0; setMetaTree(origin.getMetaTree()); setExclusive(env.shouldTransactionBeExclusive(this)); env.acquireTransaction(this); env.registerTransaction(this); env.getStatistics().getStatisticsItem(TRANSACTIONS).incTotal(); }
@Override public Transaction getReadonlySnapshot() { checkIsFinished(); return new ReadonlyTransaction(this); }
@Override protected void finishTransaction(@NotNull final TransactionBase txn) { final Thread thread = txn.getCreatingThread(); // logging.info("finished txn " + System.identityHashCode(txn) + " in thread " + thread.getName(), new Throwable()); if (!Thread.currentThread().equals(thread)) { throw new ExodusException("Can't finish transaction in a thread different from the one which it was created in"); } final Deque<TransactionBase> stack = threadTxns.get(thread); if (stack == null) { throw new ExodusException("Transaction was already finished"); } if (txn != stack.peek()) { throw new ExodusException("Can't finish transaction: nested transaction is not finished"); } stack.pop(); if (stack.isEmpty()) { threadTxns.remove(thread); } super.finishTransaction(txn); }
@NotNull public ITree getTree(@NotNull final StoreImpl store) { checkIsFinished(); final int structureId = store.getStructureId(); ITree result = immutableTrees.get(structureId); if (result == null) { result = store.openImmutableTree(getMetaTree()); synchronized (immutableTrees) { immutableTrees.put(structureId, result); } } return result; }
@Nullable TreeMetaInfo getTreeMetaInfo(@NotNull final String name) { checkIsFinished(); return metaTree.getMetaInfo(name, env); }