<!--

    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.

-->

## TsFile API

TsFile is a file format of Time Series used in IoTDB. This session introduces the usage of this file format. 



### TsFile library Installation

There are two ways to use TsFile in your own project.

* Use as jars: Compile the source codes and build to jars

```shell
git clone https://github.com/apache/iotdb.git
cd tsfile/
mvn clean package -Dmaven.test.skip=true
```

Then, all the jars are in folder named `target/`. Import `target/tsfile-0.12.0-jar-with-dependencies.jar` to your project.
	
* Use as a maven dependency: 

  Compile source codes and deploy to your local repository in three steps:

  * Get the source codes

  	```shell
  	git clone https://github.com/apache/iotdb.git
  	```
  	
  * Compile the source codes and deploy 
  	
  	```shell
  	cd tsfile/
  	mvn clean install -Dmaven.test.skip=true
  	```
  	
  * add dependencies into your project:

    ```xml
  	 <dependency>
  	   <groupId>org.apache.iotdb</groupId>
  	   <artifactId>tsfile</artifactId>
  	   <version>0.14.0-SNAPSHOT</version>
  	 </dependency>
    ```
    

  Or, you can download the dependencies from official Maven repository:

  * First, find your maven `settings.xml` on path: `${username}\.m2\settings.xml`
    , add this `<profile>` to `<profiles>`:
    ```xml
      <profile>
           <id>allow-snapshots</id>
              <activation><activeByDefault>true</activeByDefault></activation>
           <repositories>
             <repository>  
                <id>apache.snapshots</id>
                <name>Apache Development Snapshot Repository</name>
                <url>https://repository.apache.org/content/repositories/snapshots/</url>
                <releases>
                    <enabled>false</enabled>
                </releases>
                <snapshots>
                    <enabled>true</enabled>
                </snapshots>
              </repository>
           </repositories>
         </profile>
    ```
  * Then add dependencies into your project:

    ```xml
  	 <dependency>
  	   <groupId>org.apache.iotdb</groupId>
  	   <artifactId>tsfile</artifactId>
  	   <version>0.14.0-SNAPSHOT</version>
  	 </dependency>
    ```



### TsFile Usage

This section demonstrates the detailed usages of TsFile.

Time-series Data
Time-series data is considered as a sequence of quadruples. A quadruple is defined as (device, measurement, time, value).

* **measurement**: A physical or formal measurement that a time-series data takes, e.g., the temperature of a city, the 
sales number of some goods or the speed of a train at different times. As a traditional sensor (like a thermometer) also
 takes a single measurement and produce a time-series, we will use measurement and sensor interchangeably below.

* **device**: A device refers to an entity that takes several measurements (producing multiple time-series), e.g., 
a running train monitors its speed, oil meter, miles it has run, current passengers each is conveyed to a time-series dataset.


**One Line of Data**: In many industrial applications, a device normally contains more than one sensor and these sensors
 may have values at the same timestamp, which is called one line of data. 

Formally, one line of data consists of a `device_id`, a timestamp which indicates the milliseconds since January 1,
 1970, 00:00:00, and several data pairs composed of `measurement_id` and corresponding `value`. All data pairs in one 
 line belong to this `device_id` and have the same timestamp. If one of the `measurements` does not have a `value` 
 in the `timestamp`, use a space instead(Actually, TsFile does not store null values). Its format is shown as follow:

```
device_id, timestamp, <measurement_id, value>...
```

An example is illustrated as follow. In this example, the data type of two measurements are  `INT32`, `FLOAT` respectively.

```
device_1, 1490860659000, m1, 10, m2, 12.12
```



#### Write TsFile

A TsFile is generated by the following three steps and the complete code is given in the section "Example for writing TsFile".

1. construct a `TsFileWriter` instance.
  
    Here are the available constructors:
    
    * Without pre-defined schema
    
    ```java
    public TsFileWriter(File file) throws IOException
    ```
    * With pre-defined schema
    
    ```java
    public TsFileWriter(File file, Schema schema) throws IOException
    ```
    This one is for using the HDFS file system. `TsFileOutput` can be an instance of class `HDFSOutput`.
    
    ```java
    public TsFileWriter(TsFileOutput output, Schema schema) throws IOException 
    ```

    If you want to set some TSFile configuration on your own, you could use param `config`. For example:

    ```java
    TSFileConfig conf = new TSFileConfig();
    conf.setTSFileStorageFs("HDFS");
    TsFileWriter tsFileWriter = new TsFileWriter(file, schema, conf);
    ```

    In this example, data files will be stored in HDFS, instead of local file system. If you'd like to store data files in local file system, you can use `conf.setTSFileStorageFs("LOCAL")`, which is also the default config.
    
    You can also config the ip and rpc port of your HDFS by `config.setHdfsIp(...)` and `config.setHdfsPort(...)`. The default ip is `localhost` and default rpc port is `9000`.

    **Parameters:**
    
    * file : The TsFile to write

    * schema : The file schemas, will be introduced in next part.

    * config : The config of TsFile.

2. add measurements
  
    Or you can make an instance of class `Schema` first and pass this to the constructor of class `TsFileWriter`
    
    The class `Schema` contains a map whose key is the name of one measurement schema, and the value is the schema itself.
    
    Here are the interfaces:

    ```java
    // Create an empty Schema or from an existing map
    public Schema()
    public Schema(Map<String, MeasurementSchema> measurements)
    // Use this two interfaces to add measurements
    public void registerMeasurement(MeasurementSchema descriptor)
    public void registerMeasurements(Map<String, MeasurementSchema> measurements)
    // Some useful getter and checker
    public TSDataType getMeasurementDataType(String measurementId)
    public MeasurementSchema getMeasurementSchema(String measurementId)
    public Map<String, MeasurementSchema> getAllMeasurementSchema()
    public boolean hasMeasurement(String measurementId)
    ```

    You can always use the following interface in `TsFileWriter` class to add additional measurements: 

    ```java
    public void addMeasurement(MeasurementSchema measurementSchema) throws WriteProcessException
    ```

    The class `MeasurementSchema` contains the information of one measurement, there are several constructors:
    ```java
    public MeasurementSchema(String measurementId, TSDataType type, TSEncoding encoding)
    public MeasurementSchema(String measurementId, TSDataType type, TSEncoding encoding, CompressionType compressionType)
    public MeasurementSchema(String measurementId, TSDataType type, TSEncoding encoding, CompressionType compressionType, 
    Map<String, String> props)
    ```
    
    **Parameters:**
    ​    
    * measurementID: The name of this measurement, typically the name of the sensor.
      
    * type: The data type, now support six types: `BOOLEAN`, `INT32`, `INT64`, `FLOAT`, `DOUBLE`, `TEXT`;
    
    * encoding: The data encoding. 
    
    * compression: The data compression. 

    * props: Properties for special data types.Such as `max_point_number` for `FLOAT` and `DOUBLE`, `max_string_length` for
    `TEXT`. Use as string pairs into a map such as ("max_point_number", "3").
    
    > **Notice:** Although one measurement name can be used in multiple deltaObjects, the properties cannot be changed. I.e. 
        it's not allowed to add one measurement name for multiple times with different type or encoding.
        Here is a bad example:

    ```java
    // The measurement "sensor_1" is float type
    addMeasurement(new MeasurementSchema("sensor_1", TSDataType.FLOAT, TSEncoding.RLE));
    
    // This call will throw a WriteProcessException exception
addMeasurement(new MeasurementSchema("sensor_1", TSDataType.INT32, TSEncoding.RLE));
  ```
  ```

  ```

3. insert and write data continually.
  
    Use this interface to create a new `TSRecord`(a timestamp and device pair).
    
    ```java
    public TSRecord(long timestamp, String deviceId)
    ```
  ```
    Then create a `DataPoint`(a measurement and value pair), and use the addTuple method to add the DataPoint to the correct
    TsRecord.
    
    Use this method to write
    
    ```java
    public void write(TSRecord record) throws IOException, WriteProcessException
  ```

4. call `close` to finish this writing process. 
  
    ```java
    public void close() throws IOException
    ```

We are also able to write data into a closed TsFile.

1. Use `ForceAppendTsFileWriter` to open a closed file.

	```java
	public ForceAppendTsFileWriter(File file) throws IOException
	```

2. call `doTruncate` truncate the part of Metadata

3. Then use `ForceAppendTsFileWriter` to construct a new `TsFileWriter`

```java
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

You should install TsFile to your local maven repository.

```shell
mvn clean install -pl tsfile -am -DskipTests
```

You could write a TsFile by constructing **TSRecord** if you have the **non-aligned** (e.g. not all sensors contain values) time series data.

A more thorough example can be found at `/example/tsfile/src/main/java/org/apache/iotdb/tsfile/TsFileWriteWithTSRecord.java`

You could write a TsFile by constructing **Tablet** if you have the **aligned** time series data.

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

* Definition of Path

A path is a dot-separated string which uniquely identifies a time-series in TsFile, e.g., "root.area_1.device_1.sensor_1". 
The last section "sensor_1" is called "measurementId" while the remaining parts "root.area_1.device_1" is called deviceId. 
As mentioned above, the same measurement in different devices has the same data type and encoding, and devices are also unique.

In read interfaces, The parameter `paths` indicates the measurements to be selected.

Path instance can be easily constructed through the class `Path`. For example:

```java
Path p = new Path("device_1.sensor_1");
```

We will pass an ArrayList of paths for final query call to support multiple paths.

```java
List<Path> paths = new ArrayList<Path>();
paths.add(new Path("device_1.sensor_1"));
paths.add(new Path("device_1.sensor_3"));
```

> **Notice:** When constructing a Path, the format of the parameter should be a dot-separated string, the last part will
 be recognized as measurementId while the remaining parts will be recognized as deviceId.


* Definition of Filter

 * Usage Scenario
Filter is used in TsFile reading process to select data satisfying one or more given condition(s). 

 * IExpression
The `IExpression` is a filter expression interface and it will be passed to our final query call.
We create one or more filter expressions and may use binary filter operators to link them to our final expression.

* **Create a Filter Expression**
  
    There are two types of filters.
    
     * TimeFilter: A filter for `time` in time-series data.
        ```
        IExpression timeFilterExpr = new GlobalTimeExpression(TimeFilter);
        ```
        Use the following relationships to get a `TimeFilter` object (value is a long int variable).
        
        |Relationship|Description|
        |---|---|
        |TimeFilter.eq(value)|Choose the time equal to the value|
        |TimeFilter.lt(value)|Choose the time less than the value|
        |TimeFilter.gt(value)|Choose the time greater than the value|
        |TimeFilter.ltEq(value)|Choose the time less than or equal to the value|
        |TimeFilter.gtEq(value)|Choose the time greater than or equal to the value|
        |TimeFilter.notEq(value)|Choose the time not equal to the value|
        |TimeFilter.not(TimeFilter)|Choose the time not satisfy another TimeFilter|
       
     * ValueFilter: A filter for `value` in time-series data.
       
        ```
        IExpression valueFilterExpr = new SingleSeriesExpression(Path, ValueFilter);
        ```
        The usage of  `ValueFilter` is the same as using `TimeFilter`, just to make sure that the type of the value
        equal to the measurement's(defined in the path).
    
* **Binary Filter Operators**

    Binary filter operators can be used to link two single expressions.

     * BinaryExpression.and(Expression, Expression): Choose the value satisfy for both expressions.
     * BinaryExpression.or(Expression, Expression): Choose the value satisfy for at least one expression.
    

Filter Expression Examples

* **TimeFilterExpression Examples**

    ```java
    IExpression timeFilterExpr = new GlobalTimeExpression(TimeFilter.eq(15)); // series time = 15
    ```
```
    ```java
    IExpression timeFilterExpr = new GlobalTimeExpression(TimeFilter.ltEq(15)); // series time <= 15
```
```java
    IExpression timeFilterExpr = new GlobalTimeExpression(TimeFilter.lt(15)); // series time < 15
```
    ```java
IExpression timeFilterExpr = new GlobalTimeExpression(TimeFilter.gtEq(15)); // series time >= 15
    ```
    ```java
    IExpression timeFilterExpr = new GlobalTimeExpression(TimeFilter.notEq(15)); // series time != 15
```
    ```java
    IExpression timeFilterExpr = BinaryExpression.and(
        new GlobalTimeExpression(TimeFilter.gtEq(15L)),
    new GlobalTimeExpression(TimeFilter.lt(25L))); // 15 <= series time < 25
```
    ```java
    IExpression timeFilterExpr = BinaryExpression.or(
        new GlobalTimeExpression(TimeFilter.gtEq(15L)),
        new GlobalTimeExpression(TimeFilter.lt(25L))); // series time >= 15 or series time < 25
    ```
* Read Interface

First, we open the TsFile and get a `ReadOnlyTsFile` instance from a file path string `path`.

```java
TsFileSequenceReader reader = new TsFileSequenceReader(path);
   
ReadOnlyTsFile readTsFile = new ReadOnlyTsFile(reader);
```
Next, we prepare the path array and query expression, then get final `QueryExpression` object by this interface:

```java
QueryExpression queryExpression = QueryExpression.create(paths, statement);
```

The ReadOnlyTsFile class has two `query` method to perform a query.
* **Method 1**

    ```java
    public QueryDataSet query(QueryExpression queryExpression) throws IOException
    ```

* **Method 2**

    ```java
    public QueryDataSet query(QueryExpression queryExpression, long partitionStartOffset, long partitionEndOffset) throws IOException
    ```

    This method is designed for advanced applications such as the TsFile-Spark Connector.

    * **params** : For method 2, two additional parameters are added to support partial query:
        *  ```partitionStartOffset```: start offset for a TsFile
        *  ```partitionEndOffset```: end offset for a TsFile

        > **What is Partial Query ?**
        >
        > In some distributed file systems(e.g. HDFS), a file is split into severval parts which are called "Blocks" and stored in different nodes. Executing a query paralleled in each nodes involved makes better efficiency. Thus Partial Query is needed. Paritial Query only selects the results stored in the part split by ```QueryConstant.PARTITION_START_OFFSET``` and ```QueryConstant.PARTITION_END_OFFSET``` for a TsFile.

* QueryDataset Interface

The query performed above will return a `QueryDataset` object.

Here's the useful interfaces for user.

  * `bool hasNext();`

    Return true if this dataset still has elements.
  * `List<Path> getPaths()`

    Get the paths in this data set.
  * `List<TSDataType> getDataTypes();` 

   Get the data types. The class TSDataType is an enum class, the value will be one of the following:

       BOOLEAN,
       INT32,
       INT64,
       FLOAT,
       DOUBLE,
       TEXT;
 * `RowRecord next() throws IOException;`

    Get the next record.
    
    The class `RowRecord` consists of a `long` timestamp and a `List<Field>` for data in different sensors,
     we can use two getter methods to get them.
    
    ```java
    long getTimestamp();
    List<Field> getFields();
    ```
    
    To get data from one Field, use these methods:
    
    ```java
    TSDataType getDataType();
    Object getObjectValue();
    ```



#### Example for reading an existing TsFile


You should install TsFile to your local maven repository.


A more thorough example with query statement can be found at 
`/tsfile/example/src/main/java/org/apache/iotdb/tsfile/TsFileRead.java`

```java
package org.apache.iotdb.tsfile;
import java.io.IOException;
import java.util.ArrayList;
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.expression.IExpression;
import org.apache.iotdb.tsfile.read.expression.QueryExpression;
import org.apache.iotdb.tsfile.read.expression.impl.BinaryExpression;
import org.apache.iotdb.tsfile.read.expression.impl.GlobalTimeExpression;
import org.apache.iotdb.tsfile.read.expression.impl.SingleSeriesExpression;
import org.apache.iotdb.tsfile.read.filter.TimeFilter;
import org.apache.iotdb.tsfile.read.filter.ValueFilter;
import org.apache.iotdb.tsfile.read.query.dataset.QueryDataSet;

/**
 * The class is to show how to read TsFile file named "test.tsfile".
 * The TsFile file "test.tsfile" is generated from class TsFileWrite.
 * Run TsFileWrite to generate the test.tsfile first
 */
public class TsFileRead {
  private static void queryAndPrint(ArrayList<Path> paths, ReadOnlyTsFile readTsFile, IExpression statement)
          throws IOException {
    QueryExpression queryExpression = QueryExpression.create(paths, statement);
    QueryDataSet queryDataSet = readTsFile.query(queryExpression);
    while (queryDataSet.hasNext()) {
      System.out.println(queryDataSet.next());
    }
    System.out.println("------------");
  }

  public static void main(String[] args) throws IOException {

    // file path
    String path = "test.tsfile";

    // create reader and get the readTsFile interface
    TsFileSequenceReader reader = new TsFileSequenceReader(path);
    ReadOnlyTsFile readTsFile = new ReadOnlyTsFile(reader);
    // use these paths(all sensors) for all the queries
    ArrayList<Path> paths = new ArrayList<>();
    paths.add(new Path("device_1.sensor_1"));
    paths.add(new Path("device_1.sensor_2"));
    paths.add(new Path("device_1.sensor_3"));

    // no query statement
    queryAndPrint(paths, readTsFile, null);

    //close the reader when you left
    reader.close();
  }
}
```



### Change TsFile Configuration

```java
TSFileConfig config = TSFileDescriptor.getInstance().getConfig();
config.setXXX();
```



