예제 #1
0
  protected void put2(DataIO.DataOutputByteArray out, long ioRecid, long[] indexVals) {
    assert (disableLocks || locks[Store.lockPos(ioRecid)].writeLock().isHeldByCurrentThread());
    index.putLong(ioRecid, indexVals[0] | MASK_ARCHIVE);
    // write stuff
    if (indexVals.length == 1 || indexVals[1] == 0) { // is more then one? ie linked
      // write single

      phys.putData(indexVals[0] & MASK_OFFSET, out.buf, 0, out.pos);

    } else {
      int outPos = 0;
      // write linked
      for (int i = 0; i < indexVals.length; i++) {
        final int c = i == indexVals.length - 1 ? 0 : 8;
        final long indexVal = indexVals[i];
        final boolean isLast = (indexVal & MASK_LINKED) == 0;
        assert (isLast == (i == indexVals.length - 1));
        final int size = (int) (indexVal >>> 48);
        final long offset = indexVal & MASK_OFFSET;

        // write data
        phys.putData(offset + c, out.buf, outPos, size - c);
        outPos += size - c;

        if (c > 0) {
          // write position of next linked record
          phys.putLong(offset, indexVals[i + 1]);
        }
      }
      if (outPos != out.pos) throw new AssertionError();
    }
  }
예제 #2
0
 @Override
 public <A> boolean compareAndSwap(
     long recid, A expectedOldValue, A newValue, Serializer<A> serializer) {
   commitLock.readLock().lock();
   try {
     uncommitedData = true;
     Lock lock = locks[Store.lockPos(recid)].writeLock();
     lock.lock();
     try {
       boolean ret = super.compareAndSwap(recid, expectedOldValue, newValue, serializer);
       if (ret) {
         for (Reference<Tx> txr : txs) {
           Tx tx = txr.get();
           if (tx == null) continue;
           tx.old.putIfAbsent(recid, expectedOldValue);
         }
       }
       return ret;
     } finally {
       lock.unlock();
     }
   } finally {
     commitLock.readLock().unlock();
   }
 }
예제 #3
0
  @Override
  public <A> long put(A value, Serializer<A> serializer) {
    assert (value != null);
    DataIO.DataOutputByteArray out = serialize(value, serializer);
    final long ioRecid;
    if (!disableLocks) {
      newRecidLock.readLock().lock();
    }
    try {

      if (!disableLocks) {
        structuralLock.lock();
      }

      final long[] indexVals;
      try {
        ioRecid = freeIoRecidTake(true);
        indexVals = physAllocate(out.pos, true, false);
      } finally {
        if (!disableLocks) {
          structuralLock.unlock();
        }
      }
      final Lock lock;
      if (disableLocks) {
        lock = null;
      } else {
        lock = locks[Store.lockPos(ioRecid)].writeLock();
        lock.lock();
      }
      try {
        put2(out, ioRecid, indexVals);
      } finally {
        if (!disableLocks) {
          lock.unlock();
        }
      }
    } finally {
      if (!disableLocks) {
        newRecidLock.readLock().unlock();
      }
    }

    long recid = (ioRecid - IO_USER_START) / 8;
    assert (recid > 0);
    if (CC.LOG_STORE && LOG.isLoggable(Level.FINEST))
      LOG.finest(
          "Put recid="
              + recid
              + ", "
              + " size="
              + out.pos
              + ", "
              + " val="
              + value
              + " ser="
              + serializer);
    recycledDataOuts.offer(out);
    return recid;
  }
예제 #4
0
  protected void update2(DataIO.DataOutputByteArray out, long ioRecid) {
    final long indexVal = index.getLong(ioRecid);
    final int size = (int) (indexVal >>> 48);
    final boolean linked = (indexVal & MASK_LINKED) != 0;
    assert (disableLocks || locks[Store.lockPos(ioRecid)].writeLock().isHeldByCurrentThread());

    if (!linked && out.pos > 0 && size > 0 && size2ListIoRecid(size) == size2ListIoRecid(out.pos)) {
      // size did change, but still fits into this location
      final long offset = indexVal & MASK_OFFSET;

      // note: if size would not change, we still have to write MASK_ARCHIVE bit
      index.putLong(ioRecid, (((long) out.pos) << 48) | offset | MASK_ARCHIVE);

      phys.putData(offset, out.buf, 0, out.pos);
    } else {

      long[] indexVals = spaceReclaimTrack ? getLinkedRecordsIndexVals(indexVal) : null;

      if (!disableLocks) {
        structuralLock.lock();
      }
      try {

        if (spaceReclaimTrack) {
          // free first record pointed from indexVal
          if (size > 0) freePhysPut(indexVal, false);

          // if there are more linked records, free those as well
          if (indexVals != null) {
            for (int i = 0; i < indexVals.length && indexVals[i] != 0; i++) {
              freePhysPut(indexVals[i], false);
            }
          }
        }

        indexVals = physAllocate(out.pos, true, false);
      } finally {
        if (!disableLocks) {
          structuralLock.unlock();
        }
      }

      put2(out, ioRecid, indexVals);
    }
    assert (disableLocks || locks[Store.lockPos(ioRecid)].writeLock().isHeldByCurrentThread());
  }
예제 #5
0
  protected <A> A get2(long ioRecid, Serializer<A> serializer) throws IOException {
    assert (disableLocks
        || locks[Store.lockPos(ioRecid)].getWriteHoldCount() == 0
        || locks[Store.lockPos(ioRecid)].writeLock().isHeldByCurrentThread());

    long indexVal = index.getLong(ioRecid);
    if (indexVal == MASK_DISCARD) return null; // preallocated record

    int size = (int) (indexVal >>> 48);
    DataInput di;
    long offset = indexVal & MASK_OFFSET;
    if ((indexVal & MASK_LINKED) == 0) {
      // read single record
      di = phys.getDataInput(offset, size);

    } else {
      // is linked, first construct buffer we will read data to
      int pos = 0;
      int c = 8;
      // TODO use mapped bb and direct copying?
      byte[] buf = new byte[64];
      // read parts into segment
      for (; ; ) {
        DataInput in = phys.getDataInput(offset + c, size - c);

        if (buf.length < pos + size - c)
          buf = Arrays.copyOf(buf, Math.max(pos + size - c, buf.length * 2)); // buf to small, grow
        in.readFully(buf, pos, size - c);
        pos += size - c;
        if (c == 0) break;
        // read next part
        long next = phys.getLong(offset);
        offset = next & MASK_OFFSET;
        size = (int) (next >>> 48);
        // is the next part last?
        c = ((next & MASK_LINKED) == 0) ? 0 : 8;
      }
      di = new DataIO.DataInputByteArray(buf);
      size = pos;
    }
    return deserialize(serializer, size, di);
  }
예제 #6
0
  @Override
  public <A> void delete(long recid, Serializer<A> serializer) {
    assert (recid > 0);
    final long ioRecid = IO_USER_START + recid * 8;
    final Lock lock;
    if (disableLocks) {
      lock = null;
    } else {
      lock = locks[Store.lockPos(ioRecid)].writeLock();
      lock.lock();
    }
    try {
      // get index val and zero it out
      final long indexVal = index.getLong(ioRecid);
      index.putLong(ioRecid, 0L | MASK_ARCHIVE);

      if (!spaceReclaimTrack) return; // free space is not tracked, so do not mark stuff as free

      long[] linkedRecords = getLinkedRecordsIndexVals(indexVal);

      // now lock everything and mark free space
      if (!disableLocks) {
        structuralLock.lock();
      }
      try {
        // free recid
        freeIoRecidPut(ioRecid);
        // free first record pointed from indexVal\
        if ((indexVal >>> 48) > 0) freePhysPut(indexVal, false);

        // if there are more linked records, free those as well
        if (linkedRecords != null) {
          for (int i = 0; i < linkedRecords.length && linkedRecords[i] != 0; i++) {
            freePhysPut(linkedRecords[i], false);
          }
        }
      } finally {
        if (!disableLocks) {
          structuralLock.unlock();
        }
      }

    } finally {
      if (!disableLocks) {
        lock.unlock();
      }
    }
  }
예제 #7
0
 @Override
 public <A> A get(long recid, Serializer<A> serializer) {
   commitLock.readLock().lock();
   try {
     if (closed) throw new IllegalAccessError("closed");
     Lock lock = locks[Store.lockPos(recid)].readLock();
     lock.lock();
     try {
       return getNoLock(recid, serializer);
     } finally {
       lock.unlock();
     }
   } finally {
     commitLock.readLock().unlock();
   }
 }
예제 #8
0
  @Override
  public <A> boolean compareAndSwap(
      long recid, A expectedOldValue, A newValue, Serializer<A> serializer) {
    assert (expectedOldValue != null && newValue != null);
    assert (recid > 0);
    final long ioRecid = IO_USER_START + recid * 8;
    final Lock lock;
    if (disableLocks) {
      lock = null;
    } else {
      lock = locks[Store.lockPos(ioRecid)].writeLock();
      lock.lock();
    }

    DataIO.DataOutputByteArray out;
    try {
      /*
       * deserialize old value
       */

      A oldVal = get2(ioRecid, serializer);

      /*
       * compare oldValue and expected
       */
      if ((oldVal == null && expectedOldValue != null)
          || (oldVal != null && !oldVal.equals(expectedOldValue))) return false;

      /*
       * write new value
       */
      out = serialize(newValue, serializer);

      update2(out, ioRecid);

    } catch (IOException e) {
      throw new IOError(e);
    } finally {
      if (!disableLocks) {
        lock.unlock();
      }
    }
    recycledDataOuts.offer(out);
    return true;
  }
예제 #9
0
 @Override
 public void preallocate(long[] recids) {
   if (!disableLocks) {
     newRecidLock.readLock().lock();
   }
   try {
     if (!disableLocks) {
       structuralLock.lock();
     }
     try {
       for (int i = 0; i < recids.length; i++) recids[i] = freeIoRecidTake(true);
     } finally {
       if (!disableLocks) {
         structuralLock.unlock();
       }
     }
     for (int i = 0; i < recids.length; i++) {
       final long ioRecid = recids[i];
       final Lock lock;
       if (disableLocks) {
         lock = null;
       } else {
         lock = locks[Store.lockPos(ioRecid)].writeLock();
         lock.lock();
       }
       try {
         index.putLong(ioRecid, MASK_DISCARD);
       } finally {
         if (!disableLocks) {
           lock.unlock();
         }
       }
       recids[i] = (ioRecid - IO_USER_START) / 8;
       assert (recids[i] > 0);
     }
     if (CC.LOG_STORE && LOG.isLoggable(Level.FINEST))
       LOG.finest("Preallocate recids=" + Arrays.toString(recids));
   } finally {
     if (!disableLocks) {
       newRecidLock.readLock().unlock();
     }
   }
 }
예제 #10
0
  @Override
  public long preallocate() {
    if (!disableLocks) {
      newRecidLock.readLock().lock();
    }
    try {
      if (!disableLocks) {
        structuralLock.lock();
      }
      final long ioRecid;
      try {
        ioRecid = freeIoRecidTake(true);
      } finally {
        if (!disableLocks) {
          structuralLock.unlock();
        }
      }

      final Lock lock;
      if (disableLocks) {
        lock = null;
      } else {
        lock = locks[Store.lockPos(ioRecid)].writeLock();
        lock.lock();
      }
      try {
        index.putLong(ioRecid, MASK_DISCARD);
      } finally {
        if (!disableLocks) {
          lock.unlock();
        }
      }
      long recid = (ioRecid - IO_USER_START) / 8;
      assert (recid > 0);
      if (CC.LOG_STORE && LOG.isLoggable(Level.FINEST)) LOG.finest("Preallocate recid=" + recid);
      return recid;
    } finally {
      if (!disableLocks) {
        newRecidLock.readLock().unlock();
      }
    }
  }
예제 #11
0
 @Override
 public long preallocate() {
   commitLock.writeLock().lock();
   try {
     uncommitedData = true;
     long recid = super.preallocate();
     Lock lock = locks[Store.lockPos(recid)].writeLock();
     lock.lock();
     try {
       for (Reference<Tx> txr : txs) {
         Tx tx = txr.get();
         if (tx == null) continue;
         tx.old.putIfAbsent(recid, TOMBSTONE);
       }
     } finally {
       lock.unlock();
     }
     return recid;
   } finally {
     commitLock.writeLock().unlock();
   }
 }
예제 #12
0
 @Override
 public <A> void delete(long recid, Serializer<A> serializer) {
   commitLock.readLock().lock();
   try {
     uncommitedData = true;
     Lock lock = locks[Store.lockPos(recid)].writeLock();
     lock.lock();
     try {
       Object old = get(recid, serializer);
       for (Reference<Tx> txr : txs) {
         Tx tx = txr.get();
         if (tx == null) continue;
         tx.old.putIfAbsent(recid, old);
       }
       super.delete(recid, serializer);
     } finally {
       lock.unlock();
     }
   } finally {
     commitLock.readLock().unlock();
   }
 }
예제 #13
0
  @Override
  public <A> void update(long recid, A value, Serializer<A> serializer) {
    assert (value != null);
    assert (recid > 0);
    DataIO.DataOutputByteArray out = serialize(value, serializer);

    final long ioRecid = IO_USER_START + recid * 8;

    final Lock lock;
    if (disableLocks) {
      lock = null;
    } else {
      lock = locks[Store.lockPos(ioRecid)].writeLock();
      lock.lock();
    }
    try {
      update2(out, ioRecid);
    } finally {
      if (!disableLocks) {
        lock.unlock();
      }
    }
    if (CC.LOG_STORE && LOG.isLoggable(Level.FINEST))
      LOG.finest(
          "Update recid="
              + recid
              + ", "
              + " size="
              + out.pos
              + ", "
              + " val="
              + value
              + " ser="
              + serializer);

    recycledDataOuts.offer(out);
  }
예제 #14
0
 @Override
 public <A> A get(long recid, Serializer<A> serializer) {
   assert (recid > 0);
   final long ioRecid = IO_USER_START + recid * 8;
   final Lock lock;
   if (disableLocks) {
     lock = null;
   } else {
     lock = locks[Store.lockPos(ioRecid)].readLock();
     lock.lock();
   }
   try {
     final A ret = get2(ioRecid, serializer);
     if (CC.LOG_STORE && LOG.isLoggable(Level.FINEST))
       LOG.finest("GET recid=" + recid + ", " + " ret=" + ret + ", " + " ser=" + serializer);
     return ret;
   } catch (IOException e) {
     throw new IOError(e);
   } finally {
     if (!disableLocks) {
       lock.unlock();
     }
   }
 }
예제 #15
0
    @Override
    public <A> boolean compareAndSwap(
        long recid, A expectedOldValue, A newValue, Serializer<A> serializer) {
      if (!fullTx) throw new UnsupportedOperationException("read-only");

      commitLock.readLock().lock();
      try {

        Lock lock = locks[Store.lockPos(recid)].writeLock();
        lock.lock();
        try {
          A oldVal = getNoLock(recid, serializer);
          boolean ret = oldVal != null && oldVal.equals(expectedOldValue);
          if (ret) {
            mod.put(recid, Fun.t2(newValue, serializer));
          }
          return ret;
        } finally {
          lock.unlock();
        }
      } finally {
        commitLock.readLock().unlock();
      }
    }
예제 #16
0
 protected void freeIoRecidPut(long ioRecid) {
   assert (ioRecid > IO_USER_START);
   assert (disableLocks || locks[Store.lockPos(ioRecid)].writeLock().isHeldByCurrentThread());
   if (spaceReclaimTrack) longStackPut(IO_FREE_RECID, ioRecid, false);
 }