• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

apache / iotdb / #9374

pending completion
#9374

push

travis_ci

web-flow
[IOTDB-5818][Atmos][Compaction]Cross_space compaction of Aligned timeseries is stucked (#9795) (#10153)

3 of 3 new or added lines in 2 files covered. (100.0%)

65758 of 99118 relevant lines covered (66.34%)

0.66 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.33
/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/ChunkMetadata.java
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one
3
 * or more contributor license agreements.  See the NOTICE file
4
 * distributed with this work for additional information
5
 * regarding copyright ownership.  The ASF licenses this file
6
 * to you under the Apache License, Version 2.0 (the
7
 * "License"); you may not use this file except in compliance
8
 * with the License.  You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing,
13
 * software distributed under the License is distributed on an
14
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
 * KIND, either express or implied.  See the License for the
16
 * specific language governing permissions and limitations
17
 * under the License.
18
 */
19
package org.apache.iotdb.tsfile.file.metadata;
20

21
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
22
import org.apache.iotdb.tsfile.file.metadata.statistics.Statistics;
23
import org.apache.iotdb.tsfile.read.common.TimeRange;
24
import org.apache.iotdb.tsfile.read.controller.IChunkLoader;
25
import org.apache.iotdb.tsfile.utils.FilePathUtils;
26
import org.apache.iotdb.tsfile.utils.Pair;
27
import org.apache.iotdb.tsfile.utils.RamUsageEstimator;
28
import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
29

30
import java.io.IOException;
31
import java.io.OutputStream;
32
import java.io.Serializable;
33
import java.nio.ByteBuffer;
34
import java.util.ArrayList;
35
import java.util.List;
36
import java.util.Objects;
37

38
/** Metadata of one chunk. */
39
public class ChunkMetadata implements IChunkMetadata {
40

41
  private String measurementUid;
42

43
  /**
44
   * Byte offset of the corresponding data in the file Notice: include the chunk header and marker.
45
   */
46
  private long offsetOfChunkHeader;
47

48
  private TSDataType tsDataType;
49

50
  /**
51
   * version is used to define the order of operations(insertion, deletion, update). version is set
52
   * according to its belonging ChunkGroup only when being queried, so it is not persisted.
53
   */
54
  private long version;
55

56
  /** A list of deleted intervals. */
57
  private List<TimeRange> deleteIntervalList;
58

59
  private boolean modified;
60

61
  /** ChunkLoader of metadata, used to create ChunkReaderWrap */
62
  private IChunkLoader chunkLoader;
63

64
  private Statistics<? extends Serializable> statistics;
65

66
  private boolean isFromOldTsFile = false;
1✔
67

68
  private long ramSize;
69

70
  private static final int CHUNK_METADATA_FIXED_RAM_SIZE = 93;
71

72
  // used for SeriesReader to indicate whether it is a seq/unseq timeseries metadata
73
  private boolean isSeq = true;
1✔
74
  private boolean isClosed;
75
  private String filePath;
76

77
  // 0x80 for time chunk, 0x40 for value chunk, 0x00 for common chunk
78
  private byte mask;
79

80
  // used for ChunkCache, Eg:"root.sg1/0/0"
81
  private String tsFilePrefixPath;
82
  // high 32 bit is compaction level, low 32 bit is merge count
83
  private long compactionVersion;
84

85
  public ChunkMetadata() {}
1✔
86

87
  /**
88
   * constructor of ChunkMetaData.
89
   *
90
   * @param measurementUid measurement id
91
   * @param tsDataType time series data type
92
   * @param fileOffset file offset
93
   * @param statistics value statistics
94
   */
95
  public ChunkMetadata(
96
      String measurementUid,
97
      TSDataType tsDataType,
98
      long fileOffset,
99
      Statistics<? extends Serializable> statistics) {
1✔
100
    this.measurementUid = measurementUid;
1✔
101
    this.tsDataType = tsDataType;
1✔
102
    this.offsetOfChunkHeader = fileOffset;
1✔
103
    this.statistics = statistics;
1✔
104
  }
1✔
105

106
  // won't clone deleteIntervalList & modified
107
  public ChunkMetadata(ChunkMetadata other) {
1✔
108
    this.measurementUid = other.measurementUid;
1✔
109
    this.offsetOfChunkHeader = other.offsetOfChunkHeader;
1✔
110
    this.tsDataType = other.tsDataType;
1✔
111
    this.version = other.version;
1✔
112
    this.chunkLoader = other.chunkLoader;
1✔
113
    this.statistics = other.statistics;
1✔
114
    this.isFromOldTsFile = other.isFromOldTsFile;
1✔
115
    this.ramSize = other.ramSize;
1✔
116
    this.isSeq = other.isSeq;
1✔
117
    this.isClosed = other.isClosed;
1✔
118
    this.filePath = other.filePath;
1✔
119
    this.mask = other.mask;
1✔
120
    this.tsFilePrefixPath = other.tsFilePrefixPath;
1✔
121
    this.compactionVersion = other.compactionVersion;
1✔
122
  }
1✔
123

124
  @Override
125
  public String toString() {
126
    return String.format(
1✔
127
        "measurementId: %s, datatype: %s, version: %d, Statistics: %s, deleteIntervalList: %s, filePath: %s",
128
        measurementUid, tsDataType, version, statistics, deleteIntervalList, filePath);
1✔
129
  }
130

131
  public long getNumOfPoints() {
132
    return statistics.getCount();
1✔
133
  }
134

135
  /**
136
   * get offset of chunk header.
137
   *
138
   * @return Byte offset of header of this chunk (includes the marker)
139
   */
140
  @Override
141
  public long getOffsetOfChunkHeader() {
142
    return offsetOfChunkHeader;
1✔
143
  }
144

145
  public String getMeasurementUid() {
146
    return measurementUid;
1✔
147
  }
148

149
  @Override
150
  public Statistics<? extends Serializable> getStatistics() {
151
    return statistics;
1✔
152
  }
153

154
  public long getStartTime() {
155
    return statistics.getStartTime();
1✔
156
  }
157

158
  public long getEndTime() {
159
    return statistics.getEndTime();
1✔
160
  }
161

162
  public TSDataType getDataType() {
163
    return tsDataType;
1✔
164
  }
165

166
  /**
167
   * serialize to outputStream.
168
   *
169
   * @param outputStream outputStream
170
   * @return length
171
   * @throws IOException IOException
172
   */
173
  public int serializeTo(OutputStream outputStream, boolean serializeStatistic) throws IOException {
174
    int byteLen = 0;
1✔
175
    byteLen += ReadWriteIOUtils.write(offsetOfChunkHeader, outputStream);
1✔
176
    if (serializeStatistic) {
1✔
177
      byteLen += statistics.serialize(outputStream);
1✔
178
    }
179
    return byteLen;
1✔
180
  }
181

182
  /**
183
   * deserialize from ByteBuffer.
184
   *
185
   * @param buffer ByteBuffer
186
   * @return ChunkMetaData object
187
   */
188
  public static ChunkMetadata deserializeFrom(
189
      ByteBuffer buffer, TimeseriesMetadata timeseriesMetadata) {
190
    ChunkMetadata chunkMetaData = new ChunkMetadata();
1✔
191

192
    chunkMetaData.measurementUid = timeseriesMetadata.getMeasurementId();
1✔
193
    chunkMetaData.tsDataType = timeseriesMetadata.getTSDataType();
1✔
194
    chunkMetaData.offsetOfChunkHeader = ReadWriteIOUtils.readLong(buffer);
1✔
195
    // if the TimeSeriesMetadataType is not 0, it means it has more than one chunk
196
    // and each chunk's metadata has its own statistics
197
    if ((timeseriesMetadata.getTimeSeriesMetadataType() & 0x3F) != 0) {
1✔
198
      chunkMetaData.statistics = Statistics.deserialize(buffer, chunkMetaData.tsDataType);
1✔
199
    } else {
200
      // if the TimeSeriesMetadataType is 0, it means it has only one chunk
201
      // and that chunk's metadata has no statistic
202
      chunkMetaData.statistics = timeseriesMetadata.getStatistics();
1✔
203
    }
204
    return chunkMetaData;
1✔
205
  }
206

207
  public static ChunkMetadata deserializeFrom(ByteBuffer buffer, TSDataType dataType) {
208
    ChunkMetadata chunkMetadata = new ChunkMetadata();
1✔
209
    chunkMetadata.tsDataType = dataType;
1✔
210
    chunkMetadata.offsetOfChunkHeader = ReadWriteIOUtils.readLong(buffer);
1✔
211
    chunkMetadata.statistics = Statistics.deserialize(buffer, dataType);
1✔
212
    return chunkMetadata;
1✔
213
  }
214

215
  @Override
216
  public long getVersion() {
217
    return version;
1✔
218
  }
219

220
  @Override
221
  public void setVersion(long version) {
222
    this.version = version;
1✔
223
  }
1✔
224

225
  public List<TimeRange> getDeleteIntervalList() {
226
    return deleteIntervalList;
1✔
227
  }
228

229
  public void setDeleteIntervalList(List<TimeRange> list) {
230
    this.deleteIntervalList = list;
×
231
  }
×
232

233
  public void insertIntoSortedDeletions(long startTime, long endTime) {
234
    List<TimeRange> resultInterval = new ArrayList<>();
1✔
235
    if (deleteIntervalList != null) {
1✔
236
      for (TimeRange interval : deleteIntervalList) {
1✔
237
        if (interval.getMax() < startTime) {
1✔
238
          resultInterval.add(interval);
1✔
239
        } else if (interval.getMin() > endTime) {
1✔
240
          resultInterval.add(new TimeRange(startTime, endTime));
×
241
          startTime = interval.getMin();
×
242
          endTime = interval.getMax();
×
243
        } else if (interval.getMax() >= startTime || interval.getMin() <= endTime) {
1✔
244
          startTime = Math.min(interval.getMin(), startTime);
1✔
245
          endTime = Math.max(interval.getMax(), endTime);
1✔
246
        }
247
      }
1✔
248
    }
249

250
    resultInterval.add(new TimeRange(startTime, endTime));
1✔
251
    deleteIntervalList = resultInterval;
1✔
252
  }
1✔
253

254
  public IChunkLoader getChunkLoader() {
255
    return chunkLoader;
1✔
256
  }
257

258
  @Override
259
  public boolean needSetChunkLoader() {
260
    return chunkLoader == null;
1✔
261
  }
262

263
  public void setChunkLoader(IChunkLoader chunkLoader) {
264
    this.chunkLoader = chunkLoader;
1✔
265
  }
1✔
266

267
  @Override
268
  public boolean equals(Object o) {
269
    if (this == o) {
1✔
270
      return true;
1✔
271
    }
272
    if (o == null || getClass() != o.getClass()) {
1✔
273
      return false;
×
274
    }
275
    ChunkMetadata that = (ChunkMetadata) o;
1✔
276
    return offsetOfChunkHeader == that.offsetOfChunkHeader
1✔
277
        && version == that.version
278
        && compactionVersion == that.compactionVersion
279
        && tsFilePrefixPath.equals(that.tsFilePrefixPath);
1✔
280
  }
281

282
  @Override
283
  public int hashCode() {
284
    return Objects.hash(tsFilePrefixPath, version, compactionVersion, offsetOfChunkHeader);
1✔
285
  }
286

287
  @Override
288
  public boolean isModified() {
289
    return modified;
1✔
290
  }
291

292
  @Override
293
  public void setModified(boolean modified) {
294
    this.modified = modified;
1✔
295
  }
1✔
296

297
  public boolean isFromOldTsFile() {
298
    return isFromOldTsFile;
1✔
299
  }
300

301
  public void setFromOldTsFile(boolean isFromOldTsFile) {
302
    this.isFromOldTsFile = isFromOldTsFile;
×
303
  }
×
304

305
  public long calculateRamSize() {
306
    return CHUNK_METADATA_FIXED_RAM_SIZE
1✔
307
        + RamUsageEstimator.sizeOf(tsFilePrefixPath)
1✔
308
        + RamUsageEstimator.sizeOf(measurementUid)
1✔
309
        + statistics.calculateRamSize();
1✔
310
  }
311

312
  public static long calculateRamSize(String measurementId, TSDataType dataType) {
313
    return CHUNK_METADATA_FIXED_RAM_SIZE
1✔
314
        + RamUsageEstimator.sizeOf(measurementId)
1✔
315
        + Statistics.getSizeByType(dataType);
1✔
316
  }
317

318
  public void mergeChunkMetadata(ChunkMetadata chunkMetadata) {
319
    Statistics<? extends Serializable> statistics = chunkMetadata.getStatistics();
1✔
320
    this.statistics.mergeStatistics(statistics);
1✔
321
    this.ramSize = calculateRamSize();
1✔
322
  }
1✔
323

324
  @Override
325
  public void setSeq(boolean seq) {
326
    isSeq = seq;
1✔
327
  }
1✔
328

329
  @Override
330
  public boolean isSeq() {
331
    return isSeq;
1✔
332
  }
333

334
  public boolean isClosed() {
335
    return isClosed;
1✔
336
  }
337

338
  public void setClosed(boolean closed) {
339
    isClosed = closed;
1✔
340
  }
1✔
341

342
  public String getFilePath() {
343
    return filePath;
1✔
344
  }
345

346
  public void setFilePath(String filePath) {
347
    this.filePath = filePath;
1✔
348

349
    Pair<String, long[]> tsFilePrefixPathAndTsFileVersionPair =
1✔
350
        FilePathUtils.getTsFilePrefixPathAndTsFileVersionPair(filePath);
1✔
351
    // set tsFilePrefixPath
352
    tsFilePrefixPath = tsFilePrefixPathAndTsFileVersionPair.left;
1✔
353
    this.version = tsFilePrefixPathAndTsFileVersionPair.right[0];
1✔
354
    this.compactionVersion = tsFilePrefixPathAndTsFileVersionPair.right[1];
1✔
355
  }
1✔
356

357
  @Override
358
  public byte getMask() {
359
    return mask;
1✔
360
  }
361

362
  public void setMask(byte mask) {
363
    this.mask = mask;
1✔
364
  }
1✔
365
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc