private static void put()

in src/main/java/com/spotify/sparkey/IndexHash.java [551:654]


  private static void put(
      final ReadWriteData indexData, final IndexHeader header, final long hashCapacity,
      int keyLen, byte[] key,
      final BlockRandomInput logData,
      byte[] keyBuf,
      final HashType hashData,
      final AddressSize addressData,
      final int entryIndexBitmask,
      final int entryIndexBits,
      long hash,
      long address) throws IOException {

    if (header.getNumEntries() >= hashCapacity) {
      throw new IOException("No free slots in the hash: " + header.getNumEntries() + " >= " + hashCapacity);
    }

    long wantedSlot = getWantedSlot(hash, hashCapacity);

    long pos = wantedSlot * header.getSlotSize();
    indexData.seek(pos);

    long displacement = 0;
    long tries = hashCapacity;
    long slot = wantedSlot;

    int entryIndex = (int) (address) & entryIndexBitmask;
    long position = address >>> entryIndexBits;

    boolean mightBeCollision = true;
    while (--tries >= 0) {
      long hash2 = hashData.readHash(indexData);
      long address2 = addressData.readAddress(indexData);
      if (address2 == 0) {
        indexData.seek(pos);
        hashData.writeHash(hash, indexData);
        addressData.writeAddress(address, indexData);
        header.addedEntry();
        return;
      }

      int entryIndex2 = (int) (address2) & entryIndexBitmask;
      long position2 = address2 >>> entryIndexBits;


      if (mightBeCollision && hash == hash2) {
        if (keyLen == -1) {
          logData.seek(position);
          skipStuff(entryIndex, logData);
          keyLen = Util.readUnsignedVLQInt(logData) - 1;
          if (keyLen == -1) {
            // This was a delete?
            throw new RuntimeException("Corrupt data");
          }
          Util.readUnsignedVLQInt(logData); // Ignore value length
          logData.readFully(key, 0, keyLen);
        }

        logData.seek(position2);
        skipStuff(entryIndex2, logData);
        int keyLen2 = Util.readUnsignedVLQInt(logData);
        int valueLen2 = Util.readUnsignedVLQInt(logData);
        if (keyLen2 == 0) {
          throw new RuntimeException("Invalid data - reference to delete entry");
        }
        keyLen2--;
        if (keyLen == keyLen2) {
          logData.readFully(keyBuf, 0, keyLen2);
          if (Util.equals(keyLen, key, keyBuf)) {
            indexData.seek(pos);
            hashData.writeHash(hash, indexData);
            addressData.writeAddress(address, indexData);
            header.replacedEntry(keyLen2, valueLen2);
            return;
          }
        }
      }

      long otherDisplacement = getDisplacement(hashCapacity, slot, hash2);
      // TODO: skip the address < address2 - only useful for generating deterministic hash tables
      if (displacement > otherDisplacement || (displacement == otherDisplacement && address < address2)) {
        // Steal the slot, and move the other one
        indexData.seek(pos);
        hashData.writeHash(hash, indexData);
        addressData.writeAddress(address, indexData);

        position = position2;
        entryIndex = entryIndex2;
        address = address2;
        displacement = otherDisplacement;
        hash = hash2;
        mightBeCollision = false;
      }

      pos += header.getSlotSize();
      displacement++;
      slot++;
      if (slot >= hashCapacity) {
        indexData.seek(0);
        pos = 0;
        slot = 0;
      }
    }
    throw new IOException("No free slots in the hash");
  }