@Override
 public <A> void update(long recid, A value, Serializer<A> serializer) {
   if (!fullTx) throw new UnsupportedOperationException("read-only");
   commitLock.readLock().lock();
   try {
     mod.put(recid, Fun.t2(value, serializer));
   } finally {
     commitLock.readLock().unlock();
   }
 }
 @Override
 public <A> long put(A value, Serializer<A> serializer) {
   if (!fullTx) throw new UnsupportedOperationException("read-only");
   commitLock.writeLock().lock();
   try {
     Long recid = preallocRecidTake();
     usedPreallocatedRecids.add(recid);
     mod.put(recid, Fun.t2(value, serializer));
     return recid;
   } finally {
     commitLock.writeLock().unlock();
   }
 }
    @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();
      }
    }