Search in sources :

Example 1 with ONonTxOperationPerformedWALRecord

use of com.orientechnologies.orient.core.storage.impl.local.paginated.wal.ONonTxOperationPerformedWALRecord in project orientdb by orientechnologies.

the class OAtomicOperationsManager method startAtomicOperation.

/**
   * Starts atomic operation inside of current thread. If atomic operation has been already started, current atomic operation
   * instance will be returned. All durable components have to call this method at the beginning of any data modification
   * operation.
   * <p>
   * <p>In current implementation of atomic operation, each component which is participated in atomic operation is hold under
   * exclusive lock till atomic operation will not be completed (committed or rollbacked).
   * <p>
   * <p>If other thread is going to read data from component it has to acquire read lock inside of atomic operation manager {@link
   * #acquireReadLock(ODurableComponent)}, otherwise data consistency will be compromised.
   * <p>
   * <p>Atomic operation may be delayed if start of atomic operations is prohibited by call of {@link
   * #freezeAtomicOperations(Class, String)} method. If mentioned above method is called then execution of current method will be
   * stopped till call of {@link #releaseAtomicOperations(long)} method or exception will be thrown. Concrete behaviour depends on
   * real values of parameters of {@link #freezeAtomicOperations(Class, String)} method.
   *
   * @param trackNonTxOperations If this flag set to <code>true</code> then special record {@link ONonTxOperationPerformedWALRecord}
   *                             will be added to WAL in case of atomic operation is started outside of active storage transaction.
   *                             During storage restore procedure this record is monitored and if given record is present then
   *                             rebuild of all indexes is performed.
   * @param lockName             Name of lock (usually name of component) which is going participate in atomic operation.
   *
   * @return Instance of active atomic operation.
   */
public OAtomicOperation startAtomicOperation(String lockName, boolean trackNonTxOperations) throws IOException {
    OAtomicOperation operation = currentOperation.get();
    if (operation != null) {
        operation.incrementCounter();
        if (trackAtomicOperations) {
            final OPair<String, Deque<OPair<String, StackTraceElement[]>>> atomicPair = activeAtomicOperations.get(operation.getOperationUnitId());
            if (atomicPair == null) {
                throw new IllegalStateException("Atomic operation is not registered in manager");
            }
            final Deque<OPair<String, StackTraceElement[]>> stack = atomicPair.getValue();
            stack.push(new OPair<String, StackTraceElement[]>(lockName, Thread.currentThread().getStackTrace()));
        }
        if (lockName != null)
            acquireExclusiveLockTillOperationComplete(operation, lockName);
        return operation;
    }
    atomicOperationsCount.increment();
    while (freezeRequests.get() > 0) {
        assert freezeRequests.get() >= 0;
        atomicOperationsCount.decrement();
        throwFreezeExceptionIfNeeded();
        final Thread thread = Thread.currentThread();
        addThreadInWaitingList(thread);
        if (freezeRequests.get() > 0) {
            LockSupport.park(this);
        }
        atomicOperationsCount.increment();
    }
    assert freezeRequests.get() >= 0;
    final boolean useWal = useWal();
    final OOperationUnitId unitId = OOperationUnitId.generateId();
    final OLogSequenceNumber lsn = useWal ? writeAheadLog.logAtomicOperationStartRecord(true, unitId) : null;
    operation = new OAtomicOperation(lsn, unitId, readCache, writeCache, storage.getId(), performanceStatisticManager);
    currentOperation.set(operation);
    if (trackAtomicOperations) {
        final Thread thread = Thread.currentThread();
        final Deque<OPair<String, StackTraceElement[]>> lockStack = new LinkedList<OPair<String, StackTraceElement[]>>();
        final OPair<String, StackTraceElement[]> lockPair = new OPair<String, StackTraceElement[]>(lockName, thread.getStackTrace());
        lockStack.push(lockPair);
        activeAtomicOperations.put(unitId, new OPair<String, Deque<OPair<String, StackTraceElement[]>>>(thread.getName(), lockStack));
    }
    if (useWal && trackNonTxOperations && storage.getStorageTransaction() == null)
        writeAheadLog.log(new ONonTxOperationPerformedWALRecord());
    if (lockName != null)
        acquireExclusiveLockTillOperationComplete(operation, lockName);
    return operation;
}
Also used : Deque(java.util.Deque) ONonTxOperationPerformedWALRecord(com.orientechnologies.orient.core.storage.impl.local.paginated.wal.ONonTxOperationPerformedWALRecord) LinkedList(java.util.LinkedList) OLogSequenceNumber(com.orientechnologies.orient.core.storage.impl.local.paginated.wal.OLogSequenceNumber) OPair(com.orientechnologies.common.util.OPair) OOperationUnitId(com.orientechnologies.orient.core.storage.impl.local.paginated.wal.OOperationUnitId)

Aggregations

OPair (com.orientechnologies.common.util.OPair)1 OLogSequenceNumber (com.orientechnologies.orient.core.storage.impl.local.paginated.wal.OLogSequenceNumber)1 ONonTxOperationPerformedWALRecord (com.orientechnologies.orient.core.storage.impl.local.paginated.wal.ONonTxOperationPerformedWALRecord)1 OOperationUnitId (com.orientechnologies.orient.core.storage.impl.local.paginated.wal.OOperationUnitId)1 Deque (java.util.Deque)1 LinkedList (java.util.LinkedList)1