+ * @param int $flags
+ * @return array (inline value or segment list, whether the entry is usable)
+ * @since 1.34
+ */
+ final protected function makeValueOrSegmentList( $key, $value, $exptime, $flags ) {
+ $entry = $value;
+ $usable = true;
+
+ if (
+ $this->fieldHasFlags( $flags, self::WRITE_ALLOW_SEGMENTS ) &&
+ !is_int( $value ) && // avoid breaking incr()/decr()
+ is_finite( $this->segmentationSize )
+ ) {
+ $segmentSize = $this->segmentationSize;
+ $maxTotalSize = $this->segmentedValueMaxSize;
+
+ $serialized = $this->serialize( $value );
+ $size = strlen( $serialized );
+ if ( $size > $maxTotalSize ) {
+ $this->logger->warning(
+ "Value for {key} exceeds $maxTotalSize bytes; cannot segment.",
+ [ 'key' => $key ]
+ );
+ } elseif ( $size <= $segmentSize ) {
+ // The serialized value was already computed, so just use it inline
+ $entry = SerializedValueContainer::newUnified( $serialized );
+ } else {
+ // Split the serialized value into chunks and store them at different keys
+ $chunksByKey = [];
+ $segmentHashes = [];
+ $count = intdiv( $size, $segmentSize ) + ( ( $size % $segmentSize ) ? 1 : 0 );
+ for ( $i = 0; $i < $count; ++$i ) {
+ $segment = substr( $serialized, $i * $segmentSize, $segmentSize );
+ $hash = sha1( $segment );
+ $chunkKey = $this->makeGlobalKey( self::SEGMENT_COMPONENT, $key, $hash );
+ $chunksByKey[$chunkKey] = $segment;
+ $segmentHashes[] = $hash;
+ }
+ $flags &= ~self::WRITE_ALLOW_SEGMENTS; // sanity
+ $usable = $this->setMulti( $chunksByKey, $exptime, $flags );
+ $entry = SerializedValueContainer::newSegmented( $segmentHashes );
+ }
+ }
+
+ return [ $entry, $usable ];
+ }
+
+ /**
+ * @param int|float $exptime
+ * @return bool Whether the expiry is non-infinite, and, negative or not a UNIX timestamp
+ * @since 1.34