예제 #1
0
 private void moveAndClear(LongLongMap from, LongLongMap to) {
   long[] table = from.table;
   for (int i = 0; i < table.length; ) {
     long key = table[i++];
     long val = table[i++];
     if (key == 0) continue;
     to.put(key, val);
   }
   from.clear();
 }
예제 #2
0
  @Override
  public void commit() {
    if (isSnapshot) return;

    if (!tx) {
      vol.sync();
      return;
    }

    commitLock.lock();
    try {
      StoreAppend[] snaps =
          snapshots == null
              ? STORE_APPENDS_ZERO_ARRAY
              : snapshots.toArray(STORE_APPENDS_ZERO_ARRAY);

      for (int i = 0; i < locks.length; i++) {
        Lock lock = locks[i].writeLock();
        lock.lock();
        try {
          long[] m = modified[i].table;
          for (int j = 0; j < m.length; j += 2) {
            long recid = m[j];
            long recidOffset = recid * 8;
            if (recidOffset == 0) continue;
            indexTable.ensureAvailable(recidOffset + 8);
            long oldVal = indexTable.getLong(recidOffset);
            indexTable.putLong(recidOffset, m[j + 1]);

            for (StoreAppend snap : snaps) {
              LongLongMap m2 = snap.modified[i];
              if (m2.get(recid) == 0) {
                m2.put(recid, oldVal);
              }
            }
          }
          modified[i].clear();
        } finally {
          lock.unlock();
        }
      }
      long offset = alloc(1, 1);
      vol.putUnsignedByte(offset, I_TX_VALID);
      vol.sync();
    } finally {
      commitLock.unlock();
    }
  }
예제 #3
0
  protected void initOpen() {
    checkFeaturesBitmap(vol.getLong(HEAD_FEATURES));

    // replay log
    long pos = headerSize;
    final long volumeSize = vol.length();
    long lastValidPos = pos;
    long highestRecid2 = RECID_LAST_RESERVED;
    LongLongMap commitData = tx ? new LongLongMap() : null;

    try {

      while (true) {
        lastValidPos = pos;
        if (pos >= volumeSize) break;
        final long instPos = pos;
        final int inst = vol.getUnsignedByte(pos++);

        if (inst == I_INSERT || inst == I_UPDATE) {

          long recid = vol.getPackedLong(pos);
          pos += recid >>> 60;
          recid = longParityGet(recid & DataIO.PACK_LONG_RESULT_MASK);

          highestRecid2 = Math.max(highestRecid2, recid);

          commitData.put(recid, instPos);

          // skip rest of the record
          long size = vol.getPackedLong(pos);
          long dataLen = longParityGet(size & DataIO.PACK_LONG_RESULT_MASK) - 1;
          dataLen = Math.max(0, dataLen);
          pos = pos + (size >>> 60) + dataLen;
        } else if (inst == I_DELETE) {
          long recid = vol.getPackedLong(pos);
          pos += recid >>> 60;
          recid = longParityGet(recid & DataIO.PACK_LONG_RESULT_MASK);

          highestRecid2 = Math.max(highestRecid2, recid);

          commitData.put(recid, -1);
        } else if (inst == I_DELETE) {
          long recid = vol.getPackedLong(pos);
          pos += recid >>> 60;
          recid = longParityGet(recid & DataIO.PACK_LONG_RESULT_MASK);
          highestRecid2 = Math.max(highestRecid2, recid);
          commitData.put(recid, -2);

        } else if (inst == I_SKIP_SINGLE_BYTE) {
          // do nothing, just skip single byte
        } else if (inst == I_SKIP_MULTI_BYTE) {
          // read size and skip it
          // skip rest of the record
          long size = vol.getPackedLong(pos);
          pos += (size >>> 60) + longParityGet(size & DataIO.PACK_LONG_RESULT_MASK);
        } else if (inst == I_TX_VALID) {
          if (tx) {
            // apply changes from commitData to indexTable
            for (int i = 0; i < commitData.table.length; i += 2) {
              long recidOffset = commitData.table[i] * 8;
              if (recidOffset == 0) continue;
              indexTable.ensureAvailable(recidOffset + 8);
              indexTable.putLong(recidOffset, commitData.table[i + 1]);
            }
            commitData.clear();
          }
        } else if (inst == I_TX_ROLLBACK) {
          if (tx) {
            commitData.clear();
          }
        } else if (inst == 0) {
          // rollback last changes if that is necessary
          if (tx) {
            // rollback changes in index table since last valid tx
            commitData.clear();
          }

          break;
        } else {
          // TODO log here?
          LOG.warning("Unknown instruction " + inst);
          break;
        }
      }
    } catch (RuntimeException e) {
      // log replay finished
      // TODO log here?
      LOG.log(Level.WARNING, "Log replay finished", e);
      if (tx) {
        // rollback changes in index table since last valid tx
        commitData.clear();
      }
    }
    eof = lastValidPos;

    highestRecid.set(highestRecid2);
  }
예제 #4
0
  @Override
  public void commit() {
    commitLock.lock();
    try {
      // flush write caches into write ahead log
      flushWriteCache();

      // move uncommited data to committed
      for (int segment = 0; segment < locks.length; segment++) {
        locks[segment].writeLock().lock();
        try {
          // dump index vals into WAL
          long[] table = uncommittedIndexTable[segment].table;
          for (int i = 0; i < table.length; ) {
            long offset = table[i++];
            long val = table[i++];
            if (offset == 0) continue;
            wal.walPutLong(offset, val);
          }

          moveAndClear(uncommittedIndexTable[segment], committedIndexTable[segment]);
          moveAndClear(uncommittedDataLongs[segment], committedDataLongs[segment]);

        } finally {
          locks[segment].writeLock().unlock();
        }
      }

      structuralLock.lock();
      try {
        // flush modified Long Stack pages into WAL
        long[] set = uncommittedStackPages.set;
        longStackPagesLoop:
        for (int i = 0; i < set.length; i++) {
          long offset = set[i];
          if (offset == 0) continue longStackPagesLoop;
          byte[] val = (byte[]) uncommittedStackPages.values[i];

          if (val == LONG_STACK_PAGE_TOMBSTONE) committedPageLongStack.put(offset, -1);
          else {
            if (CC.ASSERT) assertLongStackPage(offset, val);

            long walPointer = wal.walPutByteArray(offset, val, 0, val.length);
            committedPageLongStack.put(offset, walPointer);
          }
        }
        uncommittedStackPages.clear();

        // update checksum
        headVol.putInt(HEAD_CHECKSUM, headChecksum(headVol));
        // take backup of headVol
        headVol.getData(0, headVolBackup, 0, headVolBackup.length);
        wal.walPutByteArray(0, headVolBackup, 0, headVolBackup.length);
        wal.commit();
        wal.seal();
        replaySoft();
        realVol.sync();
        wal.destroyWalFiles();
      } finally {
        structuralLock.unlock();
      }
    } finally {
      commitLock.unlock();
    }
  }