You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ea...@apache.org on 2019/06/04 08:07:13 UTC
[incubator-iotdb] 01/02: multi-directories avoid using disk without
space
This is an automated email from the ASF dual-hosted git repository.
east pushed a commit to branch update_mult_dir_avoid_full_disk
in repository https://gitbox.apache.org/repos/asf/incubator-iotdb.git
commit f699d67bf5d081844a7ffea93da822206e576c6f
Author: mdf369 <95...@qq.com>
AuthorDate: Mon Jun 3 18:35:09 2019 +0800
multi-directories avoid using disk without space
---
.../iotdb/db/conf/directories/Directories.java | 5 +-
.../directories/strategy/DirectoryStrategy.java | 16 ++++-
.../strategy/MaxDiskUsableSpaceFirstStrategy.java | 35 ++++------
.../strategy/MinDirOccupiedSpaceFirstStrategy.java | 76 ----------------------
.../MinFolderOccupiedSpaceFirstStrategy.java | 39 +++++------
.../directories/strategy/SequenceStrategy.java | 32 ++++++---
.../db/engine/filenode/FileNodeProcessor.java | 12 +++-
.../DiskSpaceInsufficientException.java} | 28 ++------
.../iotdb/db/sync/receiver/SyncServiceImpl.java | 14 ++--
9 files changed, 102 insertions(+), 155 deletions(-)
diff --git a/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/Directories.java b/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/Directories.java
index ad9c847..d792c37 100644
--- a/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/Directories.java
+++ b/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/Directories.java
@@ -24,6 +24,7 @@ import java.util.Arrays;
import java.util.List;
import org.apache.iotdb.db.conf.IoTDBDescriptor;
import org.apache.iotdb.db.conf.directories.strategy.DirectoryStrategy;
+import org.apache.iotdb.db.exception.DiskSpaceInsufficientException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -78,7 +79,7 @@ public class Directories {
tsfileFolders.set(0, path);
}
- public String getNextFolderForTsfile() {
+ public String getNextFolderForTsfile() throws DiskSpaceInsufficientException {
return getTsFileFolder(getNextFolderIndexForTsFile());
}
@@ -87,7 +88,7 @@ public class Directories {
*
* @return next folder index
*/
- public int getNextFolderIndexForTsFile() {
+ public int getNextFolderIndexForTsFile() throws DiskSpaceInsufficientException {
return strategy.nextFolderIndex();
}
diff --git a/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/strategy/DirectoryStrategy.java b/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/strategy/DirectoryStrategy.java
index 52b550b..04133ba 100644
--- a/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/strategy/DirectoryStrategy.java
+++ b/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/strategy/DirectoryStrategy.java
@@ -18,7 +18,9 @@
*/
package org.apache.iotdb.db.conf.directories.strategy;
+import java.io.File;
import java.util.List;
+import org.apache.iotdb.db.exception.DiskSpaceInsufficientException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -42,7 +44,7 @@ public abstract class DirectoryStrategy {
*
* @param folders the folders from conf
*/
- public void init(List<String> folders) {
+ public void init(List<String> folders) throws DiskSpaceInsufficientException {
this.folders = folders;
}
@@ -51,7 +53,7 @@ public abstract class DirectoryStrategy {
*
* @return the index of folder that will be allocated
*/
- public abstract int nextFolderIndex();
+ public abstract int nextFolderIndex() throws DiskSpaceInsufficientException;
/**
* Return the actual string value of a folder by its index.
@@ -72,4 +74,14 @@ public abstract class DirectoryStrategy {
public void setFolderForTest(String path) {
folders.set(0, path);
}
+
+ protected long getUsableSpace(String dir) {
+ long space = new File(dir).getFreeSpace();
+ LOGGER.debug("Folder {} has {} available bytes.", dir, space);
+ return space;
+ }
+
+ protected boolean hasSpace(String dir) {
+ return getUsableSpace(dir) > 0;
+ }
}
diff --git a/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/strategy/MaxDiskUsableSpaceFirstStrategy.java b/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/strategy/MaxDiskUsableSpaceFirstStrategy.java
index 8ff1450..8f3ea7d 100644
--- a/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/strategy/MaxDiskUsableSpaceFirstStrategy.java
+++ b/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/strategy/MaxDiskUsableSpaceFirstStrategy.java
@@ -18,41 +18,34 @@
*/
package org.apache.iotdb.db.conf.directories.strategy;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
+import org.apache.iotdb.db.exception.DiskSpaceInsufficientException;
public class MaxDiskUsableSpaceFirstStrategy extends DirectoryStrategy {
@Override
- public int nextFolderIndex() {
+ public int nextFolderIndex() throws DiskSpaceInsufficientException {
return getMaxSpaceFolder();
}
/**
* get max space folder.
*/
- public int getMaxSpaceFolder() {
- List<Integer> candidates = new ArrayList<>();
- long max;
+ public int getMaxSpaceFolder() throws DiskSpaceInsufficientException {
+ int maxIndex = -1;
+ long maxSpace = 0;
- candidates.add(0);
- max = new File(folders.get(0)).getUsableSpace();
- for (int i = 1; i < folders.size(); i++) {
- long current = new File(folders.get(i)).getUsableSpace();
- if (max < current) {
- candidates.clear();
- candidates.add(i);
- max = current;
- } else if (max == current) {
- candidates.add(i);
+ for (int i = 0; i < folders.size(); i++) {
+ long space = getUsableSpace(folders.get(i));
+ if (space > maxSpace) {
+ maxSpace = space;
+ maxIndex = i;
}
}
- Random random = new Random(System.currentTimeMillis());
- int index = random.nextInt(candidates.size());
+ if (maxIndex == -1) {
+ throw new DiskSpaceInsufficientException(folders);
+ }
- return candidates.get(index);
+ return maxIndex;
}
}
diff --git a/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/strategy/MinDirOccupiedSpaceFirstStrategy.java b/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/strategy/MinDirOccupiedSpaceFirstStrategy.java
deleted file mode 100644
index 8174a36..0000000
--- a/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/strategy/MinDirOccupiedSpaceFirstStrategy.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * 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.conf.directories.strategy;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-import java.util.stream.Stream;
-
-public class MinDirOccupiedSpaceFirstStrategy extends DirectoryStrategy {
-
- // directory space is measured by MB
- private static final long DATA_SIZE_SHIFT = 1024L * 1024;
-
- @Override
- public int nextFolderIndex() {
- return getMinOccupiedSpaceFolder();
- }
-
- private int getMinOccupiedSpaceFolder() {
- List<Integer> candidates = new ArrayList<>();
- candidates.add(0);
- long min = getOccupiedSpace(folders.get(0));
- for (int i = 1; i < folders.size(); i++) {
- long current = getOccupiedSpace(folders.get(i));
- if (min > current) {
- candidates.clear();
- candidates.add(i);
- min = current;
- } else if (min == current) {
- candidates.add(i);
- }
- }
-
- Random random = new Random(System.currentTimeMillis());
- int index = random.nextInt(candidates.size());
-
- return candidates.get(index);
- }
-
- private long getOccupiedSpace(String path) {
- Path folder = Paths.get(path);
- long size = 0;
- try {
- try (Stream<Path> stream = Files.walk(folder)) {
- size = stream.filter(p -> p.toFile().isFile())
- .mapToLong(p -> p.toFile().length())
- .sum();
- }
- } catch (IOException e) {
- LOGGER.error("Cannot calculate occupied space for seriesPath {}.", path, e);
- }
-
- return size / DATA_SIZE_SHIFT;
- }
-}
diff --git a/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/strategy/MinFolderOccupiedSpaceFirstStrategy.java b/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/strategy/MinFolderOccupiedSpaceFirstStrategy.java
index 90e3119..9cbe647 100644
--- a/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/strategy/MinFolderOccupiedSpaceFirstStrategy.java
+++ b/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/strategy/MinFolderOccupiedSpaceFirstStrategy.java
@@ -22,10 +22,8 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
import java.util.stream.Stream;
+import org.apache.iotdb.db.exception.DiskSpaceInsufficientException;
public class MinFolderOccupiedSpaceFirstStrategy extends DirectoryStrategy {
@@ -33,29 +31,32 @@ public class MinFolderOccupiedSpaceFirstStrategy extends DirectoryStrategy {
private static final long DATA_SIZE_SHIFT = 1024L * 1024;
@Override
- public int nextFolderIndex() {
+ public int nextFolderIndex() throws DiskSpaceInsufficientException {
return getMinOccupiedSpaceFolder();
}
- private int getMinOccupiedSpaceFolder() {
- List<Integer> candidates = new ArrayList<>();
- candidates.add(0);
- long min = getOccupiedSpace(folders.get(0));
- for (int i = 1; i < folders.size(); i++) {
- long current = getOccupiedSpace(folders.get(i));
- if (min > current) {
- candidates.clear();
- candidates.add(i);
- min = current;
- } else if (min == current) {
- candidates.add(i);
+ private int getMinOccupiedSpaceFolder() throws DiskSpaceInsufficientException {
+ int minIndex = -1;
+ long minSpace = Integer.MAX_VALUE;
+
+ for (int i = 0; i < folders.size(); i++) {
+ String folder = folders.get(i);
+ if (hasSpace(folder)) {
+ continue;
+ }
+
+ long space = getOccupiedSpace(folder);
+ if (space < minSpace) {
+ minSpace = space;
+ minIndex = i;
}
}
- Random random = new Random(System.currentTimeMillis());
- int index = random.nextInt(candidates.size());
+ if (minIndex == -1) {
+ throw new DiskSpaceInsufficientException(folders);
+ }
- return candidates.get(index);
+ return minIndex;
}
private long getOccupiedSpace(String path) {
diff --git a/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/strategy/SequenceStrategy.java b/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/strategy/SequenceStrategy.java
index d2a28bd..e119546 100644
--- a/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/strategy/SequenceStrategy.java
+++ b/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/strategy/SequenceStrategy.java
@@ -19,30 +19,46 @@
package org.apache.iotdb.db.conf.directories.strategy;
import java.util.List;
+import org.apache.iotdb.db.exception.DiskSpaceInsufficientException;
public class SequenceStrategy extends DirectoryStrategy {
private int currentIndex;
@Override
- public void init(List<String> folders) {
+ public void init(List<String> folders) throws DiskSpaceInsufficientException {
super.init(folders);
- currentIndex = 0;
+ currentIndex = -1;
+ for (int i = 0; i < folders.size(); i++) {
+ if (hasSpace(folders.get(i))) {
+ currentIndex = i;
+ break;
+ }
+ }
+
+ if (currentIndex == -1) {
+ throw new DiskSpaceInsufficientException(
+ String.format("All disks of folders %s are full, can't init.", folders));
+ }
}
@Override
- public int nextFolderIndex() {
+ public int nextFolderIndex() throws DiskSpaceInsufficientException {
int index = currentIndex;
- updateIndex();
+ currentIndex = tryGetNextIndex(index);
return index;
}
- private void updateIndex() {
- currentIndex++;
- if (currentIndex >= folders.size()) {
- currentIndex = 0;
+ private int tryGetNextIndex(int start) throws DiskSpaceInsufficientException {
+ int index = start;
+ while (!hasSpace(folders.get(index))) {
+ index = (index + 1) % folders.size();
+ if (index == start) {
+ throw new DiskSpaceInsufficientException(folders);
+ }
}
+ return index;
}
}
diff --git a/iotdb/src/main/java/org/apache/iotdb/db/engine/filenode/FileNodeProcessor.java b/iotdb/src/main/java/org/apache/iotdb/db/engine/filenode/FileNodeProcessor.java
index 209c1f1..701aefb 100644
--- a/iotdb/src/main/java/org/apache/iotdb/db/engine/filenode/FileNodeProcessor.java
+++ b/iotdb/src/main/java/org/apache/iotdb/db/engine/filenode/FileNodeProcessor.java
@@ -67,6 +67,7 @@ import org.apache.iotdb.db.engine.querycontext.UnsealedTsFile;
import org.apache.iotdb.db.engine.version.SimpleFileVersionController;
import org.apache.iotdb.db.engine.version.VersionController;
import org.apache.iotdb.db.exception.BufferWriteProcessorException;
+import org.apache.iotdb.db.exception.DiskSpaceInsufficientException;
import org.apache.iotdb.db.exception.ErrorDebugException;
import org.apache.iotdb.db.exception.FileNodeProcessorException;
import org.apache.iotdb.db.exception.OverflowProcessorException;
@@ -527,7 +528,12 @@ public class FileNodeProcessor extends Processor implements IStatistic {
params.put(FileNodeConstants.BUFFERWRITE_CLOSE_ACTION, bufferwriteCloseAction);
params
.put(FileNodeConstants.FILENODE_PROCESSOR_FLUSH_ACTION, flushFileNodeProcessorAction);
- String baseDir = directories.getNextFolderForTsfile();
+ String baseDir = null;
+ try {
+ baseDir = directories.getNextFolderForTsfile();
+ } catch (DiskSpaceInsufficientException e) {
+ throw new FileNodeProcessorException(e);
+ }
LOGGER.info("Allocate folder {} for the new bufferwrite processor.", baseDir);
// construct processor or restore
try {
@@ -1532,6 +1538,8 @@ public class FileNodeProcessor extends Processor implements IStatistic {
mergeFileWriter.endChunkGroup(footer, 0);
}
}
+ } catch (DiskSpaceInsufficientException e) {
+ throw new FileNodeProcessorException(e);
} finally {
FileReaderManager.getInstance().decreaseFileReaderReference(backupIntervalFile.getFilePath(),
true);
@@ -1557,7 +1565,7 @@ public class FileNodeProcessor extends Processor implements IStatistic {
SingleSeriesExpression seriesFilter, TSDataType dataType,
Map<String, Long> startTimeMap, Map<String, Long> endTimeMap,
OverflowSeriesDataSource overflowSeriesDataSource)
- throws IOException {
+ throws IOException, DiskSpaceInsufficientException {
int numOfChunk = 0;
try {
if (!seriesReader.hasNext()) {
diff --git a/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/strategy/SequenceStrategy.java b/iotdb/src/main/java/org/apache/iotdb/db/exception/DiskSpaceInsufficientException.java
similarity index 63%
copy from iotdb/src/main/java/org/apache/iotdb/db/conf/directories/strategy/SequenceStrategy.java
copy to iotdb/src/main/java/org/apache/iotdb/db/exception/DiskSpaceInsufficientException.java
index d2a28bd..1649fa1 100644
--- a/iotdb/src/main/java/org/apache/iotdb/db/conf/directories/strategy/SequenceStrategy.java
+++ b/iotdb/src/main/java/org/apache/iotdb/db/exception/DiskSpaceInsufficientException.java
@@ -16,33 +16,19 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.iotdb.db.conf.directories.strategy;
+package org.apache.iotdb.db.exception;
import java.util.List;
-public class SequenceStrategy extends DirectoryStrategy {
+public class DiskSpaceInsufficientException extends Exception {
- private int currentIndex;
+ private static final long serialVersionUID = 9001643829368311032L;
- @Override
- public void init(List<String> folders) {
- super.init(folders);
-
- currentIndex = 0;
- }
-
- @Override
- public int nextFolderIndex() {
- int index = currentIndex;
- updateIndex();
-
- return index;
+ public DiskSpaceInsufficientException(String message) {
+ super(message);
}
- private void updateIndex() {
- currentIndex++;
- if (currentIndex >= folders.size()) {
- currentIndex = 0;
- }
+ public DiskSpaceInsufficientException(List<String> folders) {
+ this(String.format("Can't get next folder from %s, because they are all full.", folders));
}
}
diff --git a/iotdb/src/main/java/org/apache/iotdb/db/sync/receiver/SyncServiceImpl.java b/iotdb/src/main/java/org/apache/iotdb/db/sync/receiver/SyncServiceImpl.java
index ad2722d..46919b4 100644
--- a/iotdb/src/main/java/org/apache/iotdb/db/sync/receiver/SyncServiceImpl.java
+++ b/iotdb/src/main/java/org/apache/iotdb/db/sync/receiver/SyncServiceImpl.java
@@ -46,6 +46,7 @@ import org.apache.iotdb.db.conf.directories.Directories;
import org.apache.iotdb.db.engine.filenode.FileNodeManager;
import org.apache.iotdb.db.engine.filenode.OverflowChangeType;
import org.apache.iotdb.db.engine.filenode.TsFileResource;
+import org.apache.iotdb.db.exception.DiskSpaceInsufficientException;
import org.apache.iotdb.db.exception.FileNodeManagerException;
import org.apache.iotdb.db.exception.MetadataArgsErrorException;
import org.apache.iotdb.db.exception.PathErrorException;
@@ -469,10 +470,15 @@ public class SyncServiceImpl implements SyncService.Iface {
// create a new fileNode
String header = syncDataPath;
String relativePath = path.substring(header.length());
- TsFileResource fileNode = new TsFileResource(startTimeMap, endTimeMap,
- OverflowChangeType.NO_CHANGE, new File(
- Directories.getInstance().getNextFolderIndexForTsFile() + File.separator + relativePath)
- );
+ TsFileResource fileNode = null;
+ try {
+ fileNode = new TsFileResource(startTimeMap, endTimeMap,
+ OverflowChangeType.NO_CHANGE, new File(
+ Directories.getInstance().getNextFolderIndexForTsFile() + File.separator + relativePath)
+ );
+ } catch (DiskSpaceInsufficientException e) {
+ throw new FileNodeManagerException(e);
+ }
// call interface of load external file
try {
if (!fileNodeManager.appendFileToFileNode(storageGroup, fileNode, path)) {