blob: 70274fd57e368e6b6e76da6e6bf3392f38561825 [file] [log] [blame]
/*
* 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.db.storageengine.dataregion.tsfile.generator;
import org.apache.iotdb.commons.conf.IoTDBConstant;
import org.apache.iotdb.commons.utils.TestOnly;
import org.apache.iotdb.db.exception.DiskSpaceInsufficientException;
import org.apache.iotdb.db.storageengine.dataregion.tsfile.TsFileResource;
import org.apache.iotdb.db.storageengine.dataregion.tsfile.TsFileResourceStatus;
import org.apache.iotdb.db.storageengine.rescon.disk.TierManager;
import org.apache.tsfile.common.constant.TsFileConstant;
import org.apache.tsfile.fileSystem.FSFactoryProducer;
import org.apache.tsfile.fileSystem.fsFactory.FSFactory;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.apache.iotdb.commons.conf.IoTDBConstant.FILE_NAME_SEPARATOR;
import static org.apache.tsfile.common.constant.TsFileConstant.TSFILE_SUFFIX;
public class TsFileNameGenerator {
private static FSFactory fsFactory = FSFactoryProducer.getFSFactory();
public static String generateNewTsFilePath(
String tsFileDir,
long time,
long version,
int innerSpaceCompactionCount,
int crossSpaceCompactionCount) {
return tsFileDir
+ File.separator
+ generateNewTsFileName(
time, version, innerSpaceCompactionCount, crossSpaceCompactionCount);
}
public static String generateNewTsFilePathWithMkdir(
boolean sequence,
String logicalStorageGroup,
String virtualStorageGroup,
long timePartitionId,
long time,
long version,
int innerSpaceCompactionCount,
int crossSpaceCompactionCount)
throws DiskSpaceInsufficientException {
return generateNewTsFilePathWithMkdir(
sequence,
logicalStorageGroup,
virtualStorageGroup,
timePartitionId,
time,
version,
innerSpaceCompactionCount,
crossSpaceCompactionCount,
TsFileConstant.TSFILE_SUFFIX);
}
public static String generateNewTsFilePathWithMkdir(
boolean sequence,
String logicalStorageGroup,
String virtualStorageGroup,
long timePartitionId,
long time,
long version,
int innerSpaceCompactionCount,
int crossSpaceCompactionCount,
String customSuffix)
throws DiskSpaceInsufficientException {
String tsFileDir =
generateTsFileDir(sequence, logicalStorageGroup, virtualStorageGroup, timePartitionId);
fsFactory.getFile(tsFileDir).mkdirs();
return tsFileDir
+ File.separator
+ generateNewTsFileName(
time, version, innerSpaceCompactionCount, crossSpaceCompactionCount, customSuffix);
}
public static String generateTsFileDir(
boolean sequence,
String logicalStorageGroup,
String virtualStorageGroup,
long timePartitionId)
throws DiskSpaceInsufficientException {
TierManager tierManager = TierManager.getInstance();
String baseDir = tierManager.getNextFolderForTsFile(0, sequence);
return baseDir
+ File.separator
+ logicalStorageGroup
+ File.separator
+ virtualStorageGroup
+ File.separator
+ timePartitionId;
}
public static String generateNewTsFileName(
long time, long version, int innerSpaceCompactionCount, int crossSpaceCompactionCount) {
return generateNewTsFileName(
time, version, innerSpaceCompactionCount, crossSpaceCompactionCount, TSFILE_SUFFIX);
}
public static String generateNewTsFileName(
long time,
long version,
int innerSpaceCompactionCount,
int crossSpaceCompactionCount,
String customSuffix) {
return time
+ IoTDBConstant.FILE_NAME_SEPARATOR
+ version
+ IoTDBConstant.FILE_NAME_SEPARATOR
+ innerSpaceCompactionCount
+ IoTDBConstant.FILE_NAME_SEPARATOR
+ crossSpaceCompactionCount
+ customSuffix;
}
public static TsFileName getTsFileName(String fileName) throws IOException {
Matcher matcher = TsFileName.FILE_NAME_MATCHER.matcher(fileName);
if (matcher.find()) {
try {
TsFileName tsFileName =
new TsFileName(
Long.parseLong(matcher.group(1)),
Long.parseLong(matcher.group(2)),
Integer.parseInt(matcher.group(3)),
Integer.parseInt(matcher.group(4)));
return tsFileName;
} catch (NumberFormatException e) {
throw new IOException("tsfile file name format is incorrect:" + fileName);
}
} else {
throw new IOException("tsfile file name format is incorrect:" + fileName);
}
}
@TestOnly
public static TsFileResource increaseCrossCompactionCnt(TsFileResource tsFileResource)
throws IOException {
File tsFile = tsFileResource.getTsFile();
String path = tsFile.getParent();
TsFileName tsFileName = getTsFileName(tsFileResource.getTsFile().getName());
tsFileName.setCrossCompactionCnt(tsFileName.getCrossCompactionCnt() + 1);
tsFileResource.setFile(
new File(
path,
tsFileName.time
+ FILE_NAME_SEPARATOR
+ tsFileName.version
+ FILE_NAME_SEPARATOR
+ tsFileName.innerCompactionCnt
+ FILE_NAME_SEPARATOR
+ tsFileName.crossCompactionCnt
+ TSFILE_SUFFIX));
return tsFileResource;
}
@TestOnly
public static TsFileResource increaseInnerCompactionCnt(TsFileResource tsFileResource)
throws IOException {
File tsFile = tsFileResource.getTsFile();
String path = tsFile.getParent();
TsFileName tsFileName = getTsFileName(tsFileResource.getTsFile().getName());
tsFileName.setInnerCompactionCnt(tsFileName.getInnerCompactionCnt() + 1);
tsFileResource.setFile(
new File(
path,
tsFileName.time
+ FILE_NAME_SEPARATOR
+ tsFileName.version
+ FILE_NAME_SEPARATOR
+ tsFileName.innerCompactionCnt
+ FILE_NAME_SEPARATOR
+ tsFileName.crossCompactionCnt
+ TSFILE_SUFFIX));
return tsFileResource;
}
public static File increaseCrossCompactionCnt(File tsFile) throws IOException {
String path = tsFile.getParent();
TsFileName tsFileName = getTsFileName(tsFile.getName());
tsFileName.setCrossCompactionCnt(tsFileName.getCrossCompactionCnt() + 1);
return new File(
path,
tsFileName.time
+ FILE_NAME_SEPARATOR
+ tsFileName.version
+ FILE_NAME_SEPARATOR
+ tsFileName.innerCompactionCnt
+ FILE_NAME_SEPARATOR
+ tsFileName.crossCompactionCnt
+ TSFILE_SUFFIX);
}
/**
* Create tmp target file for cross space compaction, in which each sequence source file has its
* own tmp target file.
*
* @param seqResources
* @return tmp target file list, which is xxx.cross
* @throws IOException
*/
public static List<TsFileResource> getCrossCompactionTargetFileResources(
List<TsFileResource> seqResources) throws IOException, DiskSpaceInsufficientException {
List<TsFileResource> targetFileResources = new ArrayList<>();
for (TsFileResource resource : seqResources) {
TsFileName tsFileName = getTsFileName(resource.getTsFile().getName());
tsFileName.setCrossCompactionCnt(tsFileName.getCrossCompactionCnt() + 1);
// set target resource to COMPACTING until the end of this task
targetFileResources.add(
new TsFileResource(
new File(
generateNewTsFilePathWithMkdir(
resource.isSeq(),
resource.getDatabaseName(),
resource.getDataRegionId(),
resource.getTimePartition(),
tsFileName.time,
tsFileName.version,
tsFileName.innerCompactionCnt,
tsFileName.crossCompactionCnt,
IoTDBConstant.CROSS_COMPACTION_TMP_FILE_SUFFIX)),
TsFileResourceStatus.COMPACTING));
}
return targetFileResources;
}
/**
* Create tmp target file for inner space compaction, in which all source files has only one tmp
* target file.
*
* @param tsFileResources
* @param sequence
* @return tmp target file, which is xxx.target
* @throws IOException
*/
public static TsFileResource getInnerCompactionTargetFileResource(
List<TsFileResource> tsFileResources, boolean sequence)
throws IOException, DiskSpaceInsufficientException {
long minTime = Long.MAX_VALUE;
long maxTime = Long.MIN_VALUE;
long minVersion = Long.MAX_VALUE;
long maxVersion = Long.MIN_VALUE;
long maxInnerMergeCount = Long.MIN_VALUE;
long maxCrossMergeCount = Long.MIN_VALUE;
for (TsFileResource resource : tsFileResources) {
TsFileName tsFileName = getTsFileName(resource.getTsFile().getName());
minTime = Math.min(tsFileName.time, minTime);
maxTime = Math.max(tsFileName.time, maxTime);
minVersion = Math.min(tsFileName.version, minVersion);
maxVersion = Math.max(tsFileName.version, maxVersion);
maxInnerMergeCount = Math.max(tsFileName.innerCompactionCnt, maxInnerMergeCount);
maxCrossMergeCount = Math.max(tsFileName.crossCompactionCnt, maxCrossMergeCount);
}
// set target resource to COMPACTING until the end of this task
TsFileResource resource =
sequence
? new TsFileResource(
new File(
generateNewTsFilePathWithMkdir(
sequence,
tsFileResources.get(0).getDatabaseName(),
tsFileResources.get(0).getDataRegionId(),
tsFileResources.get(0).getTimePartition(),
minTime,
minVersion,
(int) maxInnerMergeCount + 1,
(int) maxCrossMergeCount,
IoTDBConstant.INNER_COMPACTION_TMP_FILE_SUFFIX)),
TsFileResourceStatus.COMPACTING)
: new TsFileResource(
new File(
generateNewTsFilePathWithMkdir(
sequence,
tsFileResources.get(0).getDatabaseName(),
tsFileResources.get(0).getDataRegionId(),
tsFileResources.get(0).getTimePartition(),
maxTime,
maxVersion,
(int) maxInnerMergeCount + 1,
(int) maxCrossMergeCount,
IoTDBConstant.INNER_COMPACTION_TMP_FILE_SUFFIX)),
TsFileResourceStatus.COMPACTING);
resource.setSeq(sequence);
return resource;
}
public static class TsFileName {
private static final String FILE_NAME_PATTERN = "(\\d+)-(\\d+)-(\\d+)-(\\d+).tsfile$";
private static final Pattern FILE_NAME_MATCHER = Pattern.compile(TsFileName.FILE_NAME_PATTERN);
private long time;
private long version;
private int innerCompactionCnt;
private int crossCompactionCnt;
public TsFileName(long time, long version, int innerCompactionCnt, int crossCompactionCnt) {
this.time = time;
this.version = version;
this.innerCompactionCnt = innerCompactionCnt;
this.crossCompactionCnt = crossCompactionCnt;
}
public long getTime() {
return time;
}
public long getVersion() {
return version;
}
public int getInnerCompactionCnt() {
return innerCompactionCnt;
}
public int getCrossCompactionCnt() {
return crossCompactionCnt;
}
public void setTime(long time) {
this.time = time;
}
public void setVersion(long version) {
this.version = version;
}
public void setInnerCompactionCnt(int innerCompactionCnt) {
this.innerCompactionCnt = innerCompactionCnt;
}
public void setCrossCompactionCnt(int crossCompactionCnt) {
this.crossCompactionCnt = crossCompactionCnt;
}
}
}