4444import org .apache .lucene .util .packed .DirectMonotonicWriter ;
4545import org .apache .lucene .util .packed .PackedInts ;
4646import org .elasticsearch .core .IOUtils ;
47+ import org .elasticsearch .core .Nullable ;
4748import org .elasticsearch .index .codec .tsdb .BinaryDVCompressionMode ;
4849import org .elasticsearch .index .codec .tsdb .TSDBDocValuesEncoder ;
4950
@@ -79,6 +80,7 @@ final class ES819TSDBDocValuesConsumer extends XDocValuesConsumer {
7980 private final DocOffsetsCodec .Encoder docOffsetsEncoder ;
8081 private final int blockBytesThreshold ;
8182 private final int blockCountThreshold ;
83+ private final boolean writePrefixPartitions ;
8284
8385 ES819TSDBDocValuesConsumer (
8486 BinaryDVCompressionMode binaryDVCompressionMode ,
@@ -94,7 +96,8 @@ final class ES819TSDBDocValuesConsumer extends XDocValuesConsumer {
9496 String dataCodec ,
9597 String dataExtension ,
9698 String metaCodec ,
97- String metaExtension
99+ String metaExtension ,
100+ boolean writePrefixPartitions
98101 ) throws IOException {
99102 this .binaryDVCompressionMode = binaryDVCompressionMode ;
100103 this .enablePerBlockCompression = enablePerBlockCompression ;
@@ -136,6 +139,7 @@ final class ES819TSDBDocValuesConsumer extends XDocValuesConsumer {
136139 maxDoc = state .segmentInfo .maxDoc ();
137140 this .skipIndexIntervalSize = skipIndexIntervalSize ;
138141 this .enableOptimizedMerge = enableOptimizedMerge ;
142+ this .writePrefixPartitions = writePrefixPartitions ;
139143 success = true ;
140144 } finally {
141145 if (success == false ) {
@@ -158,7 +162,7 @@ public SortedNumericDocValues getSortedNumeric(FieldInfo field) throws IOExcepti
158162 writeSkipIndex (field , producer );
159163 }
160164
161- writeField (field , producer , -1 , null );
165+ writeField (field , producer , -1 , null , null );
162166 }
163167
164168 private boolean shouldEncodeOrdinalRange (FieldInfo field , long maxOrd , int numDocsWithValue , long numValues ) {
@@ -168,8 +172,13 @@ private boolean shouldEncodeOrdinalRange(FieldInfo field, long maxOrd, int numDo
168172 && (numDocsWithValue / maxOrd ) >= minDocsPerOrdinalForOrdinalRangeEncoding ;
169173 }
170174
171- private long [] writeField (FieldInfo field , TsdbDocValuesProducer valuesProducer , long maxOrd , OffsetsAccumulator offsetsAccumulator )
172- throws IOException {
175+ private long [] writeField (
176+ FieldInfo field ,
177+ TsdbDocValuesProducer valuesProducer ,
178+ long maxOrd ,
179+ OffsetsAccumulator offsetsAccumulator ,
180+ PrefixedPartitionsWriter partitionsWriter
181+ ) throws IOException {
173182 int numDocsWithValue = 0 ;
174183 long numValues = 0 ;
175184
@@ -200,6 +209,9 @@ private long[] writeField(FieldInfo field, TsdbDocValuesProducer valuesProducer,
200209 if (maxOrd == 1 ) {
201210 // Special case for maxOrd of 1, signal -1 that no blocks will be written
202211 meta .writeInt (-1 );
212+ if (partitionsWriter != null ) {
213+ partitionsWriter .trackDoc (0 , 0 );
214+ }
203215 } else if (shouldEncodeOrdinalRange (field , maxOrd , numDocsWithValue , numValues )) {
204216 assert offsetsAccumulator == null ;
205217 // When a field is sorted, use ordinal range encode for long runs of the same ordinal.
@@ -218,6 +230,9 @@ private long[] writeField(FieldInfo field, TsdbDocValuesProducer valuesProducer,
218230 );
219231 long lastOrd = 0 ;
220232 startDocs .add (0 );
233+ if (partitionsWriter != null ) {
234+ partitionsWriter .trackDoc (0 , lastOrd );
235+ }
221236 for (int doc = values .nextDoc (); doc != DocIdSetIterator .NO_MORE_DOCS ; doc = values .nextDoc ()) {
222237 if (disiAccumulator != null ) {
223238 disiAccumulator .addDocId (doc );
@@ -226,6 +241,9 @@ private long[] writeField(FieldInfo field, TsdbDocValuesProducer valuesProducer,
226241 if (nextOrd != lastOrd ) {
227242 lastOrd = nextOrd ;
228243 startDocs .add (doc );
244+ if (partitionsWriter != null ) {
245+ partitionsWriter .trackDoc (doc , nextOrd );
246+ }
229247 }
230248 }
231249 startDocs .add (maxDoc );
@@ -255,7 +273,11 @@ private long[] writeField(FieldInfo field, TsdbDocValuesProducer valuesProducer,
255273 offsetsAccumulator .addDoc (count );
256274 }
257275 for (int i = 0 ; i < count ; ++i ) {
258- buffer [bufferSize ++] = values .nextValue ();
276+ final long v = values .nextValue ();
277+ buffer [bufferSize ++] = v ;
278+ if (partitionsWriter != null ) {
279+ partitionsWriter .trackDoc (doc , v );
280+ }
259281 if (bufferSize == numericBlockSize ) {
260282 indexWriter .add (data .getFilePointer () - valuesDataOffset );
261283 if (maxOrd >= 0 ) {
@@ -694,13 +716,23 @@ public long cost() {
694716 if (addTypeByte ) {
695717 meta .writeByte ((byte ) 0 ); // multiValued (0 = singleValued)
696718 }
697- SortedDocValues sorted = valuesProducer .getSorted (field );
698- int maxOrd = sorted .getValueCount ();
699- writeField (field , producer , maxOrd , null );
700- addTermsDict (DocValues .singleton (valuesProducer .getSorted (field )));
719+ final SortedDocValues sorted = valuesProducer .getSorted (field );
720+ final int maxOrd = sorted .getValueCount ();
721+ var partitionWriter = primarySortFieldNumber == field .number && writePrefixPartitions ? new PrefixedPartitionsWriter () : null ;
722+ addTermsDict (DocValues .singleton (sorted ), partitionWriter );
723+ if (partitionWriter != null ) {
724+ partitionWriter .prepareForTrackingDocs ();
725+ }
726+ writeField (field , producer , maxOrd , null , partitionWriter );
727+ if (primarySortFieldNumber == field .number ) {
728+ meta .writeByte (partitionWriter != null ? (byte ) 1 : (byte ) 0 );
729+ }
730+ if (partitionWriter != null ) {
731+ partitionWriter .flush (data , meta );
732+ }
701733 }
702734
703- private void addTermsDict (SortedSetDocValues values ) throws IOException {
735+ private void addTermsDict (SortedSetDocValues values , @ Nullable PrefixedPartitionsWriter partitionWriter ) throws IOException {
704736 final long size = values .getValueCount ();
705737 meta .writeVLong (size );
706738
@@ -755,6 +787,9 @@ private void addTermsDict(SortedSetDocValues values) throws IOException {
755787 }
756788 bufferedOutput .writeBytes (term .bytes , term .offset + prefixLength , suffixLength );
757789 }
790+ if (partitionWriter != null ) {
791+ partitionWriter .trackTerm (term , ord );
792+ }
758793 maxLength = Math .max (maxLength , term .length );
759794 previous .copyBytes (term );
760795 ++ord ;
@@ -860,16 +895,16 @@ private void writeSortedNumericField(FieldInfo field, TsdbDocValuesProducer valu
860895 int numDocsWithField = valuesProducer .mergeStats .sumNumDocsWithField ();
861896 long numValues = valuesProducer .mergeStats .sumNumValues ();
862897 if (numDocsWithField == numValues ) {
863- writeField (field , valuesProducer , maxOrd , null );
898+ writeField (field , valuesProducer , maxOrd , null , null );
864899 } else {
865900 assert numValues > numDocsWithField ;
866901 try (var accumulator = new OffsetsAccumulator (dir , context , data , numDocsWithField )) {
867- writeField (field , valuesProducer , maxOrd , accumulator );
902+ writeField (field , valuesProducer , maxOrd , accumulator , null );
868903 accumulator .build (meta , data );
869904 }
870905 }
871906 } else {
872- long [] stats = writeField (field , valuesProducer , maxOrd , null );
907+ long [] stats = writeField (field , valuesProducer , maxOrd , null , null );
873908 int numDocsWithField = Math .toIntExact (stats [0 ]);
874909 long numValues = stats [1 ];
875910 assert numValues >= numDocsWithField ;
@@ -1012,7 +1047,7 @@ public long cost() {
10121047 }
10131048 }, maxOrd );
10141049
1015- addTermsDict (valuesProducer .getSortedSet (field ));
1050+ addTermsDict (valuesProducer .getSortedSet (field ), null );
10161051 }
10171052
10181053 @ Override
0 commit comments