|
34 | 34 | import com.linkedin.davinci.helix.LeaderFollowerPartitionStateModel; |
35 | 35 | import com.linkedin.davinci.ingestion.LagType; |
36 | 36 | import com.linkedin.davinci.listener.response.AdminResponse; |
37 | | -import com.linkedin.davinci.listener.response.NoOpReadResponseStats; |
38 | 37 | import com.linkedin.davinci.notifier.VeniceNotifier; |
39 | 38 | import com.linkedin.davinci.stats.AggVersionedDIVStats; |
40 | 39 | import com.linkedin.davinci.stats.AggVersionedDaVinciRecordTransformerStats; |
|
43 | 42 | import com.linkedin.davinci.stats.ingestion.heartbeat.HeartbeatMonitoringService; |
44 | 43 | import com.linkedin.davinci.storage.StorageMetadataService; |
45 | 44 | import com.linkedin.davinci.storage.StorageService; |
46 | | -import com.linkedin.davinci.storage.chunking.ChunkedValueManifestContainer; |
47 | 45 | import com.linkedin.davinci.storage.chunking.ChunkingUtils; |
48 | | -import com.linkedin.davinci.storage.chunking.GenericChunkingAdapter; |
49 | 46 | import com.linkedin.davinci.store.DelegatingStorageEngine; |
50 | 47 | import com.linkedin.davinci.store.StorageEngine; |
51 | 48 | import com.linkedin.davinci.store.StoragePartitionAdjustmentTrigger; |
|
119 | 116 | import com.linkedin.venice.pubsub.manager.TopicManagerRepository; |
120 | 117 | import com.linkedin.venice.pushmonitor.ExecutionStatus; |
121 | 118 | import com.linkedin.venice.schema.SchemaEntry; |
122 | | -import com.linkedin.venice.serialization.RawBytesStoreDeserializerCache; |
123 | 119 | import com.linkedin.venice.serialization.avro.AvroProtocolDefinition; |
124 | 120 | import com.linkedin.venice.serialization.avro.ChunkedValueManifestSerializer; |
125 | 121 | import com.linkedin.venice.serialization.avro.InternalAvroSpecificSerializer; |
@@ -4111,50 +4107,59 @@ protected void putInStorageEngine(int partition, byte[] keyBytes, Put put) { |
4111 | 4107 |
|
4112 | 4108 | protected void putGlobalRtDivStateInMetadata(int partition, byte[] keyBytes, Put put) { |
4113 | 4109 | if (put.schemaId == CHUNK_SCHEMA_ID) { |
4114 | | - // Intermediate chunk: store in user-data storage for later assembly when the manifest arrives. |
4115 | | - prependHeaderAndWriteToStorageEngine(partition, keyBytes, put); |
| 4110 | + // Intermediate chunk: store in the metadata partition for later assembly when the manifest arrives. |
| 4111 | + byte[] chunkPayload = ByteUtils.extractByteArray(put.putValue); |
| 4112 | + byte[] valueWithHeader = new byte[ValueRecord.SCHEMA_HEADER_LENGTH + chunkPayload.length]; |
| 4113 | + ByteUtils.writeInt(valueWithHeader, CHUNK_SCHEMA_ID, 0); |
| 4114 | + System.arraycopy(chunkPayload, 0, valueWithHeader, ValueRecord.SCHEMA_HEADER_LENGTH, chunkPayload.length); |
| 4115 | + executeStorageEngineRunnable( |
| 4116 | + partition, |
| 4117 | + () -> storageEngine.putGlobalRtDivChunk(partition, keyBytes, valueWithHeader)); |
4116 | 4118 | return; |
4117 | 4119 | } |
4118 | 4120 |
|
4119 | 4121 | if (put.schemaId == CHUNK_MANIFEST_SCHEMA_ID) { |
4120 | | - // Manifest for a chunked GlobalRtDiv: write manifest to user-data storage, then assemble all chunks |
4121 | | - // and persist the assembled (decompressed) value in the metadata partition. |
4122 | | - prependHeaderAndWriteToStorageEngine(partition, keyBytes, put); |
4123 | | - // Strip the KeyWithChunkingSuffixSerializer suffix to recover the original broker-URL key. |
| 4122 | + // Manifest for a chunked GlobalRtDiv: assemble all chunks from the metadata partition, |
| 4123 | + // decompress the result, then persist it in the metadata partition. |
4124 | 4124 | byte[] originalKeyBytes = Arrays.copyOf(keyBytes, keyBytes.length - KEY_CHUNKING_SUFFIX_LENGTH); |
4125 | 4125 | String key = new String(originalKeyBytes); |
4126 | 4126 | if (!key.startsWith(GLOBAL_RT_DIV_KEY_PREFIX)) { |
4127 | 4127 | throw new VeniceException("Invalid chunked Global RT DIV manifest key: " + Arrays.toString(keyBytes)); |
4128 | 4128 | } |
4129 | 4129 | String brokerUrl = key.substring(GLOBAL_RT_DIV_KEY_PREFIX.length()); |
| 4130 | + byte[] manifestBytes = ByteUtils.extractByteArray(put.putValue); |
| 4131 | + ChunkedValueManifest manifest = manifestSerializer.deserialize(manifestBytes, CHUNK_MANIFEST_SCHEMA_ID); |
| 4132 | + ByteBuffer assembled = ByteBuffer.allocate(manifest.size); |
| 4133 | + for (ByteBuffer chunkKeyBuf: manifest.keysWithChunkIdSuffix) { |
| 4134 | + byte[] chunkKey = ByteUtils.extractByteArray(chunkKeyBuf); |
| 4135 | + byte[] chunkBytes = storageEngine.getGlobalRtDivChunk(partition, chunkKey); |
| 4136 | + if (chunkBytes == null) { |
| 4137 | + throw new VeniceException( |
| 4138 | + "Missing GlobalRtDiv chunk in metadata partition for partition: " + partition + ", broker: " + brokerUrl); |
| 4139 | + } |
| 4140 | + if (ValueRecord.parseSchemaId(chunkBytes) != CHUNK_SCHEMA_ID) { |
| 4141 | + throw new VeniceException( |
| 4142 | + "Unexpected schema ID in GlobalRtDiv chunk: " + ValueRecord.parseSchemaId(chunkBytes)); |
| 4143 | + } |
| 4144 | + assembled |
| 4145 | + .put(chunkBytes, ValueRecord.SCHEMA_HEADER_LENGTH, chunkBytes.length - ValueRecord.SCHEMA_HEADER_LENGTH); |
| 4146 | + } |
| 4147 | + assembled.flip(); |
4130 | 4148 | try { |
4131 | | - // Use the serialized manifest key (keyBytes) directly with isChunked=false so the adapter does not |
4132 | | - // double-serialize it. All chunks were already written to user-data storage above. |
4133 | | - ByteBuffer assembledValue = (ByteBuffer) GenericChunkingAdapter.INSTANCE.get( |
4134 | | - storageEngine, |
| 4149 | + byte[] valueBytes = |
| 4150 | + ByteUtils.extractByteArray(compressor.get().decompress(assembled.array(), 0, assembled.limit())); |
| 4151 | + executeStorageEngineRunnable( |
4135 | 4152 | partition, |
4136 | | - ByteBuffer.wrap(keyBytes), |
4137 | | - false, |
4138 | | - null, |
4139 | | - null, |
4140 | | - NoOpReadResponseStats.SINGLETON, |
4141 | | - AvroProtocolDefinition.GLOBAL_RT_DIV_STATE.getCurrentProtocolVersion(), |
4142 | | - RawBytesStoreDeserializerCache.getInstance(), |
4143 | | - compressor.get(), |
4144 | | - new ChunkedValueManifestContainer()); |
4145 | | - if (assembledValue != null) { |
4146 | | - byte[] valueBytes = ByteUtils.extractByteArray(assembledValue); |
4147 | | - executeStorageEngineRunnable( |
4148 | | - partition, |
4149 | | - () -> storageMetadataService.putGlobalRtDivState(kafkaVersionTopic, partition, brokerUrl, valueBytes)); |
4150 | | - } else { |
4151 | | - LOGGER.warn("Assembled Global RT DIV value was null for partition: {}, broker: {}", partition, brokerUrl); |
4152 | | - } |
4153 | | - } catch (Exception e) { |
| 4153 | + () -> storageMetadataService.putGlobalRtDivState(kafkaVersionTopic, partition, brokerUrl, valueBytes)); |
| 4154 | + } catch (IOException e) { |
4154 | 4155 | throw new VeniceException( |
4155 | | - "Failed to assemble chunked Global RT DIV state for partition: " + partition + ", broker: " + brokerUrl, |
| 4156 | + "Failed to decompress assembled GlobalRtDiv state for partition: " + partition + ", broker: " + brokerUrl, |
4156 | 4157 | e); |
4157 | 4158 | } |
| 4159 | + for (ByteBuffer chunkKeyBuf: manifest.keysWithChunkIdSuffix) { |
| 4160 | + byte[] chunkKey = ByteUtils.extractByteArray(chunkKeyBuf); |
| 4161 | + executeStorageEngineRunnable(partition, () -> storageEngine.deleteGlobalRtDivChunk(partition, chunkKey)); |
| 4162 | + } |
4158 | 4163 | return; |
4159 | 4164 | } |
4160 | 4165 |
|
|
0 commit comments