static int insert()

in cachelib/compact_cache/CCacheVariableLruBucket.h [291:373]


  static int insert(Bucket* bucket,
                    const Key& key,
                    const Value* val,
                    size_t size,
                    EvictionCb evictionCb) {
    /* The caller should ensure that the value is small enough to fit in
     * the bucket. */
    XDCHECK_LE(size, kMaxValueSize);
    if (size > kMaxValueSize) {
      XLOG(ERR) << "Cannot insert an value of size " << size
                << ", the size must be smaller than " << kMaxValueSize;
      return -1;
    }

    /* Make sure that EntryDataSize is wide enough to hold the given
     * size. */
    checkOverflow<EntryDataOffset>(size);
    if (size > std::numeric_limits<EntryDataSize>::max()) {
      XLOG(ERR)
          << "Cannot insert an value of size " << size
          << ", the size must be smaller than the max value of EntryDataSize";
      return -1;
    }

#ifndef NDEBUG
    checkBucketConsistency(bucket);
#endif

    /* 1) Compute the required space for our entry. */
    size_t requiredSpace = size + sizeof(EntryHdr) + sizeof(EntryData);

    /* 2) Call evictEntries, which takes care of evicting as many entries as
     * required in order to have the necessary space. */
    bool evicted = evictEntries(bucket, requiredSpace, evictionCb);

#ifndef NDEBUG
    /* EvictEntries should leave the bucket in a consistent state. */
    checkBucketConsistency(bucket);
#endif

    /* 3) Allocate a new spot in the "Empty" section by increasing
     * bucket->totalDataSize. */
    checkOverflow<EntryDataOffset>(bucket->totalDataSize + size +
                                   sizeof(EntryData));
    bucket->totalDataSize += size + sizeof(EntryData);

    /* 4) Write the entry's data (EntryData) in the new spot. */
    EntryData* newEntryData = getFirstEntryData(bucket);
    memcpy(newEntryData->data, val, size);

    /* 5) Update the headerIndex of all the existing EntryData objects
     * since their header is about to get shifted one position to the
     * right. */
    for (unsigned int i = 0; i < bucket->numEntries; i++) {
      getEntryData(bucket, i)->headerIndex++;
    }

    /* 6) Shift all the EntryHdr headers to the right so that we can
     * write our new entry header in the first position. */
    memmove(getEntryHeader(bucket, 1),
            getEntryHeader(bucket, 0),
            bucket->numEntries * sizeof(EntryHdr));

    /* 7) Write the entry's header (EntryHdr) */
    EntryHdr* newEntry = getEntryHeader(bucket, 0);
    memcpy(&newEntry->key, &key, sizeof(Key));
    newEntry->dataSize = size;

    /* 8) Set the offsets in both the EntryHdr header and the
     * EntryData so that they have a reference to each other. */
    newEntry->dataOffset = kBucketDataSize - bucket->totalDataSize;
    newEntryData->headerIndex = 0;

    /* 9) Update the number of entries in the bucket. */
    checkOverflow<EntryNum>(bucket->numEntries + 1);
    bucket->numEntries++;

#ifndef NDEBUG
    checkBucketConsistency(bucket);
#endif

    return evicted ? 1 : 0;
  }