@Override
  protected int enumerateImpl(final Data value, final boolean onlyCheckForExisting, boolean saveNewValue) throws IOException {
    (onlyCheckForExisting ? getReadLock() : getWriteLock()).lock();
    try {
      if (onlyCheckForExisting) {
        lockStorageRead();
      }
      else {
        lockStorageWrite();
      }

      try {
        if (IntToIntBtree.doDump) System.out.println(value);
        final int valueHC = myDataDescriptor.getHashCode(value);

        //FIXME RC: use of shared myResultBuf -- prevents get rid of getReadLock() here
        final boolean hasMapping = myBTree.get(valueHC, myResultBuf);
        if (!hasMapping && onlyCheckForExisting) {
          return NULL_ID;
        }

        final int indexNodeValueAddress = hasMapping ? myResultBuf[0] : 0;
        int collisionAddress = NULL_ID;
        boolean hasExistingData = false;

        if (!myInlineKeysNoMapping) {
          if (indexNodeValueAddress > 0) {
            // we found reference to no dupe key
            if (isKeyAtIndex(value, indexNodeValueAddress)) {
              if (!saveNewValue) {
                return indexNodeValueAddress;
              }
              hasExistingData = true;
            }

            collisionAddress = indexNodeValueAddress;
          }
          else if (indexNodeValueAddress < 0) { // indexNodeValueAddress points to duplicates list
            collisionAddress = -indexNodeValueAddress;

            while (true) {
              final int address = myCollisionResolutionStorage.getInt(collisionAddress);
              if (isKeyAtIndex(value, address)) {
                if (!saveNewValue) return address;
                hasExistingData = true;
                break;
              }

              int newCollisionAddress = myCollisionResolutionStorage.getInt(collisionAddress + COLLISION_OFFSET);
              if (newCollisionAddress == 0) break;
              collisionAddress = newCollisionAddress;
            }
          }

          if (onlyCheckForExisting) return NULL_ID;
        }
        else {
          if (hasMapping) {
            if (!saveNewValue) return indexNodeValueAddress;
            hasExistingData = true;
          }
        }

        assert !onlyCheckForExisting;
        int newValueId = writeData(value, valueHC);
        //FIXME RC: use of myValuesCount -- prevents get rid of getReadLock() here
        ++myValuesCount;
        if (myWal != null) {
          myWal.enumerate(value, newValueId);
        }

        if (IOStatistics.DEBUG && (myValuesCount & IOStatistics.KEYS_FACTOR_MASK) == 0) {
          IOStatistics.dump("Enumerator " + myFile + ": " + getStatistics());
        }

        if (collisionAddress != NULL_ID) {
          if (hasExistingData) {
            if (indexNodeValueAddress > 0) {
              myBTree.put(valueHC, newValueId);
            }
            else {
              myCollisionResolutionStorage.putInt(collisionAddress, newValueId);
            }
          }
          else {
            if (indexNodeValueAddress > 0) {
              // organize collision type reference
              int duplicatedValueOff = nextDuplicatedValueRecord();
              myBTree.put(valueHC, -duplicatedValueOff);

              myCollisionResolutionStorage.putInt(duplicatedValueOff, indexNodeValueAddress); // we will set collision offset in next if
              collisionAddress = duplicatedValueOff;
              ++myCollisions;
            }

            ++myCollisions;
            int duplicatedValueOff = nextDuplicatedValueRecord();
            myCollisionResolutionStorage.putInt(collisionAddress + COLLISION_OFFSET, duplicatedValueOff);
            myCollisionResolutionStorage.putInt(duplicatedValueOff, newValueId);
            myCollisionResolutionStorage.putInt(duplicatedValueOff + COLLISION_OFFSET, 0);
          }
        }
        else {
          myBTree.put(valueHC, newValueId);
        }

        if (IntToIntBtree.doSanityCheck) {
          if (!myInlineKeysNoMapping) {
            Data data = valueOf(newValueId);
            assert myDataDescriptor.isEqual(value, data);
          }
        }
        return newValueId;
      }
      finally {
        if (onlyCheckForExisting) {
          unlockStorageRead();
        }
        else {
          unlockStorageWrite();
        }
      }
    }
    finally {
      (onlyCheckForExisting ? getReadLock() : getWriteLock()).unlock();
    }
  }
@Override
  protected int enumerateImpl(final Data value, final boolean onlyCheckForExisting, boolean saveNewValue)