This is an automated email from the ASF dual-hosted git repository. hxd pushed a commit to branch iotdb-726 in repository https://gitbox.apache.org/repos/asf/incubator-iotdb.git
commit a32494404225a864bb47944776278aac4876afe0 Author: xiangdong huang <[email protected]> AuthorDate: Tue Jun 23 17:41:58 2020 +0800 fix error that the line number error after restart the server while mlog.txt exists but snapshot file does not exist --- .../org/apache/iotdb/db/metadata/MLogWriter.java | 8 ++ .../org/apache/iotdb/db/metadata/MManager.java | 88 +++++++++++++------ .../iotdb/db/metadata/id/ID2NodeManager.java | 42 +++++++++ .../org/apache/iotdb/db/metadata/id/IDManager.java | 99 ++++++++++++++++++++++ .../java/org/apache/iotdb/db/service/IoTDB.java | 5 +- 5 files changed, 215 insertions(+), 27 deletions(-) diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MLogWriter.java b/server/src/main/java/org/apache/iotdb/db/metadata/MLogWriter.java index 0b9ab3e..8f22ffc 100644 --- a/server/src/main/java/org/apache/iotdb/db/metadata/MLogWriter.java +++ b/server/src/main/java/org/apache/iotdb/db/metadata/MLogWriter.java @@ -169,4 +169,12 @@ public class MLogWriter { int getLineNumber() { return lineNumber; } + + /** + * only used for initialize a mlog file writer. + * @param number + */ + void settLineNumber(int number) { + lineNumber = number; + } } \ No newline at end of file diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java b/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java index 16847ca..3cd2ac4 100644 --- a/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java +++ b/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java @@ -205,7 +205,7 @@ public class MManager { tagLogFile = new TagLogFile(config.getSchemaDir(), MetadataConstant.TAG_LOG); isRecovering = true; - initFromLog(logFile); + int lineNumber = initFromLog(logFile); if (config.isEnableParameterAdapter()) { List<String> storageGroups = mtree.getAllStorageGroupNames(); @@ -218,6 +218,7 @@ public class MManager { } logWriter = new MLogWriter(config.getSchemaDir(), MetadataConstant.METADATA_LOG); + logWriter.settLineNumber(lineNumber); isRecovering = false; } catch (IOException | MetadataException e) { mtree = new MTree(); @@ -226,7 +227,13 @@ public class MManager { initialized = true; } - private void initFromLog(File logFile) throws IOException { + /** + * + * @param logFile + * @return line number of the logFile + * @throws IOException + */ + private int initFromLog(File logFile) throws IOException { File tmpFile = SystemFileFactory.INSTANCE.getFile(mtreeSnapshotTmpPath); if (tmpFile.exists()) { logger.warn("Creating MTree snapshot not successful before crashing..."); @@ -238,25 +245,37 @@ public class MManager { mtree = new MTree(); } else { mtree = MTree.deserializeFrom(mtreeSnapshot); + lastSnapshotLogLineNumber = mtree.getSnapshotLineNumber(); } // init the metadata from the operation log if (logFile.exists()) { + int idx = 0; try (FileReader fr = new FileReader(logFile); BufferedReader br = new BufferedReader(fr)) { String cmd; - int idx = 0; while (idx < mtree.getSnapshotLineNumber()) { cmd = br.readLine(); + if (cmd == null) { + throw new IOException(String + .format("mtree snapshot file has %d lines but the mlog.txt has only %d lines.", + mtree.getSnapshotLineNumber(), idx)); + } idx++; } while ((cmd = br.readLine()) != null) { try { operation(cmd); + idx++; } catch (Exception e) { logger.error("Can not operate cmd {}", cmd, e); } } } + return idx; + } else if (mtreeSnapshot.exists()) { + throw new IOException("mtree snapshot file exists but mlog.txt does not exist."); + } else { + return 0; } } @@ -1773,31 +1792,48 @@ public class MManager { } private void checkMTreeModified() { - if (System.currentTimeMillis() - logFile.lastModified() < mtreeSnapshotThresholdTime) { - logger.info("MTree snapshot is not created because of active modification"); - } else if (logWriter.getLineNumber() - lastSnapshotLogLineNumber < mtreeSnapshotInterval) { - logger.info( - "MTree snapshot need not be created. Current mlog line number: {}, last snapshot line number: {}", - logWriter.getLineNumber(), lastSnapshotLogLineNumber); + if (logWriter == null || logFile == null) { + //the logWriter is not initialized now, we skip the check once. + return; + } + if (System.currentTimeMillis() - logFile.lastModified() >= mtreeSnapshotThresholdTime + && logWriter.getLineNumber() > lastSnapshotLogLineNumber) { + logger.info("Start creating MTree snapshot, because {} ms elaspse.", System.currentTimeMillis() - logFile.lastModified()); + createSnapshot(); + } else if (logWriter.getLineNumber() - lastSnapshotLogLineNumber >= mtreeSnapshotInterval) { + logger.info("Start creating MTree snapshot, because of {} new lines are added.", logWriter.getLineNumber() - lastSnapshotLogLineNumber); + createSnapshot(); } else { - lock.readLock().lock(); - logger.info("Start creating MTree snapshot. This may take a while..."); - try { - mtree.serializeTo(mtreeSnapshotTmpPath, logWriter.getLineNumber()); - lastSnapshotLogLineNumber = logWriter.getLineNumber(); - File tmpFile = SystemFileFactory.INSTANCE.getFile(mtreeSnapshotTmpPath); - File snapshotFile = SystemFileFactory.INSTANCE.getFile(mtreeSnapshotPath); - if (snapshotFile.exists()) { - Files.delete(snapshotFile.toPath()); - } - if (tmpFile.renameTo(snapshotFile)) { - logger.info("Finish creating MTree snapshot to {}.", mtreeSnapshotPath); - } - } catch (IOException e) { - logger.warn("Failed to create MTree snapshot to {}", mtreeSnapshotPath, e); - } finally { - lock.readLock().unlock(); + ///if (logger.isDebugEnabled()) { + logger.info( + "MTree snapshot need not be created. Current mlog line number: {}, last snapshot line number: {}, time difference from last modification: {}ms", + logWriter.getLineNumber(), lastSnapshotLogLineNumber, + System.currentTimeMillis() - logFile.lastModified()); + //} + } + } + + private void createSnapshot() { + lock.readLock().lock(); + long time = System.currentTimeMillis(); + try { + mtree.serializeTo(mtreeSnapshotTmpPath, logWriter.getLineNumber()); + lastSnapshotLogLineNumber = logWriter.getLineNumber(); + File tmpFile = SystemFileFactory.INSTANCE.getFile(mtreeSnapshotTmpPath); + File snapshotFile = SystemFileFactory.INSTANCE.getFile(mtreeSnapshotPath); + if (snapshotFile.exists()) { + Files.delete(snapshotFile.toPath()); } + if (tmpFile.renameTo(snapshotFile)) { + logger.info("Finish creating MTree snapshot to {}, spend {}ms.", mtreeSnapshotPath, System.currentTimeMillis() - time); + } + } catch (IOException e) { + logger.warn("Failed to create MTree snapshot to {}", mtreeSnapshotPath, e); + if (SystemFileFactory.INSTANCE.getFile(mtreeSnapshotTmpPath).exists()) { + SystemFileFactory.INSTANCE.getFile(mtreeSnapshotTmpPath).delete(); + } + } finally { + lock.readLock().unlock(); } } } diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/id/ID2NodeManager.java b/server/src/main/java/org/apache/iotdb/db/metadata/id/ID2NodeManager.java new file mode 100644 index 0000000..ae6dc6b --- /dev/null +++ b/server/src/main/java/org/apache/iotdb/db/metadata/id/ID2NodeManager.java @@ -0,0 +1,42 @@ +/* + * 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.metadata.id; + +import java.util.ArrayList; +import java.util.List; +import org.apache.iotdb.db.metadata.mnode.MNode; + +public class ID2NodeManager { + List<MNode> id2strings = new ArrayList<>(); + + + /** + * when calling this method, you must guarantee that all ids that less than id has been put. + * @param id + * @param node + */ + public void put(int id, MNode node) { + id2strings.set(id, node); + } + + public MNode get(int id) { + return id2strings.get(id); + } +} diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/id/IDManager.java b/server/src/main/java/org/apache/iotdb/db/metadata/id/IDManager.java new file mode 100644 index 0000000..5848ae0 --- /dev/null +++ b/server/src/main/java/org/apache/iotdb/db/metadata/id/IDManager.java @@ -0,0 +1,99 @@ +/* + * 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.metadata.id; + +import java.util.concurrent.atomic.AtomicInteger; +import org.apache.iotdb.db.exception.metadata.MetadataException; + +/** + * ID generator for storage groups, devices, and measurements + */ +public class IDManager { + + private static int storageGroupIDLength = 12; //must be not greater than 32 + private static int deviceIDLength = 32; //must be not greater than 32 + private static int measurementLength = 20; //must be not greater than 32 + + private static int maxSGID; + private static int maxDeivceID; + private static int maxMeasurementID; + static { + if (storageGroupIDLength == 32) { + maxSGID = 0xFFFFFFFF; + } else { + maxSGID = 1 << storageGroupIDLength - 1; + } + + if (deviceIDLength == 32) { + maxDeivceID = 0xFFFFFFFF; + } else { + maxDeivceID = 1 << deviceIDLength - 1; + } + + if (measurementLength == 32) { + maxMeasurementID = 0xFFFFFFFF; + } else { + maxMeasurementID = 1 << measurementLength - 1; + } + } + + private static AtomicInteger sgGenerator = new AtomicInteger(0); + private static AtomicInteger deviceGenerator = new AtomicInteger(0); + private static AtomicInteger measurementGenerator = new AtomicInteger(0); + + + public static int newSGNumber() throws MetadataException { + if (sgGenerator.get() == maxSGID) { + throw new MetadataException("too many storage groups: {}", sgGenerator.get()); + } + return sgGenerator.incrementAndGet(); + } + + public static int newDeviceNumber() throws MetadataException { + if (deviceGenerator.get() == maxDeivceID) { + throw new MetadataException("too many devices: {}", deviceGenerator.get()); + } + return deviceGenerator.incrementAndGet(); + } + + public static int newMeasurementNumber() throws MetadataException { + if (measurementGenerator.get() == maxMeasurementID) { + throw new MetadataException("too many measurements: {}", measurementGenerator.get()); + } + return measurementGenerator.incrementAndGet(); + } + + public static long newID() throws MetadataException { + return (0L | ((long) newSGNumber()) << (deviceIDLength + measurementLength) | ((long) newDeviceNumber()) << measurementLength | newMeasurementNumber()); + } + + public static int getStorageGroupID(long fullId) { + return (int)(fullId >>> (deviceIDLength + measurementLength)); + } + + public static int getDeviceID(long fullId) { + return (int)((fullId << storageGroupIDLength) >>> (storageGroupIDLength + measurementLength)); + } + + public static int getMeasurementID(long fullId) { + return (int)((fullId << storageGroupIDLength + deviceIDLength) >>> (storageGroupIDLength + deviceIDLength)); + } + + +} diff --git a/server/src/main/java/org/apache/iotdb/db/service/IoTDB.java b/server/src/main/java/org/apache/iotdb/db/service/IoTDB.java index eedf20d..dc3ffa6 100644 --- a/server/src/main/java/org/apache/iotdb/db/service/IoTDB.java +++ b/server/src/main/java/org/apache/iotdb/db/service/IoTDB.java @@ -89,7 +89,7 @@ public class IoTDB implements IoTDBMBean { Runtime.getRuntime().addShutdownHook(new IoTDBShutdownHook()); setUncaughtExceptionHandler(); - + logger.info("recover the schema..."); initMManager(); registerManager.register(JMXService.getInstance()); registerManager.register(FlushManager.getInstance()); @@ -131,7 +131,10 @@ public class IoTDB implements IoTDBMBean { } private void initMManager() { + long time = System.currentTimeMillis(); MManager.getInstance().init(); + long end = System.currentTimeMillis() - time; + logger.info("spend {}ms to recover schema.", end); IoTDBConfigDynamicAdapter.getInstance().setInitialized(true); logger.info( "After initializing, max memTable num is {}, tsFile threshold is {}, memtableSize is {}",
