| 1042 | template <typename AllocatorT> |
| 1043 | template <typename T> |
| 1044 | std::pair<typename ObjectCache<AllocatorT>::AllocStatus, std::shared_ptr<T>> |
| 1045 | ObjectCache<AllocatorT>::insert(folly::StringPiece key, |
| 1046 | std::unique_ptr<T> object, |
| 1047 | size_t objectSize, |
| 1048 | uint32_t ttlSecs) { |
| 1049 | if (config_.objectSizeTrackingEnabled && objectSize == 0) { |
| 1050 | throw std::invalid_argument( |
| 1051 | "Object size tracking is enabled but object size is set to be 0."); |
| 1052 | } |
| 1053 | |
| 1054 | if (!config_.objectSizeTrackingEnabled && objectSize != 0) { |
| 1055 | throw std::invalid_argument( |
| 1056 | "Object size tracking is not enabled but object size is set. Are you " |
| 1057 | "trying to set TTL?"); |
| 1058 | } |
| 1059 | |
| 1060 | inserts_.inc(); |
| 1061 | |
| 1062 | auto handle = |
| 1063 | allocateFromL1(key, ttlSecs, 0 /* use current time as creationTime */); |
| 1064 | if (!handle) { |
| 1065 | insertErrors_.inc(); |
| 1066 | return {AllocStatus::kAllocError, std::shared_ptr<T>(std::move(object))}; |
| 1067 | } |
| 1068 | T* ptr = object.get(); |
| 1069 | *getAlignedItemPtr(handle->getMemory()) = |
| 1070 | ObjectCacheItem{reinterpret_cast<uintptr_t>(ptr), objectSize}; |
| 1071 | |
| 1072 | auto success = this->l1Cache_->insert(handle); |
| 1073 | if (!success) { |
| 1074 | return {AllocStatus::kKeyAlreadyExists, |
| 1075 | std::shared_ptr<T>(std::move(object))}; |
| 1076 | } |
| 1077 | |
| 1078 | // update total object size |
| 1079 | if (config_.objectSizeTrackingEnabled) { |
| 1080 | totalObjectSizeBytes_.fetch_add(objectSize, std::memory_order_relaxed); |
| 1081 | totalKeyPaddingBytes_.fetch_add(getValueAlignmentPadding(key.size())); |
| 1082 | } |
| 1083 | // Release the handle now since we have inserted the handle into the cache, |
| 1084 | // and from now the Cache will be responsible for destroying the object |
| 1085 | // when it's evicted/removed. |
| 1086 | object.release(); |
| 1087 | |
| 1088 | // Use custom deleter |
| 1089 | auto deleter = Deleter<T>(std::move(handle)); |
| 1090 | return {AllocStatus::kSuccess, std::shared_ptr<T>(ptr, std::move(deleter))}; |
| 1091 | } |
| 1092 | |
| 1093 | template <typename AllocatorT> |
| 1094 | typename AllocatorT::WriteHandle ObjectCache<AllocatorT>::allocateFromL1( |