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

apache / iotdb / #10019

07 Sep 2023 04:50AM UTC coverage: 47.489% (-0.2%) from 47.655%
#10019

push

travis_ci

web-flow
Pipe: Fix ConcurrentModificationException caused by concurrently iterating through CachedSchemaPatternMatcher.extractors when an PipeHeartbeatEvent is being assigned (#11074)

* try to fix ConcurrentModificationException when assigning PipeHeartbeatEvent

* Update CachedSchemaPatternMatcher.java

---------

Co-authored-by: 马子坤 <55695098+DanielWang2035@users.noreply.github.com>

1 of 1 new or added line in 1 file covered. (100.0%)

80551 of 169622 relevant lines covered (47.49%)

0.47 hits per line

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

54.2
/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/TsBlockBuilder.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

20
package org.apache.iotdb.tsfile.read.common.block;
21

22
import org.apache.iotdb.tsfile.common.conf.TSFileDescriptor;
23
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
24
import org.apache.iotdb.tsfile.read.common.block.column.BinaryColumnBuilder;
25
import org.apache.iotdb.tsfile.read.common.block.column.BooleanColumnBuilder;
26
import org.apache.iotdb.tsfile.read.common.block.column.Column;
27
import org.apache.iotdb.tsfile.read.common.block.column.ColumnBuilder;
28
import org.apache.iotdb.tsfile.read.common.block.column.DoubleColumnBuilder;
29
import org.apache.iotdb.tsfile.read.common.block.column.FloatColumnBuilder;
30
import org.apache.iotdb.tsfile.read.common.block.column.IntColumnBuilder;
31
import org.apache.iotdb.tsfile.read.common.block.column.LongColumnBuilder;
32
import org.apache.iotdb.tsfile.read.common.block.column.TimeColumn;
33
import org.apache.iotdb.tsfile.read.common.block.column.TimeColumnBuilder;
34
import org.apache.iotdb.tsfile.utils.Binary;
35

36
import java.util.List;
37

38
import static java.lang.String.format;
39
import static java.util.Objects.requireNonNull;
40
import static org.apache.iotdb.tsfile.read.common.block.TsBlockBuilderStatus.DEFAULT_MAX_TSBLOCK_SIZE_IN_BYTES;
41

42
public class TsBlockBuilder {
43

44
  // We choose default initial size to be 8 for TsBlockBuilder and ColumnBuilder
45
  // so the underlying data is larger than the object overhead, and the size is power of 2.
46
  //
47
  // This could be any other small number.
48
  private static final int DEFAULT_INITIAL_EXPECTED_ENTRIES = 8;
49

50
  private static final int MAX_LINE_NUMBER =
1✔
51
      TSFileDescriptor.getInstance().getConfig().getMaxTsBlockLineNumber();
1✔
52

53
  private TimeColumnBuilder timeColumnBuilder;
54
  private ColumnBuilder[] valueColumnBuilders;
55
  private List<TSDataType> types;
56
  private TsBlockBuilderStatus tsBlockBuilderStatus;
57
  private int declaredPositions;
58

59
  private TsBlockBuilder() {}
60

61
  /**
62
   * Create a TsBlockBuilder with given types.
63
   *
64
   * <p>A TsBlockBuilder instance created with this constructor has no estimation about bytes per
65
   * entry, therefore it can resize frequently while appending new rows.
66
   *
67
   * <p>This constructor should only be used to get the initial TsBlockBuilder. Once the
68
   * TsBlockBuilder is full use reset() or createTsBlockBuilderLike() to create a new TsBlockBuilder
69
   * instance with its size estimated based on previous data.
70
   */
71
  public TsBlockBuilder(List<TSDataType> types) {
72
    this(DEFAULT_INITIAL_EXPECTED_ENTRIES, types);
1✔
73
  }
1✔
74

75
  public TsBlockBuilder(int initialExpectedEntries, List<TSDataType> types) {
76
    this(initialExpectedEntries, DEFAULT_MAX_TSBLOCK_SIZE_IN_BYTES, types);
1✔
77
  }
1✔
78

79
  public static TsBlockBuilder createWithOnlyTimeColumn() {
80
    TsBlockBuilder res = new TsBlockBuilder();
×
81
    res.tsBlockBuilderStatus = new TsBlockBuilderStatus(DEFAULT_INITIAL_EXPECTED_ENTRIES);
×
82
    res.timeColumnBuilder =
×
83
        new TimeColumnBuilder(
84
            res.tsBlockBuilderStatus.createColumnBuilderStatus(), DEFAULT_INITIAL_EXPECTED_ENTRIES);
×
85
    res.valueColumnBuilders = new ColumnBuilder[0];
×
86
    return res;
×
87
  }
88

89
  public static TsBlockBuilder withMaxTsBlockSize(int maxTsBlockBytes, List<TSDataType> types) {
90
    return new TsBlockBuilder(DEFAULT_INITIAL_EXPECTED_ENTRIES, maxTsBlockBytes, types);
×
91
  }
92

93
  private TsBlockBuilder(int initialExpectedEntries, int maxTsBlockBytes, List<TSDataType> types) {
1✔
94
    this.types = requireNonNull(types, "types is null");
1✔
95

96
    tsBlockBuilderStatus = new TsBlockBuilderStatus(maxTsBlockBytes);
1✔
97
    timeColumnBuilder =
1✔
98
        new TimeColumnBuilder(
99
            tsBlockBuilderStatus.createColumnBuilderStatus(), initialExpectedEntries);
1✔
100
    valueColumnBuilders = new ColumnBuilder[types.size()];
1✔
101

102
    for (int i = 0; i < valueColumnBuilders.length; i++) {
1✔
103
      // TODO use Type interface to encapsulate createColumnBuilder to each concrete type class
104
      // instead of switch-case
105
      switch (types.get(i)) {
1✔
106
        case BOOLEAN:
107
          valueColumnBuilders[i] =
1✔
108
              new BooleanColumnBuilder(
109
                  tsBlockBuilderStatus.createColumnBuilderStatus(), initialExpectedEntries);
1✔
110
          break;
1✔
111
        case INT32:
112
          valueColumnBuilders[i] =
1✔
113
              new IntColumnBuilder(
114
                  tsBlockBuilderStatus.createColumnBuilderStatus(), initialExpectedEntries);
1✔
115
          break;
1✔
116
        case INT64:
117
          valueColumnBuilders[i] =
1✔
118
              new LongColumnBuilder(
119
                  tsBlockBuilderStatus.createColumnBuilderStatus(), initialExpectedEntries);
1✔
120
          break;
1✔
121
        case FLOAT:
122
          valueColumnBuilders[i] =
1✔
123
              new FloatColumnBuilder(
124
                  tsBlockBuilderStatus.createColumnBuilderStatus(), initialExpectedEntries);
1✔
125
          break;
1✔
126
        case DOUBLE:
127
          valueColumnBuilders[i] =
1✔
128
              new DoubleColumnBuilder(
129
                  tsBlockBuilderStatus.createColumnBuilderStatus(), initialExpectedEntries);
1✔
130
          break;
1✔
131
        case TEXT:
132
          valueColumnBuilders[i] =
1✔
133
              new BinaryColumnBuilder(
134
                  tsBlockBuilderStatus.createColumnBuilderStatus(), initialExpectedEntries);
1✔
135
          break;
1✔
136
        default:
137
          throw new IllegalArgumentException("Unknown data type: " + types.get(i));
×
138
      }
139
    }
140
  }
1✔
141

142
  private TsBlockBuilder(
143
      int maxTsBlockBytes,
144
      List<TSDataType> types,
145
      TimeColumnBuilder templateTimeColumnBuilder,
146
      ColumnBuilder[] templateValueColumnBuilders) {
×
147
    this.types = requireNonNull(types, "types is null");
×
148

149
    tsBlockBuilderStatus = new TsBlockBuilderStatus(maxTsBlockBytes);
×
150
    valueColumnBuilders = new ColumnBuilder[types.size()];
×
151

152
    checkArgument(
×
153
        templateValueColumnBuilders.length == types.size(),
×
154
        "Size of templates and types should match");
155
    timeColumnBuilder =
×
156
        (TimeColumnBuilder)
157
            templateTimeColumnBuilder.newColumnBuilderLike(
×
158
                tsBlockBuilderStatus.createColumnBuilderStatus());
×
159
    for (int i = 0; i < valueColumnBuilders.length; i++) {
×
160
      valueColumnBuilders[i] =
×
161
          templateValueColumnBuilders[i].newColumnBuilderLike(
×
162
              tsBlockBuilderStatus.createColumnBuilderStatus());
×
163
    }
164
  }
×
165

166
  public void buildValueColumnBuilders(List<TSDataType> types) {
167
    this.types = requireNonNull(types, "types is null");
×
168
    valueColumnBuilders = new ColumnBuilder[types.size()];
×
169
    int initialExpectedEntries = timeColumnBuilder.getPositionCount();
×
170
    for (int i = 0; i < valueColumnBuilders.length; i++) {
×
171
      // TODO use Type interface to encapsulate createColumnBuilder to each concrete type class
172
      // instead of switch-case
173
      switch (types.get(i)) {
×
174
        case BOOLEAN:
175
          valueColumnBuilders[i] =
×
176
              new BooleanColumnBuilder(
177
                  tsBlockBuilderStatus.createColumnBuilderStatus(), initialExpectedEntries);
×
178
          break;
×
179
        case INT32:
180
          valueColumnBuilders[i] =
×
181
              new IntColumnBuilder(
182
                  tsBlockBuilderStatus.createColumnBuilderStatus(), initialExpectedEntries);
×
183
          break;
×
184
        case INT64:
185
          valueColumnBuilders[i] =
×
186
              new LongColumnBuilder(
187
                  tsBlockBuilderStatus.createColumnBuilderStatus(), initialExpectedEntries);
×
188
          break;
×
189
        case FLOAT:
190
          valueColumnBuilders[i] =
×
191
              new FloatColumnBuilder(
192
                  tsBlockBuilderStatus.createColumnBuilderStatus(), initialExpectedEntries);
×
193
          break;
×
194
        case DOUBLE:
195
          valueColumnBuilders[i] =
×
196
              new DoubleColumnBuilder(
197
                  tsBlockBuilderStatus.createColumnBuilderStatus(), initialExpectedEntries);
×
198
          break;
×
199
        case TEXT:
200
          valueColumnBuilders[i] =
×
201
              new BinaryColumnBuilder(
202
                  tsBlockBuilderStatus.createColumnBuilderStatus(), initialExpectedEntries);
×
203
          break;
×
204
        default:
205
          throw new IllegalArgumentException("Unknown data type: " + types.get(i));
×
206
      }
207
    }
208
  }
×
209

210
  public void reset() {
211
    if (isEmpty()) {
1✔
212
      return;
1✔
213
    }
214
    tsBlockBuilderStatus =
1✔
215
        new TsBlockBuilderStatus(tsBlockBuilderStatus.getMaxTsBlockSizeInBytes());
1✔
216

217
    declaredPositions = 0;
1✔
218

219
    timeColumnBuilder =
1✔
220
        (TimeColumnBuilder)
221
            timeColumnBuilder.newColumnBuilderLike(
1✔
222
                tsBlockBuilderStatus.createColumnBuilderStatus());
1✔
223
    for (int i = 0; i < valueColumnBuilders.length; i++) {
1✔
224
      valueColumnBuilders[i] =
1✔
225
          valueColumnBuilders[i].newColumnBuilderLike(
1✔
226
              tsBlockBuilderStatus.createColumnBuilderStatus());
1✔
227
    }
228
  }
1✔
229

230
  public TsBlockBuilder newTsBlockBuilderLike() {
231
    return new TsBlockBuilder(
×
232
        tsBlockBuilderStatus.getMaxTsBlockSizeInBytes(),
×
233
        types,
234
        timeColumnBuilder,
235
        valueColumnBuilders);
236
  }
237

238
  public TimeColumnBuilder getTimeColumnBuilder() {
239
    return timeColumnBuilder;
1✔
240
  }
241

242
  public ColumnBuilder getColumnBuilder(int channel) {
243
    return valueColumnBuilders[channel];
1✔
244
  }
245

246
  public ColumnBuilder[] getValueColumnBuilders() {
247
    return valueColumnBuilders;
1✔
248
  }
249

250
  public TSDataType getType(int channel) {
251
    return types.get(channel);
×
252
  }
253

254
  // Indicate current row number
255
  public void declarePosition() {
256
    declaredPositions++;
1✔
257
  }
1✔
258

259
  public void declarePositions(int deltaPositions) {
260
    declaredPositions += deltaPositions;
1✔
261
  }
1✔
262

263
  public boolean isFull() {
264
    return declaredPositions >= MAX_LINE_NUMBER || tsBlockBuilderStatus.isFull();
1✔
265
  }
266

267
  public boolean isEmpty() {
268
    return declaredPositions == 0;
1✔
269
  }
270

271
  public int getPositionCount() {
272
    return declaredPositions;
1✔
273
  }
274

275
  public long getSizeInBytes() {
276
    return tsBlockBuilderStatus.getSizeInBytes();
×
277
  }
278

279
  public long getRetainedSizeInBytes() {
280
    // We use a foreach loop instead of streams
281
    // as it has much better performance.
282
    long retainedSizeInBytes = timeColumnBuilder.getRetainedSizeInBytes();
1✔
283
    for (ColumnBuilder columnBuilder : valueColumnBuilders) {
1✔
284
      retainedSizeInBytes += columnBuilder.getRetainedSizeInBytes();
1✔
285
    }
286
    return retainedSizeInBytes;
1✔
287
  }
288

289
  public TsBlock build() {
290
    TimeColumn timeColumn = (TimeColumn) timeColumnBuilder.build();
1✔
291
    if (timeColumn.getPositionCount() != declaredPositions) {
1✔
292
      throw new IllegalStateException(
×
293
          format(
×
294
              "Declared positions (%s) does not match time column's number of entries (%s)",
295
              declaredPositions, timeColumn.getPositionCount()));
×
296
    }
297

298
    Column[] columns = new Column[valueColumnBuilders.length];
1✔
299
    for (int i = 0; i < columns.length; i++) {
1✔
300
      columns[i] = valueColumnBuilders[i].build();
1✔
301
      if (columns[i].getPositionCount() != declaredPositions) {
1✔
302
        throw new IllegalStateException(
×
303
            format(
×
304
                "Declared positions (%s) does not match column %s's number of entries (%s)",
305
                declaredPositions, i, columns[i].getPositionCount()));
×
306
      }
307
    }
308

309
    return TsBlock.wrapBlocksWithoutCopy(declaredPositions, timeColumn, columns);
1✔
310
  }
311

312
  /**
313
   * Write a text value to the columnIndex. If the value is null, then the place will be recorded
314
   * with null.
315
   *
316
   * @param columnIndex the target column index.
317
   * @param value the text value to be inserted.
318
   */
319
  public void writeNullableText(int columnIndex, String value) {
320
    if (value == null) {
1✔
321
      getColumnBuilder(columnIndex).appendNull();
1✔
322
    } else {
323
      getColumnBuilder(columnIndex).writeBinary(new Binary(value));
1✔
324
    }
325
  }
1✔
326

327
  private static void checkArgument(boolean expression, String errorMessage) {
328
    if (!expression) {
×
329
      throw new IllegalArgumentException(errorMessage);
×
330
    }
331
  }
×
332
}
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

© 2026 Coveralls, Inc