This is an automated email from the ASF dual-hosted git repository.

qiaojialin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 4c09acd  Fix ForceAppendTsFileWriter (#1275)
4c09acd is described below

commit 4c09acd5b62557ce01f518c09059e2580b0803cb
Author: Haonan <[email protected]>
AuthorDate: Thu May 28 20:35:37 2020 +0800

    Fix ForceAppendTsFileWriter (#1275)
    
    * fix ForceAppendTsFileWriter
---
 docs/UserGuide/Client/Programming - TsFile API.md  |  19 ++++
 .../UserGuide/Client/Programming - TsFile API.md   |  19 +++-
 .../iotdb/tsfile/TsFileForceAppendWrite.java       | 108 +++++++++++++++++++++
 .../write/writer/ForceAppendTsFileWriter.java      |  19 ++++
 .../write/writer/ForceAppendTsFileWriterTest.java  |  42 ++++++++
 5 files changed, 206 insertions(+), 1 deletion(-)

diff --git a/docs/UserGuide/Client/Programming - TsFile API.md 
b/docs/UserGuide/Client/Programming - TsFile API.md
index fbf0eb7..8010d50 100644
--- a/docs/UserGuide/Client/Programming - TsFile API.md 
+++ b/docs/UserGuide/Client/Programming - TsFile API.md 
@@ -263,6 +263,21 @@ A TsFile can be generated by following three steps and the 
complete code will be
     ```
     public void close() throws IOException
     ```
+We are also able to write data into a closed TsFile.
+
+* Use `ForceAppendTsFileWriter` to open a closed file.
+
+```
+public ForceAppendTsFileWriter(File file) throws IOException
+```
+* call `doTruncate` truncate the part of Metadata
+
+* Then use `ForceAppendTsFileWriter` to construct a new `TsFileWriter`
+
+```
+public TsFileWriter(TsFileIOWriter fileWriter) throws IOException
+```
+Please note, we should redo the step of adding measurements before writing new 
data to the TsFile.
 
 #### Example for writing a TsFile
 
@@ -280,6 +295,10 @@ You could write a TsFile by constructing **Tablet** if you 
have the **aligned**
 
 A more thorough example can be found at 
`/example/tsfile/src/main/java/org/apache/iotdb/tsfile/TsFileWriteWithTablet.java`
 
+You could write data into a closed TsFile by using **ForceAppendTsFileWriter**.
+
+A more thorough example can be found at 
`/example/tsfile/src/main/java/org/apache/iotdb/tsfile/TsFileForceAppendWrite.java`
+
 ### Interface for Reading TsFile
 
 #### Before the Start
diff --git a/docs/zh/UserGuide/Client/Programming - TsFile API.md 
b/docs/zh/UserGuide/Client/Programming - TsFile API.md
index edc1337..64e5679 100644
--- a/docs/zh/UserGuide/Client/Programming - TsFile API.md      
+++ b/docs/zh/UserGuide/Client/Programming - TsFile API.md      
@@ -185,7 +185,7 @@ TsFile可以通过以下三个步骤生成,完整的代码参见"写入 TsFile
     
     * config : TsFile 的一些配置项
 
-* 第二部,添加测量值(measurement)
+* 第二步,添加测量值(measurement)
   
     你也可以先创建一个`Schema`类的实例然后把它传递给`TsFileWriter`类的构造函数
     
@@ -262,6 +262,22 @@ TsFile可以通过以下三个步骤生成,完整的代码参见"写入 TsFile
     public void close() throws IOException
     ```
 
+我们也支持将数据写入已关闭的 TsFile 文件中。
+
+* 使用`ForceAppendTsFileWriter`打开已经关闭的文件。
+
+```
+public ForceAppendTsFileWriter(File file) throws IOException
+```
+* 调用 `doTruncate` 去掉文件的Metadata部分
+
+* 然后使用  `ForceAppendTsFileWriter` 构造另一个`TsFileWriter`
+
+```
+public TsFileWriter(TsFileIOWriter fileWriter) throws IOException
+```
+请注意 此时需要重新添加测量值(measurement) 再进行上述写入操作。
+
 #### 写入 TsFile 示例
 
 您需要安装 TsFile 到本地的 Maven 仓库中。
@@ -279,6 +295,7 @@ mvn clean install -pl tsfile -am -DskipTests
 
 
更详细的例子可以在`/example/tsfile/src/main/java/org/apache/iotdb/tsfile/TsFileWriteWithTablet.java`中查看
 
+在已关闭的TsFile 
文件中写入新数据的详细例子可以在`/example/tsfile/src/main/java/org/apache/iotdb/tsfile/TsFileForceAppendWrite.java`中查看
 
 ### 读取 TsFile 接口
 
diff --git 
a/example/tsfile/src/main/java/org/apache/iotdb/tsfile/TsFileForceAppendWrite.java
 
b/example/tsfile/src/main/java/org/apache/iotdb/tsfile/TsFileForceAppendWrite.java
new file mode 100644
index 0000000..be25806
--- /dev/null
+++ 
b/example/tsfile/src/main/java/org/apache/iotdb/tsfile/TsFileForceAppendWrite.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.iotdb.tsfile;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
+import org.apache.iotdb.tsfile.fileSystem.FSFactoryProducer;
+import org.apache.iotdb.tsfile.read.common.Path;
+import org.apache.iotdb.tsfile.write.TsFileWriter;
+import org.apache.iotdb.tsfile.write.record.TSRecord;
+import org.apache.iotdb.tsfile.write.record.datapoint.DataPoint;
+import org.apache.iotdb.tsfile.write.record.datapoint.LongDataPoint;
+import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
+import org.apache.iotdb.tsfile.write.writer.ForceAppendTsFileWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TsFileForceAppendWrite {
+
+  private static final Logger logger = 
LoggerFactory.getLogger(TsFileForceAppendWrite.class);
+
+  public static void main(String[] args) throws IOException {
+    String path = "test.tsfile";
+    File f = FSFactoryProducer.getFSFactory().getFile(path);
+    if (f.exists()) {
+      Files.delete(f.toPath());
+    }
+    try (TsFileWriter tsFileWriter = new TsFileWriter(f)) {
+
+      // add measurements into file schema
+      for (int i = 0; i < 4; i++) {
+        tsFileWriter.registerTimeseries(new Path(Constant.DEVICE_PREFIX + i, 
Constant.SENSOR_1),
+            new MeasurementSchema(Constant.SENSOR_1, TSDataType.INT64, 
TSEncoding.RLE));
+        tsFileWriter.registerTimeseries(new Path(Constant.DEVICE_PREFIX + i, 
Constant.SENSOR_2),
+            new MeasurementSchema(Constant.SENSOR_2, TSDataType.INT64, 
TSEncoding.RLE));
+        tsFileWriter.registerTimeseries(new Path(Constant.DEVICE_PREFIX + i, 
Constant.SENSOR_3),
+            new MeasurementSchema(Constant.SENSOR_3, TSDataType.INT64, 
TSEncoding.RLE));
+      }
+
+      // construct TSRecord
+      for (int i = 0; i < 100; i++) {
+        TSRecord tsRecord = new TSRecord(i, Constant.DEVICE_PREFIX + (i % 4));
+        DataPoint dPoint1 = new LongDataPoint(Constant.SENSOR_1, i);
+        DataPoint dPoint2 = new LongDataPoint(Constant.SENSOR_2, i);
+        DataPoint dPoint3 = new LongDataPoint(Constant.SENSOR_3, i);
+        tsRecord.addTuple(dPoint1);
+        tsRecord.addTuple(dPoint2);
+        tsRecord.addTuple(dPoint3);
+
+        // write TSRecord
+        tsFileWriter.write(tsRecord);
+      }
+    } catch (Exception e) {
+      logger.error("meet error in TsFileWrite ", e);
+    }
+
+    // open the closed file with ForceAppendTsFileWriter
+    ForceAppendTsFileWriter fwriter = new ForceAppendTsFileWriter(f);
+    fwriter.doTruncate();
+    try (TsFileWriter tsFileWriter1 = new TsFileWriter(fwriter)) {
+      // add measurements into file schema
+      for (int i = 0; i < 4; i++) {
+        tsFileWriter1.registerTimeseries(new Path(Constant.DEVICE_PREFIX + i, 
Constant.SENSOR_1),
+            new MeasurementSchema(Constant.SENSOR_1, TSDataType.INT64, 
TSEncoding.RLE));
+        tsFileWriter1.registerTimeseries(new Path(Constant.DEVICE_PREFIX + i, 
Constant.SENSOR_2),
+            new MeasurementSchema(Constant.SENSOR_2, TSDataType.INT64, 
TSEncoding.RLE));
+        tsFileWriter1.registerTimeseries(new Path(Constant.DEVICE_PREFIX + i, 
Constant.SENSOR_3),
+            new MeasurementSchema(Constant.SENSOR_3, TSDataType.INT64, 
TSEncoding.RLE));
+      }
+      // construct TSRecord
+      for (int i = 100; i < 120; i++) {
+        TSRecord tsRecord = new TSRecord(i, Constant.DEVICE_PREFIX + (i % 4));
+        DataPoint dPoint1 = new LongDataPoint(Constant.SENSOR_1, i);
+        DataPoint dPoint2 = new LongDataPoint(Constant.SENSOR_2, i);
+        DataPoint dPoint3 = new LongDataPoint(Constant.SENSOR_3, i);
+        tsRecord.addTuple(dPoint1);
+        tsRecord.addTuple(dPoint2);
+        tsRecord.addTuple(dPoint3);
+
+        // write TSRecord
+        tsFileWriter1.write(tsRecord);
+      }
+    } catch (Exception e) {
+      logger.error("meet error in TsFileWrite ", e);
+    }
+    fwriter.close();
+  }
+}
diff --git 
a/tsfile/src/main/java/org/apache/iotdb/tsfile/write/writer/ForceAppendTsFileWriter.java
 
b/tsfile/src/main/java/org/apache/iotdb/tsfile/write/writer/ForceAppendTsFileWriter.java
index f23e99b..d677e38 100644
--- 
a/tsfile/src/main/java/org/apache/iotdb/tsfile/write/writer/ForceAppendTsFileWriter.java
+++ 
b/tsfile/src/main/java/org/apache/iotdb/tsfile/write/writer/ForceAppendTsFileWriter.java
@@ -20,7 +20,12 @@ package org.apache.iotdb.tsfile.write.writer;
 
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
 import org.apache.iotdb.tsfile.exception.write.TsFileNotCompleteException;
+import org.apache.iotdb.tsfile.file.metadata.ChunkGroupMetadata;
+import org.apache.iotdb.tsfile.file.metadata.ChunkMetadata;
 import org.apache.iotdb.tsfile.file.metadata.TsFileMetadata;
 import org.apache.iotdb.tsfile.read.TsFileSequenceReader;
 import org.slf4j.Logger;
@@ -57,6 +62,20 @@ public class ForceAppendTsFileWriter extends TsFileIOWriter {
       TsFileMetadata tsFileMetadata = reader.readFileMetadata();
       // truncate metadata and marker
       truncatePosition = tsFileMetadata.getMetaOffset();
+
+      canWrite = true;
+      versionInfo = tsFileMetadata.getVersionInfo();
+      totalChunkNum = tsFileMetadata.getTotalChunkNum();
+      invalidChunkNum = tsFileMetadata.getInvalidChunkNum();
+      
+      List<String> devices = reader.getAllDevices();
+      for (String device : devices) {
+        List<ChunkMetadata> chunkMetadataList = new ArrayList<>();
+        reader.readChunkMetadataInDevice(device).values()
+            .forEach(chunkMetadataList::addAll);          
+        ChunkGroupMetadata chunkGroupMetadata = new ChunkGroupMetadata(device, 
chunkMetadataList);
+        chunkGroupMetadataList.add(chunkGroupMetadata);
+      }
     }
   }
 
diff --git 
a/tsfile/src/test/java/org/apache/iotdb/tsfile/write/writer/ForceAppendTsFileWriterTest.java
 
b/tsfile/src/test/java/org/apache/iotdb/tsfile/write/writer/ForceAppendTsFileWriterTest.java
index 694d7c1..aff1a20 100644
--- 
a/tsfile/src/test/java/org/apache/iotdb/tsfile/write/writer/ForceAppendTsFileWriterTest.java
+++ 
b/tsfile/src/test/java/org/apache/iotdb/tsfile/write/writer/ForceAppendTsFileWriterTest.java
@@ -19,15 +19,24 @@
 package org.apache.iotdb.tsfile.write.writer;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
 
 import org.apache.iotdb.tsfile.constant.TestConstant;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
 import org.apache.iotdb.tsfile.fileSystem.FSFactoryProducer;
 import org.apache.iotdb.tsfile.fileSystem.fsFactory.FSFactory;
+import org.apache.iotdb.tsfile.read.ReadOnlyTsFile;
+import org.apache.iotdb.tsfile.read.TsFileSequenceReader;
 import org.apache.iotdb.tsfile.read.common.Path;
+import org.apache.iotdb.tsfile.read.common.RowRecord;
+import org.apache.iotdb.tsfile.read.expression.QueryExpression;
+import org.apache.iotdb.tsfile.read.query.dataset.QueryDataSet;
 import org.apache.iotdb.tsfile.write.TsFileWriter;
 import org.apache.iotdb.tsfile.write.record.TSRecord;
 import org.apache.iotdb.tsfile.write.record.datapoint.FloatDataPoint;
@@ -56,6 +65,39 @@ public class ForceAppendTsFileWriterTest {
     writer.close();
     ForceAppendTsFileWriter fwriter = new ForceAppendTsFileWriter(file);
     assertEquals(firstMetadataPosition, fwriter.getTruncatePosition());
+    fwriter.doTruncate();
+
+    // write more data into this TsFile
+    writer = new TsFileWriter(fwriter);
+    writer.registerTimeseries(new Path("d1.s1"),
+        new MeasurementSchema("s1", TSDataType.FLOAT, TSEncoding.RLE));
+    writer.registerTimeseries(new Path("d1.s2"),
+        new MeasurementSchema("s2", TSDataType.FLOAT, TSEncoding.RLE));
+    writer.write(new TSRecord(3, "d1").addTuple(new FloatDataPoint("s1", 5))
+        .addTuple(new FloatDataPoint("s2", 4)));
+    writer.close();
+    ReadOnlyTsFile readOnlyTsFile = new ReadOnlyTsFile(new 
TsFileSequenceReader(file.getPath()));
+    List<Path> pathList = new ArrayList<>();
+    pathList.add(new Path("d1", "s1"));
+    pathList.add(new Path("d1", "s2"));
+    QueryExpression queryExpression = QueryExpression.create(pathList, null);
+    QueryDataSet dataSet = readOnlyTsFile.query(queryExpression);
+    RowRecord record = dataSet.next();
+    assertEquals(1, record.getTimestamp());
+    assertEquals(5.0f, record.getFields().get(0).getFloatV(), 0.001);
+    assertEquals(4.0f, record.getFields().get(1).getFloatV(), 0.001);
+    record = dataSet.next();
+    assertEquals(2, record.getTimestamp());
+    assertEquals(5.0f, record.getFields().get(0).getFloatV(), 0.001);
+    assertEquals(4.0f, record.getFields().get(1).getFloatV(), 0.001);
+    record = dataSet.next();
+    assertEquals(3, record.getTimestamp());
+    assertEquals(5.0f, record.getFields().get(0).getFloatV(), 0.001);
+    assertEquals(4.0f, record.getFields().get(1).getFloatV(), 0.001);
+    readOnlyTsFile.close();
+    assertFalse(dataSet.hasNext());
+
+    assertTrue(file.delete());
   }
 
 }

Reply via email to