Beispiel #1
0
 @Override
 public boolean commit() {
   try {
     if (!writeSet.isEmpty()) {
       int v = status.get();
       int s = v & STATUS_MASK;
       if (s == TX_ACTIVE && status.compareAndSet(v, v + (TX_COMMITTING - TX_ACTIVE))) {
         long newClock = clock.incrementAndGet();
         if (newClock != startTime.get() + 1 && !readSet.validate(this, id)) {
           rollback0();
           return false;
         }
         // Write values and release locks
         writeSet.commit(newClock);
         status.set(v + (TX_COMMITTED - TX_ACTIVE));
       } else {
         // We have been killed: wait for our locks to have been released
         while (s != TX_ABORTED) s = status.get() & STATUS_MASK;
         return false;
       }
     } else {
       // No need to set status to COMMITTED (we cannot be killed with an empty write set)
     }
     attempts = 0;
     return true;
   } finally {
     if (irrevocableState) {
       irrevocableState = false;
       irrevocableAccessLock.writeLock().unlock();
     } else {
       irrevocableAccessLock.readLock().unlock();
     }
   }
 }
Beispiel #2
0
 private boolean extend() {
   long now = clock.get();
   if (readSet.validate(this, id)) {
     endTime = now;
     return true;
   }
   return false;
 }
Beispiel #3
0
  private boolean onReadAccess(Object obj, long field, Type type) {
    if (vr) {
      // Visible read
      if (readLock == LockTable.LOCKED_WRITE) {
        // We already own that lock in write mode
        WriteFieldAccess w = writeSet.get(readHash, obj, field);
        if (w == null) return false;
        readValue = w.getValue();
        return true;
      } else {
        // We already own that lock in read mode
        return false;
      }
    } else {
      // Invisible read
      if ((status.get() & STATUS_MASK) != TX_ACTIVE) {
        // We have been killed: abort
        throw KILLED_EXCEPTION;
      }
      if (readLock == LockTable.LOCKED_WRITE) {
        // We already own that lock in write mode
        WriteFieldAccess w = writeSet.get(readHash, obj, field);
        if (w == null) return false;
        readValue = w.getValue();
        return true;
      } else if (readLock == LockTable.LOCKED_READ) {
        // We already own that lock in read mode
        return false;
      }
      boolean b = false;
      while (true) {
        while (readLock <= endTime) {
          // Re-read timestamp (check for race)
          long lock = LockTable.checkLock(this, readHash, id);
          if (lock != readLock) {
            readLock = lock;
            readValue = Field.getValue(obj, field, type);
            b = true;
            continue;
          }
          // We have read a valid value (in snapshot)
          if (readWriteHint) {
            // Save to read set
            readSet.add(obj, field, readHash, lock);
          }
          return b;
        }

        // Try to extend snapshot
        if (!(readWriteHint && extend())) {
          throw EXTEND_FAILURE_EXCEPTION;
        }
      }
    }
  }
Beispiel #4
0
  @Override
  public void init(int blockId, String metainf) {
    readSet.clear();
    writeSet.clear();

    // Lock according to the transaction irrevocable state
    if (irrevocableState) irrevocableAccessLock.writeLock().lock();
    else irrevocableAccessLock.readLock().lock();

    endTime = clock.get();
    startTime.set(endTime);
    status.set(((status.get() + (1 << STATUS_BITS)) & ~STATUS_MASK) | TX_ACTIVE);
    if (RO_HINT) {
      atomicBlockId = blockId;
      readWriteHint = readWriteMarkers.get(atomicBlockId);
    }
    attempts++;
    vr = (VR_THRESHOLD > 0 && VR_THRESHOLD <= attempts);
  }
Beispiel #5
0
  private void onWriteAccess(Object obj, long field, Object value, Type type) {
    if (!readWriteHint) {
      // Change hint to read-write
      readWriteMarkers.insert(atomicBlockId, true);
      throw READ_ONLY_FAILURE_EXCEPTION;
    }

    int hash = LockTable.hash(obj, field);
    // Lock entry in write mode (might throw an exception)
    long timestamp = LockTable.lock(this, hash, id, true);

    synchronized (writeSet) {
      // Mutual exclusion on write set to allow other transaction to drop locks
      if ((status.get() & STATUS_MASK) != TX_ACTIVE) {
        // We have been killed
        if (timestamp >= 0) {
          // Drop lock we just acquired (not in write set)
          LockTable.setAndReleaseLock(hash, timestamp);
        }
        // Abort
        throw KILLED_EXCEPTION;
      }
      if (timestamp < 0) {
        // We already own that lock
        writeSet.appendWrite(hash, obj, field, value, type);
      } else {
        // Add to write set
        if (timestamp > endTime) {
          // Handle write-after-read
          if (readSet.contains(obj, field)) {
            // Abort
            LockTable.setAndReleaseLock(hash, timestamp);
            throw WRITE_FAILURE_EXCEPTION;
          }
          // We delay validation until later (although we could already validate once here)
        }
        // Add to write set
        writeSet.addWrite(hash, obj, field, value, type, timestamp);
      }
    }
  }