fix
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/StateMachine.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/StateMachine.java
index bcaa4bb..86e9c66 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/StateMachine.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/StateMachine.java
@@ -19,7 +19,6 @@
 
 package org.apache.iotdb.db.queryengine.execution;
 
-import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.util.concurrent.ListenableFuture;
@@ -298,12 +297,10 @@
     safeExecute(() -> stateChangeListener.stateChanged(currentState));
   }
 
-  @VisibleForTesting
   boolean isTerminalState(T state) {
     return terminalStates.contains(state);
   }
 
-  @VisibleForTesting
   List<StateChangeListener<T>> getStateChangeListeners() {
     synchronized (lock) {
       return ImmutableList.copyOf(stateChangeListeners);
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/rowpattern/matcher/ArrayView.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/rowpattern/matcher/ArrayView.java
index 63197a2..c38eb23 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/rowpattern/matcher/ArrayView.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/rowpattern/matcher/ArrayView.java
@@ -19,8 +19,6 @@
 
 package org.apache.iotdb.db.queryengine.execution.operator.process.rowpattern.matcher;
 
-import com.google.common.annotations.VisibleForTesting;
-
 import java.util.Arrays;
 
 import static com.google.common.base.Preconditions.checkArgument;
@@ -48,7 +46,6 @@
     return length;
   }
 
-  @VisibleForTesting
   public int[] toArray() {
     return Arrays.copyOf(array, length);
   }
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/aggregation/grouped/array/ShortBigArray.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/aggregation/grouped/array/ShortBigArray.java
index 38bdb76..c2013dd 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/aggregation/grouped/array/ShortBigArray.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/aggregation/grouped/array/ShortBigArray.java
@@ -19,10 +19,9 @@
 
 package org.apache.iotdb.db.queryengine.execution.operator.source.relational.aggregation.grouped.array;
 
-import com.google.common.primitives.Shorts;
-
 import java.util.Arrays;
 
+import static com.google.common.base.Preconditions.checkArgument;
 import static org.apache.iotdb.db.queryengine.execution.operator.source.relational.aggregation.grouped.array.BigArrays.INITIAL_SEGMENTS;
 import static org.apache.iotdb.db.queryengine.execution.operator.source.relational.aggregation.grouped.array.BigArrays.SEGMENT_SIZE;
 import static org.apache.iotdb.db.queryengine.execution.operator.source.relational.aggregation.grouped.array.BigArrays.offset;
@@ -97,7 +96,21 @@
    * @param value the value
    */
   public void add(long index, long value) {
-    array[segment(index)][offset(index)] += Shorts.checkedCast(value);
+    array[segment(index)][offset(index)] += checkedCast(value);
+  }
+
+  /**
+   * Returns the {@code short} value that is equal to {@code value}, if possible.
+   *
+   * @param value any value in the range of the {@code short} type
+   * @return the {@code short} value that equals {@code value}
+   * @throws IllegalArgumentException if {@code value} is greater than {@link Short#MAX_VALUE} or
+   *     less than {@link Short#MIN_VALUE}
+   */
+  public static short checkedCast(long value) {
+    short result = (short) value;
+    checkArgument(result == value, "Out of range: %s", value);
+    return result;
   }
 
   /**
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/aggregation/grouped/hash/GroupByHash.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/aggregation/grouped/hash/GroupByHash.java
index 60059ae..524dee9 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/aggregation/grouped/hash/GroupByHash.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/aggregation/grouped/hash/GroupByHash.java
@@ -21,7 +21,6 @@
 
 import org.apache.iotdb.db.queryengine.execution.operator.source.relational.aggregation.grouped.UpdateMemory;
 
-import com.google.common.annotations.VisibleForTesting;
 import org.apache.tsfile.block.column.Column;
 import org.apache.tsfile.read.common.block.TsBlockBuilder;
 import org.apache.tsfile.read.common.type.Type;
@@ -56,6 +55,5 @@
 
   long getRawHash(int groupId);
 
-  @VisibleForTesting
   int getCapacity();
 }
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/aggregation/grouped/hash/MarkDistinctHash.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/aggregation/grouped/hash/MarkDistinctHash.java
index 7001bdf..c866dc0 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/aggregation/grouped/hash/MarkDistinctHash.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/aggregation/grouped/hash/MarkDistinctHash.java
@@ -21,7 +21,6 @@
 
 import org.apache.iotdb.db.queryengine.execution.operator.source.relational.aggregation.grouped.UpdateMemory;
 
-import com.google.common.annotations.VisibleForTesting;
 import org.apache.tsfile.block.column.Column;
 import org.apache.tsfile.read.common.block.column.BooleanColumn;
 import org.apache.tsfile.read.common.block.column.RunLengthEncodedColumn;
@@ -55,7 +54,6 @@
         groupByHash.getGroupCount(), groupIds, columns[0].getPositionCount());
   }
 
-  @VisibleForTesting
   public int getCapacity() {
     return groupByHash.getCapacity();
   }
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/EqualityInference.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/EqualityInference.java
index f5ecd7d..d31d1f0 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/EqualityInference.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/EqualityInference.java
@@ -25,7 +25,6 @@
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SymbolReference;
 import org.apache.iotdb.db.queryengine.plan.relational.utils.DisjointSet;
 
-import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
@@ -354,7 +353,6 @@
    * Returns a canonical expression that is fully contained by the symbolScope and that is
    * equivalent to the specified expression. Returns null if unable to find a canonical.
    */
-  @VisibleForTesting
   Expression getScopedCanonical(Expression expression, Predicate<Symbol> symbolScope) {
     Expression canonicalIndex = canonicalMap.get(expression);
     if (canonicalIndex == null) {
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/base/Functions.java b/iotdb-core/node-commons/src/main/java/com/google/common/base/Functions.java
new file mode 100644
index 0000000..53c6457
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/base/Functions.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2007 The Guava Authors
+ *
+ * Licensed 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 com.google.common.base;
+
+import javax.annotation.CheckForNull;
+
+/**
+ * Static utility methods pertaining to {@code com.google.common.base.Function} instances; see that
+ * class for information about migrating to {@code java.util.function}.
+ *
+ * <p>All methods return serializable functions as long as they're given serializable parameters.
+ *
+ * <p>See the Guava User Guide article on <a
+ * href="https://github.com/google/guava/wiki/FunctionalExplained">the use of {@code Function}</a>.
+ *
+ * @author Mike Bostock
+ * @author Jared Levy
+ * @since 2.0
+ */
+public final class Functions {
+  private Functions() {}
+
+  /**
+   * Returns the identity function.
+   *
+   * <p><b>Discouraged:</b> Prefer using a lambda like {@code v -> v}, which is shorter and often
+   * more readable.
+   */
+  // implementation is "fully variant"; E has become a "pass-through" type
+  @SuppressWarnings("unchecked")
+  public static <E extends Object> Function<E, E> identity() {
+    return (Function<E, E>) IdentityFunction.INSTANCE;
+  }
+
+  // enum singleton pattern
+  private enum IdentityFunction implements Function<Object, Object> {
+    INSTANCE;
+
+    @Override
+    @CheckForNull
+    public Object apply(@CheckForNull Object o) {
+      return o;
+    }
+
+    @Override
+    public String toString() {
+      return "Functions.identity()";
+    }
+  }
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/base/Splitter.java b/iotdb-core/node-commons/src/main/java/com/google/common/base/Splitter.java
index d850ede..7d626a3 100644
--- a/iotdb-core/node-commons/src/main/java/com/google/common/base/Splitter.java
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/base/Splitter.java
@@ -16,15 +16,9 @@
 
 import javax.annotation.CheckForNull;
 
-import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.regex.Pattern;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
@@ -241,83 +235,6 @@
   }
 
   /**
-   * Returns a splitter that considers any subsequence matching a given pattern (regular expression)
-   * to be a separator. For example, {@code Splitter.onPattern("\r?\n").split(entireFile)} splits a
-   * string into lines whether it uses DOS-style or UNIX-style line terminators. This is equivalent
-   * to {@code Splitter.on(Pattern.compile(pattern))}.
-   *
-   * @param separatorPattern the pattern that determines whether a subsequence is a separator. This
-   *     pattern may not match the empty string.
-   * @return a splitter, with default settings, that uses this pattern
-   * @throws IllegalArgumentException if {@code separatorPattern} matches the empty string or is a
-   *     malformed expression
-   */
-  public static Splitter onPattern(String separatorPattern) {
-    return on(Platform.compilePattern(separatorPattern));
-  }
-
-  /**
-   * Returns a splitter that divides strings into pieces of the given length. For example, {@code
-   * Splitter.fixedLength(2).split("abcde")} returns an iterable containing {@code ["ab", "cd",
-   * "e"]}. The last piece can be smaller than {@code length} but will never be empty.
-   *
-   * <p><b>Note:</b> if {@link #fixedLength} is used in conjunction with {@link #limit}, the final
-   * split piece <i>may be longer than the specified fixed length</i>. This is because the splitter
-   * will <i>stop splitting when the limit is reached</i>, and just return the final piece as-is.
-   *
-   * <p><b>Exception:</b> for consistency with separator-based splitters, {@code split("")} does not
-   * yield an empty iterable, but an iterable containing {@code ""}. This is the only case in which
-   * {@code Iterables.size(split(input))} does not equal {@code IntMath.divide(input.length(),
-   * length, CEILING)}. To avoid this behavior, use {@code omitEmptyStrings}.
-   *
-   * @param length the desired length of pieces after splitting, a positive integer
-   * @return a splitter, with default settings, that can split into fixed sized pieces
-   * @throws IllegalArgumentException if {@code length} is zero or negative
-   */
-  public static Splitter fixedLength(final int length) {
-    checkArgument(length > 0, "The length may not be less than 1");
-
-    return new Splitter(
-        new Strategy() {
-          @Override
-          public SplittingIterator iterator(final Splitter splitter, CharSequence toSplit) {
-            return new SplittingIterator(splitter, toSplit) {
-              @Override
-              public int separatorStart(int start) {
-                int nextChunkStart = start + length;
-                return (nextChunkStart < toSplit.length() ? nextChunkStart : -1);
-              }
-
-              @Override
-              public int separatorEnd(int separatorPosition) {
-                return separatorPosition;
-              }
-            };
-          }
-        });
-  }
-
-  /**
-   * Returns a splitter that behaves equivalently to {@code this} splitter, but automatically omits
-   * empty strings from the results. For example, {@code
-   * Splitter.on(',').omitEmptyStrings().split(",a,,,b,c,,")} returns an iterable containing only
-   * {@code ["a", "b", "c"]}.
-   *
-   * <p>If either {@code trimResults} option is also specified when creating a splitter, that
-   * splitter always trims results first before checking for emptiness. So, for example, {@code
-   * Splitter.on(':').omitEmptyStrings().trimResults().split(": : : ")} returns an empty iterable.
-   *
-   * <p>Note that it is ordinarily not possible for {@link #split(CharSequence)} to return an empty
-   * iterable, but when using this option, it can (if the input sequence consists of nothing but
-   * separators).
-   *
-   * @return a splitter with the desired configuration
-   */
-  public Splitter omitEmptyStrings() {
-    return new Splitter(strategy, true, trimmer, limit);
-  }
-
-  /**
    * Returns a splitter that behaves equivalently to {@code this} splitter but stops splitting after
    * it reaches the limit. The limit defines the maximum number of items returned by the iterator,
    * or the maximum size of the list returned by {@link #splitToList}.
@@ -398,132 +315,6 @@
     return strategy.iterator(this, sequence);
   }
 
-  /**
-   * Splits {@code sequence} into string components and returns them as an immutable list. If you
-   * want an {@link Iterable} which may be lazily evaluated, use {@link #split(CharSequence)}.
-   *
-   * @param sequence the sequence of characters to split
-   * @return an immutable list of the segments split from the parameter
-   * @since 15.0
-   */
-  public List<String> splitToList(CharSequence sequence) {
-    checkNotNull(sequence);
-
-    Iterator<String> iterator = splittingIterator(sequence);
-    List<String> result = new ArrayList<>();
-
-    while (iterator.hasNext()) {
-      result.add(iterator.next());
-    }
-
-    return Collections.unmodifiableList(result);
-  }
-
-  /**
-   * Splits {@code sequence} into string components and makes them available through an {@link
-   * Stream}, which may be lazily evaluated. If you want an eagerly computed {@link List}, use
-   * {@link #splitToList(CharSequence)}.
-   *
-   * @param sequence the sequence of characters to split
-   * @return a stream over the segments split from the parameter
-   * @since 28.2
-   */
-  public Stream<String> splitToStream(CharSequence sequence) {
-    // Can't use Streams.stream() from base
-    return StreamSupport.stream(split(sequence).spliterator(), false);
-  }
-
-  /**
-   * Returns a {@code MapSplitter} which splits entries based on this splitter, and splits entries
-   * into keys and values using the specified separator.
-   *
-   * @since 10.0
-   */
-  public MapSplitter withKeyValueSeparator(String separator) {
-    return withKeyValueSeparator(on(separator));
-  }
-
-  /**
-   * Returns a {@code MapSplitter} which splits entries based on this splitter, and splits entries
-   * into keys and values using the specified separator.
-   *
-   * @since 14.0
-   */
-  public MapSplitter withKeyValueSeparator(char separator) {
-    return withKeyValueSeparator(on(separator));
-  }
-
-  /**
-   * Returns a {@code MapSplitter} which splits entries based on this splitter, and splits entries
-   * into keys and values using the specified key-value splitter.
-   *
-   * <p>Note: Any configuration option configured on this splitter, such as {@link #trimResults},
-   * does not change the behavior of the {@code keyValueSplitter}.
-   *
-   * <p>Example:
-   *
-   * <pre>{@code
-   * String toSplit = " x -> y, z-> a ";
-   * Splitter outerSplitter = Splitter.on(',').trimResults();
-   * MapSplitter mapSplitter = outerSplitter.withKeyValueSeparator(Splitter.on("->"));
-   * Map<String, String> result = mapSplitter.split(toSplit);
-   * assertThat(result).isEqualTo(ImmutableMap.of("x ", " y", "z", " a"));
-   * }</pre>
-   *
-   * @since 10.0
-   */
-  public MapSplitter withKeyValueSeparator(Splitter keyValueSplitter) {
-    return new MapSplitter(this, keyValueSplitter);
-  }
-
-  /**
-   * An object that splits strings into maps as {@code Splitter} splits iterables and lists. Like
-   * {@code Splitter}, it is thread-safe and immutable. The common way to build instances is by
-   * providing an additional {@linkplain Splitter#withKeyValueSeparator key-value separator} to
-   * {@link Splitter}.
-   *
-   * @since 10.0
-   */
-  public static final class MapSplitter {
-    private static final String INVALID_ENTRY_MESSAGE = "Chunk [%s] is not a valid entry";
-    private final Splitter outerSplitter;
-    private final Splitter entrySplitter;
-
-    private MapSplitter(Splitter outerSplitter, Splitter entrySplitter) {
-      this.outerSplitter = outerSplitter; // only "this" is passed
-      this.entrySplitter = checkNotNull(entrySplitter);
-    }
-
-    /**
-     * Splits {@code sequence} into substrings, splits each substring into an entry, and returns an
-     * unmodifiable map with each of the entries. For example, {@code
-     * Splitter.on(';').trimResults().withKeyValueSeparator("=>").split("a=>b ; c=>b")} will return
-     * a mapping from {@code "a"} to {@code "b"} and {@code "c"} to {@code "b"}.
-     *
-     * <p>The returned map preserves the order of the entries from {@code sequence}.
-     *
-     * @throws IllegalArgumentException if the specified sequence does not split into valid map
-     *     entries, or if there are duplicate keys
-     */
-    public Map<String, String> split(CharSequence sequence) {
-      Map<String, String> map = new LinkedHashMap<>();
-      for (String entry : outerSplitter.split(sequence)) {
-        Iterator<String> entryFields = entrySplitter.splittingIterator(entry);
-
-        checkArgument(entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry);
-        String key = entryFields.next();
-        checkArgument(!map.containsKey(key), "Duplicate key [%s] found.", key);
-
-        checkArgument(entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry);
-        String value = entryFields.next();
-        map.put(key, value);
-
-        checkArgument(!entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry);
-      }
-      return Collections.unmodifiableMap(map);
-    }
-  }
-
   private interface Strategy {
     Iterator<String> iterator(Splitter splitter, CharSequence toSplit);
   }
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/base/Strings.java b/iotdb-core/node-commons/src/main/java/com/google/common/base/Strings.java
index eab6202..c75da4d 100644
--- a/iotdb-core/node-commons/src/main/java/com/google/common/base/Strings.java
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/base/Strings.java
@@ -32,16 +32,6 @@
   private Strings() {}
 
   /**
-   * Returns the given string if it is non-null; the empty string otherwise.
-   *
-   * @param string the string to test and possibly return
-   * @return {@code string} itself if it is non-null; {@code ""} if it is null
-   */
-  public static String nullToEmpty(@CheckForNull String string) {
-    return Platform.nullToEmpty(string);
-  }
-
-  /**
    * Returns the given string if it is nonempty; {@code null} otherwise.
    *
    * @param string the string to test and possibly return
@@ -68,68 +58,6 @@
   }
 
   /**
-   * Returns a string, of length at least {@code minLength}, consisting of {@code string} prepended
-   * with as many copies of {@code padChar} as are necessary to reach that length. For example,
-   *
-   * <ul>
-   *   <li>{@code padStart("7", 3, '0')} returns {@code "007"}
-   *   <li>{@code padStart("2010", 3, '0')} returns {@code "2010"}
-   * </ul>
-   *
-   * <p>See {@link java.util.Formatter} for a richer set of formatting capabilities.
-   *
-   * @param string the string which should appear at the end of the result
-   * @param minLength the minimum length the resulting string must have. Can be zero or negative, in
-   *     which case the input string is always returned.
-   * @param padChar the character to insert at the beginning of the result until the minimum length
-   *     is reached
-   * @return the padded string
-   */
-  public static String padStart(String string, int minLength, char padChar) {
-    checkNotNull(string); // eager for GWT.
-    if (string.length() >= minLength) {
-      return string;
-    }
-    StringBuilder sb = new StringBuilder(minLength);
-    for (int i = string.length(); i < minLength; i++) {
-      sb.append(padChar);
-    }
-    sb.append(string);
-    return sb.toString();
-  }
-
-  /**
-   * Returns a string, of length at least {@code minLength}, consisting of {@code string} appended
-   * with as many copies of {@code padChar} as are necessary to reach that length. For example,
-   *
-   * <ul>
-   *   <li>{@code padEnd("4.", 5, '0')} returns {@code "4.000"}
-   *   <li>{@code padEnd("2010", 3, '!')} returns {@code "2010"}
-   * </ul>
-   *
-   * <p>See {@link java.util.Formatter} for a richer set of formatting capabilities.
-   *
-   * @param string the string which should appear at the beginning of the result
-   * @param minLength the minimum length the resulting string must have. Can be zero or negative, in
-   *     which case the input string is always returned.
-   * @param padChar the character to append to the end of the result until the minimum length is
-   *     reached
-   * @return the padded string
-   */
-  public static String padEnd(String string, int minLength, char padChar) {
-    checkNotNull(string); // eager for GWT.
-    if (string.length() >= minLength) {
-      return string;
-    }
-    StringBuilder sb = new StringBuilder(minLength);
-    sb.append(string);
-    for (int i = string.length(); i < minLength; i++) {
-      sb.append(padChar);
-    }
-    return sb.toString();
-  }
-
-  /**
    * Returns a string consisting of a specific number of concatenated copies of an input string. For
    * example, {@code repeat("hey", 3)} returns the string {@code "heyheyhey"}.
    *
@@ -168,62 +96,6 @@
   }
 
   /**
-   * Returns the longest string {@code prefix} such that {@code a.toString().startsWith(prefix) &&
-   * b.toString().startsWith(prefix)}, taking care not to split surrogate pairs. If {@code a} and
-   * {@code b} have no common prefix, returns the empty string.
-   *
-   * @since 11.0
-   */
-  public static String commonPrefix(CharSequence a, CharSequence b) {
-    checkNotNull(a);
-    checkNotNull(b);
-
-    int maxPrefixLength = Math.min(a.length(), b.length());
-    int p = 0;
-    while (p < maxPrefixLength && a.charAt(p) == b.charAt(p)) {
-      p++;
-    }
-    if (validSurrogatePairAt(a, p - 1) || validSurrogatePairAt(b, p - 1)) {
-      p--;
-    }
-    return a.subSequence(0, p).toString();
-  }
-
-  /**
-   * Returns the longest string {@code suffix} such that {@code a.toString().endsWith(suffix) &&
-   * b.toString().endsWith(suffix)}, taking care not to split surrogate pairs. If {@code a} and
-   * {@code b} have no common suffix, returns the empty string.
-   *
-   * @since 11.0
-   */
-  public static String commonSuffix(CharSequence a, CharSequence b) {
-    checkNotNull(a);
-    checkNotNull(b);
-
-    int maxSuffixLength = Math.min(a.length(), b.length());
-    int s = 0;
-    while (s < maxSuffixLength && a.charAt(a.length() - s - 1) == b.charAt(b.length() - s - 1)) {
-      s++;
-    }
-    if (validSurrogatePairAt(a, a.length() - s - 1)
-        || validSurrogatePairAt(b, b.length() - s - 1)) {
-      s--;
-    }
-    return a.subSequence(a.length() - s, a.length()).toString();
-  }
-
-  /**
-   * True when a valid surrogate pair starts at the given {@code index} in the given {@code string}.
-   * Out-of-range indexes return false.
-   */
-  static boolean validSurrogatePairAt(CharSequence string, int index) {
-    return index >= 0
-        && index <= (string.length() - 2)
-        && Character.isHighSurrogate(string.charAt(index))
-        && Character.isLowSurrogate(string.charAt(index + 1));
-  }
-
-  /**
    * Returns the given {@code template} string with each occurrence of {@code "%s"} replaced with
    * the corresponding argument value from {@code args}; or, if the placeholder and argument counts
    * do not match, returns a best-effort form of that string. Will not throw an exception under
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/collect/ArrayListMultimap.java b/iotdb-core/node-commons/src/main/java/com/google/common/collect/ArrayListMultimap.java
new file mode 100644
index 0000000..4a5252b
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/collect/ArrayListMultimap.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2007 The Guava Authors
+ *
+ * Licensed 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 com.google.common.collect;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static com.google.common.collect.CollectPreconditions.checkNonnegative;
+
+/**
+ * Implementation of {@code Multimap} that uses an {@code ArrayList} to store the values for a given
+ * key. A {@link HashMap} associates each key with an {@link ArrayList} of values.
+ *
+ * <p>When iterating through the collections supplied by this class, the ordering of values for a
+ * given key agrees with the order in which the values were added.
+ *
+ * <p>This multimap allows duplicate key-value pairs. After adding a new key-value pair equal to an
+ * existing key-value pair, the {@code ArrayListMultimap} will contain entries for both the new
+ * value and the old value.
+ *
+ * <p>Keys and values may be null. All optional multimap methods are supported, and all returned
+ * views are modifiable.
+ *
+ * <p>The lists returned by {@link #get}, {@link #removeAll}, and {@link #replaceValues} all
+ * implement {@link java.util.RandomAccess}.
+ *
+ * <p>This class is not threadsafe when any concurrent operations update the multimap. Concurrent
+ * read operations will work correctly. To allow concurrent update operations, wrap your multimap
+ * with a call to {@link Multimaps#synchronizedListMultimap}.
+ *
+ * <p>See the Guava User Guide article on <a href=
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">{@code Multimap}</a>.
+ *
+ * @author Jared Levy
+ * @since 2.0
+ */
+public final class ArrayListMultimap<K extends Object, V extends Object>
+    extends ArrayListMultimapGwtSerializationDependencies<K, V> {
+  // Default from ArrayList
+  private static final int DEFAULT_VALUES_PER_KEY = 3;
+
+  transient int expectedValuesPerKey;
+
+  /**
+   * Creates a new, empty {@code ArrayListMultimap} with the default initial capacities.
+   *
+   * <p>This method will soon be deprecated in favor of {@code
+   * MultimapBuilder.hashKeys().arrayListValues().build()}.
+   */
+  public static <K extends Object, V extends Object> ArrayListMultimap<K, V> create() {
+    return new ArrayListMultimap<>();
+  }
+
+  /**
+   * Constructs an empty {@code ArrayListMultimap} with enough capacity to hold the specified
+   * numbers of keys and values without resizing.
+   *
+   * <p>This method will soon be deprecated in favor of {@code
+   * MultimapBuilder.hashKeys(expectedKeys).arrayListValues(expectedValuesPerKey).build()}.
+   *
+   * @param expectedKeys the expected number of distinct keys
+   * @param expectedValuesPerKey the expected average number of values per key
+   * @throws IllegalArgumentException if {@code expectedKeys} or {@code expectedValuesPerKey} is
+   *     negative
+   */
+  public static <K extends Object, V extends Object> ArrayListMultimap<K, V> create(
+      int expectedKeys, int expectedValuesPerKey) {
+    return new ArrayListMultimap<>(expectedKeys, expectedValuesPerKey);
+  }
+
+  /**
+   * Constructs an {@code ArrayListMultimap} with the same mappings as the specified multimap.
+   *
+   * <p>This method will soon be deprecated in favor of {@code
+   * MultimapBuilder.hashKeys().arrayListValues().build(multimap)}.
+   *
+   * @param multimap the multimap whose contents are copied to this multimap
+   */
+  public static <K extends Object, V extends Object> ArrayListMultimap<K, V> create(
+      Multimap<? extends K, ? extends V> multimap) {
+    return new ArrayListMultimap<>(multimap);
+  }
+
+  private ArrayListMultimap() {
+    this(12, DEFAULT_VALUES_PER_KEY);
+  }
+
+  private ArrayListMultimap(int expectedKeys, int expectedValuesPerKey) {
+    super(Platform.<K, Collection<V>>newHashMapWithExpectedSize(expectedKeys));
+    checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey");
+    this.expectedValuesPerKey = expectedValuesPerKey;
+  }
+
+  private ArrayListMultimap(Multimap<? extends K, ? extends V> multimap) {
+    this(
+        multimap.keySet().size(),
+        (multimap instanceof ArrayListMultimap)
+            ? ((ArrayListMultimap<?, ?>) multimap).expectedValuesPerKey
+            : DEFAULT_VALUES_PER_KEY);
+    putAll(multimap);
+  }
+
+  /**
+   * Creates a new, empty {@code ArrayList} to hold the collection of values for an arbitrary key.
+   */
+  @Override
+  List<V> createCollection() {
+    return new ArrayList<V>(expectedValuesPerKey);
+  }
+
+  /**
+   * Reduces the memory used by this {@code ArrayListMultimap}, if feasible.
+   *
+   * @deprecated For a {@link ListMultimap} that automatically trims to size, use {@link
+   *     ImmutableListMultimap}. If you need a mutable collection, remove the {@code trimToSize}
+   *     call, or switch to a {@code HashMap<K, ArrayList<V>>}.
+   */
+  @Deprecated
+  public void trimToSize() {
+    for (Collection<V> collection : backingMap().values()) {
+      ArrayList<V> arrayList = (ArrayList<V>) collection;
+      arrayList.trimToSize();
+    }
+  }
+
+  /**
+   * @serialData expectedValuesPerKey, number of distinct keys, and then for each distinct key: the
+   *     key, number of values for that key, and the key's values
+   */
+  private void writeObject(ObjectOutputStream stream) throws IOException {
+    stream.defaultWriteObject();
+    Serialization.writeMultimap(this, stream);
+  }
+
+  private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
+    stream.defaultReadObject();
+    expectedValuesPerKey = DEFAULT_VALUES_PER_KEY;
+    int distinctKeys = Serialization.readCount(stream);
+    Map<K, Collection<V>> map = Maps.newHashMap();
+    setMap(map);
+    Serialization.populateMultimap(this, stream, distinctKeys);
+  }
+
+  private static final long serialVersionUID = 0;
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/collect/ArrayListMultimapGwtSerializationDependencies.java b/iotdb-core/node-commons/src/main/java/com/google/common/collect/ArrayListMultimapGwtSerializationDependencies.java
new file mode 100644
index 0000000..15220cf
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/collect/ArrayListMultimapGwtSerializationDependencies.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 The Guava Authors
+ *
+ * Licensed 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 com.google.common.collect;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * A dummy superclass to support GWT serialization of the element types of an {@link
+ * ArrayListMultimap}. The GWT supersource for this class contains a field for each type.
+ *
+ * <p>For details about this hack, see {@code GwtSerializationDependencies}, which takes the same
+ * approach but with a subclass rather than a superclass.
+ *
+ * <p>TODO(cpovirk): Consider applying this subclass approach to our other types.
+ */
+abstract class ArrayListMultimapGwtSerializationDependencies<K, V>
+    extends AbstractListMultimap<K, V> {
+  ArrayListMultimapGwtSerializationDependencies(Map<K, Collection<V>> map) {
+    super(map);
+  }
+  // TODO(cpovirk): Maybe I should have just one shared superclass for AbstractMultimap itself?
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/collect/LinkedHashMultimap.java b/iotdb-core/node-commons/src/main/java/com/google/common/collect/LinkedHashMultimap.java
new file mode 100644
index 0000000..b3a361d
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/collect/LinkedHashMultimap.java
@@ -0,0 +1,642 @@
+/*
+ * Copyright (C) 2007 The Guava Authors
+ *
+ * Licensed 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 com.google.common.collect;
+
+import com.google.common.base.Objects;
+
+import javax.annotation.CheckForNull;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.Consumer;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.CollectPreconditions.checkNonnegative;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Implementation of {@code Multimap} that does not allow duplicate key-value entries and that
+ * returns collections whose iterators follow the ordering in which the data was added to the
+ * multimap.
+ *
+ * <p>The collections returned by {@code keySet}, {@code keys}, and {@code asMap} iterate through
+ * the keys in the order they were first added to the multimap. Similarly, {@code get}, {@code
+ * removeAll}, and {@code replaceValues} return collections that iterate through the values in the
+ * order they were added. The collections generated by {@code entries} and {@code values} iterate
+ * across the key-value mappings in the order they were added to the multimap.
+ *
+ * <p>The iteration ordering of the collections generated by {@code keySet}, {@code keys}, and
+ * {@code asMap} has a few subtleties. As long as the set of keys remains unchanged, adding or
+ * removing mappings does not affect the key iteration order. However, if you remove all values
+ * associated with a key and then add the key back to the multimap, that key will come last in the
+ * key iteration order.
+ *
+ * <p>The multimap does not store duplicate key-value pairs. Adding a new key-value pair equal to an
+ * existing key-value pair has no effect.
+ *
+ * <p>Keys and values may be null. All optional multimap methods are supported, and all returned
+ * views are modifiable.
+ *
+ * <p>This class is not threadsafe when any concurrent operations update the multimap. Concurrent
+ * read operations will work correctly. To allow concurrent update operations, wrap your multimap
+ * with a call to {@link Multimaps#synchronizedSetMultimap}.
+ *
+ * <p><b>Warning:</b> Do not modify either a key <i>or a value</i> of a {@code LinkedHashMultimap}
+ * in a way that affects its {@link Object#equals} behavior. Undefined behavior and bugs will
+ * result.
+ *
+ * <p>See the Guava User Guide article on <a href=
+ * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap">{@code Multimap}</a>.
+ *
+ * @author Jared Levy
+ * @author Louis Wasserman
+ * @since 2.0
+ */
+public final class LinkedHashMultimap<K extends Object, V extends Object>
+    extends LinkedHashMultimapGwtSerializationDependencies<K, V> {
+
+  /** Creates a new, empty {@code LinkedHashMultimap} with the default initial capacities. */
+  public static <K extends Object, V extends Object> LinkedHashMultimap<K, V> create() {
+    return new LinkedHashMultimap<>(DEFAULT_KEY_CAPACITY, DEFAULT_VALUE_SET_CAPACITY);
+  }
+
+  /**
+   * Constructs an empty {@code LinkedHashMultimap} with enough capacity to hold the specified
+   * numbers of keys and values without rehashing.
+   *
+   * @param expectedKeys the expected number of distinct keys
+   * @param expectedValuesPerKey the expected average number of values per key
+   * @throws IllegalArgumentException if {@code expectedKeys} or {@code expectedValuesPerKey} is
+   *     negative
+   */
+  public static <K extends Object, V extends Object> LinkedHashMultimap<K, V> create(
+      int expectedKeys, int expectedValuesPerKey) {
+    return new LinkedHashMultimap<>(
+        Maps.capacity(expectedKeys), Maps.capacity(expectedValuesPerKey));
+  }
+
+  /**
+   * Constructs a {@code LinkedHashMultimap} with the same mappings as the specified multimap. If a
+   * key-value mapping appears multiple times in the input multimap, it only appears once in the
+   * constructed multimap. The new multimap has the same {@link Multimap#entries()} iteration order
+   * as the input multimap, except for excluding duplicate mappings.
+   *
+   * @param multimap the multimap whose contents are copied to this multimap
+   */
+  public static <K extends Object, V extends Object> LinkedHashMultimap<K, V> create(
+      Multimap<? extends K, ? extends V> multimap) {
+    LinkedHashMultimap<K, V> result = create(multimap.keySet().size(), DEFAULT_VALUE_SET_CAPACITY);
+    result.putAll(multimap);
+    return result;
+  }
+
+  private interface ValueSetLink<K extends Object, V extends Object> {
+    ValueSetLink<K, V> getPredecessorInValueSet();
+
+    ValueSetLink<K, V> getSuccessorInValueSet();
+
+    void setPredecessorInValueSet(ValueSetLink<K, V> entry);
+
+    void setSuccessorInValueSet(ValueSetLink<K, V> entry);
+  }
+
+  private static <K extends Object, V extends Object> void succeedsInValueSet(
+      ValueSetLink<K, V> pred, ValueSetLink<K, V> succ) {
+    pred.setSuccessorInValueSet(succ);
+    succ.setPredecessorInValueSet(pred);
+  }
+
+  private static <K extends Object, V extends Object> void succeedsInMultimap(
+      ValueEntry<K, V> pred, ValueEntry<K, V> succ) {
+    pred.setSuccessorInMultimap(succ);
+    succ.setPredecessorInMultimap(pred);
+  }
+
+  private static <K extends Object, V extends Object> void deleteFromValueSet(
+      ValueSetLink<K, V> entry) {
+    succeedsInValueSet(entry.getPredecessorInValueSet(), entry.getSuccessorInValueSet());
+  }
+
+  private static <K extends Object, V extends Object> void deleteFromMultimap(
+      ValueEntry<K, V> entry) {
+    succeedsInMultimap(entry.getPredecessorInMultimap(), entry.getSuccessorInMultimap());
+  }
+
+  /**
+   * LinkedHashMultimap entries are in no less than three coexisting linked lists: a bucket in the
+   * hash table for a {@code Set<V>} associated with a key, the linked list of insertion-ordered
+   * entries in that {@code Set<V>}, and the linked list of entries in the LinkedHashMultimap as a
+   * whole.
+   */
+  static final class ValueEntry<K extends Object, V extends Object> extends ImmutableEntry<K, V>
+      implements ValueSetLink<K, V> {
+    final int smearedValueHash;
+
+    @CheckForNull ValueEntry<K, V> nextInValueBucket;
+    /*
+     * The *InValueSet and *InMultimap fields below are null after construction, but we almost
+     * always call succeedsIn*() to initialize them immediately thereafter.
+     *
+     * The exception is the *InValueSet fields of multimapHeaderEntry, which are never set. (That
+     * works out fine as long as we continue to be careful not to try to delete them or iterate
+     * past them.)
+     *
+     * We could consider "lying" and omitting @CheckNotNull from all these fields. Normally, I'm not
+     * a fan of that: What if we someday implement (presumably to be enabled during tests only)
+     * bytecode rewriting that checks for any null value that passes through an API with a
+     * known-non-null type? But that particular problem might not arise here, since we're not
+     * actually reading from the fields in any case in which they might be null (as proven by the
+     * requireNonNull checks below). Plus, we're *already* lying here, since newHeader passes a null
+     * key and value, which we pass to the superconstructor, even though the key and value type for
+     * a given entry might not include null. The right fix for the header problems is probably to
+     * define a separate MultimapLink interface with a separate "header" implementation, which
+     * hopefully could avoid implementing Entry or ValueSetLink at all. (But note that that approach
+     * requires us to define extra classes -- unfortunate under Android.) *Then* we could consider
+     * lying about the fields below on the grounds that we always initialize them just after the
+     * constructor -- an example of the kind of lying that our hypothetical bytecode rewriter would
+     * already have to deal with, thanks to DI frameworks that perform field and method injection,
+     * frameworks like Android that define post-construct hooks like Activity.onCreate, etc.
+     */
+
+    @CheckForNull ValueSetLink<K, V> predecessorInValueSet;
+    @CheckForNull ValueSetLink<K, V> successorInValueSet;
+
+    @CheckForNull ValueEntry<K, V> predecessorInMultimap;
+    @CheckForNull ValueEntry<K, V> successorInMultimap;
+
+    ValueEntry(
+        K key, V value, int smearedValueHash, @CheckForNull ValueEntry<K, V> nextInValueBucket) {
+      super(key, value);
+      this.smearedValueHash = smearedValueHash;
+      this.nextInValueBucket = nextInValueBucket;
+    }
+
+    @SuppressWarnings("nullness") // see the comment on the class fields, especially about newHeader
+    static <K extends Object, V extends Object> ValueEntry<K, V> newHeader() {
+      return new ValueEntry<>(null, null, 0, null);
+    }
+
+    boolean matchesValue(@CheckForNull Object v, int smearedVHash) {
+      return smearedValueHash == smearedVHash && Objects.equal(getValue(), v);
+    }
+
+    @Override
+    public ValueSetLink<K, V> getPredecessorInValueSet() {
+      return requireNonNull(predecessorInValueSet); // see the comment on the class fields
+    }
+
+    @Override
+    public ValueSetLink<K, V> getSuccessorInValueSet() {
+      return requireNonNull(successorInValueSet); // see the comment on the class fields
+    }
+
+    @Override
+    public void setPredecessorInValueSet(ValueSetLink<K, V> entry) {
+      predecessorInValueSet = entry;
+    }
+
+    @Override
+    public void setSuccessorInValueSet(ValueSetLink<K, V> entry) {
+      successorInValueSet = entry;
+    }
+
+    public ValueEntry<K, V> getPredecessorInMultimap() {
+      return requireNonNull(predecessorInMultimap); // see the comment on the class fields
+    }
+
+    public ValueEntry<K, V> getSuccessorInMultimap() {
+      return requireNonNull(successorInMultimap); // see the comment on the class fields
+    }
+
+    public void setSuccessorInMultimap(ValueEntry<K, V> multimapSuccessor) {
+      this.successorInMultimap = multimapSuccessor;
+    }
+
+    public void setPredecessorInMultimap(ValueEntry<K, V> multimapPredecessor) {
+      this.predecessorInMultimap = multimapPredecessor;
+    }
+  }
+
+  private static final int DEFAULT_KEY_CAPACITY = 16;
+  private static final int DEFAULT_VALUE_SET_CAPACITY = 2;
+  static final double VALUE_SET_LOAD_FACTOR = 1.0;
+
+  transient int valueSetCapacity = DEFAULT_VALUE_SET_CAPACITY;
+  private transient ValueEntry<K, V> multimapHeaderEntry;
+
+  private LinkedHashMultimap(int keyCapacity, int valueSetCapacity) {
+    super(Platform.<K, Collection<V>>newLinkedHashMapWithExpectedSize(keyCapacity));
+    checkNonnegative(valueSetCapacity, "expectedValuesPerKey");
+
+    this.valueSetCapacity = valueSetCapacity;
+    this.multimapHeaderEntry = ValueEntry.newHeader();
+    succeedsInMultimap(multimapHeaderEntry, multimapHeaderEntry);
+  }
+
+  /**
+   * {@inheritDoc}
+   *
+   * <p>Creates an empty {@code LinkedHashSet} for a collection of values for one key.
+   *
+   * @return a new {@code LinkedHashSet} containing a collection of values for one key
+   */
+  @Override
+  Set<V> createCollection() {
+    return Platform.newLinkedHashSetWithExpectedSize(valueSetCapacity);
+  }
+
+  /**
+   * {@inheritDoc}
+   *
+   * <p>Creates a decorated insertion-ordered set that also keeps track of the order in which
+   * key-value pairs are added to the multimap.
+   *
+   * @param key key to associate with values in the collection
+   * @return a new decorated set containing a collection of values for one key
+   */
+  @Override
+  Collection<V> createCollection(K key) {
+    return new ValueSet(key, valueSetCapacity);
+  }
+
+  /**
+   * {@inheritDoc}
+   *
+   * <p>If {@code values} is not empty and the multimap already contains a mapping for {@code key},
+   * the {@code keySet()} ordering is unchanged. However, the provided values always come last in
+   * the {@link #entries()} and {@link #values()} iteration orderings.
+   */
+  @Override
+  public Set<V> replaceValues(K key, Iterable<? extends V> values) {
+    return super.replaceValues(key, values);
+  }
+
+  /**
+   * Returns a set of all key-value pairs. Changes to the returned set will update the underlying
+   * multimap, and vice versa. The entries set does not support the {@code add} or {@code addAll}
+   * operations.
+   *
+   * <p>The iterator generated by the returned set traverses the entries in the order they were
+   * added to the multimap.
+   *
+   * <p>Each entry is an immutable snapshot of a key-value mapping in the multimap, taken at the
+   * time the entry is returned by a method call to the collection or its iterator.
+   */
+  @Override
+  public Set<Entry<K, V>> entries() {
+    return super.entries();
+  }
+
+  /**
+   * Returns a view collection of all <i>distinct</i> keys contained in this multimap. Note that the
+   * key set contains a key if and only if this multimap maps that key to at least one value.
+   *
+   * <p>The iterator generated by the returned set traverses the keys in the order they were first
+   * added to the multimap.
+   *
+   * <p>Changes to the returned set will update the underlying multimap, and vice versa. However,
+   * <i>adding</i> to the returned set is not possible.
+   */
+  @Override
+  public Set<K> keySet() {
+    return super.keySet();
+  }
+
+  /**
+   * Returns a collection of all values in the multimap. Changes to the returned collection will
+   * update the underlying multimap, and vice versa.
+   *
+   * <p>The iterator generated by the returned collection traverses the values in the order they
+   * were added to the multimap.
+   */
+  @Override
+  public Collection<V> values() {
+    return super.values();
+  }
+
+  final class ValueSet extends Sets.ImprovedAbstractSet<V> implements ValueSetLink<K, V> {
+    /*
+     * We currently use a fixed load factor of 1.0, a bit higher than normal to reduce memory
+     * consumption.
+     */
+
+    private final K key;
+    ValueEntry<K, V>[] hashTable;
+    private int size = 0;
+    private int modCount = 0;
+
+    // We use the set object itself as the end of the linked list, avoiding an unnecessary
+    // entry object per key.
+    private ValueSetLink<K, V> firstEntry;
+    private ValueSetLink<K, V> lastEntry;
+
+    ValueSet(K key, int expectedValues) {
+      this.key = key;
+      this.firstEntry = this;
+      this.lastEntry = this;
+      // Round expected values up to a power of 2 to get the table size.
+      int tableSize = Hashing.closedTableSize(expectedValues, VALUE_SET_LOAD_FACTOR);
+
+      @SuppressWarnings({"rawtypes", "unchecked"})
+      ValueEntry<K, V>[] hashTable = new ValueEntry[tableSize];
+      this.hashTable = hashTable;
+    }
+
+    private int mask() {
+      return hashTable.length - 1;
+    }
+
+    @Override
+    public ValueSetLink<K, V> getPredecessorInValueSet() {
+      return lastEntry;
+    }
+
+    @Override
+    public ValueSetLink<K, V> getSuccessorInValueSet() {
+      return firstEntry;
+    }
+
+    @Override
+    public void setPredecessorInValueSet(ValueSetLink<K, V> entry) {
+      lastEntry = entry;
+    }
+
+    @Override
+    public void setSuccessorInValueSet(ValueSetLink<K, V> entry) {
+      firstEntry = entry;
+    }
+
+    @Override
+    public Iterator<V> iterator() {
+      return new Iterator<V>() {
+        ValueSetLink<K, V> nextEntry = firstEntry;
+        @CheckForNull ValueEntry<K, V> toRemove;
+        int expectedModCount = modCount;
+
+        private void checkForComodification() {
+          if (modCount != expectedModCount) {
+            throw new ConcurrentModificationException();
+          }
+        }
+
+        @Override
+        public boolean hasNext() {
+          checkForComodification();
+          return nextEntry != ValueSet.this;
+        }
+
+        @Override
+        public V next() {
+          if (!hasNext()) {
+            throw new NoSuchElementException();
+          }
+          ValueEntry<K, V> entry = (ValueEntry<K, V>) nextEntry;
+          V result = entry.getValue();
+          toRemove = entry;
+          nextEntry = entry.getSuccessorInValueSet();
+          return result;
+        }
+
+        @Override
+        public void remove() {
+          checkForComodification();
+          checkState(toRemove != null, "no calls to next() since the last call to remove()");
+          ValueSet.this.remove(toRemove.getValue());
+          expectedModCount = modCount;
+          toRemove = null;
+        }
+      };
+    }
+
+    @Override
+    public void forEach(Consumer<? super V> action) {
+      checkNotNull(action);
+      for (ValueSetLink<K, V> entry = firstEntry;
+          entry != ValueSet.this;
+          entry = entry.getSuccessorInValueSet()) {
+        action.accept(((ValueEntry<K, V>) entry).getValue());
+      }
+    }
+
+    @Override
+    public int size() {
+      return size;
+    }
+
+    @Override
+    public boolean contains(@CheckForNull Object o) {
+      int smearedHash = Hashing.smearedHash(o);
+      for (ValueEntry<K, V> entry = hashTable[smearedHash & mask()];
+          entry != null;
+          entry = entry.nextInValueBucket) {
+        if (entry.matchesValue(o, smearedHash)) {
+          return true;
+        }
+      }
+      return false;
+    }
+
+    @Override
+    public boolean add(V value) {
+      int smearedHash = Hashing.smearedHash(value);
+      int bucket = smearedHash & mask();
+      ValueEntry<K, V> rowHead = hashTable[bucket];
+      for (ValueEntry<K, V> entry = rowHead; entry != null; entry = entry.nextInValueBucket) {
+        if (entry.matchesValue(value, smearedHash)) {
+          return false;
+        }
+      }
+
+      ValueEntry<K, V> newEntry = new ValueEntry<>(key, value, smearedHash, rowHead);
+      succeedsInValueSet(lastEntry, newEntry);
+      succeedsInValueSet(newEntry, this);
+      succeedsInMultimap(multimapHeaderEntry.getPredecessorInMultimap(), newEntry);
+      succeedsInMultimap(newEntry, multimapHeaderEntry);
+      hashTable[bucket] = newEntry;
+      size++;
+      modCount++;
+      rehashIfNecessary();
+      return true;
+    }
+
+    private void rehashIfNecessary() {
+      if (Hashing.needsResizing(size, hashTable.length, VALUE_SET_LOAD_FACTOR)) {
+        @SuppressWarnings("unchecked")
+        ValueEntry<K, V>[] hashTable = new ValueEntry[this.hashTable.length * 2];
+        this.hashTable = hashTable;
+        int mask = hashTable.length - 1;
+        for (ValueSetLink<K, V> entry = firstEntry;
+            entry != this;
+            entry = entry.getSuccessorInValueSet()) {
+          ValueEntry<K, V> valueEntry = (ValueEntry<K, V>) entry;
+          int bucket = valueEntry.smearedValueHash & mask;
+          valueEntry.nextInValueBucket = hashTable[bucket];
+          hashTable[bucket] = valueEntry;
+        }
+      }
+    }
+
+    @Override
+    public boolean remove(@CheckForNull Object o) {
+      int smearedHash = Hashing.smearedHash(o);
+      int bucket = smearedHash & mask();
+      ValueEntry<K, V> prev = null;
+      for (ValueEntry<K, V> entry = hashTable[bucket];
+          entry != null;
+          prev = entry, entry = entry.nextInValueBucket) {
+        if (entry.matchesValue(o, smearedHash)) {
+          if (prev == null) {
+            // first entry in the bucket
+            hashTable[bucket] = entry.nextInValueBucket;
+          } else {
+            prev.nextInValueBucket = entry.nextInValueBucket;
+          }
+          deleteFromValueSet(entry);
+          deleteFromMultimap(entry);
+          size--;
+          modCount++;
+          return true;
+        }
+      }
+      return false;
+    }
+
+    @Override
+    public void clear() {
+      Arrays.fill(hashTable, null);
+      size = 0;
+      for (ValueSetLink<K, V> entry = firstEntry;
+          entry != this;
+          entry = entry.getSuccessorInValueSet()) {
+        ValueEntry<K, V> valueEntry = (ValueEntry<K, V>) entry;
+        deleteFromMultimap(valueEntry);
+      }
+      succeedsInValueSet(this, this);
+      modCount++;
+    }
+  }
+
+  @Override
+  Iterator<Entry<K, V>> entryIterator() {
+    return new Iterator<Entry<K, V>>() {
+      ValueEntry<K, V> nextEntry = multimapHeaderEntry.getSuccessorInMultimap();
+      @CheckForNull ValueEntry<K, V> toRemove;
+
+      @Override
+      public boolean hasNext() {
+        return nextEntry != multimapHeaderEntry;
+      }
+
+      @Override
+      public Entry<K, V> next() {
+        if (!hasNext()) {
+          throw new NoSuchElementException();
+        }
+        ValueEntry<K, V> result = nextEntry;
+        toRemove = result;
+        nextEntry = nextEntry.getSuccessorInMultimap();
+        return result;
+      }
+
+      @Override
+      public void remove() {
+        checkState(toRemove != null, "no calls to next() since the last call to remove()");
+        LinkedHashMultimap.this.remove(toRemove.getKey(), toRemove.getValue());
+        toRemove = null;
+      }
+    };
+  }
+
+  @Override
+  Spliterator<Entry<K, V>> entrySpliterator() {
+    return Spliterators.spliterator(entries(), Spliterator.DISTINCT | Spliterator.ORDERED);
+  }
+
+  @Override
+  Iterator<V> valueIterator() {
+    return Maps.valueIterator(entryIterator());
+  }
+
+  @Override
+  Spliterator<V> valueSpliterator() {
+    return CollectSpliterators.map(entrySpliterator(), Entry::getValue);
+  }
+
+  @Override
+  public void clear() {
+    super.clear();
+    succeedsInMultimap(multimapHeaderEntry, multimapHeaderEntry);
+  }
+
+  /**
+   * @serialData the expected values per key, the number of distinct keys, the number of entries,
+   *     and the entries in order
+   */
+  private void writeObject(ObjectOutputStream stream) throws IOException {
+    stream.defaultWriteObject();
+    stream.writeInt(keySet().size());
+    for (K key : keySet()) {
+      stream.writeObject(key);
+    }
+    stream.writeInt(size());
+    for (Entry<K, V> entry : entries()) {
+      stream.writeObject(entry.getKey());
+      stream.writeObject(entry.getValue());
+    }
+  }
+
+  private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
+    stream.defaultReadObject();
+    multimapHeaderEntry = ValueEntry.newHeader();
+    succeedsInMultimap(multimapHeaderEntry, multimapHeaderEntry);
+    valueSetCapacity = DEFAULT_VALUE_SET_CAPACITY;
+    int distinctKeys = stream.readInt();
+    Map<K, Collection<V>> map = Platform.newLinkedHashMapWithExpectedSize(12);
+    for (int i = 0; i < distinctKeys; i++) {
+      @SuppressWarnings("unchecked")
+      K key = (K) stream.readObject();
+      map.put(key, createCollection(key));
+    }
+    int entries = stream.readInt();
+    for (int i = 0; i < entries; i++) {
+      @SuppressWarnings("unchecked")
+      K key = (K) stream.readObject();
+      @SuppressWarnings("unchecked")
+      V value = (V) stream.readObject();
+      /*
+       * requireNonNull is safe for a properly serialized multimap: We've already inserted a
+       * collection for each key that we expect.
+       */
+      requireNonNull(map.get(key)).add(value);
+    }
+    setMap(map);
+  }
+
+  private static final long serialVersionUID = 1;
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/collect/LinkedHashMultimapGwtSerializationDependencies.java b/iotdb-core/node-commons/src/main/java/com/google/common/collect/LinkedHashMultimapGwtSerializationDependencies.java
new file mode 100644
index 0000000..994ff54
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/collect/LinkedHashMultimapGwtSerializationDependencies.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 The Guava Authors
+ *
+ * Licensed 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 com.google.common.collect;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * A dummy superclass to support GWT serialization of the element types of a {@link
+ * LinkedHashMultimap}. The GWT supersource for this class contains a field for each type.
+ *
+ * <p>For details about this hack, see {@code GwtSerializationDependencies}, which takes the same
+ * approach but with a subclass rather than a superclass.
+ *
+ * <p>TODO(cpovirk): Consider applying this subclass approach to our other types.
+ */
+abstract class LinkedHashMultimapGwtSerializationDependencies<K, V>
+    extends AbstractSetMultimap<K, V> {
+  LinkedHashMultimapGwtSerializationDependencies(Map<K, Collection<V>> map) {
+    super(map);
+  }
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/collect/Lists.java b/iotdb-core/node-commons/src/main/java/com/google/common/collect/Lists.java
index 982fbfd..f8355c1 100644
--- a/iotdb-core/node-commons/src/main/java/com/google/common/collect/Lists.java
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/collect/Lists.java
@@ -32,12 +32,10 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.NoSuchElementException;
 import java.util.RandomAccess;
-import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.function.Predicate;
 
 import static com.google.common.base.Preconditions.checkArgument;
@@ -165,96 +163,6 @@
   }
 
   /**
-   * Creates an {@code ArrayList} instance to hold {@code estimatedSize} elements, <i>plus</i> an
-   * unspecified amount of padding; you almost certainly mean to call {@link
-   * #newArrayListWithCapacity} (see that method for further advice on usage).
-   *
-   * <p><b>Note:</b> This method will soon be deprecated. Even in the rare case that you do want
-   * some amount of padding, it's best if you choose your desired amount explicitly.
-   *
-   * @param estimatedSize an estimate of the eventual {@link List#size()} of the new list
-   * @return a new, empty {@code ArrayList}, sized appropriately to hold the estimated number of
-   *     elements
-   * @throws IllegalArgumentException if {@code estimatedSize} is negative
-   */
-  public static <E extends Object> ArrayList<E> newArrayListWithExpectedSize(int estimatedSize) {
-    return new ArrayList<>(computeArrayListCapacity(estimatedSize));
-  }
-
-  // LinkedList
-
-  /**
-   * Creates a <i>mutable</i>, empty {@code LinkedList} instance (for Java 6 and earlier).
-   *
-   * <p><b>Note:</b> if you won't be adding any elements to the list, use {@link ImmutableList#of()}
-   * instead.
-   *
-   * <p><b>Performance note:</b> {@link ArrayList} and {@link java.util.ArrayDeque} consistently
-   * outperform {@code LinkedList} except in certain rare and specific situations. Unless you have
-   * spent a lot of time benchmarking your specific needs, use one of those instead.
-   *
-   * <p><b>Note:</b> this method is now unnecessary and should be treated as deprecated. Instead,
-   * use the {@code LinkedList} {@linkplain LinkedList#LinkedList() constructor} directly, taking
-   * advantage of <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
-   */
-  public static <E extends Object> LinkedList<E> newLinkedList() {
-    return new LinkedList<>();
-  }
-
-  /**
-   * Creates a <i>mutable</i> {@code LinkedList} instance containing the given elements; a very thin
-   * shortcut for creating an empty list then calling {@link Iterables#addAll}.
-   *
-   * <p><b>Note:</b> if mutability is not required and the elements are non-null, use {@link
-   * ImmutableList#copyOf(Iterable)} instead. (Or, change {@code elements} to be a {@link
-   * FluentIterable} and call {@code elements.toList()}.)
-   *
-   * <p><b>Performance note:</b> {@link ArrayList} and {@link java.util.ArrayDeque} consistently
-   * outperform {@code LinkedList} except in certain rare and specific situations. Unless you have
-   * spent a lot of time benchmarking your specific needs, use one of those instead.
-   *
-   * <p><b>Note:</b> if {@code elements} is a {@link Collection}, you don't need this method. Use
-   * the {@code LinkedList} {@linkplain LinkedList#LinkedList(Collection) constructor} directly,
-   * taking advantage of <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
-   */
-  public static <E extends Object> LinkedList<E> newLinkedList(Iterable<? extends E> elements) {
-    LinkedList<E> list = newLinkedList();
-    Iterables.addAll(list, elements);
-    return list;
-  }
-
-  /**
-   * Creates an empty {@code CopyOnWriteArrayList} instance.
-   *
-   * <p><b>Note:</b> if you need an immutable empty {@link List}, use {@link Collections#emptyList}
-   * instead.
-   *
-   * @return a new, empty {@code CopyOnWriteArrayList}
-   * @since 12.0
-   */
-  public static <E extends Object> CopyOnWriteArrayList<E> newCopyOnWriteArrayList() {
-    return new CopyOnWriteArrayList<>();
-  }
-
-  /**
-   * Creates a {@code CopyOnWriteArrayList} instance containing the given elements.
-   *
-   * @param elements the elements that the list should contain, in order
-   * @return a new {@code CopyOnWriteArrayList} containing those elements
-   * @since 12.0
-   */
-  public static <E extends Object> CopyOnWriteArrayList<E> newCopyOnWriteArrayList(
-      Iterable<? extends E> elements) {
-    // We copy elements to an ArrayList first, rather than incurring the
-    // quadratic cost of adding them to the COWAL directly.
-    Collection<? extends E> elementsCollection =
-        (elements instanceof Collection)
-            ? (Collection<? extends E>) elements
-            : newArrayList(elements);
-    return new CopyOnWriteArrayList<>(elementsCollection);
-  }
-
-  /**
    * Returns an unmodifiable list containing the specified first element and backed by the specified
    * array of additional elements. Changes to the {@code rest} array will be reflected in the
    * returned list. Unlike {@link Arrays#asList}, the returned list is unmodifiable.
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/collect/Maps.java b/iotdb-core/node-commons/src/main/java/com/google/common/collect/Maps.java
index 7b034e6..bb836bb 100644
--- a/iotdb-core/node-commons/src/main/java/com/google/common/collect/Maps.java
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/collect/Maps.java
@@ -34,7 +34,6 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.EnumMap;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.IdentityHashMap;
@@ -62,10 +61,8 @@
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Predicates.compose;
-import static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
 import static com.google.common.collect.CollectPreconditions.checkNonnegative;
 import static com.google.common.collect.NullnessCasts.uncheckedCastNullableTToT;
-import static java.util.Collections.singletonMap;
 import static java.util.Objects.requireNonNull;
 
 /**
@@ -133,65 +130,6 @@
   }
 
   /**
-   * Returns an immutable map instance containing the given entries. Internally, the returned map
-   * will be backed by an {@link EnumMap}.
-   *
-   * <p>The iteration order of the returned map follows the enum's iteration order, not the order in
-   * which the elements appear in the given map.
-   *
-   * @param map the map to make an immutable copy of
-   * @return an immutable map containing those entries
-   * @since 14.0
-   */
-  public static <K extends Enum<K>, V> ImmutableMap<K, V> immutableEnumMap(
-      Map<K, ? extends V> map) {
-    if (map instanceof ImmutableEnumMap) {
-      @SuppressWarnings("unchecked") // safe covariant cast
-      ImmutableEnumMap<K, V> result = (ImmutableEnumMap<K, V>) map;
-      return result;
-    }
-    Iterator<? extends Entry<K, ? extends V>> entryItr = map.entrySet().iterator();
-    if (!entryItr.hasNext()) {
-      return ImmutableMap.of();
-    }
-    Entry<K, ? extends V> entry1 = entryItr.next();
-    K key1 = entry1.getKey();
-    V value1 = entry1.getValue();
-    checkEntryNotNull(key1, value1);
-    // Do something that works for j2cl, where we can't call getDeclaredClass():
-    EnumMap<K, V> enumMap = new EnumMap<>(singletonMap(key1, value1));
-    while (entryItr.hasNext()) {
-      Entry<K, ? extends V> entry = entryItr.next();
-      K key = entry.getKey();
-      V value = entry.getValue();
-      checkEntryNotNull(key, value);
-      enumMap.put(key, value);
-    }
-    return ImmutableEnumMap.asImmutable(enumMap);
-  }
-
-  /**
-   * Returns a {@link Collector} that accumulates elements into an {@code ImmutableMap} whose keys
-   * and values are the result of applying the provided mapping functions to the input elements. The
-   * resulting implementation is specialized for enum key types. The returned map and its views will
-   * iterate over keys in their enum definition order, not encounter order.
-   *
-   * <p>If the mapped keys contain duplicates, an {@code IllegalArgumentException} is thrown when
-   * the collection operation is performed. (This differs from the {@code Collector} returned by
-   * {@link java.util.stream.Collectors#toMap(java.util.function.Function,
-   * java.util.function.Function) Collectors.toMap(Function, Function)}, which throws an {@code
-   * IllegalStateException}.)
-   *
-   * @since 21.0
-   */
-  public static <T extends Object, K extends Enum<K>, V>
-      Collector<T, ?, ImmutableMap<K, V>> toImmutableEnumMap(
-          java.util.function.Function<? super T, ? extends K> keyFunction,
-          java.util.function.Function<? super T, ? extends V> valueFunction) {
-    return CollectCollectors.toImmutableEnumMap(keyFunction, valueFunction);
-  }
-
-  /**
    * Returns a {@link Collector} that accumulates elements into an {@code ImmutableMap} whose keys
    * and values are the result of applying the provided mapping functions to the input elements. The
    * resulting implementation is specialized for enum key types. The returned map and its views will
@@ -228,25 +166,6 @@
   }
 
   /**
-   * Creates a <i>mutable</i> {@code HashMap} instance with the same mappings as the specified map.
-   *
-   * <p><b>Note:</b> if mutability is not required, use {@link ImmutableMap#copyOf(Map)} instead.
-   *
-   * <p><b>Note:</b> if {@code K} is an {@link Enum} type, use {@link #newEnumMap} instead.
-   *
-   * <p><b>Note:</b> this method is now unnecessary and should be treated as deprecated. Instead,
-   * use the {@code HashMap} constructor directly, taking advantage of <a
-   * href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
-   *
-   * @param map the mappings to be placed in the new map
-   * @return a new {@code HashMap} initialized with the mappings from {@code map}
-   */
-  public static <K extends Object, V extends Object> HashMap<K, V> newHashMap(
-      Map<? extends K, ? extends V> map) {
-    return new HashMap<>(map);
-  }
-
-  /**
    * Creates a {@code HashMap} instance, with a high enough "initial capacity" that it <i>should</i>
    * hold {@code expectedSize} elements without growth. This behavior cannot be broadly guaranteed,
    * but it is observed to be true for OpenJDK 1.7. It also can't be guaranteed that the method
@@ -305,24 +224,6 @@
   }
 
   /**
-   * Creates a <i>mutable</i>, insertion-ordered {@code LinkedHashMap} instance with the same
-   * mappings as the specified map.
-   *
-   * <p><b>Note:</b> if mutability is not required, use {@link ImmutableMap#copyOf(Map)} instead.
-   *
-   * <p><b>Note:</b> this method is now unnecessary and should be treated as deprecated. Instead,
-   * use the {@code LinkedHashMap} constructor directly, taking advantage of <a
-   * href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
-   *
-   * @param map the mappings to be placed in the new map
-   * @return a new, {@code LinkedHashMap} initialized with the mappings from {@code map}
-   */
-  public static <K extends Object, V extends Object> LinkedHashMap<K, V> newLinkedHashMap(
-      Map<? extends K, ? extends V> map) {
-    return new LinkedHashMap<>(map);
-  }
-
-  /**
    * Creates a {@code LinkedHashMap} instance, with a high enough "initial capacity" that it
    * <i>should</i> hold {@code expectedSize} elements without growth. This behavior cannot be
    * broadly guaranteed, but it is observed to be true for OpenJDK 1.7. It also can't be guaranteed
@@ -349,43 +250,6 @@
   }
 
   /**
-   * Creates a <i>mutable</i>, empty {@code TreeMap} instance using the natural ordering of its
-   * elements.
-   *
-   * <p><b>Note:</b> if mutability is not required, use {@link ImmutableSortedMap#of()} instead.
-   *
-   * <p><b>Note:</b> this method is now unnecessary and should be treated as deprecated. Instead,
-   * use the {@code TreeMap} constructor directly, taking advantage of <a
-   * href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
-   *
-   * @return a new, empty {@code TreeMap}
-   */
-  public static <K extends Comparable, V extends Object> TreeMap<K, V> newTreeMap() {
-    return new TreeMap<>();
-  }
-
-  /**
-   * Creates a <i>mutable</i> {@code TreeMap} instance with the same mappings as the specified map
-   * and using the same ordering as the specified map.
-   *
-   * <p><b>Note:</b> if mutability is not required, use {@link
-   * ImmutableSortedMap#copyOfSorted(SortedMap)} instead.
-   *
-   * <p><b>Note:</b> this method is now unnecessary and should be treated as deprecated. Instead,
-   * use the {@code TreeMap} constructor directly, taking advantage of <a
-   * href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
-   *
-   * @param map the sorted map whose mappings are to be placed in the new map and whose comparator
-   *     is to be used to sort the new map
-   * @return a new {@code TreeMap} initialized with the mappings from {@code map} and using the
-   *     comparator of {@code map}
-   */
-  public static <K extends Object, V extends Object> TreeMap<K, V> newTreeMap(
-      SortedMap<K, ? extends V> map) {
-    return new TreeMap<>(map);
-  }
-
-  /**
    * Creates a <i>mutable</i>, empty {@code TreeMap} instance using the given comparator.
    *
    * <p><b>Note:</b> if mutability is not required, use {@code
@@ -409,33 +273,6 @@
   }
 
   /**
-   * Creates an {@code EnumMap} instance.
-   *
-   * @param type the key type for this map
-   * @return a new, empty {@code EnumMap}
-   */
-  public static <K extends Enum<K>, V extends Object> EnumMap<K, V> newEnumMap(Class<K> type) {
-    return new EnumMap<>(checkNotNull(type));
-  }
-
-  /**
-   * Creates an {@code EnumMap} with the same mappings as the specified map.
-   *
-   * <p><b>Note:</b> this method is now unnecessary and should be treated as deprecated. Instead,
-   * use the {@code EnumMap} constructor directly, taking advantage of <a
-   * href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
-   *
-   * @param map the map from which to initialize this {@code EnumMap}
-   * @return a new {@code EnumMap} initialized with the mappings from {@code map}
-   * @throws IllegalArgumentException if {@code m} is not an {@code EnumMap} instance and contains
-   *     no mappings
-   */
-  public static <K extends Enum<K>, V extends Object> EnumMap<K, V> newEnumMap(
-      Map<K, ? extends V> map) {
-    return new EnumMap<>(map);
-  }
-
-  /**
    * Creates an {@code IdentityHashMap} instance.
    *
    * <p><b>Note:</b> this method is now unnecessary and should be treated as deprecated. Instead,
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/collect/MoreCollectors.java b/iotdb-core/node-commons/src/main/java/com/google/common/collect/MoreCollectors.java
new file mode 100644
index 0000000..6a78296
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/collect/MoreCollectors.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2016 The Guava Authors
+ *
+ * Licensed 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 com.google.common.collect;
+
+import javax.annotation.CheckForNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Optional;
+import java.util.stream.Collector;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.Collections.emptyList;
+
+/**
+ * Collectors not present in {@code java.util.stream.Collectors} that are not otherwise associated
+ * with a {@code com.google.common} type.
+ *
+ * @author Louis Wasserman
+ * @since 21.0
+ */
+public final class MoreCollectors {
+
+  /*
+   * TODO(lowasser): figure out if we can convert this to a concurrent AtomicReference-based
+   * collector without breaking j2cl?
+   */
+  private static final Collector<Object, ?, Optional<Object>> TO_OPTIONAL =
+      Collector.of(
+          ToOptionalState::new,
+          ToOptionalState::add,
+          ToOptionalState::combine,
+          ToOptionalState::getOptional,
+          Collector.Characteristics.UNORDERED);
+
+  /**
+   * A collector that converts a stream of zero or one elements to an {@code Optional}.
+   *
+   * @throws IllegalArgumentException if the stream consists of two or more elements.
+   * @throws NullPointerException if any element in the stream is {@code null}.
+   * @return {@code Optional.of(onlyElement)} if the stream has exactly one element (must not be
+   *     {@code null}) and returns {@code Optional.empty()} if it has none.
+   */
+  @SuppressWarnings("unchecked")
+  public static <T> Collector<T, ?, Optional<T>> toOptional() {
+    return (Collector) TO_OPTIONAL;
+  }
+
+  private static final Object NULL_PLACEHOLDER = new Object();
+
+  private static final Collector<Object, ?, Object> ONLY_ELEMENT =
+      Collector.<Object, ToOptionalState, Object>of(
+          ToOptionalState::new,
+          (state, o) -> state.add((o == null) ? NULL_PLACEHOLDER : o),
+          ToOptionalState::combine,
+          state -> {
+            Object result = state.getElement();
+            return (result == NULL_PLACEHOLDER) ? null : result;
+          },
+          Collector.Characteristics.UNORDERED);
+
+  /**
+   * A collector that takes a stream containing exactly one element and returns that element. The
+   * returned collector throws an {@code IllegalArgumentException} if the stream consists of two or
+   * more elements, and a {@code NoSuchElementException} if the stream is empty.
+   */
+  @SuppressWarnings("unchecked")
+  public static <T extends Object> Collector<T, ?, T> onlyElement() {
+    return (Collector) ONLY_ELEMENT;
+  }
+
+  /**
+   * This atrocity is here to let us report several of the elements in the stream if there were more
+   * than one, not just two.
+   */
+  private static final class ToOptionalState {
+    static final int MAX_EXTRAS = 4;
+
+    @CheckForNull Object element;
+    List<Object> extras;
+
+    ToOptionalState() {
+      element = null;
+      extras = emptyList();
+    }
+
+    IllegalArgumentException multiples(boolean overflow) {
+      StringBuilder sb =
+          new StringBuilder().append("expected one element but was: <").append(element);
+      for (Object o : extras) {
+        sb.append(", ").append(o);
+      }
+      if (overflow) {
+        sb.append(", ...");
+      }
+      sb.append('>');
+      throw new IllegalArgumentException(sb.toString());
+    }
+
+    void add(Object o) {
+      checkNotNull(o);
+      if (element == null) {
+        this.element = o;
+      } else if (extras.isEmpty()) {
+        // Replace immutable empty list with mutable list.
+        extras = new ArrayList<>(MAX_EXTRAS);
+        extras.add(o);
+      } else if (extras.size() < MAX_EXTRAS) {
+        extras.add(o);
+      } else {
+        throw multiples(true);
+      }
+    }
+
+    ToOptionalState combine(ToOptionalState other) {
+      if (element == null) {
+        return other;
+      } else if (other.element == null) {
+        return this;
+      } else {
+        if (extras.isEmpty()) {
+          // Replace immutable empty list with mutable list.
+          extras = new ArrayList<>();
+        }
+        extras.add(other.element);
+        extras.addAll(other.extras);
+        if (extras.size() > MAX_EXTRAS) {
+          extras.subList(MAX_EXTRAS, extras.size()).clear();
+          throw multiples(true);
+        }
+        return this;
+      }
+    }
+
+    Optional<Object> getOptional() {
+      if (extras.isEmpty()) {
+        return Optional.ofNullable(element);
+      } else {
+        throw multiples(false);
+      }
+    }
+
+    Object getElement() {
+      if (element == null) {
+        throw new NoSuchElementException();
+      } else if (extras.isEmpty()) {
+        return element;
+      } else {
+        throw multiples(false);
+      }
+    }
+  }
+
+  private MoreCollectors() {}
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/collect/Queues.java b/iotdb-core/node-commons/src/main/java/com/google/common/collect/Queues.java
index 384e42d..8f17611 100644
--- a/iotdb-core/node-commons/src/main/java/com/google/common/collect/Queues.java
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/collect/Queues.java
@@ -14,21 +14,11 @@
 
 package com.google.common.collect;
 
-import com.google.common.base.Preconditions;
-
 import java.util.ArrayDeque;
-import java.util.Collection;
 import java.util.Deque;
-import java.util.PriorityQueue;
 import java.util.Queue;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.LinkedBlockingDeque;
 import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.PriorityBlockingQueue;
-import java.util.concurrent.SynchronousQueue;
-import java.util.concurrent.TimeUnit;
 
 /**
  * Static utility methods pertaining to {@link Queue} and {@link Deque} instances. Also see this
@@ -40,16 +30,6 @@
 public final class Queues {
   private Queues() {}
 
-  // ArrayBlockingQueue
-
-  /**
-   * Creates an empty {@code ArrayBlockingQueue} with the given (fixed) capacity and nonfair access
-   * policy.
-   */
-  public static <E> ArrayBlockingQueue<E> newArrayBlockingQueue(int capacity) {
-    return new ArrayBlockingQueue<E>(capacity);
-  }
-
   // ArrayDeque
 
   /**
@@ -61,21 +41,6 @@
     return new ArrayDeque<E>();
   }
 
-  /**
-   * Creates an {@code ArrayDeque} containing the elements of the specified iterable, in the order
-   * they are returned by the iterable's iterator.
-   *
-   * @since 12.0
-   */
-  public static <E> ArrayDeque<E> newArrayDeque(Iterable<? extends E> elements) {
-    if (elements instanceof Collection) {
-      return new ArrayDeque<E>((Collection<? extends E>) elements);
-    }
-    ArrayDeque<E> deque = new ArrayDeque<E>();
-    Iterables.addAll(deque, elements);
-    return deque;
-  }
-
   // ConcurrentLinkedQueue
 
   /** Creates an empty {@code ConcurrentLinkedQueue}. */
@@ -83,365 +48,10 @@
     return new ConcurrentLinkedQueue<E>();
   }
 
-  /**
-   * Creates a {@code ConcurrentLinkedQueue} containing the elements of the specified iterable, in
-   * the order they are returned by the iterable's iterator.
-   */
-  public static <E> ConcurrentLinkedQueue<E> newConcurrentLinkedQueue(
-      Iterable<? extends E> elements) {
-    if (elements instanceof Collection) {
-      return new ConcurrentLinkedQueue<E>((Collection<? extends E>) elements);
-    }
-    ConcurrentLinkedQueue<E> queue = new ConcurrentLinkedQueue<E>();
-    Iterables.addAll(queue, elements);
-    return queue;
-  }
-
-  // LinkedBlockingDeque
-
-  /**
-   * Creates an empty {@code LinkedBlockingDeque} with a capacity of {@link Integer#MAX_VALUE}.
-   *
-   * @since 12.0
-   */
-  public static <E> LinkedBlockingDeque<E> newLinkedBlockingDeque() {
-    return new LinkedBlockingDeque<E>();
-  }
-
-  /**
-   * Creates an empty {@code LinkedBlockingDeque} with the given (fixed) capacity.
-   *
-   * @throws IllegalArgumentException if {@code capacity} is less than 1
-   * @since 12.0
-   */
-  public static <E> LinkedBlockingDeque<E> newLinkedBlockingDeque(int capacity) {
-    return new LinkedBlockingDeque<E>(capacity);
-  }
-
-  /**
-   * Creates a {@code LinkedBlockingDeque} with a capacity of {@link Integer#MAX_VALUE}, containing
-   * the elements of the specified iterable, in the order they are returned by the iterable's
-   * iterator.
-   *
-   * @since 12.0
-   */
-  public static <E> LinkedBlockingDeque<E> newLinkedBlockingDeque(Iterable<? extends E> elements) {
-    if (elements instanceof Collection) {
-      return new LinkedBlockingDeque<E>((Collection<? extends E>) elements);
-    }
-    LinkedBlockingDeque<E> deque = new LinkedBlockingDeque<E>();
-    Iterables.addAll(deque, elements);
-    return deque;
-  }
-
   // LinkedBlockingQueue
 
   /** Creates an empty {@code LinkedBlockingQueue} with a capacity of {@link Integer#MAX_VALUE}. */
   public static <E> LinkedBlockingQueue<E> newLinkedBlockingQueue() {
     return new LinkedBlockingQueue<E>();
   }
-
-  /**
-   * Creates an empty {@code LinkedBlockingQueue} with the given (fixed) capacity.
-   *
-   * @throws IllegalArgumentException if {@code capacity} is less than 1
-   */
-  public static <E> LinkedBlockingQueue<E> newLinkedBlockingQueue(int capacity) {
-    return new LinkedBlockingQueue<E>(capacity);
-  }
-
-  /**
-   * Creates a {@code LinkedBlockingQueue} with a capacity of {@link Integer#MAX_VALUE}, containing
-   * the elements of the specified iterable, in the order they are returned by the iterable's
-   * iterator.
-   *
-   * @param elements the elements that the queue should contain, in order
-   * @return a new {@code LinkedBlockingQueue} containing those elements
-   */
-  public static <E> LinkedBlockingQueue<E> newLinkedBlockingQueue(Iterable<? extends E> elements) {
-    if (elements instanceof Collection) {
-      return new LinkedBlockingQueue<E>((Collection<? extends E>) elements);
-    }
-    LinkedBlockingQueue<E> queue = new LinkedBlockingQueue<E>();
-    Iterables.addAll(queue, elements);
-    return queue;
-  }
-
-  // LinkedList: see {@link com.google.common.collect.Lists}
-
-  // PriorityBlockingQueue
-
-  /**
-   * Creates an empty {@code PriorityBlockingQueue} with the ordering given by its elements' natural
-   * ordering.
-   *
-   * @since 11.0 (but the bound of {@code E} was changed from {@code Object} to {@code Comparable}
-   *     in 15.0)
-   */
-  public static <E extends Comparable> PriorityBlockingQueue<E> newPriorityBlockingQueue() {
-    return new PriorityBlockingQueue<E>();
-  }
-
-  /**
-   * Creates a {@code PriorityBlockingQueue} containing the given elements.
-   *
-   * <p><b>Note:</b> If the specified iterable is a {@code SortedSet} or a {@code PriorityQueue},
-   * this priority queue will be ordered according to the same ordering.
-   *
-   * @since 11.0 (but the bound of {@code E} was changed from {@code Object} to {@code Comparable}
-   *     in 15.0)
-   */
-  public static <E extends Comparable> PriorityBlockingQueue<E> newPriorityBlockingQueue(
-      Iterable<? extends E> elements) {
-    if (elements instanceof Collection) {
-      return new PriorityBlockingQueue<E>((Collection<? extends E>) elements);
-    }
-    PriorityBlockingQueue<E> queue = new PriorityBlockingQueue<E>();
-    Iterables.addAll(queue, elements);
-    return queue;
-  }
-
-  // PriorityQueue
-
-  /**
-   * Creates an empty {@code PriorityQueue} with the ordering given by its elements' natural
-   * ordering.
-   *
-   * @since 11.0 (but the bound of {@code E} was changed from {@code Object} to {@code Comparable}
-   *     in 15.0)
-   */
-  public static <E extends Comparable> PriorityQueue<E> newPriorityQueue() {
-    return new PriorityQueue<E>();
-  }
-
-  /**
-   * Creates a {@code PriorityQueue} containing the given elements.
-   *
-   * <p><b>Note:</b> If the specified iterable is a {@code SortedSet} or a {@code PriorityQueue},
-   * this priority queue will be ordered according to the same ordering.
-   *
-   * @since 11.0 (but the bound of {@code E} was changed from {@code Object} to {@code Comparable}
-   *     in 15.0)
-   */
-  public static <E extends Comparable> PriorityQueue<E> newPriorityQueue(
-      Iterable<? extends E> elements) {
-    if (elements instanceof Collection) {
-      return new PriorityQueue<E>((Collection<? extends E>) elements);
-    }
-    PriorityQueue<E> queue = new PriorityQueue<E>();
-    Iterables.addAll(queue, elements);
-    return queue;
-  }
-
-  // SynchronousQueue
-
-  /** Creates an empty {@code SynchronousQueue} with nonfair access policy. */
-  public static <E> SynchronousQueue<E> newSynchronousQueue() {
-    return new SynchronousQueue<E>();
-  }
-
-  /**
-   * Drains the queue as {@link BlockingQueue#drainTo(Collection, int)}, but if the requested {@code
-   * numElements} elements are not available, it will wait for them up to the specified timeout.
-   *
-   * @param q the blocking queue to be drained
-   * @param buffer where to add the transferred elements
-   * @param numElements the number of elements to be waited for
-   * @param timeout how long to wait before giving up
-   * @return the number of elements transferred
-   * @throws InterruptedException if interrupted while waiting
-   * @since 28.0
-   */
-  public static <E> int drain(
-      BlockingQueue<E> q, Collection<? super E> buffer, int numElements, java.time.Duration timeout)
-      throws InterruptedException {
-    // TODO(b/126049426): Consider using saturateToNanos(timeout) instead.
-    return drain(q, buffer, numElements, timeout.toNanos(), TimeUnit.NANOSECONDS);
-  }
-
-  /**
-   * Drains the queue as {@link BlockingQueue#drainTo(Collection, int)}, but if the requested {@code
-   * numElements} elements are not available, it will wait for them up to the specified timeout.
-   *
-   * @param q the blocking queue to be drained
-   * @param buffer where to add the transferred elements
-   * @param numElements the number of elements to be waited for
-   * @param timeout how long to wait before giving up, in units of {@code unit}
-   * @param unit a {@code TimeUnit} determining how to interpret the timeout parameter
-   * @return the number of elements transferred
-   * @throws InterruptedException if interrupted while waiting
-   */
-  @SuppressWarnings("GoodTime") // should accept a java.time.Duration
-  public static <E> int drain(
-      BlockingQueue<E> q,
-      Collection<? super E> buffer,
-      int numElements,
-      long timeout,
-      TimeUnit unit)
-      throws InterruptedException {
-    Preconditions.checkNotNull(buffer);
-    /*
-     * This code performs one System.nanoTime() more than necessary, and in return, the time to
-     * execute Queue#drainTo is not added *on top* of waiting for the timeout (which could make
-     * the timeout arbitrarily inaccurate, given a queue that is slow to drain).
-     */
-    long deadline = System.nanoTime() + unit.toNanos(timeout);
-    int added = 0;
-    while (added < numElements) {
-      // we could rely solely on #poll, but #drainTo might be more efficient when there are multiple
-      // elements already available (e.g. LinkedBlockingQueue#drainTo locks only once)
-      added += q.drainTo(buffer, numElements - added);
-      if (added < numElements) { // not enough elements immediately available; will have to poll
-        E e = q.poll(deadline - System.nanoTime(), TimeUnit.NANOSECONDS);
-        if (e == null) {
-          break; // we already waited enough, and there are no more elements in sight
-        }
-        buffer.add(e);
-        added++;
-      }
-    }
-    return added;
-  }
-
-  /**
-   * Drains the queue as {@linkplain #drain(BlockingQueue, Collection, int, Duration)}, but with a
-   * different behavior in case it is interrupted while waiting. In that case, the operation will
-   * continue as usual, and in the end the thread's interruption status will be set (no {@code
-   * InterruptedException} is thrown).
-   *
-   * @param q the blocking queue to be drained
-   * @param buffer where to add the transferred elements
-   * @param numElements the number of elements to be waited for
-   * @param timeout how long to wait before giving up
-   * @return the number of elements transferred
-   * @since 28.0
-   */
-  public static <E> int drainUninterruptibly(
-      BlockingQueue<E> q,
-      Collection<? super E> buffer,
-      int numElements,
-      java.time.Duration timeout) {
-    // TODO(b/126049426): Consider using saturateToNanos(timeout) instead.
-    return drainUninterruptibly(q, buffer, numElements, timeout.toNanos(), TimeUnit.NANOSECONDS);
-  }
-
-  /**
-   * Drains the queue as {@linkplain #drain(BlockingQueue, Collection, int, long, TimeUnit)}, but
-   * with a different behavior in case it is interrupted while waiting. In that case, the operation
-   * will continue as usual, and in the end the thread's interruption status will be set (no {@code
-   * InterruptedException} is thrown).
-   *
-   * @param q the blocking queue to be drained
-   * @param buffer where to add the transferred elements
-   * @param numElements the number of elements to be waited for
-   * @param timeout how long to wait before giving up, in units of {@code unit}
-   * @param unit a {@code TimeUnit} determining how to interpret the timeout parameter
-   * @return the number of elements transferred
-   */
-  @SuppressWarnings("GoodTime") // should accept a java.time.Duration
-  public static <E> int drainUninterruptibly(
-      BlockingQueue<E> q,
-      Collection<? super E> buffer,
-      int numElements,
-      long timeout,
-      TimeUnit unit) {
-    Preconditions.checkNotNull(buffer);
-    long deadline = System.nanoTime() + unit.toNanos(timeout);
-    int added = 0;
-    boolean interrupted = false;
-    try {
-      while (added < numElements) {
-        // we could rely solely on #poll, but #drainTo might be more efficient when there are
-        // multiple elements already available (e.g. LinkedBlockingQueue#drainTo locks only once)
-        added += q.drainTo(buffer, numElements - added);
-        if (added < numElements) { // not enough elements immediately available; will have to poll
-          E e; // written exactly once, by a successful (uninterrupted) invocation of #poll
-          while (true) {
-            try {
-              e = q.poll(deadline - System.nanoTime(), TimeUnit.NANOSECONDS);
-              break;
-            } catch (InterruptedException ex) {
-              interrupted = true; // note interruption and retry
-            }
-          }
-          if (e == null) {
-            break; // we already waited enough, and there are no more elements in sight
-          }
-          buffer.add(e);
-          added++;
-        }
-      }
-    } finally {
-      if (interrupted) {
-        Thread.currentThread().interrupt();
-      }
-    }
-    return added;
-  }
-
-  /**
-   * Returns a synchronized (thread-safe) queue backed by the specified queue. In order to guarantee
-   * serial access, it is critical that <b>all</b> access to the backing queue is accomplished
-   * through the returned queue.
-   *
-   * <p>It is imperative that the user manually synchronize on the returned queue when accessing the
-   * queue's iterator:
-   *
-   * <pre>{@code
-   * Queue<E> queue = Queues.synchronizedQueue(MinMaxPriorityQueue.<E>create());
-   * ...
-   * queue.add(element);  // Needn't be in synchronized block
-   * ...
-   * synchronized (queue) {  // Must synchronize on queue!
-   *   Iterator<E> i = queue.iterator(); // Must be in synchronized block
-   *   while (i.hasNext()) {
-   *     foo(i.next());
-   *   }
-   * }
-   * }</pre>
-   *
-   * <p>Failure to follow this advice may result in non-deterministic behavior.
-   *
-   * <p>The returned queue will be serializable if the specified queue is serializable.
-   *
-   * @param queue the queue to be wrapped in a synchronized view
-   * @return a synchronized view of the specified queue
-   * @since 14.0
-   */
-  public static <E extends Object> Queue<E> synchronizedQueue(Queue<E> queue) {
-    return Synchronized.queue(queue, null);
-  }
-
-  /**
-   * Returns a synchronized (thread-safe) deque backed by the specified deque. In order to guarantee
-   * serial access, it is critical that <b>all</b> access to the backing deque is accomplished
-   * through the returned deque.
-   *
-   * <p>It is imperative that the user manually synchronize on the returned deque when accessing any
-   * of the deque's iterators:
-   *
-   * <pre>{@code
-   * Deque<E> deque = Queues.synchronizedDeque(Queues.<E>newArrayDeque());
-   * ...
-   * deque.add(element);  // Needn't be in synchronized block
-   * ...
-   * synchronized (deque) {  // Must synchronize on deque!
-   *   Iterator<E> i = deque.iterator(); // Must be in synchronized block
-   *   while (i.hasNext()) {
-   *     foo(i.next());
-   *   }
-   * }
-   * }</pre>
-   *
-   * <p>Failure to follow this advice may result in non-deterministic behavior.
-   *
-   * <p>The returned deque will be serializable if the specified deque is serializable.
-   *
-   * @param deque the deque to be wrapped in a synchronized view
-   * @return a synchronized view of the specified deque
-   * @since 15.0
-   */
-  public static <E extends Object> Deque<E> synchronizedDeque(Deque<E> deque) {
-    return Synchronized.deque(deque, null);
-  }
 }
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/collect/Sets.java b/iotdb-core/node-commons/src/main/java/com/google/common/collect/Sets.java
index 4678eed..894a46d 100644
--- a/iotdb-core/node-commons/src/main/java/com/google/common/collect/Sets.java
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/collect/Sets.java
@@ -42,9 +42,7 @@
 import java.util.SortedSet;
 import java.util.TreeSet;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArraySet;
 import java.util.function.Consumer;
-import java.util.stream.Collector;
 import java.util.stream.Stream;
 
 import static com.google.common.base.Preconditions.checkArgument;
@@ -82,79 +80,6 @@
     }
   }
 
-  /**
-   * Returns an immutable set instance containing the given enum elements. Internally, the returned
-   * set will be backed by an {@link EnumSet}.
-   *
-   * <p>The iteration order of the returned set follows the enum's iteration order, not the order in
-   * which the elements are provided to the method.
-   *
-   * @param anElement one of the elements the set should contain
-   * @param otherElements the rest of the elements the set should contain
-   * @return an immutable set containing those elements, minus duplicates
-   */
-  // http://code.google.com/p/google-web-toolkit/issues/detail?id=3028
-  public static <E extends Enum<E>> ImmutableSet<E> immutableEnumSet(
-      E anElement, E... otherElements) {
-    return ImmutableEnumSet.asImmutable(EnumSet.of(anElement, otherElements));
-  }
-
-  /**
-   * Returns an immutable set instance containing the given enum elements. Internally, the returned
-   * set will be backed by an {@link EnumSet}.
-   *
-   * <p>The iteration order of the returned set follows the enum's iteration order, not the order in
-   * which the elements appear in the given collection.
-   *
-   * @param elements the elements, all of the same {@code enum} type, that the set should contain
-   * @return an immutable set containing those elements, minus duplicates
-   */
-  // http://code.google.com/p/google-web-toolkit/issues/detail?id=3028
-  public static <E extends Enum<E>> ImmutableSet<E> immutableEnumSet(Iterable<E> elements) {
-    if (elements instanceof ImmutableEnumSet) {
-      return (ImmutableEnumSet<E>) elements;
-    } else if (elements instanceof Collection) {
-      Collection<E> collection = (Collection<E>) elements;
-      if (collection.isEmpty()) {
-        return ImmutableSet.of();
-      } else {
-        return ImmutableEnumSet.asImmutable(EnumSet.copyOf(collection));
-      }
-    } else {
-      Iterator<E> itr = elements.iterator();
-      if (itr.hasNext()) {
-        EnumSet<E> enumSet = EnumSet.of(itr.next());
-        Iterators.addAll(enumSet, itr);
-        return ImmutableEnumSet.asImmutable(enumSet);
-      } else {
-        return ImmutableSet.of();
-      }
-    }
-  }
-
-  /**
-   * Returns a {@code Collector} that accumulates the input elements into a new {@code ImmutableSet}
-   * with an implementation specialized for enums. Unlike {@link ImmutableSet#toImmutableSet}, the
-   * resulting set will iterate over elements in their enum definition order, not encounter order.
-   *
-   * @since 21.0
-   */
-  public static <E extends Enum<E>> Collector<E, ?, ImmutableSet<E>> toImmutableEnumSet() {
-    return CollectCollectors.toImmutableEnumSet();
-  }
-
-  /**
-   * Returns a new, <i>mutable</i> {@code EnumSet} instance containing the given elements in their
-   * natural order. This method behaves identically to {@link EnumSet#copyOf(Collection)}, but also
-   * accepts non-{@code Collection} iterables and empty iterables.
-   */
-  public static <E extends Enum<E>> EnumSet<E> newEnumSet(
-      Iterable<E> iterable, Class<E> elementType) {
-    EnumSet<E> set = EnumSet.noneOf(elementType);
-    Iterables.addAll(set, iterable);
-    return set;
-  }
-
   // HashSet
 
   /**
@@ -387,111 +312,6 @@
     return set;
   }
 
-  /**
-   * Creates a <i>mutable</i>, empty {@code TreeSet} instance with the given comparator.
-   *
-   * <p><b>Note:</b> if mutability is not required, use {@code
-   * ImmutableSortedSet.orderedBy(comparator).build()} instead.
-   *
-   * <p><b>Note:</b> this method is now unnecessary and should be treated as deprecated. Instead,
-   * use the {@code TreeSet} constructor directly, taking advantage of <a
-   * href="http://goo.gl/iz2Wi">"diamond" syntax</a>. One caveat to this is that the {@code TreeSet}
-   * constructor uses a null {@code Comparator} to mean "natural ordering," whereas this factory
-   * rejects null. Clean your code accordingly.
-   *
-   * @param comparator the comparator to use to sort the set
-   * @return a new, empty {@code TreeSet}
-   * @throws NullPointerException if {@code comparator} is null
-   */
-  public static <E extends Object> TreeSet<E> newTreeSet(Comparator<? super E> comparator) {
-    return new TreeSet<E>(checkNotNull(comparator));
-  }
-
-  /**
-   * Creates an empty {@code Set} that uses identity to determine equality. It compares object
-   * references, instead of calling {@code equals}, to determine whether a provided object matches
-   * an element in the set. For example, {@code contains} returns {@code false} when passed an
-   * object that equals a set member, but isn't the same instance. This behavior is similar to the
-   * way {@code IdentityHashMap} handles key lookups.
-   *
-   * @since 8.0
-   */
-  public static <E extends Object> Set<E> newIdentityHashSet() {
-    return Collections.newSetFromMap(Maps.<E, Boolean>newIdentityHashMap());
-  }
-
-  /**
-   * Creates an empty {@code CopyOnWriteArraySet} instance.
-   *
-   * <p><b>Note:</b> if you need an immutable empty {@link Set}, use {@link Collections#emptySet}
-   * instead.
-   *
-   * @return a new, empty {@code CopyOnWriteArraySet}
-   * @since 12.0
-   */
-  public static <E extends Object> CopyOnWriteArraySet<E> newCopyOnWriteArraySet() {
-    return new CopyOnWriteArraySet<E>();
-  }
-
-  /**
-   * Creates a {@code CopyOnWriteArraySet} instance containing the given elements.
-   *
-   * @param elements the elements that the set should contain, in order
-   * @return a new {@code CopyOnWriteArraySet} containing those elements
-   * @since 12.0
-   */
-  public static <E extends Object> CopyOnWriteArraySet<E> newCopyOnWriteArraySet(
-      Iterable<? extends E> elements) {
-    // We copy elements to an ArrayList first, rather than incurring the
-    // quadratic cost of adding them to the COWAS directly.
-    Collection<? extends E> elementsCollection =
-        (elements instanceof Collection)
-            ? (Collection<? extends E>) elements
-            : Lists.newArrayList(elements);
-    return new CopyOnWriteArraySet<E>(elementsCollection);
-  }
-
-  /**
-   * Creates an {@code EnumSet} consisting of all enum values that are not in the specified
-   * collection. If the collection is an {@link EnumSet}, this method has the same behavior as
-   * {@link EnumSet#complementOf}. Otherwise, the specified collection must contain at least one
-   * element, in order to determine the element type. If the collection could be empty, use {@link
-   * #complementOf(Collection, Class)} instead of this method.
-   *
-   * @param collection the collection whose complement should be stored in the enum set
-   * @return a new, modifiable {@code EnumSet} containing all values of the enum that aren't present
-   *     in the given collection
-   * @throws IllegalArgumentException if {@code collection} is not an {@code EnumSet} instance and
-   *     contains no elements
-   */
-  public static <E extends Enum<E>> EnumSet<E> complementOf(Collection<E> collection) {
-    if (collection instanceof EnumSet) {
-      return EnumSet.complementOf((EnumSet<E>) collection);
-    }
-    checkArgument(
-        !collection.isEmpty(), "collection is empty; use the other version of this method");
-    Class<E> type = collection.iterator().next().getDeclaringClass();
-    return makeComplementByHand(collection, type);
-  }
-
-  /**
-   * Creates an {@code EnumSet} consisting of all enum values that are not in the specified
-   * collection. This is equivalent to {@link EnumSet#complementOf}, but can act on any input
-   * collection, as long as the elements are of enum type.
-   *
-   * @param collection the collection whose complement should be stored in the {@code EnumSet}
-   * @param type the type of the elements in the set
-   * @return a new, modifiable {@code EnumSet} initially containing all the values of the enum not
-   *     present in the given collection
-   */
-  public static <E extends Enum<E>> EnumSet<E> complementOf(
-      Collection<E> collection, Class<E> type) {
-    checkNotNull(collection);
-    return (collection instanceof EnumSet)
-        ? EnumSet.complementOf((EnumSet<E>) collection)
-        : makeComplementByHand(collection, type);
-  }
-
   private static <E extends Enum<E>> EnumSet<E> makeComplementByHand(
       Collection<E> collection, Class<E> type) {
     EnumSet<E> result = EnumSet.allOf(type);
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/graph/BaseGraph.java b/iotdb-core/node-commons/src/main/java/com/google/common/graph/BaseGraph.java
new file mode 100644
index 0000000..1df5de7
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/graph/BaseGraph.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2017 The Guava Authors
+ *
+ * Licensed 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 com.google.common.graph;
+
+import java.util.Set;
+
+/**
+ * A non-public interface for the methods shared between {@link Graph} and {@link ValueGraph}.
+ *
+ * @author James Sexton
+ * @param <N> Node parameter type
+ */
+interface BaseGraph<N> extends SuccessorsFunction<N>, PredecessorsFunction<N> {
+  //
+  // Graph-level accessors
+  //
+
+  /** Returns all nodes in this graph, in the order specified by {@link #nodeOrder()}. */
+  Set<N> nodes();
+
+  /** Returns all edges in this graph. */
+  Set<EndpointPair<N>> edges();
+
+  //
+  // Graph properties
+  //
+
+  /**
+   * Returns true if the edges in this graph are directed. Directed edges connect a {@link
+   * EndpointPair#source() source node} to a {@link EndpointPair#target() target node}, while
+   * undirected edges connect a pair of nodes to each other.
+   */
+  boolean isDirected();
+
+  /**
+   * Returns true if this graph allows self-loops (edges that connect a node to itself). Attempting
+   * to add a self-loop to a graph that does not allow them will throw an {@link
+   * IllegalArgumentException}.
+   */
+  boolean allowsSelfLoops();
+
+  /** Returns the order of iteration for the elements of {@link #nodes()}. */
+  ElementOrder<N> nodeOrder();
+
+  /**
+   * Returns an {@link ElementOrder} that specifies the order of iteration for the elements of
+   * {@link #edges()}, {@link #adjacentNodes(Object)}, {@link #predecessors(Object)}, {@link
+   * #successors(Object)} and {@link #incidentEdges(Object)}.
+   *
+   * @since 29.0
+   */
+  ElementOrder<N> incidentEdgeOrder();
+
+  //
+  // Element-level accessors
+  //
+
+  /**
+   * Returns the nodes which have an incident edge in common with {@code node} in this graph.
+   *
+   * <p>This is equal to the union of {@link #predecessors(Object)} and {@link #successors(Object)}.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this graph
+   */
+  Set<N> adjacentNodes(N node);
+
+  /**
+   * Returns all nodes in this graph adjacent to {@code node} which can be reached by traversing
+   * {@code node}'s incoming edges <i>against</i> the direction (if any) of the edge.
+   *
+   * <p>In an undirected graph, this is equivalent to {@link #adjacentNodes(Object)}.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this graph
+   */
+  @Override
+  Set<N> predecessors(N node);
+
+  /**
+   * Returns all nodes in this graph adjacent to {@code node} which can be reached by traversing
+   * {@code node}'s outgoing edges in the direction (if any) of the edge.
+   *
+   * <p>In an undirected graph, this is equivalent to {@link #adjacentNodes(Object)}.
+   *
+   * <p>This is <i>not</i> the same as "all nodes reachable from {@code node} by following outgoing
+   * edges". For that functionality, see {@link Graphs#reachableNodes(Graph, Object)}.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this graph
+   */
+  @Override
+  Set<N> successors(N node);
+
+  /**
+   * Returns the edges in this graph whose endpoints include {@code node}.
+   *
+   * <p>This is equal to the union of incoming and outgoing edges.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this graph
+   * @since 24.0
+   */
+  Set<EndpointPair<N>> incidentEdges(N node);
+
+  /**
+   * Returns the count of {@code node}'s incident edges, counting self-loops twice (equivalently,
+   * the number of times an edge touches {@code node}).
+   *
+   * <p>For directed graphs, this is equal to {@code inDegree(node) + outDegree(node)}.
+   *
+   * <p>For undirected graphs, this is equal to {@code incidentEdges(node).size()} + (number of
+   * self-loops incident to {@code node}).
+   *
+   * <p>If the count is greater than {@code Integer.MAX_VALUE}, returns {@code Integer.MAX_VALUE}.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this graph
+   */
+  int degree(N node);
+
+  /**
+   * Returns the count of {@code node}'s incoming edges (equal to {@code predecessors(node).size()})
+   * in a directed graph. In an undirected graph, returns the {@link #degree(Object)}.
+   *
+   * <p>If the count is greater than {@code Integer.MAX_VALUE}, returns {@code Integer.MAX_VALUE}.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this graph
+   */
+  int inDegree(N node);
+
+  /**
+   * Returns the count of {@code node}'s outgoing edges (equal to {@code successors(node).size()})
+   * in a directed graph. In an undirected graph, returns the {@link #degree(Object)}.
+   *
+   * <p>If the count is greater than {@code Integer.MAX_VALUE}, returns {@code Integer.MAX_VALUE}.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this graph
+   */
+  int outDegree(N node);
+
+  /**
+   * Returns true if there is an edge that directly connects {@code nodeU} to {@code nodeV}. This is
+   * equivalent to {@code nodes().contains(nodeU) && successors(nodeU).contains(nodeV)}.
+   *
+   * <p>In an undirected graph, this is equal to {@code hasEdgeConnecting(nodeV, nodeU)}.
+   *
+   * @since 23.0
+   */
+  boolean hasEdgeConnecting(N nodeU, N nodeV);
+
+  /**
+   * Returns true if there is an edge that directly connects {@code endpoints} (in the order, if
+   * any, specified by {@code endpoints}). This is equivalent to {@code
+   * edges().contains(endpoints)}.
+   *
+   * <p>Unlike the other {@code EndpointPair}-accepting methods, this method does not throw if the
+   * endpoints are unordered; it simply returns false. This is for consistency with the behavior of
+   * {@link Collection#contains(Object)} (which does not generally throw if the object cannot be
+   * present in the collection), and the desire to have this method's behavior be compatible with
+   * {@code edges().contains(endpoints)}.
+   *
+   * @since 27.1
+   */
+  boolean hasEdgeConnecting(EndpointPair<N> endpoints);
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/graph/ElementOrder.java b/iotdb-core/node-commons/src/main/java/com/google/common/graph/ElementOrder.java
new file mode 100644
index 0000000..370b060
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/graph/ElementOrder.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2016 The Guava Authors
+ *
+ * Licensed 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 com.google.common.graph;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.MoreObjects.ToStringHelper;
+import com.google.common.base.Objects;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Ordering;
+
+import javax.annotation.CheckForNull;
+
+import java.util.Comparator;
+import java.util.Map;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * Used to represent the order of elements in a data structure that supports different options for
+ * iteration order guarantees.
+ *
+ * <p>Example usage:
+ *
+ * <pre>{@code
+ * MutableGraph<Integer> graph =
+ *     GraphBuilder.directed().nodeOrder(ElementOrder.<Integer>natural()).build();
+ * }</pre>
+ *
+ * @author Joshua O'Madadhain
+ * @since 20.0
+ */
+public final class ElementOrder<T> {
+  private final Type type;
+
+  @SuppressWarnings("Immutable") // Hopefully the comparator provided is immutable!
+  @CheckForNull
+  private final Comparator<T> comparator;
+
+  /**
+   * The type of ordering that this object specifies.
+   *
+   * <ul>
+   *   <li>UNORDERED: no order is guaranteed.
+   *   <li>STABLE: ordering is guaranteed to follow a pattern that won't change between releases.
+   *       Some methods may have stronger guarantees.
+   *   <li>INSERTION: insertion ordering is guaranteed.
+   *   <li>SORTED: ordering according to a supplied comparator is guaranteed.
+   * </ul>
+   */
+  public enum Type {
+    UNORDERED,
+    STABLE,
+    INSERTION,
+    SORTED
+  }
+
+  private ElementOrder(Type type, @CheckForNull Comparator<T> comparator) {
+    this.type = checkNotNull(type);
+    this.comparator = comparator;
+    checkState((type == Type.SORTED) == (comparator != null));
+  }
+
+  /** Returns an instance which specifies that no ordering is guaranteed. */
+  public static <S> ElementOrder<S> unordered() {
+    return new ElementOrder<>(Type.UNORDERED, null);
+  }
+
+  /**
+   * Returns an instance which specifies that ordering is guaranteed to be always be the same across
+   * iterations, and across releases. Some methods may have stronger guarantees.
+   *
+   * <p>This instance is only useful in combination with {@code incidentEdgeOrder}, e.g. {@code
+   * graphBuilder.incidentEdgeOrder(ElementOrder.stable())}.
+   *
+   * <h3>In combination with {@code incidentEdgeOrder}</h3>
+   *
+   * <p>{@code incidentEdgeOrder(ElementOrder.stable())} guarantees the ordering of the returned
+   * collections of the following methods:
+   *
+   * <ul>
+   *   <li>For {@link Graph} and {@link ValueGraph}:
+   *       <ul>
+   *         <li>{@code edges()}: Stable order
+   *         <li>{@code adjacentNodes(node)}: Connecting edge insertion order
+   *         <li>{@code predecessors(node)}: Connecting edge insertion order
+   *         <li>{@code successors(node)}: Connecting edge insertion order
+   *         <li>{@code incidentEdges(node)}: Edge insertion order
+   *       </ul>
+   *   <li>For {@link Network}:
+   *       <ul>
+   *         <li>{@code adjacentNodes(node)}: Stable order
+   *         <li>{@code predecessors(node)}: Connecting edge insertion order
+   *         <li>{@code successors(node)}: Connecting edge insertion order
+   *         <li>{@code incidentEdges(node)}: Stable order
+   *         <li>{@code inEdges(node)}: Edge insertion order
+   *         <li>{@code outEdges(node)}: Edge insertion order
+   *         <li>{@code adjacentEdges(edge)}: Stable order
+   *         <li>{@code edgesConnecting(nodeU, nodeV)}: Edge insertion order
+   *       </ul>
+   * </ul>
+   *
+   * @since 29.0
+   */
+  public static <S> ElementOrder<S> stable() {
+    return new ElementOrder<>(Type.STABLE, null);
+  }
+
+  /** Returns an instance which specifies that insertion ordering is guaranteed. */
+  public static <S> ElementOrder<S> insertion() {
+    return new ElementOrder<>(Type.INSERTION, null);
+  }
+
+  /**
+   * Returns an instance which specifies that the natural ordering of the elements is guaranteed.
+   */
+  public static <S extends Comparable<? super S>> ElementOrder<S> natural() {
+    return new ElementOrder<>(Type.SORTED, Ordering.<S>natural());
+  }
+
+  /**
+   * Returns an instance which specifies that the ordering of the elements is guaranteed to be
+   * determined by {@code comparator}.
+   */
+  public static <S> ElementOrder<S> sorted(Comparator<S> comparator) {
+    return new ElementOrder<>(Type.SORTED, checkNotNull(comparator));
+  }
+
+  /** Returns the type of ordering used. */
+  public Type type() {
+    return type;
+  }
+
+  /**
+   * Returns the {@link Comparator} used.
+   *
+   * @throws UnsupportedOperationException if comparator is not defined
+   */
+  public Comparator<T> comparator() {
+    if (comparator != null) {
+      return comparator;
+    }
+    throw new UnsupportedOperationException("This ordering does not define a comparator.");
+  }
+
+  @Override
+  public boolean equals(@CheckForNull Object obj) {
+    if (obj == this) {
+      return true;
+    }
+    if (!(obj instanceof ElementOrder)) {
+      return false;
+    }
+
+    ElementOrder<?> other = (ElementOrder<?>) obj;
+    return (type == other.type) && Objects.equal(comparator, other.comparator);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(type, comparator);
+  }
+
+  @Override
+  public String toString() {
+    ToStringHelper helper = MoreObjects.toStringHelper(this).add("type", type);
+    if (comparator != null) {
+      helper.add("comparator", comparator);
+    }
+    return helper.toString();
+  }
+
+  /** Returns an empty mutable map whose keys will respect this {@link ElementOrder}. */
+  <K extends T, V> Map<K, V> createMap(int expectedSize) {
+    switch (type) {
+      case UNORDERED:
+        return Maps.newHashMapWithExpectedSize(expectedSize);
+      case INSERTION:
+      case STABLE:
+        return Maps.newLinkedHashMapWithExpectedSize(expectedSize);
+      case SORTED:
+        return Maps.newTreeMap(comparator());
+      default:
+        throw new AssertionError();
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  <T1 extends T> ElementOrder<T1> cast() {
+    return (ElementOrder<T1>) this;
+  }
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/graph/EndpointPair.java b/iotdb-core/node-commons/src/main/java/com/google/common/graph/EndpointPair.java
new file mode 100644
index 0000000..04543be
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/graph/EndpointPair.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2016 The Guava Authors
+ *
+ * Licensed 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 com.google.common.graph;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.UnmodifiableIterator;
+
+import javax.annotation.CheckForNull;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.graph.GraphConstants.NOT_AVAILABLE_ON_UNDIRECTED;
+
+/**
+ * An immutable pair representing the two endpoints of an edge in a graph. The {@link EndpointPair}
+ * of a directed edge is an ordered pair of nodes ({@link #source()} and {@link #target()}). The
+ * {@link EndpointPair} of an undirected edge is an unordered pair of nodes ({@link #nodeU()} and
+ * {@link #nodeV()}).
+ *
+ * <p>The edge is a self-loop if, and only if, the two endpoints are equal.
+ *
+ * @author James Sexton
+ * @since 20.0
+ */
+public abstract class EndpointPair<N> implements Iterable<N> {
+  private final N nodeU;
+  private final N nodeV;
+
+  private EndpointPair(N nodeU, N nodeV) {
+    this.nodeU = checkNotNull(nodeU);
+    this.nodeV = checkNotNull(nodeV);
+  }
+
+  /** Returns an {@link EndpointPair} representing the endpoints of a directed edge. */
+  public static <N> EndpointPair<N> ordered(N source, N target) {
+    return new Ordered<>(source, target);
+  }
+
+  /** Returns an {@link EndpointPair} representing the endpoints of an undirected edge. */
+  public static <N> EndpointPair<N> unordered(N nodeU, N nodeV) {
+    // Swap nodes on purpose to prevent callers from relying on the "ordering" of an unordered pair.
+    return new Unordered<>(nodeV, nodeU);
+  }
+
+  /** Returns an {@link EndpointPair} representing the endpoints of an edge in {@code graph}. */
+  static <N> EndpointPair<N> of(Graph<?> graph, N nodeU, N nodeV) {
+    return graph.isDirected() ? ordered(nodeU, nodeV) : unordered(nodeU, nodeV);
+  }
+
+  /** Returns an {@link EndpointPair} representing the endpoints of an edge in {@code network}. */
+  static <N> EndpointPair<N> of(Network<?, ?> network, N nodeU, N nodeV) {
+    return network.isDirected() ? ordered(nodeU, nodeV) : unordered(nodeU, nodeV);
+  }
+
+  /**
+   * If this {@link EndpointPair} {@link #isOrdered()}, returns the node which is the source.
+   *
+   * @throws UnsupportedOperationException if this {@link EndpointPair} is not ordered
+   */
+  public abstract N source();
+
+  /**
+   * If this {@link EndpointPair} {@link #isOrdered()}, returns the node which is the target.
+   *
+   * @throws UnsupportedOperationException if this {@link EndpointPair} is not ordered
+   */
+  public abstract N target();
+
+  /**
+   * If this {@link EndpointPair} {@link #isOrdered()} returns the {@link #source()}; otherwise,
+   * returns an arbitrary (but consistent) endpoint of the origin edge.
+   */
+  public final N nodeU() {
+    return nodeU;
+  }
+
+  /**
+   * Returns the node {@link #adjacentNode(Object) adjacent} to {@link #nodeU()} along the origin
+   * edge. If this {@link EndpointPair} {@link #isOrdered()}, this is equal to {@link #target()}.
+   */
+  public final N nodeV() {
+    return nodeV;
+  }
+
+  /**
+   * Returns the node that is adjacent to {@code node} along the origin edge.
+   *
+   * @throws IllegalArgumentException if this {@link EndpointPair} does not contain {@code node}
+   * @since 20.0 (but the argument type was changed from {@code Object} to {@code N} in 31.0)
+   */
+  public final N adjacentNode(N node) {
+    if (node.equals(nodeU)) {
+      return nodeV;
+    } else if (node.equals(nodeV)) {
+      return nodeU;
+    } else {
+      throw new IllegalArgumentException("EndpointPair " + this + " does not contain node " + node);
+    }
+  }
+
+  /**
+   * Returns {@code true} if this {@link EndpointPair} is an ordered pair (i.e. represents the
+   * endpoints of a directed edge).
+   */
+  public abstract boolean isOrdered();
+
+  /** Iterates in the order {@link #nodeU()}, {@link #nodeV()}. */
+  @Override
+  public final UnmodifiableIterator<N> iterator() {
+    return Iterators.forArray(nodeU, nodeV);
+  }
+
+  /**
+   * Two ordered {@link EndpointPair}s are equal if their {@link #source()} and {@link #target()}
+   * are equal. Two unordered {@link EndpointPair}s are equal if they contain the same nodes. An
+   * ordered {@link EndpointPair} is never equal to an unordered {@link EndpointPair}.
+   */
+  @Override
+  public abstract boolean equals(@CheckForNull Object obj);
+
+  /**
+   * The hashcode of an ordered {@link EndpointPair} is equal to {@code Objects.hashCode(source(),
+   * target())}. The hashcode of an unordered {@link EndpointPair} is equal to {@code
+   * nodeU().hashCode() + nodeV().hashCode()}.
+   */
+  @Override
+  public abstract int hashCode();
+
+  private static final class Ordered<N> extends EndpointPair<N> {
+    private Ordered(N source, N target) {
+      super(source, target);
+    }
+
+    @Override
+    public N source() {
+      return nodeU();
+    }
+
+    @Override
+    public N target() {
+      return nodeV();
+    }
+
+    @Override
+    public boolean isOrdered() {
+      return true;
+    }
+
+    @Override
+    public boolean equals(@CheckForNull Object obj) {
+      if (obj == this) {
+        return true;
+      }
+      if (!(obj instanceof EndpointPair)) {
+        return false;
+      }
+
+      EndpointPair<?> other = (EndpointPair<?>) obj;
+      if (isOrdered() != other.isOrdered()) {
+        return false;
+      }
+
+      return source().equals(other.source()) && target().equals(other.target());
+    }
+
+    @Override
+    public int hashCode() {
+      return Objects.hashCode(source(), target());
+    }
+
+    @Override
+    public String toString() {
+      return "<" + source() + " -> " + target() + ">";
+    }
+  }
+
+  private static final class Unordered<N> extends EndpointPair<N> {
+    private Unordered(N nodeU, N nodeV) {
+      super(nodeU, nodeV);
+    }
+
+    @Override
+    public N source() {
+      throw new UnsupportedOperationException(NOT_AVAILABLE_ON_UNDIRECTED);
+    }
+
+    @Override
+    public N target() {
+      throw new UnsupportedOperationException(NOT_AVAILABLE_ON_UNDIRECTED);
+    }
+
+    @Override
+    public boolean isOrdered() {
+      return false;
+    }
+
+    @Override
+    public boolean equals(@CheckForNull Object obj) {
+      if (obj == this) {
+        return true;
+      }
+      if (!(obj instanceof EndpointPair)) {
+        return false;
+      }
+
+      EndpointPair<?> other = (EndpointPair<?>) obj;
+      if (isOrdered() != other.isOrdered()) {
+        return false;
+      }
+
+      // Equivalent to the following simple implementation:
+      // boolean condition1 = nodeU().equals(other.nodeU()) && nodeV().equals(other.nodeV());
+      // boolean condition2 = nodeU().equals(other.nodeV()) && nodeV().equals(other.nodeU());
+      // return condition1 || condition2;
+      if (nodeU().equals(other.nodeU())) { // check condition1
+        // Here's the tricky bit. We don't have to explicitly check for condition2 in this case.
+        // Why? The second half of condition2 requires that nodeV equals other.nodeU.
+        // We already know that nodeU equals other.nodeU. Combined with the earlier statement,
+        // and the transitive property of equality, this implies that nodeU equals nodeV.
+        // If nodeU equals nodeV, condition1 == condition2, so checking condition1 is sufficient.
+        return nodeV().equals(other.nodeV());
+      }
+      return nodeU().equals(other.nodeV()) && nodeV().equals(other.nodeU()); // check condition2
+    }
+
+    @Override
+    public int hashCode() {
+      return nodeU().hashCode() + nodeV().hashCode();
+    }
+
+    @Override
+    public String toString() {
+      return "[" + nodeU() + ", " + nodeV() + "]";
+    }
+  }
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/graph/Graph.java b/iotdb-core/node-commons/src/main/java/com/google/common/graph/Graph.java
new file mode 100644
index 0000000..50b32e3
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/graph/Graph.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2014 The Guava Authors
+ *
+ * Licensed 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 com.google.common.graph;
+
+import javax.annotation.CheckForNull;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * An interface for <a
+ * href="https://en.wikipedia.org/wiki/Graph_(discrete_mathematics)">graph</a>-structured data,
+ * whose edges are anonymous entities with no identity or information of their own.
+ *
+ * <p>A graph is composed of a set of nodes and a set of edges connecting pairs of nodes.
+ *
+ * <p>There are three primary interfaces provided to represent graphs. In order of increasing
+ * complexity they are: {@link Graph}, {@link ValueGraph}, and {@link Network}. You should generally
+ * prefer the simplest interface that satisfies your use case. See the <a
+ * href="https://github.com/google/guava/wiki/GraphsExplained#choosing-the-right-graph-type">
+ * "Choosing the right graph type"</a> section of the Guava User Guide for more details.
+ *
+ * <h3>Capabilities</h3>
+ *
+ * <p>{@code Graph} supports the following use cases (<a
+ * href="https://github.com/google/guava/wiki/GraphsExplained#definitions">definitions of
+ * terms</a>):
+ *
+ * <ul>
+ *   <li>directed graphs
+ *   <li>undirected graphs
+ *   <li>graphs that do/don't allow self-loops
+ *   <li>graphs whose nodes/edges are insertion-ordered, sorted, or unordered
+ * </ul>
+ *
+ * <p>{@code Graph} explicitly does not support parallel edges, and forbids implementations or
+ * extensions with parallel edges. If you need parallel edges, use {@link Network}.
+ *
+ * <h3>Building a {@code Graph}</h3>
+ *
+ * <p>The implementation classes that {@code common.graph} provides are not public, by design. To
+ * create an instance of one of the built-in implementations of {@code Graph}, use the {@link
+ * GraphBuilder} class:
+ *
+ * <pre>{@code
+ * MutableGraph<Integer> graph = GraphBuilder.undirected().build();
+ * }</pre>
+ *
+ * <p>{@link GraphBuilder#build()} returns an instance of {@link MutableGraph}, which is a subtype
+ * of {@code Graph} that provides methods for adding and removing nodes and edges. If you do not
+ * need to mutate a graph (e.g. if you write a method than runs a read-only algorithm on the graph),
+ * you should use the non-mutating {@link Graph} interface, or an {@link ImmutableGraph}.
+ *
+ * <p>You can create an immutable copy of an existing {@code Graph} using {@link
+ * ImmutableGraph#copyOf(Graph)}:
+ *
+ * <pre>{@code
+ * ImmutableGraph<Integer> immutableGraph = ImmutableGraph.copyOf(graph);
+ * }</pre>
+ *
+ * <p>Instances of {@link ImmutableGraph} do not implement {@link MutableGraph} (obviously!) and are
+ * contractually guaranteed to be unmodifiable and thread-safe.
+ *
+ * <p>The Guava User Guide has <a
+ * href="https://github.com/google/guava/wiki/GraphsExplained#building-graph-instances">more
+ * information on (and examples of) building graphs</a>.
+ *
+ * <h3>Additional documentation</h3>
+ *
+ * <p>See the Guava User Guide for the {@code common.graph} package (<a
+ * href="https://github.com/google/guava/wiki/GraphsExplained">"Graphs Explained"</a>) for
+ * additional documentation, including:
+ *
+ * <ul>
+ *   <li><a
+ *       href="https://github.com/google/guava/wiki/GraphsExplained#equals-hashcode-and-graph-equivalence">
+ *       {@code equals()}, {@code hashCode()}, and graph equivalence</a>
+ *   <li><a href="https://github.com/google/guava/wiki/GraphsExplained#synchronization">
+ *       Synchronization policy</a>
+ *   <li><a href="https://github.com/google/guava/wiki/GraphsExplained#notes-for-implementors">Notes
+ *       for implementors</a>
+ * </ul>
+ *
+ * @author James Sexton
+ * @author Joshua O'Madadhain
+ * @param <N> Node parameter type
+ * @since 20.0
+ */
+public interface Graph<N> extends BaseGraph<N> {
+  //
+  // Graph-level accessors
+  //
+
+  /** Returns all nodes in this graph, in the order specified by {@link #nodeOrder()}. */
+  @Override
+  Set<N> nodes();
+
+  /** Returns all edges in this graph. */
+  @Override
+  Set<EndpointPair<N>> edges();
+
+  //
+  // Graph properties
+  //
+
+  /**
+   * Returns true if the edges in this graph are directed. Directed edges connect a {@link
+   * EndpointPair#source() source node} to a {@link EndpointPair#target() target node}, while
+   * undirected edges connect a pair of nodes to each other.
+   */
+  @Override
+  boolean isDirected();
+
+  /**
+   * Returns true if this graph allows self-loops (edges that connect a node to itself). Attempting
+   * to add a self-loop to a graph that does not allow them will throw an {@link
+   * IllegalArgumentException}.
+   */
+  @Override
+  boolean allowsSelfLoops();
+
+  /** Returns the order of iteration for the elements of {@link #nodes()}. */
+  @Override
+  ElementOrder<N> nodeOrder();
+
+  /**
+   * Returns an {@link ElementOrder} that specifies the order of iteration for the elements of
+   * {@link #edges()}, {@link #adjacentNodes(Object)}, {@link #predecessors(Object)}, {@link
+   * #successors(Object)} and {@link #incidentEdges(Object)}.
+   *
+   * @since 29.0
+   */
+  @Override
+  ElementOrder<N> incidentEdgeOrder();
+
+  //
+  // Element-level accessors
+  //
+
+  /**
+   * Returns the nodes which have an incident edge in common with {@code node} in this graph.
+   *
+   * <p>This is equal to the union of {@link #predecessors(Object)} and {@link #successors(Object)}.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this graph
+   */
+  @Override
+  Set<N> adjacentNodes(N node);
+
+  /**
+   * Returns all nodes in this graph adjacent to {@code node} which can be reached by traversing
+   * {@code node}'s incoming edges <i>against</i> the direction (if any) of the edge.
+   *
+   * <p>In an undirected graph, this is equivalent to {@link #adjacentNodes(Object)}.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this graph
+   */
+  @Override
+  Set<N> predecessors(N node);
+
+  /**
+   * Returns all nodes in this graph adjacent to {@code node} which can be reached by traversing
+   * {@code node}'s outgoing edges in the direction (if any) of the edge.
+   *
+   * <p>In an undirected graph, this is equivalent to {@link #adjacentNodes(Object)}.
+   *
+   * <p>This is <i>not</i> the same as "all nodes reachable from {@code node} by following outgoing
+   * edges". For that functionality, see {@link Graphs#reachableNodes(Graph, Object)}.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this graph
+   */
+  @Override
+  Set<N> successors(N node);
+
+  /**
+   * Returns the edges in this graph whose endpoints include {@code node}.
+   *
+   * <p>This is equal to the union of incoming and outgoing edges.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this graph
+   * @since 24.0
+   */
+  @Override
+  Set<EndpointPair<N>> incidentEdges(N node);
+
+  /**
+   * Returns the count of {@code node}'s incident edges, counting self-loops twice (equivalently,
+   * the number of times an edge touches {@code node}).
+   *
+   * <p>For directed graphs, this is equal to {@code inDegree(node) + outDegree(node)}.
+   *
+   * <p>For undirected graphs, this is equal to {@code incidentEdges(node).size()} + (number of
+   * self-loops incident to {@code node}).
+   *
+   * <p>If the count is greater than {@code Integer.MAX_VALUE}, returns {@code Integer.MAX_VALUE}.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this graph
+   */
+  @Override
+  int degree(N node);
+
+  /**
+   * Returns the count of {@code node}'s incoming edges (equal to {@code predecessors(node).size()})
+   * in a directed graph. In an undirected graph, returns the {@link #degree(Object)}.
+   *
+   * <p>If the count is greater than {@code Integer.MAX_VALUE}, returns {@code Integer.MAX_VALUE}.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this graph
+   */
+  @Override
+  int inDegree(N node);
+
+  /**
+   * Returns the count of {@code node}'s outgoing edges (equal to {@code successors(node).size()})
+   * in a directed graph. In an undirected graph, returns the {@link #degree(Object)}.
+   *
+   * <p>If the count is greater than {@code Integer.MAX_VALUE}, returns {@code Integer.MAX_VALUE}.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this graph
+   */
+  @Override
+  int outDegree(N node);
+
+  /**
+   * Returns true if there is an edge that directly connects {@code nodeU} to {@code nodeV}. This is
+   * equivalent to {@code nodes().contains(nodeU) && successors(nodeU).contains(nodeV)}.
+   *
+   * <p>In an undirected graph, this is equal to {@code hasEdgeConnecting(nodeV, nodeU)}.
+   *
+   * @since 23.0
+   */
+  @Override
+  boolean hasEdgeConnecting(N nodeU, N nodeV);
+
+  /**
+   * Returns true if there is an edge that directly connects {@code endpoints} (in the order, if
+   * any, specified by {@code endpoints}). This is equivalent to {@code
+   * edges().contains(endpoints)}.
+   *
+   * <p>Unlike the other {@code EndpointPair}-accepting methods, this method does not throw if the
+   * endpoints are unordered and the graph is directed; it simply returns {@code false}. This is for
+   * consistency with the behavior of {@link Collection#contains(Object)} (which does not generally
+   * throw if the object cannot be present in the collection), and the desire to have this method's
+   * behavior be compatible with {@code edges().contains(endpoints)}.
+   *
+   * @since 27.1
+   */
+  @Override
+  boolean hasEdgeConnecting(EndpointPair<N> endpoints);
+
+  //
+  // Graph identity
+  //
+
+  /**
+   * Returns {@code true} iff {@code object} is a {@link Graph} that has the same elements and the
+   * same structural relationships as those in this graph.
+   *
+   * <p>Thus, two graphs A and B are equal if <b>all</b> of the following are true:
+   *
+   * <ul>
+   *   <li>A and B have equal {@link #isDirected() directedness}.
+   *   <li>A and B have equal {@link #nodes() node sets}.
+   *   <li>A and B have equal {@link #edges() edge sets}.
+   * </ul>
+   *
+   * <p>Graph properties besides {@link #isDirected() directedness} do <b>not</b> affect equality.
+   * For example, two graphs may be considered equal even if one allows self-loops and the other
+   * doesn't. Additionally, the order in which nodes or edges are added to the graph, and the order
+   * in which they are iterated over, are irrelevant.
+   *
+   * <p>A reference implementation of this is provided by {@link AbstractGraph#equals(Object)}.
+   */
+  @Override
+  boolean equals(@CheckForNull Object object);
+
+  /**
+   * Returns the hash code for this graph. The hash code of a graph is defined as the hash code of
+   * the set returned by {@link #edges()}.
+   *
+   * <p>A reference implementation of this is provided by {@link AbstractGraph#hashCode()}.
+   */
+  @Override
+  int hashCode();
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/graph/GraphConstants.java b/iotdb-core/node-commons/src/main/java/com/google/common/graph/GraphConstants.java
new file mode 100644
index 0000000..3c58f00
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/graph/GraphConstants.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Guava Authors
+ *
+ * Licensed 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 com.google.common.graph;
+
+/** A utility class to hold various constants used by the Guava Graph library. */
+final class GraphConstants {
+
+  private GraphConstants() {}
+
+  static final int EXPECTED_DEGREE = 2;
+
+  static final int DEFAULT_NODE_COUNT = 10;
+  static final int DEFAULT_EDGE_COUNT = DEFAULT_NODE_COUNT * EXPECTED_DEGREE;
+
+  // Load factor and capacity for "inner" (i.e. per node/edge element) hash sets or maps
+  static final float INNER_LOAD_FACTOR = 1.0f;
+  static final int INNER_CAPACITY = 2; // ceiling(EXPECTED_DEGREE / INNER_LOAD_FACTOR)
+
+  // Error messages
+  static final String NODE_NOT_IN_GRAPH = "Node %s is not an element of this graph.";
+  static final String EDGE_NOT_IN_GRAPH = "Edge %s is not an element of this graph.";
+  static final String REUSING_EDGE =
+      "Edge %s already exists between the following nodes: %s, "
+          + "so it cannot be reused to connect the following nodes: %s.";
+  static final String MULTIPLE_EDGES_CONNECTING =
+      "Cannot call edgeConnecting() when parallel edges exist between %s and %s. Consider calling "
+          + "edgesConnecting() instead.";
+  static final String PARALLEL_EDGES_NOT_ALLOWED =
+      "Nodes %s and %s are already connected by a different edge. To construct a graph "
+          + "that allows parallel edges, call allowsParallelEdges(true) on the Builder.";
+  static final String SELF_LOOPS_NOT_ALLOWED =
+      "Cannot add self-loop edge on node %s, as self-loops are not allowed. To construct a graph "
+          + "that allows self-loops, call allowsSelfLoops(true) on the Builder.";
+  static final String NOT_AVAILABLE_ON_UNDIRECTED =
+      "Cannot call source()/target() on a EndpointPair from an undirected graph. Consider calling "
+          + "adjacentNode(node) if you already have a node, or nodeU()/nodeV() if you don't.";
+  static final String EDGE_ALREADY_EXISTS = "Edge %s already exists in the graph.";
+  static final String ENDPOINTS_MISMATCH =
+      "Mismatch: endpoints' ordering is not compatible with directionality of the graph";
+
+  /** Singleton edge value for {@link Graph} implementations backed by {@link ValueGraph}s. */
+  enum Presence {
+    EDGE_EXISTS
+  }
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/graph/Network.java b/iotdb-core/node-commons/src/main/java/com/google/common/graph/Network.java
new file mode 100644
index 0000000..05707d1
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/graph/Network.java
@@ -0,0 +1,428 @@
+/*
+ * Copyright (C) 2014 The Guava Authors
+ *
+ * Licensed 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 com.google.common.graph;
+
+import javax.annotation.CheckForNull;
+
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * An interface for <a
+ * href="https://en.wikipedia.org/wiki/Graph_(discrete_mathematics)">graph</a>-structured data,
+ * whose edges are unique objects.
+ *
+ * <p>A graph is composed of a set of nodes and a set of edges connecting pairs of nodes.
+ *
+ * <p>There are three primary interfaces provided to represent graphs. In order of increasing
+ * complexity they are: {@link Graph}, {@link ValueGraph}, and {@link Network}. You should generally
+ * prefer the simplest interface that satisfies your use case. See the <a
+ * href="https://github.com/google/guava/wiki/GraphsExplained#choosing-the-right-graph-type">
+ * "Choosing the right graph type"</a> section of the Guava User Guide for more details.
+ *
+ * <h3>Capabilities</h3>
+ *
+ * <p>{@code Network} supports the following use cases (<a
+ * href="https://github.com/google/guava/wiki/GraphsExplained#definitions">definitions of
+ * terms</a>):
+ *
+ * <ul>
+ *   <li>directed graphs
+ *   <li>undirected graphs
+ *   <li>graphs that do/don't allow parallel edges
+ *   <li>graphs that do/don't allow self-loops
+ *   <li>graphs whose nodes/edges are insertion-ordered, sorted, or unordered
+ *   <li>graphs whose edges are unique objects
+ * </ul>
+ *
+ * <h3>Building a {@code Network}</h3>
+ *
+ * <p>The implementation classes that {@code common.graph} provides are not public, by design. To
+ * create an instance of one of the built-in implementations of {@code Network}, use the {@link
+ * NetworkBuilder} class:
+ *
+ * <pre>{@code
+ * MutableNetwork<Integer, MyEdge> graph = NetworkBuilder.directed().build();
+ * }</pre>
+ *
+ * <p>{@link NetworkBuilder#build()} returns an instance of {@link MutableNetwork}, which is a
+ * subtype of {@code Network} that provides methods for adding and removing nodes and edges. If you
+ * do not need to mutate a graph (e.g. if you write a method than runs a read-only algorithm on the
+ * graph), you should use the non-mutating {@link Network} interface, or an {@link
+ * ImmutableNetwork}.
+ *
+ * <p>You can create an immutable copy of an existing {@code Network} using {@link
+ * ImmutableNetwork#copyOf(Network)}:
+ *
+ * <pre>{@code
+ * ImmutableNetwork<Integer, MyEdge> immutableGraph = ImmutableNetwork.copyOf(graph);
+ * }</pre>
+ *
+ * <p>Instances of {@link ImmutableNetwork} do not implement {@link MutableNetwork} (obviously!) and
+ * are contractually guaranteed to be unmodifiable and thread-safe.
+ *
+ * <p>The Guava User Guide has <a
+ * href="https://github.com/google/guava/wiki/GraphsExplained#building-graph-instances">more
+ * information on (and examples of) building graphs</a>.
+ *
+ * <h3>Additional documentation</h3>
+ *
+ * <p>See the Guava User Guide for the {@code common.graph} package (<a
+ * href="https://github.com/google/guava/wiki/GraphsExplained">"Graphs Explained"</a>) for
+ * additional documentation, including:
+ *
+ * <ul>
+ *   <li><a
+ *       href="https://github.com/google/guava/wiki/GraphsExplained#equals-hashcode-and-graph-equivalence">
+ *       {@code equals()}, {@code hashCode()}, and graph equivalence</a>
+ *   <li><a href="https://github.com/google/guava/wiki/GraphsExplained#synchronization">
+ *       Synchronization policy</a>
+ *   <li><a href="https://github.com/google/guava/wiki/GraphsExplained#notes-for-implementors">Notes
+ *       for implementors</a>
+ * </ul>
+ *
+ * @author James Sexton
+ * @author Joshua O'Madadhain
+ * @param <N> Node parameter type
+ * @param <E> Edge parameter type
+ * @since 20.0
+ */
+public interface Network<N, E> extends SuccessorsFunction<N>, PredecessorsFunction<N> {
+  //
+  // Network-level accessors
+  //
+
+  /** Returns all nodes in this network, in the order specified by {@link #nodeOrder()}. */
+  Set<N> nodes();
+
+  /** Returns all edges in this network, in the order specified by {@link #edgeOrder()}. */
+  Set<E> edges();
+
+  /**
+   * Returns a live view of this network as a {@link Graph}. The resulting {@link Graph} will have
+   * an edge connecting node A to node B if this {@link Network} has an edge connecting A to B.
+   *
+   * <p>If this network {@link #allowsParallelEdges() allows parallel edges}, parallel edges will be
+   * treated as if collapsed into a single edge. For example, the {@link #degree(Object)} of a node
+   * in the {@link Graph} view may be less than the degree of the same node in this {@link Network}.
+   */
+  Graph<N> asGraph();
+
+  //
+  // Network properties
+  //
+
+  /**
+   * Returns true if the edges in this network are directed. Directed edges connect a {@link
+   * EndpointPair#source() source node} to a {@link EndpointPair#target() target node}, while
+   * undirected edges connect a pair of nodes to each other.
+   */
+  boolean isDirected();
+
+  /**
+   * Returns true if this network allows parallel edges. Attempting to add a parallel edge to a
+   * network that does not allow them will throw an {@link IllegalArgumentException}.
+   */
+  boolean allowsParallelEdges();
+
+  /**
+   * Returns true if this network allows self-loops (edges that connect a node to itself).
+   * Attempting to add a self-loop to a network that does not allow them will throw an {@link
+   * IllegalArgumentException}.
+   */
+  boolean allowsSelfLoops();
+
+  /** Returns the order of iteration for the elements of {@link #nodes()}. */
+  ElementOrder<N> nodeOrder();
+
+  /** Returns the order of iteration for the elements of {@link #edges()}. */
+  ElementOrder<E> edgeOrder();
+
+  //
+  // Element-level accessors
+  //
+
+  /**
+   * Returns the nodes which have an incident edge in common with {@code node} in this network.
+   *
+   * <p>This is equal to the union of {@link #predecessors(Object)} and {@link #successors(Object)}.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this network
+   */
+  Set<N> adjacentNodes(N node);
+
+  /**
+   * Returns all nodes in this network adjacent to {@code node} which can be reached by traversing
+   * {@code node}'s incoming edges <i>against</i> the direction (if any) of the edge.
+   *
+   * <p>In an undirected network, this is equivalent to {@link #adjacentNodes(Object)}.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this network
+   */
+  @Override
+  Set<N> predecessors(N node);
+
+  /**
+   * Returns all nodes in this network adjacent to {@code node} which can be reached by traversing
+   * {@code node}'s outgoing edges in the direction (if any) of the edge.
+   *
+   * <p>In an undirected network, this is equivalent to {@link #adjacentNodes(Object)}.
+   *
+   * <p>This is <i>not</i> the same as "all nodes reachable from {@code node} by following outgoing
+   * edges". For that functionality, see {@link Graphs#reachableNodes(Graph, Object)}.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this network
+   */
+  @Override
+  Set<N> successors(N node);
+
+  /**
+   * Returns the edges whose {@link #incidentNodes(Object) incident nodes} in this network include
+   * {@code node}.
+   *
+   * <p>This is equal to the union of {@link #inEdges(Object)} and {@link #outEdges(Object)}.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this network
+   */
+  Set<E> incidentEdges(N node);
+
+  /**
+   * Returns all edges in this network which can be traversed in the direction (if any) of the edge
+   * to end at {@code node}.
+   *
+   * <p>In a directed network, an incoming edge's {@link EndpointPair#target()} equals {@code node}.
+   *
+   * <p>In an undirected network, this is equivalent to {@link #incidentEdges(Object)}.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this network
+   */
+  Set<E> inEdges(N node);
+
+  /**
+   * Returns all edges in this network which can be traversed in the direction (if any) of the edge
+   * starting from {@code node}.
+   *
+   * <p>In a directed network, an outgoing edge's {@link EndpointPair#source()} equals {@code node}.
+   *
+   * <p>In an undirected network, this is equivalent to {@link #incidentEdges(Object)}.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this network
+   */
+  Set<E> outEdges(N node);
+
+  /**
+   * Returns the count of {@code node}'s {@link #incidentEdges(Object) incident edges}, counting
+   * self-loops twice (equivalently, the number of times an edge touches {@code node}).
+   *
+   * <p>For directed networks, this is equal to {@code inDegree(node) + outDegree(node)}.
+   *
+   * <p>For undirected networks, this is equal to {@code incidentEdges(node).size()} + (number of
+   * self-loops incident to {@code node}).
+   *
+   * <p>If the count is greater than {@code Integer.MAX_VALUE}, returns {@code Integer.MAX_VALUE}.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this network
+   */
+  int degree(N node);
+
+  /**
+   * Returns the count of {@code node}'s {@link #inEdges(Object) incoming edges} in a directed
+   * network. In an undirected network, returns the {@link #degree(Object)}.
+   *
+   * <p>If the count is greater than {@code Integer.MAX_VALUE}, returns {@code Integer.MAX_VALUE}.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this network
+   */
+  int inDegree(N node);
+
+  /**
+   * Returns the count of {@code node}'s {@link #outEdges(Object) outgoing edges} in a directed
+   * network. In an undirected network, returns the {@link #degree(Object)}.
+   *
+   * <p>If the count is greater than {@code Integer.MAX_VALUE}, returns {@code Integer.MAX_VALUE}.
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this network
+   */
+  int outDegree(N node);
+
+  /**
+   * Returns the nodes which are the endpoints of {@code edge} in this network.
+   *
+   * @throws IllegalArgumentException if {@code edge} is not an element of this network
+   */
+  EndpointPair<N> incidentNodes(E edge);
+
+  /**
+   * Returns the edges which have an {@link #incidentNodes(Object) incident node} in common with
+   * {@code edge}. An edge is not considered adjacent to itself.
+   *
+   * @throws IllegalArgumentException if {@code edge} is not an element of this network
+   */
+  Set<E> adjacentEdges(E edge);
+
+  /**
+   * Returns the set of edges that each directly connect {@code nodeU} to {@code nodeV}.
+   *
+   * <p>In an undirected network, this is equal to {@code edgesConnecting(nodeV, nodeU)}.
+   *
+   * <p>The resulting set of edges will be parallel (i.e. have equal {@link
+   * #incidentNodes(Object)}). If this network does not {@link #allowsParallelEdges() allow parallel
+   * edges}, the resulting set will contain at most one edge (equivalent to {@code
+   * edgeConnecting(nodeU, nodeV).asSet()}).
+   *
+   * @throws IllegalArgumentException if {@code nodeU} or {@code nodeV} is not an element of this
+   *     network
+   */
+  Set<E> edgesConnecting(N nodeU, N nodeV);
+
+  /**
+   * Returns the set of edges that each directly connect {@code endpoints} (in the order, if any,
+   * specified by {@code endpoints}).
+   *
+   * <p>The resulting set of edges will be parallel (i.e. have equal {@link
+   * #incidentNodes(Object)}). If this network does not {@link #allowsParallelEdges() allow parallel
+   * edges}, the resulting set will contain at most one edge (equivalent to {@code
+   * edgeConnecting(endpoints).asSet()}).
+   *
+   * <p>If this network is directed, {@code endpoints} must be ordered.
+   *
+   * @throws IllegalArgumentException if either endpoint is not an element of this network
+   * @throws IllegalArgumentException if the endpoints are unordered and the graph is directed
+   * @since 27.1
+   */
+  Set<E> edgesConnecting(EndpointPair<N> endpoints);
+
+  /**
+   * Returns the single edge that directly connects {@code nodeU} to {@code nodeV}, if one is
+   * present, or {@code Optional.empty()} if no such edge exists.
+   *
+   * <p>In an undirected network, this is equal to {@code edgeConnecting(nodeV, nodeU)}.
+   *
+   * @throws IllegalArgumentException if there are multiple parallel edges connecting {@code nodeU}
+   *     to {@code nodeV}
+   * @throws IllegalArgumentException if {@code nodeU} or {@code nodeV} is not an element of this
+   *     network
+   * @since 23.0
+   */
+  Optional<E> edgeConnecting(N nodeU, N nodeV);
+
+  /**
+   * Returns the single edge that directly connects {@code endpoints} (in the order, if any,
+   * specified by {@code endpoints}), if one is present, or {@code Optional.empty()} if no such edge
+   * exists.
+   *
+   * <p>If this graph is directed, the endpoints must be ordered.
+   *
+   * @throws IllegalArgumentException if there are multiple parallel edges connecting {@code nodeU}
+   *     to {@code nodeV}
+   * @throws IllegalArgumentException if either endpoint is not an element of this network
+   * @throws IllegalArgumentException if the endpoints are unordered and the graph is directed
+   * @since 27.1
+   */
+  Optional<E> edgeConnecting(EndpointPair<N> endpoints);
+
+  /**
+   * Returns the single edge that directly connects {@code nodeU} to {@code nodeV}, if one is
+   * present, or {@code null} if no such edge exists.
+   *
+   * <p>In an undirected network, this is equal to {@code edgeConnectingOrNull(nodeV, nodeU)}.
+   *
+   * @throws IllegalArgumentException if there are multiple parallel edges connecting {@code nodeU}
+   *     to {@code nodeV}
+   * @throws IllegalArgumentException if {@code nodeU} or {@code nodeV} is not an element of this
+   *     network
+   * @since 23.0
+   */
+  @CheckForNull
+  E edgeConnectingOrNull(N nodeU, N nodeV);
+
+  /**
+   * Returns the single edge that directly connects {@code endpoints} (in the order, if any,
+   * specified by {@code endpoints}), if one is present, or {@code null} if no such edge exists.
+   *
+   * <p>If this graph is directed, the endpoints must be ordered.
+   *
+   * @throws IllegalArgumentException if there are multiple parallel edges connecting {@code nodeU}
+   *     to {@code nodeV}
+   * @throws IllegalArgumentException if either endpoint is not an element of this network
+   * @throws IllegalArgumentException if the endpoints are unordered and the graph is directed
+   * @since 27.1
+   */
+  @CheckForNull
+  E edgeConnectingOrNull(EndpointPair<N> endpoints);
+
+  /**
+   * Returns true if there is an edge that directly connects {@code nodeU} to {@code nodeV}. This is
+   * equivalent to {@code nodes().contains(nodeU) && successors(nodeU).contains(nodeV)}, and to
+   * {@code edgeConnectingOrNull(nodeU, nodeV) != null}.
+   *
+   * <p>In an undirected graph, this is equal to {@code hasEdgeConnecting(nodeV, nodeU)}.
+   *
+   * @since 23.0
+   */
+  boolean hasEdgeConnecting(N nodeU, N nodeV);
+
+  /**
+   * Returns true if there is an edge that directly connects {@code endpoints} (in the order, if
+   * any, specified by {@code endpoints}).
+   *
+   * <p>Unlike the other {@code EndpointPair}-accepting methods, this method does not throw if the
+   * endpoints are unordered and the graph is directed; it simply returns {@code false}. This is for
+   * consistency with {@link Graph#hasEdgeConnecting(EndpointPair)} and {@link
+   * ValueGraph#hasEdgeConnecting(EndpointPair)}.
+   *
+   * @since 27.1
+   */
+  boolean hasEdgeConnecting(EndpointPair<N> endpoints);
+
+  //
+  // Network identity
+  //
+
+  /**
+   * Returns {@code true} iff {@code object} is a {@link Network} that has the same elements and the
+   * same structural relationships as those in this network.
+   *
+   * <p>Thus, two networks A and B are equal if <b>all</b> of the following are true:
+   *
+   * <ul>
+   *   <li>A and B have equal {@link #isDirected() directedness}.
+   *   <li>A and B have equal {@link #nodes() node sets}.
+   *   <li>A and B have equal {@link #edges() edge sets}.
+   *   <li>Every edge in A and B connects the same nodes in the same direction (if any).
+   * </ul>
+   *
+   * <p>Network properties besides {@link #isDirected() directedness} do <b>not</b> affect equality.
+   * For example, two networks may be considered equal even if one allows parallel edges and the
+   * other doesn't. Additionally, the order in which nodes or edges are added to the network, and
+   * the order in which they are iterated over, are irrelevant.
+   *
+   * <p>A reference implementation of this is provided by {@link AbstractNetwork#equals(Object)}.
+   */
+  @Override
+  boolean equals(@CheckForNull Object object);
+
+  /**
+   * Returns the hash code for this network. The hash code of a network is defined as the hash code
+   * of a map from each of its {@link #edges() edges} to their {@link #incidentNodes(Object)
+   * incident nodes}.
+   *
+   * <p>A reference implementation of this is provided by {@link AbstractNetwork#hashCode()}.
+   */
+  @Override
+  int hashCode();
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/graph/PredecessorsFunction.java b/iotdb-core/node-commons/src/main/java/com/google/common/graph/PredecessorsFunction.java
new file mode 100644
index 0000000..c5fdb81
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/graph/PredecessorsFunction.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2014 The Guava Authors
+ *
+ * Licensed 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 com.google.common.graph;
+
+/**
+ * A functional interface for <a
+ * href="https://en.wikipedia.org/wiki/Graph_(discrete_mathematics)">graph</a>-structured data.
+ *
+ * <p>This interface is meant to be used as the type of a parameter to graph algorithms (such as
+ * topological sort) that only need a way of accessing the predecessors of a node in a graph.
+ *
+ * <h3>Usage</h3>
+ *
+ * Given an algorithm, for example:
+ *
+ * <pre>{@code
+ * public <N> someGraphAlgorithm(N startNode, PredecessorsFunction<N> predecessorsFunction);
+ * }</pre>
+ *
+ * you will invoke it depending on the graph representation you're using.
+ *
+ * <p>If you have an instance of one of the primary {@code common.graph} types ({@link Graph},
+ * {@link ValueGraph}, and {@link Network}):
+ *
+ * <pre>{@code
+ * someGraphAlgorithm(startNode, graph);
+ * }</pre>
+ *
+ * This works because those types each implement {@code PredecessorsFunction}. It will also work
+ * with any other implementation of this interface.
+ *
+ * <p>If you have your own graph implementation based around a custom node type {@code MyNode},
+ * which has a method {@code getParents()} that retrieves its predecessors in a graph:
+ *
+ * <pre>{@code
+ * someGraphAlgorithm(startNode, MyNode::getParents);
+ * }</pre>
+ *
+ * <p>If you have some other mechanism for returning the predecessors of a node, or one that doesn't
+ * return a {@code Iterable<? extends N>}, then you can use a lambda to perform a more general
+ * transformation:
+ *
+ * <pre>{@code
+ * someGraphAlgorithm(startNode, node -> ImmutableList.of(node.mother(), node.father()));
+ * }</pre>
+ *
+ * <p>Graph algorithms that need additional capabilities (accessing both predecessors and
+ * successors, iterating over the edges, etc.) should declare their input to be of a type that
+ * provides those capabilities, such as {@link Graph}, {@link ValueGraph}, or {@link Network}.
+ *
+ * <h3>Additional documentation</h3>
+ *
+ * <p>See the Guava User Guide for the {@code common.graph} package (<a
+ * href="https://github.com/google/guava/wiki/GraphsExplained">"Graphs Explained"</a>) for
+ * additional documentation, including <a
+ * href="https://github.com/google/guava/wiki/GraphsExplained#notes-for-implementors">notes for
+ * implementors</a>
+ *
+ * @author Joshua O'Madadhain
+ * @author Jens Nyman
+ * @param <N> Node parameter type
+ * @since 23.0
+ */
+public interface PredecessorsFunction<N> {
+
+  /**
+   * Returns all nodes in this graph adjacent to {@code node} which can be reached by traversing
+   * {@code node}'s incoming edges <i>against</i> the direction (if any) of the edge.
+   *
+   * <p>Some algorithms that operate on a {@code PredecessorsFunction} may produce undesired results
+   * if the returned {@link Iterable} contains duplicate elements. Implementations of such
+   * algorithms should document their behavior in the presence of duplicates.
+   *
+   * <p>The elements of the returned {@code Iterable} must each be:
+   *
+   * <ul>
+   *   <li>Non-null
+   *   <li>Usable as {@code Map} keys (see the Guava User Guide's section on <a
+   *       href="https://github.com/google/guava/wiki/GraphsExplained#graph-elements-nodes-and-edges">
+   *       graph elements</a> for details)
+   * </ul>
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this graph
+   */
+  Iterable<? extends N> predecessors(N node);
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/graph/SuccessorsFunction.java b/iotdb-core/node-commons/src/main/java/com/google/common/graph/SuccessorsFunction.java
new file mode 100644
index 0000000..1481310
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/graph/SuccessorsFunction.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2014 The Guava Authors
+ *
+ * Licensed 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 com.google.common.graph;
+
+/**
+ * A functional interface for <a
+ * href="https://en.wikipedia.org/wiki/Graph_(discrete_mathematics)">graph</a>-structured data.
+ *
+ * <p>This interface is meant to be used as the type of a parameter to graph algorithms (such as
+ * breadth first traversal) that only need a way of accessing the successors of a node in a graph.
+ *
+ * <h3>Usage</h3>
+ *
+ * Given an algorithm, for example:
+ *
+ * <pre>{@code
+ * public <N> someGraphAlgorithm(N startNode, SuccessorsFunction<N> successorsFunction);
+ * }</pre>
+ *
+ * you will invoke it depending on the graph representation you're using.
+ *
+ * <p>If you have an instance of one of the primary {@code common.graph} types ({@link Graph},
+ * {@link ValueGraph}, and {@link Network}):
+ *
+ * <pre>{@code
+ * someGraphAlgorithm(startNode, graph);
+ * }</pre>
+ *
+ * This works because those types each implement {@code SuccessorsFunction}. It will also work with
+ * any other implementation of this interface.
+ *
+ * <p>If you have your own graph implementation based around a custom node type {@code MyNode},
+ * which has a method {@code getChildren()} that retrieves its successors in a graph:
+ *
+ * <pre>{@code
+ * someGraphAlgorithm(startNode, MyNode::getChildren);
+ * }</pre>
+ *
+ * <p>If you have some other mechanism for returning the successors of a node, or one that doesn't
+ * return an {@code Iterable<? extends N>}, then you can use a lambda to perform a more general
+ * transformation:
+ *
+ * <pre>{@code
+ * someGraphAlgorithm(startNode, node -> ImmutableList.of(node.leftChild(), node.rightChild()));
+ * }</pre>
+ *
+ * <p>Graph algorithms that need additional capabilities (accessing both predecessors and
+ * successors, iterating over the edges, etc.) should declare their input to be of a type that
+ * provides those capabilities, such as {@link Graph}, {@link ValueGraph}, or {@link Network}.
+ *
+ * <h3>Additional documentation</h3>
+ *
+ * <p>See the Guava User Guide for the {@code common.graph} package (<a
+ * href="https://github.com/google/guava/wiki/GraphsExplained">"Graphs Explained"</a>) for
+ * additional documentation, including <a
+ * href="https://github.com/google/guava/wiki/GraphsExplained#notes-for-implementors">notes for
+ * implementors</a>
+ *
+ * @author Joshua O'Madadhain
+ * @author Jens Nyman
+ * @param <N> Node parameter type
+ * @since 23.0
+ */
+public interface SuccessorsFunction<N> {
+
+  /**
+   * Returns all nodes in this graph adjacent to {@code node} which can be reached by traversing
+   * {@code node}'s outgoing edges in the direction (if any) of the edge.
+   *
+   * <p>This is <i>not</i> the same as "all nodes reachable from {@code node} by following outgoing
+   * edges". For that functionality, see {@link Graphs#reachableNodes(Graph, Object)}.
+   *
+   * <p>Some algorithms that operate on a {@code SuccessorsFunction} may produce undesired results
+   * if the returned {@link Iterable} contains duplicate elements. Implementations of such
+   * algorithms should document their behavior in the presence of duplicates.
+   *
+   * <p>The elements of the returned {@code Iterable} must each be:
+   *
+   * <ul>
+   *   <li>Non-null
+   *   <li>Usable as {@code Map} keys (see the Guava User Guide's section on <a
+   *       href="https://github.com/google/guava/wiki/GraphsExplained#graph-elements-nodes-and-edges">
+   *       graph elements</a> for details)
+   * </ul>
+   *
+   * @throws IllegalArgumentException if {@code node} is not an element of this graph
+   */
+  Iterable<? extends N> successors(N node);
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/graph/Traverser.java b/iotdb-core/node-commons/src/main/java/com/google/common/graph/Traverser.java
new file mode 100644
index 0000000..c4d20eb
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/graph/Traverser.java
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2017 The Guava Authors
+ *
+ * Licensed 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 com.google.common.graph;
+
+import com.google.common.collect.AbstractIterator;
+import com.google.common.collect.ImmutableSet;
+
+import javax.annotation.CheckForNull;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * An object that can traverse the nodes that are reachable from a specified (set of) start node(s)
+ * using a specified {@link SuccessorsFunction}.
+ *
+ * <p>There are two entry points for creating a {@code Traverser}: {@link
+ * #forTree(SuccessorsFunction)} and {@link #forGraph(SuccessorsFunction)}. You should choose one
+ * based on your answers to the following questions:
+ *
+ * <ol>
+ *   <li>Is there only one path to any node that's reachable from any start node? (If so, the graph
+ *       to be traversed is a tree or forest even if it is a subgraph of a graph which is neither.)
+ *   <li>Are the node objects' implementations of {@code equals()}/{@code hashCode()} <a
+ *       href="https://github.com/google/guava/wiki/GraphsExplained#non-recursiveness">recursive</a>?
+ * </ol>
+ *
+ * <p>If your answers are:
+ *
+ * <ul>
+ *   <li>(1) "no" and (2) "no", use {@link #forGraph(SuccessorsFunction)}.
+ *   <li>(1) "yes" and (2) "yes", use {@link #forTree(SuccessorsFunction)}.
+ *   <li>(1) "yes" and (2) "no", you can use either, but {@code forTree()} will be more efficient.
+ *   <li>(1) "no" and (2) "yes", <b><i>neither will work</i></b>, but if you transform your node
+ *       objects into a non-recursive form, you can use {@code forGraph()}.
+ * </ul>
+ *
+ * @author Jens Nyman
+ * @param <N> Node parameter type
+ * @since 23.1
+ */
+public abstract class Traverser<N> {
+  private final SuccessorsFunction<N> successorFunction;
+
+  private Traverser(SuccessorsFunction<N> successorFunction) {
+    this.successorFunction = checkNotNull(successorFunction);
+  }
+
+  /**
+   * Creates a new traverser for the given general {@code graph}.
+   *
+   * <p>Traversers created using this method are guaranteed to visit each node reachable from the
+   * start node(s) at most once.
+   *
+   * <p>If you know that no node in {@code graph} is reachable by more than one path from the start
+   * node(s), consider using {@link #forTree(SuccessorsFunction)} instead.
+   *
+   * <p><b>Performance notes</b>
+   *
+   * <ul>
+   *   <li>Traversals require <i>O(n)</i> time (where <i>n</i> is the number of nodes reachable from
+   *       the start node), assuming that the node objects have <i>O(1)</i> {@code equals()} and
+   *       {@code hashCode()} implementations. (See the <a
+   *       href="https://github.com/google/guava/wiki/GraphsExplained#elements-must-be-useable-as-map-keys">
+   *       notes on element objects</a> for more information.)
+   *   <li>While traversing, the traverser will use <i>O(n)</i> space (where <i>n</i> is the number
+   *       of nodes that have thus far been visited), plus <i>O(H)</i> space (where <i>H</i> is the
+   *       number of nodes that have been seen but not yet visited, that is, the "horizon").
+   * </ul>
+   *
+   * @param graph {@link SuccessorsFunction} representing a general graph that may have cycles.
+   */
+  public static <N> Traverser<N> forGraph(SuccessorsFunction<N> graph) {
+    return new Traverser<N>(graph) {
+      @Override
+      Traversal<N> newTraversal() {
+        return Traversal.inGraph(graph);
+      }
+    };
+  }
+
+  /**
+   * Creates a new traverser for a directed acyclic graph that has at most one path from the start
+   * node(s) to any node reachable from the start node(s), and has no paths from any start node to
+   * any other start node, such as a tree or forest.
+   *
+   * <p>{@code forTree()} is especially useful (versus {@code forGraph()}) in cases where the data
+   * structure being traversed is, in addition to being a tree/forest, also defined <a
+   * href="https://github.com/google/guava/wiki/GraphsExplained#non-recursiveness">recursively</a>.
+   * This is because the {@code forTree()}-based implementations don't keep track of visited nodes,
+   * and therefore don't need to call `equals()` or `hashCode()` on the node objects; this saves
+   * both time and space versus traversing the same graph using {@code forGraph()}.
+   *
+   * <p>Providing a graph to be traversed for which there is more than one path from the start
+   * node(s) to any node may lead to:
+   *
+   * <ul>
+   *   <li>Traversal not terminating (if the graph has cycles)
+   *   <li>Nodes being visited multiple times (if multiple paths exist from any start node to any
+   *       node reachable from any start node)
+   * </ul>
+   *
+   * <p><b>Performance notes</b>
+   *
+   * <ul>
+   *   <li>Traversals require <i>O(n)</i> time (where <i>n</i> is the number of nodes reachable from
+   *       the start node).
+   *   <li>While traversing, the traverser will use <i>O(H)</i> space (where <i>H</i> is the number
+   *       of nodes that have been seen but not yet visited, that is, the "horizon").
+   * </ul>
+   *
+   * <p><b>Examples</b> (all edges are directed facing downwards)
+   *
+   * <p>The graph below would be valid input with start nodes of {@code a, f, c}. However, if {@code
+   * b} were <i>also</i> a start node, then there would be multiple paths to reach {@code e} and
+   * {@code h}.
+   *
+   * <pre>{@code
+   *    a     b      c
+   *   / \   / \     |
+   *  /   \ /   \    |
+   * d     e     f   g
+   *       |
+   *       |
+   *       h
+   * }</pre>
+   *
+   * <p>.
+   *
+   * <p>The graph below would be a valid input with start nodes of {@code a, f}. However, if {@code
+   * b} were a start node, there would be multiple paths to {@code f}.
+   *
+   * <pre>{@code
+   *    a     b
+   *   / \   / \
+   *  /   \ /   \
+   * c     d     e
+   *        \   /
+   *         \ /
+   *          f
+   * }</pre>
+   *
+   * <p><b>Note on binary trees</b>
+   *
+   * <p>This method can be used to traverse over a binary tree. Given methods {@code
+   * leftChild(node)} and {@code rightChild(node)}, this method can be called as
+   *
+   * <pre>{@code
+   * Traverser.forTree(node -> ImmutableList.of(leftChild(node), rightChild(node)));
+   * }</pre>
+   *
+   * @param tree {@link SuccessorsFunction} representing a directed acyclic graph that has at most
+   *     one path between any two nodes
+   */
+  public static <N> Traverser<N> forTree(SuccessorsFunction<N> tree) {
+    if (tree instanceof BaseGraph) {
+      checkArgument(((BaseGraph<?>) tree).isDirected(), "Undirected graphs can never be trees.");
+    }
+    if (tree instanceof Network) {
+      checkArgument(((Network<?, ?>) tree).isDirected(), "Undirected networks can never be trees.");
+    }
+    return new Traverser<N>(tree) {
+      @Override
+      Traversal<N> newTraversal() {
+        return Traversal.inTree(tree);
+      }
+    };
+  }
+
+  /**
+   * Returns an unmodifiable {@code Iterable} over the nodes reachable from {@code startNode}, in
+   * the order of a breadth-first traversal. That is, all the nodes of depth 0 are returned, then
+   * depth 1, then 2, and so on.
+   *
+   * <p><b>Example:</b> The following graph with {@code startNode} {@code a} would return nodes in
+   * the order {@code abcdef} (assuming successors are returned in alphabetical order).
+   *
+   * <pre>{@code
+   * b ---- a ---- d
+   * |      |
+   * |      |
+   * e ---- c ---- f
+   * }</pre>
+   *
+   * <p>The behavior of this method is undefined if the nodes, or the topology of the graph, change
+   * while iteration is in progress.
+   *
+   * <p>The returned {@code Iterable} can be iterated over multiple times. Every iterator will
+   * compute its next element on the fly. It is thus possible to limit the traversal to a certain
+   * number of nodes as follows:
+   *
+   * <pre>{@code
+   * Iterables.limit(Traverser.forGraph(graph).breadthFirst(node), maxNumberOfNodes);
+   * }</pre>
+   *
+   * <p>See <a href="https://en.wikipedia.org/wiki/Breadth-first_search">Wikipedia</a> for more
+   * info.
+   *
+   * @throws IllegalArgumentException if {@code startNode} is not an element of the graph
+   */
+  public final Iterable<N> breadthFirst(N startNode) {
+    return breadthFirst(ImmutableSet.of(startNode));
+  }
+
+  /**
+   * Returns an unmodifiable {@code Iterable} over the nodes reachable from any of the {@code
+   * startNodes}, in the order of a breadth-first traversal. This is equivalent to a breadth-first
+   * traversal of a graph with an additional root node whose successors are the listed {@code
+   * startNodes}.
+   *
+   * @throws IllegalArgumentException if any of {@code startNodes} is not an element of the graph
+   * @see #breadthFirst(Object)
+   * @since 24.1
+   */
+  public final Iterable<N> breadthFirst(Iterable<? extends N> startNodes) {
+    ImmutableSet<N> validated = validate(startNodes);
+    return new Iterable<N>() {
+      @Override
+      public Iterator<N> iterator() {
+        return newTraversal().breadthFirst(validated.iterator());
+      }
+    };
+  }
+
+  /**
+   * Returns an unmodifiable {@code Iterable} over the nodes reachable from {@code startNode}, in
+   * the order of a depth-first pre-order traversal. "Pre-order" implies that nodes appear in the
+   * {@code Iterable} in the order in which they are first visited.
+   *
+   * <p><b>Example:</b> The following graph with {@code startNode} {@code a} would return nodes in
+   * the order {@code abecfd} (assuming successors are returned in alphabetical order).
+   *
+   * <pre>{@code
+   * b ---- a ---- d
+   * |      |
+   * |      |
+   * e ---- c ---- f
+   * }</pre>
+   *
+   * <p>The behavior of this method is undefined if the nodes, or the topology of the graph, change
+   * while iteration is in progress.
+   *
+   * <p>The returned {@code Iterable} can be iterated over multiple times. Every iterator will
+   * compute its next element on the fly. It is thus possible to limit the traversal to a certain
+   * number of nodes as follows:
+   *
+   * <pre>{@code
+   * Iterables.limit(
+   *     Traverser.forGraph(graph).depthFirstPreOrder(node), maxNumberOfNodes);
+   * }</pre>
+   *
+   * <p>See <a href="https://en.wikipedia.org/wiki/Depth-first_search">Wikipedia</a> for more info.
+   *
+   * @throws IllegalArgumentException if {@code startNode} is not an element of the graph
+   */
+  public final Iterable<N> depthFirstPreOrder(N startNode) {
+    return depthFirstPreOrder(ImmutableSet.of(startNode));
+  }
+
+  /**
+   * Returns an unmodifiable {@code Iterable} over the nodes reachable from any of the {@code
+   * startNodes}, in the order of a depth-first pre-order traversal. This is equivalent to a
+   * depth-first pre-order traversal of a graph with an additional root node whose successors are
+   * the listed {@code startNodes}.
+   *
+   * @throws IllegalArgumentException if any of {@code startNodes} is not an element of the graph
+   * @see #depthFirstPreOrder(Object)
+   * @since 24.1
+   */
+  public final Iterable<N> depthFirstPreOrder(Iterable<? extends N> startNodes) {
+    ImmutableSet<N> validated = validate(startNodes);
+    return new Iterable<N>() {
+      @Override
+      public Iterator<N> iterator() {
+        return newTraversal().preOrder(validated.iterator());
+      }
+    };
+  }
+
+  /**
+   * Returns an unmodifiable {@code Iterable} over the nodes reachable from {@code startNode}, in
+   * the order of a depth-first post-order traversal. "Post-order" implies that nodes appear in the
+   * {@code Iterable} in the order in which they are visited for the last time.
+   *
+   * <p><b>Example:</b> The following graph with {@code startNode} {@code a} would return nodes in
+   * the order {@code fcebda} (assuming successors are returned in alphabetical order).
+   *
+   * <pre>{@code
+   * b ---- a ---- d
+   * |      |
+   * |      |
+   * e ---- c ---- f
+   * }</pre>
+   *
+   * <p>The behavior of this method is undefined if the nodes, or the topology of the graph, change
+   * while iteration is in progress.
+   *
+   * <p>The returned {@code Iterable} can be iterated over multiple times. Every iterator will
+   * compute its next element on the fly. It is thus possible to limit the traversal to a certain
+   * number of nodes as follows:
+   *
+   * <pre>{@code
+   * Iterables.limit(
+   *     Traverser.forGraph(graph).depthFirstPostOrder(node), maxNumberOfNodes);
+   * }</pre>
+   *
+   * <p>See <a href="https://en.wikipedia.org/wiki/Depth-first_search">Wikipedia</a> for more info.
+   *
+   * @throws IllegalArgumentException if {@code startNode} is not an element of the graph
+   */
+  public final Iterable<N> depthFirstPostOrder(N startNode) {
+    return depthFirstPostOrder(ImmutableSet.of(startNode));
+  }
+
+  /**
+   * Returns an unmodifiable {@code Iterable} over the nodes reachable from any of the {@code
+   * startNodes}, in the order of a depth-first post-order traversal. This is equivalent to a
+   * depth-first post-order traversal of a graph with an additional root node whose successors are
+   * the listed {@code startNodes}.
+   *
+   * @throws IllegalArgumentException if any of {@code startNodes} is not an element of the graph
+   * @see #depthFirstPostOrder(Object)
+   * @since 24.1
+   */
+  public final Iterable<N> depthFirstPostOrder(Iterable<? extends N> startNodes) {
+    ImmutableSet<N> validated = validate(startNodes);
+    return new Iterable<N>() {
+      @Override
+      public Iterator<N> iterator() {
+        return newTraversal().postOrder(validated.iterator());
+      }
+    };
+  }
+
+  abstract Traversal<N> newTraversal();
+
+  @SuppressWarnings("CheckReturnValue")
+  private ImmutableSet<N> validate(Iterable<? extends N> startNodes) {
+    ImmutableSet<N> copy = ImmutableSet.copyOf(startNodes);
+    for (N node : copy) {
+      successorFunction.successors(node); // Will throw if node doesn't exist
+    }
+    return copy;
+  }
+
+  /**
+   * Abstracts away the difference between traversing a graph vs. a tree. For a tree, we just take
+   * the next element from the next non-empty iterator; for graph, we need to loop through the next
+   * non-empty iterator to find first unvisited node.
+   */
+  private abstract static class Traversal<N> {
+    final SuccessorsFunction<N> successorFunction;
+
+    Traversal(SuccessorsFunction<N> successorFunction) {
+      this.successorFunction = successorFunction;
+    }
+
+    static <N> Traversal<N> inGraph(SuccessorsFunction<N> graph) {
+      Set<N> visited = new HashSet<>();
+      return new Traversal<N>(graph) {
+        @Override
+        @CheckForNull
+        N visitNext(Deque<Iterator<? extends N>> horizon) {
+          Iterator<? extends N> top = horizon.getFirst();
+          while (top.hasNext()) {
+            N element = top.next();
+            // requireNonNull is safe because horizon contains only graph nodes.
+            /*
+             * TODO(cpovirk): Replace these two statements with one (`N element =
+             * requireNonNull(top.next())`) once our checker supports it.
+             *
+             * (The problem is likely
+             * https://github.com/jspecify/jspecify-reference-checker/blob/61aafa4ae52594830cfc2d61c8b113009dbdb045/src/main/java/com/google/jspecify/nullness/NullSpecAnnotatedTypeFactory.java#L896)
+             */
+            requireNonNull(element);
+            if (visited.add(element)) {
+              return element;
+            }
+          }
+          horizon.removeFirst();
+          return null;
+        }
+      };
+    }
+
+    static <N> Traversal<N> inTree(SuccessorsFunction<N> tree) {
+      return new Traversal<N>(tree) {
+        @CheckForNull
+        @Override
+        N visitNext(Deque<Iterator<? extends N>> horizon) {
+          Iterator<? extends N> top = horizon.getFirst();
+          if (top.hasNext()) {
+            return checkNotNull(top.next());
+          }
+          horizon.removeFirst();
+          return null;
+        }
+      };
+    }
+
+    final Iterator<N> breadthFirst(Iterator<? extends N> startNodes) {
+      return topDown(startNodes, InsertionOrder.BACK);
+    }
+
+    final Iterator<N> preOrder(Iterator<? extends N> startNodes) {
+      return topDown(startNodes, InsertionOrder.FRONT);
+    }
+
+    /**
+     * In top-down traversal, an ancestor node is always traversed before any of its descendant
+     * nodes. The traversal order among descendant nodes (particularly aunts and nieces) are
+     * determined by the {@code InsertionOrder} parameter: nieces are placed at the FRONT before
+     * aunts for pre-order; while in BFS they are placed at the BACK after aunts.
+     */
+    private Iterator<N> topDown(Iterator<? extends N> startNodes, InsertionOrder order) {
+      Deque<Iterator<? extends N>> horizon = new ArrayDeque<>();
+      horizon.add(startNodes);
+      return new AbstractIterator<N>() {
+        @Override
+        @CheckForNull
+        protected N computeNext() {
+          do {
+            N next = visitNext(horizon);
+            if (next != null) {
+              Iterator<? extends N> successors = successorFunction.successors(next).iterator();
+              if (successors.hasNext()) {
+                // BFS: horizon.addLast(successors)
+                // Pre-order: horizon.addFirst(successors)
+                order.insertInto(horizon, successors);
+              }
+              return next;
+            }
+          } while (!horizon.isEmpty());
+          return endOfData();
+        }
+      };
+    }
+
+    final Iterator<N> postOrder(Iterator<? extends N> startNodes) {
+      Deque<N> ancestorStack = new ArrayDeque<>();
+      Deque<Iterator<? extends N>> horizon = new ArrayDeque<>();
+      horizon.add(startNodes);
+      return new AbstractIterator<N>() {
+        @Override
+        @CheckForNull
+        protected N computeNext() {
+          for (N next = visitNext(horizon); next != null; next = visitNext(horizon)) {
+            Iterator<? extends N> successors = successorFunction.successors(next).iterator();
+            if (!successors.hasNext()) {
+              return next;
+            }
+            horizon.addFirst(successors);
+            ancestorStack.push(next);
+          }
+          // TODO(b/192579700): Use a ternary once it no longer confuses our nullness checker.
+          if (!ancestorStack.isEmpty()) {
+            return ancestorStack.pop();
+          }
+          return endOfData();
+        }
+      };
+    }
+
+    /**
+     * Visits the next node from the top iterator of {@code horizon} and returns the visited node.
+     * Null is returned to indicate reaching the end of the top iterator.
+     *
+     * <p>For example, if horizon is {@code [[a, b], [c, d], [e]]}, {@code visitNext()} will return
+     * {@code [a, b, null, c, d, null, e, null]} sequentially, encoding the topological structure.
+     * (Note, however, that the callers of {@code visitNext()} often insert additional iterators
+     * into {@code horizon} between calls to {@code visitNext()}. This causes them to receive
+     * additional values interleaved with those shown above.)
+     */
+    @CheckForNull
+    abstract N visitNext(Deque<Iterator<? extends N>> horizon);
+  }
+
+  /** Poor man's method reference for {@code Deque::addFirst} and {@code Deque::addLast}. */
+  private enum InsertionOrder {
+    FRONT {
+      @Override
+      <T> void insertInto(Deque<T> deque, T value) {
+        deque.addFirst(value);
+      }
+    },
+    BACK {
+      @Override
+      <T> void insertInto(Deque<T> deque, T value) {
+        deque.addLast(value);
+      }
+    };
+
+    abstract <T> void insertInto(Deque<T> deque, T value);
+  }
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/hash/AbstractHashFunction.java b/iotdb-core/node-commons/src/main/java/com/google/common/hash/AbstractHashFunction.java
new file mode 100644
index 0000000..4c84d13
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/hash/AbstractHashFunction.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2017 The Guava Authors
+ *
+ * Licensed 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 com.google.common.hash;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkPositionIndexes;
+
+/**
+ * Skeleton implementation of {@link HashFunction} in terms of {@link #newHasher()}.
+ *
+ * <p>TODO(lowasser): make public
+ */
+abstract class AbstractHashFunction implements HashFunction {
+  @Override
+  public <T extends Object> HashCode hashObject(T instance, Funnel<? super T> funnel) {
+    return newHasher().putObject(instance, funnel).hash();
+  }
+
+  @Override
+  public HashCode hashUnencodedChars(CharSequence input) {
+    int len = input.length();
+    return newHasher(len * 2).putUnencodedChars(input).hash();
+  }
+
+  @Override
+  public HashCode hashString(CharSequence input, Charset charset) {
+    return newHasher().putString(input, charset).hash();
+  }
+
+  @Override
+  public HashCode hashInt(int input) {
+    return newHasher(4).putInt(input).hash();
+  }
+
+  @Override
+  public HashCode hashLong(long input) {
+    return newHasher(8).putLong(input).hash();
+  }
+
+  @Override
+  public HashCode hashBytes(byte[] input) {
+    return hashBytes(input, 0, input.length);
+  }
+
+  @Override
+  public HashCode hashBytes(byte[] input, int off, int len) {
+    checkPositionIndexes(off, off + len, input.length);
+    return newHasher(len).putBytes(input, off, len).hash();
+  }
+
+  @Override
+  public HashCode hashBytes(ByteBuffer input) {
+    return newHasher(input.remaining()).putBytes(input).hash();
+  }
+
+  @Override
+  public Hasher newHasher(int expectedInputSize) {
+    checkArgument(
+        expectedInputSize >= 0, "expectedInputSize must be >= 0 but was %s", expectedInputSize);
+    return newHasher();
+  }
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/hash/AbstractHasher.java b/iotdb-core/node-commons/src/main/java/com/google/common/hash/AbstractHasher.java
new file mode 100644
index 0000000..eb49f37
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/hash/AbstractHasher.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed 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 com.google.common.hash;
+
+import com.google.common.base.Preconditions;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * An abstract implementation of {@link Hasher}, which only requires subtypes to implement {@link
+ * #putByte}. Subtypes may provide more efficient implementations, however.
+ *
+ * @author Dimitris Andreou
+ */
+abstract class AbstractHasher implements Hasher {
+  @Override
+  public final Hasher putBoolean(boolean b) {
+    return putByte(b ? (byte) 1 : (byte) 0);
+  }
+
+  @Override
+  public final Hasher putDouble(double d) {
+    return putLong(Double.doubleToRawLongBits(d));
+  }
+
+  @Override
+  public final Hasher putFloat(float f) {
+    return putInt(Float.floatToRawIntBits(f));
+  }
+
+  @Override
+  public Hasher putUnencodedChars(CharSequence charSequence) {
+    for (int i = 0, len = charSequence.length(); i < len; i++) {
+      putChar(charSequence.charAt(i));
+    }
+    return this;
+  }
+
+  @Override
+  public Hasher putString(CharSequence charSequence, Charset charset) {
+    return putBytes(charSequence.toString().getBytes(charset));
+  }
+
+  @Override
+  public Hasher putBytes(byte[] bytes) {
+    return putBytes(bytes, 0, bytes.length);
+  }
+
+  @Override
+  public Hasher putBytes(byte[] bytes, int off, int len) {
+    Preconditions.checkPositionIndexes(off, off + len, bytes.length);
+    for (int i = 0; i < len; i++) {
+      putByte(bytes[off + i]);
+    }
+    return this;
+  }
+
+  @Override
+  public Hasher putBytes(ByteBuffer b) {
+    if (b.hasArray()) {
+      putBytes(b.array(), b.arrayOffset() + b.position(), b.remaining());
+      Java8Compatibility.position(b, b.limit());
+    } else {
+      for (int remaining = b.remaining(); remaining > 0; remaining--) {
+        putByte(b.get());
+      }
+    }
+    return this;
+  }
+
+  @Override
+  public Hasher putShort(short s) {
+    putByte((byte) s);
+    putByte((byte) (s >>> 8));
+    return this;
+  }
+
+  @Override
+  public Hasher putInt(int i) {
+    putByte((byte) i);
+    putByte((byte) (i >>> 8));
+    putByte((byte) (i >>> 16));
+    putByte((byte) (i >>> 24));
+    return this;
+  }
+
+  @Override
+  public Hasher putLong(long l) {
+    for (int i = 0; i < 64; i += 8) {
+      putByte((byte) (l >>> i));
+    }
+    return this;
+  }
+
+  @Override
+  public Hasher putChar(char c) {
+    putByte((byte) c);
+    putByte((byte) (c >>> 8));
+    return this;
+  }
+
+  @Override
+  public <T extends Object> Hasher putObject(T instance, Funnel<? super T> funnel) {
+    funnel.funnel(instance, this);
+    return this;
+  }
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/hash/AbstractStreamingHasher.java b/iotdb-core/node-commons/src/main/java/com/google/common/hash/AbstractStreamingHasher.java
new file mode 100644
index 0000000..718fb36
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/hash/AbstractStreamingHasher.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed 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 com.google.common.hash;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * A convenience base class for implementors of {@code Hasher}; handles accumulating data until an
+ * entire "chunk" (of implementation-dependent length) is ready to be hashed.
+ *
+ * @author Kevin Bourrillion
+ * @author Dimitris Andreou
+ */
+// TODO(kevinb): this class still needs some design-and-document-for-inheritance love
+abstract class AbstractStreamingHasher extends AbstractHasher {
+  /** Buffer via which we pass data to the hash algorithm (the implementor) */
+  private final ByteBuffer buffer;
+
+  /** Number of bytes to be filled before process() invocation(s). */
+  private final int bufferSize;
+
+  /** Number of bytes processed per process() invocation. */
+  private final int chunkSize;
+
+  /**
+   * Constructor for use by subclasses. This hasher instance will process chunks of the specified
+   * size.
+   *
+   * @param chunkSize the number of bytes available per {@link #process(ByteBuffer)} invocation;
+   *     must be at least 4
+   */
+  protected AbstractStreamingHasher(int chunkSize) {
+    this(chunkSize, chunkSize);
+  }
+
+  /**
+   * Constructor for use by subclasses. This hasher instance will process chunks of the specified
+   * size, using an internal buffer of {@code bufferSize} size, which must be a multiple of {@code
+   * chunkSize}.
+   *
+   * @param chunkSize the number of bytes available per {@link #process(ByteBuffer)} invocation;
+   *     must be at least 4
+   * @param bufferSize the size of the internal buffer. Must be a multiple of chunkSize
+   */
+  protected AbstractStreamingHasher(int chunkSize, int bufferSize) {
+    // TODO(kevinb): check more preconditions (as bufferSize >= chunkSize) if this is ever public
+    checkArgument(bufferSize % chunkSize == 0);
+
+    // TODO(user): benchmark performance difference with longer buffer
+    // always space for a single primitive
+    this.buffer = ByteBuffer.allocate(bufferSize + 7).order(ByteOrder.LITTLE_ENDIAN);
+    this.bufferSize = bufferSize;
+    this.chunkSize = chunkSize;
+  }
+
+  /** Processes the available bytes of the buffer (at most {@code chunk} bytes). */
+  protected abstract void process(ByteBuffer bb);
+
+  /**
+   * This is invoked for the last bytes of the input, which are not enough to fill a whole chunk.
+   * The passed {@code ByteBuffer} is guaranteed to be non-empty.
+   *
+   * <p>This implementation simply pads with zeros and delegates to {@link #process(ByteBuffer)}.
+   */
+  protected void processRemaining(ByteBuffer bb) {
+    Java8Compatibility.position(bb, bb.limit()); // move at the end
+    Java8Compatibility.limit(bb, chunkSize + 7); // get ready to pad with longs
+    while (bb.position() < chunkSize) {
+      bb.putLong(0);
+    }
+    Java8Compatibility.limit(bb, chunkSize);
+    Java8Compatibility.flip(bb);
+    process(bb);
+  }
+
+  @Override
+  public final Hasher putBytes(byte[] bytes, int off, int len) {
+    return putBytesInternal(ByteBuffer.wrap(bytes, off, len).order(ByteOrder.LITTLE_ENDIAN));
+  }
+
+  @Override
+  public final Hasher putBytes(ByteBuffer readBuffer) {
+    ByteOrder order = readBuffer.order();
+    try {
+      readBuffer.order(ByteOrder.LITTLE_ENDIAN);
+      return putBytesInternal(readBuffer);
+    } finally {
+      readBuffer.order(order);
+    }
+  }
+
+  private Hasher putBytesInternal(ByteBuffer readBuffer) {
+    // If we have room for all of it, this is easy
+    if (readBuffer.remaining() <= buffer.remaining()) {
+      buffer.put(readBuffer);
+      munchIfFull();
+      return this;
+    }
+
+    // First add just enough to fill buffer size, and munch that
+    int bytesToCopy = bufferSize - buffer.position();
+    for (int i = 0; i < bytesToCopy; i++) {
+      buffer.put(readBuffer.get());
+    }
+    munch(); // buffer becomes empty here, since chunkSize divides bufferSize
+
+    // Now process directly from the rest of the input buffer
+    while (readBuffer.remaining() >= chunkSize) {
+      process(readBuffer);
+    }
+
+    // Finally stick the remainder back in our usual buffer
+    buffer.put(readBuffer);
+    return this;
+  }
+
+  /*
+   * Note: hashString(CharSequence, Charset) is intentionally not overridden.
+   *
+   * While intuitively, using CharsetEncoder to encode the CharSequence directly to the buffer (or
+   * even to an intermediate buffer) should be considerably more efficient than potentially
+   * copying the CharSequence to a String and then calling getBytes(Charset) on that String, in
+   * reality there are optimizations that make the getBytes(Charset) approach considerably faster,
+   * at least for commonly used charsets like UTF-8.
+   */
+
+  @Override
+  public final Hasher putByte(byte b) {
+    buffer.put(b);
+    munchIfFull();
+    return this;
+  }
+
+  @Override
+  public final Hasher putShort(short s) {
+    buffer.putShort(s);
+    munchIfFull();
+    return this;
+  }
+
+  @Override
+  public final Hasher putChar(char c) {
+    buffer.putChar(c);
+    munchIfFull();
+    return this;
+  }
+
+  @Override
+  public final Hasher putInt(int i) {
+    buffer.putInt(i);
+    munchIfFull();
+    return this;
+  }
+
+  @Override
+  public final Hasher putLong(long l) {
+    buffer.putLong(l);
+    munchIfFull();
+    return this;
+  }
+
+  @Override
+  public final HashCode hash() {
+    munch();
+    Java8Compatibility.flip(buffer);
+    if (buffer.remaining() > 0) {
+      processRemaining(buffer);
+      Java8Compatibility.position(buffer, buffer.limit());
+    }
+    return makeHash();
+  }
+
+  /**
+   * Computes a hash code based on the data that have been provided to this hasher. This is called
+   * after all chunks are handled with {@link #process} and any leftover bytes that did not make a
+   * complete chunk are handled with {@link #processRemaining}.
+   */
+  protected abstract HashCode makeHash();
+
+  // Process pent-up data in chunks
+  private void munchIfFull() {
+    if (buffer.remaining() < 8) {
+      // buffer is full; not enough room for a primitive. We have at least one full chunk.
+      munch();
+    }
+  }
+
+  private void munch() {
+    Java8Compatibility.flip(buffer);
+    while (buffer.remaining() >= chunkSize) {
+      // we could limit the buffer to ensure process() does not read more than
+      // chunkSize number of bytes, but we trust the implementations
+      process(buffer);
+    }
+    buffer.compact(); // preserve any remaining data that do not make a full chunk
+  }
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/hash/Funnel.java b/iotdb-core/node-commons/src/main/java/com/google/common/hash/Funnel.java
new file mode 100644
index 0000000..a0bbd91
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/hash/Funnel.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed 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 com.google.common.hash;
+
+import java.io.Serializable;
+
+/**
+ * An object which can send data from an object of type {@code T} into a {@code PrimitiveSink}.
+ * Implementations for common types can be found in {@link Funnels}.
+ *
+ * <p>Note that serialization of {@linkplain BloomFilter bloom filters} requires the proper
+ * serialization of funnels. When possible, it is recommended that funnels be implemented as a
+ * single-element enum to maintain serialization guarantees. See Effective Java (2nd Edition), Item
+ * 3: "Enforce the singleton property with a private constructor or an enum type". For example:
+ *
+ * <pre>{@code
+ * public enum PersonFunnel implements Funnel<Person> {
+ *   INSTANCE;
+ *   public void funnel(Person person, PrimitiveSink into) {
+ *     into.putUnencodedChars(person.getFirstName())
+ *         .putUnencodedChars(person.getLastName())
+ *         .putInt(person.getAge());
+ *   }
+ * }
+ * }</pre>
+ *
+ * @author Dimitris Andreou
+ * @since 11.0
+ */
+public interface Funnel<T extends Object> extends Serializable {
+
+  /**
+   * Sends a stream of data from the {@code from} object into the sink {@code into}. There is no
+   * requirement that this data be complete enough to fully reconstitute the object later.
+   *
+   * @since 12.0 (in Guava 11.0, {@code PrimitiveSink} was named {@code Sink})
+   */
+  void funnel(T from, PrimitiveSink into);
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/hash/HashCode.java b/iotdb-core/node-commons/src/main/java/com/google/common/hash/HashCode.java
new file mode 100644
index 0000000..69eae71
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/hash/HashCode.java
@@ -0,0 +1,430 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed 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 com.google.common.hash;
+
+import com.google.common.base.Preconditions;
+import com.google.common.primitives.Ints;
+
+import javax.annotation.CheckForNull;
+
+import java.io.Serializable;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * An immutable hash code of arbitrary bit length.
+ *
+ * @author Dimitris Andreou
+ * @author Kurt Alfred Kluever
+ * @since 11.0
+ */
+public abstract class HashCode {
+  HashCode() {}
+
+  /** Returns the number of bits in this hash code; a positive multiple of 8. */
+  public abstract int bits();
+
+  /**
+   * Returns the first four bytes of {@linkplain #asBytes() this hashcode's bytes}, converted to an
+   * {@code int} value in little-endian order.
+   *
+   * @throws IllegalStateException if {@code bits() < 32}
+   */
+  public abstract int asInt();
+
+  /**
+   * Returns the first eight bytes of {@linkplain #asBytes() this hashcode's bytes}, converted to a
+   * {@code long} value in little-endian order.
+   *
+   * @throws IllegalStateException if {@code bits() < 64}
+   */
+  public abstract long asLong();
+
+  /**
+   * If this hashcode has enough bits, returns {@code asLong()}, otherwise returns a {@code long}
+   * value with {@code asBytes()} as the least-significant bytes and {@code 0x00} as the remaining
+   * most-significant bytes.
+   *
+   * @since 14.0 (since 11.0 as {@code Hashing.padToLong(HashCode)})
+   */
+  public abstract long padToLong();
+
+  /**
+   * Returns the value of this hash code as a byte array. The caller may modify the byte array;
+   * changes to it will <i>not</i> be reflected in this {@code HashCode} object or any other arrays
+   * returned by this method.
+   */
+  // TODO(user): consider ByteString here, when that is available
+  public abstract byte[] asBytes();
+
+  /**
+   * Copies bytes from this hash code into {@code dest}.
+   *
+   * @param dest the byte array into which the hash code will be written
+   * @param offset the start offset in the data
+   * @param maxLength the maximum number of bytes to write
+   * @return the number of bytes written to {@code dest}
+   * @throws IndexOutOfBoundsException if there is not enough room in {@code dest}
+   */
+  public int writeBytesTo(byte[] dest, int offset, int maxLength) {
+    maxLength = Ints.min(maxLength, bits() / 8);
+    Preconditions.checkPositionIndexes(offset, offset + maxLength, dest.length);
+    writeBytesToImpl(dest, offset, maxLength);
+    return maxLength;
+  }
+
+  abstract void writeBytesToImpl(byte[] dest, int offset, int maxLength);
+
+  /**
+   * Returns a mutable view of the underlying bytes for the given {@code HashCode} if it is a
+   * byte-based hashcode. Otherwise it returns {@link HashCode#asBytes}. Do <i>not</i> mutate this
+   * array or else you will break the immutability contract of {@code HashCode}.
+   */
+  byte[] getBytesInternal() {
+    return asBytes();
+  }
+
+  /**
+   * Returns whether this {@code HashCode} and that {@code HashCode} have the same value, given that
+   * they have the same number of bits.
+   */
+  abstract boolean equalsSameBits(HashCode that);
+
+  /**
+   * Creates a 32-bit {@code HashCode} representation of the given int value. The underlying bytes
+   * are interpreted in little endian order.
+   *
+   * @since 15.0 (since 12.0 in HashCodes)
+   */
+  public static HashCode fromInt(int hash) {
+    return new IntHashCode(hash);
+  }
+
+  private static final class IntHashCode extends HashCode implements Serializable {
+    static final long INT_MASK = 0xffffffffL;
+    final int hash;
+
+    IntHashCode(int hash) {
+      this.hash = hash;
+    }
+
+    @Override
+    public int bits() {
+      return 32;
+    }
+
+    @Override
+    public byte[] asBytes() {
+      return new byte[] {(byte) hash, (byte) (hash >> 8), (byte) (hash >> 16), (byte) (hash >> 24)};
+    }
+
+    @Override
+    public int asInt() {
+      return hash;
+    }
+
+    @Override
+    public long asLong() {
+      throw new IllegalStateException("this HashCode only has 32 bits; cannot create a long");
+    }
+
+    @Override
+    public long padToLong() {
+      return toLong(hash);
+    }
+
+    /**
+     * Returns the value of the given {@code int} as a {@code long}, when treated as unsigned.
+     *
+     * <p><b>Java 8 users:</b> use {@link Integer#toUnsignedLong(int)} instead.
+     */
+    public static long toLong(int value) {
+      return value & INT_MASK;
+    }
+
+    @Override
+    void writeBytesToImpl(byte[] dest, int offset, int maxLength) {
+      for (int i = 0; i < maxLength; i++) {
+        dest[offset + i] = (byte) (hash >> (i * 8));
+      }
+    }
+
+    @Override
+    boolean equalsSameBits(HashCode that) {
+      return hash == that.asInt();
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+
+  /**
+   * Creates a 64-bit {@code HashCode} representation of the given long value. The underlying bytes
+   * are interpreted in little endian order.
+   *
+   * @since 15.0 (since 12.0 in HashCodes)
+   */
+  public static HashCode fromLong(long hash) {
+    return new LongHashCode(hash);
+  }
+
+  private static final class LongHashCode extends HashCode implements Serializable {
+    final long hash;
+
+    LongHashCode(long hash) {
+      this.hash = hash;
+    }
+
+    @Override
+    public int bits() {
+      return 64;
+    }
+
+    @Override
+    public byte[] asBytes() {
+      return new byte[] {
+        (byte) hash,
+        (byte) (hash >> 8),
+        (byte) (hash >> 16),
+        (byte) (hash >> 24),
+        (byte) (hash >> 32),
+        (byte) (hash >> 40),
+        (byte) (hash >> 48),
+        (byte) (hash >> 56)
+      };
+    }
+
+    @Override
+    public int asInt() {
+      return (int) hash;
+    }
+
+    @Override
+    public long asLong() {
+      return hash;
+    }
+
+    @Override
+    public long padToLong() {
+      return hash;
+    }
+
+    @Override
+    void writeBytesToImpl(byte[] dest, int offset, int maxLength) {
+      for (int i = 0; i < maxLength; i++) {
+        dest[offset + i] = (byte) (hash >> (i * 8));
+      }
+    }
+
+    @Override
+    boolean equalsSameBits(HashCode that) {
+      return hash == that.asLong();
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+
+  /**
+   * Creates a {@code HashCode} from a byte array. The array is defensively copied to preserve the
+   * immutability contract of {@code HashCode}. The array cannot be empty.
+   *
+   * @since 15.0 (since 12.0 in HashCodes)
+   */
+  public static HashCode fromBytes(byte[] bytes) {
+    checkArgument(bytes.length >= 1, "A HashCode must contain at least 1 byte.");
+    return fromBytesNoCopy(bytes.clone());
+  }
+
+  /**
+   * Creates a {@code HashCode} from a byte array. The array is <i>not</i> copied defensively, so it
+   * must be handed-off so as to preserve the immutability contract of {@code HashCode}.
+   */
+  static HashCode fromBytesNoCopy(byte[] bytes) {
+    return new BytesHashCode(bytes);
+  }
+
+  private static final class BytesHashCode extends HashCode implements Serializable {
+    final byte[] bytes;
+
+    BytesHashCode(byte[] bytes) {
+      this.bytes = checkNotNull(bytes);
+    }
+
+    @Override
+    public int bits() {
+      return bytes.length * 8;
+    }
+
+    @Override
+    public byte[] asBytes() {
+      return bytes.clone();
+    }
+
+    @Override
+    public int asInt() {
+      checkState(
+          bytes.length >= 4,
+          "HashCode#asInt() requires >= 4 bytes (it only has %s bytes).",
+          bytes.length);
+      return (bytes[0] & 0xFF)
+          | ((bytes[1] & 0xFF) << 8)
+          | ((bytes[2] & 0xFF) << 16)
+          | ((bytes[3] & 0xFF) << 24);
+    }
+
+    @Override
+    public long asLong() {
+      checkState(
+          bytes.length >= 8,
+          "HashCode#asLong() requires >= 8 bytes (it only has %s bytes).",
+          bytes.length);
+      return padToLong();
+    }
+
+    @Override
+    public long padToLong() {
+      long retVal = (bytes[0] & 0xFF);
+      for (int i = 1; i < Math.min(bytes.length, 8); i++) {
+        retVal |= (bytes[i] & 0xFFL) << (i * 8);
+      }
+      return retVal;
+    }
+
+    @Override
+    void writeBytesToImpl(byte[] dest, int offset, int maxLength) {
+      System.arraycopy(bytes, 0, dest, offset, maxLength);
+    }
+
+    @Override
+    byte[] getBytesInternal() {
+      return bytes;
+    }
+
+    @Override
+    boolean equalsSameBits(HashCode that) {
+      // We don't use MessageDigest.isEqual() here because its contract does not guarantee
+      // constant-time evaluation (no short-circuiting).
+      if (this.bytes.length != that.getBytesInternal().length) {
+        return false;
+      }
+
+      boolean areEqual = true;
+      for (int i = 0; i < this.bytes.length; i++) {
+        areEqual &= (this.bytes[i] == that.getBytesInternal()[i]);
+      }
+      return areEqual;
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+
+  /**
+   * Creates a {@code HashCode} from a hexadecimal ({@code base 16}) encoded string. The string must
+   * be at least 2 characters long, and contain only valid, lower-cased hexadecimal characters.
+   *
+   * <p>This method accepts the exact format generated by {@link #toString}. If you require more
+   * lenient {@code base 16} decoding, please use {@link com.google.common.io.BaseEncoding#decode}
+   * (and pass the result to {@link #fromBytes}).
+   *
+   * @since 15.0
+   */
+  public static HashCode fromString(String string) {
+    checkArgument(
+        string.length() >= 2, "input string (%s) must have at least 2 characters", string);
+    checkArgument(
+        string.length() % 2 == 0,
+        "input string (%s) must have an even number of characters",
+        string);
+
+    byte[] bytes = new byte[string.length() / 2];
+    for (int i = 0; i < string.length(); i += 2) {
+      int ch1 = decode(string.charAt(i)) << 4;
+      int ch2 = decode(string.charAt(i + 1));
+      bytes[i / 2] = (byte) (ch1 + ch2);
+    }
+    return fromBytesNoCopy(bytes);
+  }
+
+  private static int decode(char ch) {
+    if (ch >= '0' && ch <= '9') {
+      return ch - '0';
+    }
+    if (ch >= 'a' && ch <= 'f') {
+      return ch - 'a' + 10;
+    }
+    throw new IllegalArgumentException("Illegal hexadecimal character: " + ch);
+  }
+
+  /**
+   * Returns {@code true} if {@code object} is a {@link HashCode} instance with the identical byte
+   * representation to this hash code.
+   *
+   * <p><b>Security note:</b> this method uses a constant-time (not short-circuiting) implementation
+   * to protect against <a href="http://en.wikipedia.org/wiki/Timing_attack">timing attacks</a>.
+   */
+  @Override
+  public final boolean equals(@CheckForNull Object object) {
+    if (object instanceof HashCode) {
+      HashCode that = (HashCode) object;
+      return bits() == that.bits() && equalsSameBits(that);
+    }
+    return false;
+  }
+
+  /**
+   * Returns a "Java hash code" for this {@code HashCode} instance; this is well-defined (so, for
+   * example, you can safely put {@code HashCode} instances into a {@code HashSet}) but is otherwise
+   * probably not what you want to use.
+   */
+  @Override
+  public final int hashCode() {
+    // If we have at least 4 bytes (32 bits), just take the first 4 bytes. Since this is
+    // already a (presumably) high-quality hash code, any four bytes of it will do.
+    if (bits() >= 32) {
+      return asInt();
+    }
+    // If we have less than 4 bytes, use them all.
+    byte[] bytes = getBytesInternal();
+    int val = (bytes[0] & 0xFF);
+    for (int i = 1; i < bytes.length; i++) {
+      val |= ((bytes[i] & 0xFF) << (i * 8));
+    }
+    return val;
+  }
+
+  /**
+   * Returns a string containing each byte of {@link #asBytes}, in order, as a two-digit unsigned
+   * hexadecimal number in lower case.
+   *
+   * <p>Note that if the output is considered to be a single hexadecimal number, whether this string
+   * is big-endian or little-endian depends on the byte order of {@link #asBytes}. This may be
+   * surprising for implementations of {@code HashCode} that represent the number in big-endian
+   * since everything else in the hashing API uniformly treats multibyte values as little-endian.
+   *
+   * <p>To create a {@code HashCode} from its string representation, see {@link #fromString}.
+   */
+  @Override
+  public final String toString() {
+    byte[] bytes = getBytesInternal();
+    StringBuilder sb = new StringBuilder(2 * bytes.length);
+    for (byte b : bytes) {
+      sb.append(hexDigits[(b >> 4) & 0xf]).append(hexDigits[b & 0xf]);
+    }
+    return sb.toString();
+  }
+
+  private static final char[] hexDigits = "0123456789abcdef".toCharArray();
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/hash/HashFunction.java b/iotdb-core/node-commons/src/main/java/com/google/common/hash/HashFunction.java
new file mode 100644
index 0000000..a6ed525
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/hash/HashFunction.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed 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 com.google.common.hash;
+
+import com.google.common.primitives.Ints;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * A hash function is a collision-averse pure function that maps an arbitrary block of data to a
+ * number called a <i>hash code</i>.
+ *
+ * <h3>Definition</h3>
+ *
+ * <p>Unpacking this definition:
+ *
+ * <ul>
+ *   <li><b>block of data:</b> the input for a hash function is always, in concept, an ordered byte
+ *       array. This hashing API accepts an arbitrary sequence of byte and multibyte values (via
+ *       {@link Hasher}), but this is merely a convenience; these are always translated into raw
+ *       byte sequences under the covers.
+ *   <li><b>hash code:</b> each hash function always yields hash codes of the same fixed bit length
+ *       (given by {@link #bits}). For example, {@link Hashing#sha1} produces a 160-bit number,
+ *       while {@link Hashing#murmur3_32()} yields only 32 bits. Because a {@code long} value is
+ *       clearly insufficient to hold all hash code values, this API represents a hash code as an
+ *       instance of {@link HashCode}.
+ *   <li><b>pure function:</b> the value produced must depend only on the input bytes, in the order
+ *       they appear. Input data is never modified. {@link HashFunction} instances should always be
+ *       stateless, and therefore thread-safe.
+ *   <li><b>collision-averse:</b> while it can't be helped that a hash function will sometimes
+ *       produce the same hash code for distinct inputs (a "collision"), every hash function strives
+ *       to <i>some</i> degree to make this unlikely. (Without this condition, a function that
+ *       always returns zero could be called a hash function. It is not.)
+ * </ul>
+ *
+ * <p>Summarizing the last two points: "equal yield equal <i>always</i>; unequal yield unequal
+ * <i>often</i>." This is the most important characteristic of all hash functions.
+ *
+ * <h3>Desirable properties</h3>
+ *
+ * <p>A high-quality hash function strives for some subset of the following virtues:
+ *
+ * <ul>
+ *   <li><b>collision-resistant:</b> while the definition above requires making at least <i>some</i>
+ *       token attempt, one measure of the quality of a hash function is <i>how well</i> it succeeds
+ *       at this goal. Important note: it may be easy to achieve the theoretical minimum collision
+ *       rate when using completely <i>random</i> sample input. The true test of a hash function is
+ *       how it performs on representative real-world data, which tends to contain many hidden
+ *       patterns and clumps. The goal of a good hash function is to stamp these patterns out as
+ *       thoroughly as possible.
+ *   <li><b>bit-dispersing:</b> masking out any <i>single bit</i> from a hash code should yield only
+ *       the expected <i>twofold</i> increase to all collision rates. Informally, the "information"
+ *       in the hash code should be as evenly "spread out" through the hash code's bits as possible.
+ *       The result is that, for example, when choosing a bucket in a hash table of size 2^8,
+ *       <i>any</i> eight bits could be consistently used.
+ *   <li><b>cryptographic:</b> certain hash functions such as {@link Hashing#sha512} are designed to
+ *       make it as infeasible as possible to reverse-engineer the input that produced a given hash
+ *       code, or even to discover <i>any</i> two distinct inputs that yield the same result. These
+ *       are called <i>cryptographic hash functions</i>. But, whenever it is learned that either of
+ *       these feats has become computationally feasible, the function is deemed "broken" and should
+ *       no longer be used for secure purposes. (This is the likely eventual fate of <i>all</i>
+ *       cryptographic hashes.)
+ *   <li><b>fast:</b> perhaps self-explanatory, but often the most important consideration.
+ * </ul>
+ *
+ * <h3>Providing input to a hash function</h3>
+ *
+ * <p>The primary way to provide the data that your hash function should act on is via a {@link
+ * Hasher}. Obtain a new hasher from the hash function using {@link #newHasher}, "push" the relevant
+ * data into it using methods like {@link Hasher#putBytes(byte[])}, and finally ask for the {@code
+ * HashCode} when finished using {@link Hasher#hash}. (See an {@linkplain #newHasher example} of
+ * this.)
+ *
+ * <p>If all you want to hash is a single byte array, string or {@code long} value, there are
+ * convenient shortcut methods defined directly on {@link HashFunction} to make this easier.
+ *
+ * <p>Hasher accepts primitive data types, but can also accept any Object of type {@code T} provided
+ * that you implement a {@link Funnel}{@code <T>} to specify how to "feed" data from that object
+ * into the function. (See {@linkplain Hasher#putObject an example} of this.)
+ *
+ * <p><b>Compatibility note:</b> Throughout this API, multibyte values are always interpreted in
+ * <i>little-endian</i> order. That is, hashing the byte array {@code {0x01, 0x02, 0x03, 0x04}} is
+ * equivalent to hashing the {@code int} value {@code 0x04030201}. If this isn't what you need,
+ * methods such as {@link Integer#reverseBytes} and {@link Ints#toByteArray} will help.
+ *
+ * <h3>Relationship to {@link Object#hashCode}</h3>
+ *
+ * <p>Java's baked-in concept of hash codes is constrained to 32 bits, and provides no separation
+ * between hash algorithms and the data they act on, so alternate hash algorithms can't be easily
+ * substituted. Also, implementations of {@code hashCode} tend to be poor-quality, in part because
+ * they end up depending on <i>other</i> existing poor-quality {@code hashCode} implementations,
+ * including those in many JDK classes.
+ *
+ * <p>{@code Object.hashCode} implementations tend to be very fast, but have weak collision
+ * prevention and <i>no</i> expectation of bit dispersion. This leaves them perfectly suitable for
+ * use in hash tables, because extra collisions cause only a slight performance hit, while poor bit
+ * dispersion is easily corrected using a secondary hash function (which all reasonable hash table
+ * implementations in Java use). For the many uses of hash functions beyond data structures,
+ * however, {@code Object.hashCode} almost always falls short -- hence this library.
+ *
+ * @author Kevin Bourrillion
+ * @since 11.0
+ */
+public interface HashFunction {
+  /**
+   * Begins a new hash code computation by returning an initialized, stateful {@code Hasher}
+   * instance that is ready to receive data. Example:
+   *
+   * <pre>{@code
+   * HashFunction hf = Hashing.md5();
+   * HashCode hc = hf.newHasher()
+   *     .putLong(id)
+   *     .putBoolean(isActive)
+   *     .hash();
+   * }</pre>
+   */
+  Hasher newHasher();
+
+  /**
+   * Begins a new hash code computation as {@link #newHasher()}, but provides a hint of the expected
+   * size of the input (in bytes). This is only important for non-streaming hash functions (hash
+   * functions that need to buffer their whole input before processing any of it).
+   */
+  Hasher newHasher(int expectedInputSize);
+
+  /**
+   * Shortcut for {@code newHasher().putInt(input).hash()}; returns the hash code for the given
+   * {@code int} value, interpreted in little-endian byte order. The implementation <i>might</i>
+   * perform better than its longhand equivalent, but should not perform worse.
+   *
+   * @since 12.0
+   */
+  HashCode hashInt(int input);
+
+  /**
+   * Shortcut for {@code newHasher().putLong(input).hash()}; returns the hash code for the given
+   * {@code long} value, interpreted in little-endian byte order. The implementation <i>might</i>
+   * perform better than its longhand equivalent, but should not perform worse.
+   */
+  HashCode hashLong(long input);
+
+  /**
+   * Shortcut for {@code newHasher().putBytes(input).hash()}. The implementation <i>might</i>
+   * perform better than its longhand equivalent, but should not perform worse.
+   */
+  HashCode hashBytes(byte[] input);
+
+  /**
+   * Shortcut for {@code newHasher().putBytes(input, off, len).hash()}. The implementation
+   * <i>might</i> perform better than its longhand equivalent, but should not perform worse.
+   *
+   * @throws IndexOutOfBoundsException if {@code off < 0} or {@code off + len > bytes.length} or
+   *     {@code len < 0}
+   */
+  HashCode hashBytes(byte[] input, int off, int len);
+
+  /**
+   * Shortcut for {@code newHasher().putBytes(input).hash()}. The implementation <i>might</i>
+   * perform better than its longhand equivalent, but should not perform worse.
+   *
+   * @since 23.0
+   */
+  HashCode hashBytes(ByteBuffer input);
+
+  /**
+   * Shortcut for {@code newHasher().putUnencodedChars(input).hash()}. The implementation
+   * <i>might</i> perform better than its longhand equivalent, but should not perform worse. Note
+   * that no character encoding is performed; the low byte and high byte of each {@code char} are
+   * hashed directly (in that order).
+   *
+   * <p><b>Warning:</b> This method will produce different output than most other languages do when
+   * running the same hash function on the equivalent input. For cross-language compatibility, use
+   * {@link #hashString}, usually with a charset of UTF-8. For other use cases, use {@code
+   * hashUnencodedChars}.
+   *
+   * @since 15.0 (since 11.0 as hashString(CharSequence)).
+   */
+  HashCode hashUnencodedChars(CharSequence input);
+
+  /**
+   * Shortcut for {@code newHasher().putString(input, charset).hash()}. Characters are encoded using
+   * the given {@link Charset}. The implementation <i>might</i> perform better than its longhand
+   * equivalent, but should not perform worse.
+   *
+   * <p><b>Warning:</b> This method, which reencodes the input before hashing it, is useful only for
+   * cross-language compatibility. For other use cases, prefer {@link #hashUnencodedChars}, which is
+   * faster, produces the same output across Java releases, and hashes every {@code char} in the
+   * input, even if some are invalid.
+   */
+  HashCode hashString(CharSequence input, Charset charset);
+
+  /**
+   * Shortcut for {@code newHasher().putObject(instance, funnel).hash()}. The implementation
+   * <i>might</i> perform better than its longhand equivalent, but should not perform worse.
+   *
+   * @since 14.0
+   */
+  <T extends Object> HashCode hashObject(T instance, Funnel<? super T> funnel);
+
+  /**
+   * Returns the number of bits (a multiple of 32) that each hash code produced by this hash
+   * function has.
+   */
+  int bits();
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/hash/Hasher.java b/iotdb-core/node-commons/src/main/java/com/google/common/hash/Hasher.java
new file mode 100644
index 0000000..034753df
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/hash/Hasher.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed 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 com.google.common.hash;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * A {@link PrimitiveSink} that can compute a hash code after reading the input. Each hasher should
+ * translate all multibyte values ({@link #putInt(int)}, {@link #putLong(long)}, etc) to bytes in
+ * little-endian order.
+ *
+ * <p><b>Warning:</b> The result of calling any methods after calling {@link #hash} is undefined.
+ *
+ * <p><b>Warning:</b> Using a specific character encoding when hashing a {@link CharSequence} with
+ * {@link #putString(CharSequence, Charset)} is generally only useful for cross-language
+ * compatibility (otherwise prefer {@link #putUnencodedChars}). However, the character encodings
+ * must be identical across languages. Also beware that {@link Charset} definitions may occasionally
+ * change between Java releases.
+ *
+ * <p><b>Warning:</b> Chunks of data that are put into the {@link Hasher} are not delimited. The
+ * resulting {@link HashCode} is dependent only on the bytes inserted, and the order in which they
+ * were inserted, not how those bytes were chunked into discrete put() operations. For example, the
+ * following three expressions all generate colliding hash codes:
+ *
+ * <pre>{@code
+ * newHasher().putByte(b1).putByte(b2).putByte(b3).hash()
+ * newHasher().putByte(b1).putBytes(new byte[] { b2, b3 }).hash()
+ * newHasher().putBytes(new byte[] { b1, b2, b3 }).hash()
+ * }</pre>
+ *
+ * <p>If you wish to avoid this, you should either prepend or append the size of each chunk. Keep in
+ * mind that when dealing with char sequences, the encoded form of two concatenated char sequences
+ * is not equivalent to the concatenation of their encoded form. Therefore, {@link
+ * #putString(CharSequence, Charset)} should only be used consistently with <i>complete</i>
+ * sequences and not broken into chunks.
+ *
+ * @author Kevin Bourrillion
+ * @since 11.0
+ */
+public interface Hasher extends PrimitiveSink {
+  @Override
+  Hasher putByte(byte b);
+
+  @Override
+  Hasher putBytes(byte[] bytes);
+
+  @Override
+  Hasher putBytes(byte[] bytes, int off, int len);
+
+  @Override
+  Hasher putBytes(ByteBuffer bytes);
+
+  @Override
+  Hasher putShort(short s);
+
+  @Override
+  Hasher putInt(int i);
+
+  @Override
+  Hasher putLong(long l);
+
+  /** Equivalent to {@code putInt(Float.floatToRawIntBits(f))}. */
+  @Override
+  Hasher putFloat(float f);
+
+  /** Equivalent to {@code putLong(Double.doubleToRawLongBits(d))}. */
+  @Override
+  Hasher putDouble(double d);
+
+  /** Equivalent to {@code putByte(b ? (byte) 1 : (byte) 0)}. */
+  @Override
+  Hasher putBoolean(boolean b);
+
+  @Override
+  Hasher putChar(char c);
+
+  /**
+   * Equivalent to processing each {@code char} value in the {@code CharSequence}, in order. In
+   * other words, no character encoding is performed; the low byte and high byte of each {@code
+   * char} are hashed directly (in that order). The input must not be updated while this method is
+   * in progress.
+   *
+   * <p><b>Warning:</b> This method will produce different output than most other languages do when
+   * running the same hash function on the equivalent input. For cross-language compatibility, use
+   * {@link #putString}, usually with a charset of UTF-8. For other use cases, use {@code
+   * putUnencodedChars}.
+   *
+   * @since 15.0 (since 11.0 as putString(CharSequence)).
+   */
+  @Override
+  Hasher putUnencodedChars(CharSequence charSequence);
+
+  /**
+   * Equivalent to {@code putBytes(charSequence.toString().getBytes(charset))}.
+   *
+   * <p><b>Warning:</b> This method, which reencodes the input before hashing it, is useful only for
+   * cross-language compatibility. For other use cases, prefer {@link #putUnencodedChars}, which is
+   * faster, produces the same output across Java releases, and hashes every {@code char} in the
+   * input, even if some are invalid.
+   */
+  @Override
+  Hasher putString(CharSequence charSequence, Charset charset);
+
+  /** A simple convenience for {@code funnel.funnel(object, this)}. */
+  <T extends Object> Hasher putObject(T instance, Funnel<? super T> funnel);
+
+  /**
+   * Computes a hash code based on the data that have been provided to this hasher. The result is
+   * unspecified if this method is called more than once on the same instance.
+   */
+  HashCode hash();
+
+  /**
+   * {@inheritDoc}
+   *
+   * @deprecated This returns {@link Object#hashCode()}; you almost certainly mean to call {@code
+   *     hash().asInt()}.
+   */
+  @Override
+  @Deprecated
+  int hashCode();
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/hash/Hashing.java b/iotdb-core/node-commons/src/main/java/com/google/common/hash/Hashing.java
new file mode 100644
index 0000000..6a350dd
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/hash/Hashing.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed 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 com.google.common.hash;
+
+/**
+ * Static methods to obtain {@link HashFunction} instances, and other static hashing-related
+ * utilities.
+ *
+ * <p>A comparison of the various hash functions can be found <a
+ * href="http://goo.gl/jS7HH">here</a>.
+ *
+ * @author Kevin Bourrillion
+ * @author Dimitris Andreou
+ * @author Kurt Alfred Kluever
+ * @since 11.0
+ */
+public final class Hashing {
+  /**
+   * Used to randomize {@link #goodFastHash} instances, so that programs which persist anything
+   * dependent on the hash codes they produce will fail sooner.
+   */
+  @SuppressWarnings("GoodTime") // reading system time without TimeSource
+  static final int GOOD_FAST_HASH_SEED = (int) System.currentTimeMillis();
+
+  /**
+   * Returns a hash function implementing the <a
+   * href="https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp">128-bit murmur3
+   * algorithm, x64 variant</a> (little-endian variant), using a seed value of zero.
+   *
+   * <p>The exact C++ equivalent is the MurmurHash3_x64_128 function (Murmur3F).
+   */
+  public static HashFunction murmur3_128() {
+    return Murmur3_128HashFunction.MURMUR3_128;
+  }
+
+  private Hashing() {}
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/hash/Java8Compatibility.java b/iotdb-core/node-commons/src/main/java/com/google/common/hash/Java8Compatibility.java
new file mode 100644
index 0000000..ee8e9e8
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/hash/Java8Compatibility.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 The Guava Authors
+ *
+ * Licensed 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 com.google.common.hash;
+
+import java.nio.Buffer;
+
+/**
+ * Wrappers around {@link Buffer} methods that are covariantly overridden in Java 9+. See
+ * https://github.com/google/guava/issues/3990
+ */
+final class Java8Compatibility {
+  static void clear(Buffer b) {
+    b.clear();
+  }
+
+  static void flip(Buffer b) {
+    b.flip();
+  }
+
+  static void limit(Buffer b, int limit) {
+    b.limit(limit);
+  }
+
+  static void position(Buffer b, int position) {
+    b.position(position);
+  }
+
+  private Java8Compatibility() {}
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/hash/Murmur3_128HashFunction.java b/iotdb-core/node-commons/src/main/java/com/google/common/hash/Murmur3_128HashFunction.java
new file mode 100644
index 0000000..fddb59a
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/hash/Murmur3_128HashFunction.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed 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.
+ */
+
+/*
+ * MurmurHash3 was written by Austin Appleby, and is placed in the public
+ * domain. The author hereby disclaims copyright to this source code.
+ */
+
+/*
+ * Source:
+ * https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp
+ * (Modified to adapt to Guava coding conventions and to use the HashFunction interface)
+ */
+
+package com.google.common.hash;
+
+import javax.annotation.CheckForNull;
+
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * See MurmurHash3_x64_128 in <a href="http://smhasher.googlecode.com/svn/trunk/MurmurHash3.cpp">the
+ * C++ implementation</a>.
+ *
+ * @author Austin Appleby
+ * @author Dimitris Andreou
+ */
+final class Murmur3_128HashFunction extends AbstractHashFunction implements Serializable {
+  static final HashFunction MURMUR3_128 = new Murmur3_128HashFunction(0);
+
+  static final HashFunction GOOD_FAST_HASH_128 =
+      new Murmur3_128HashFunction(Hashing.GOOD_FAST_HASH_SEED);
+
+  // TODO(user): when the shortcuts are implemented, update BloomFilterStrategies
+  private final int seed;
+
+  Murmur3_128HashFunction(int seed) {
+    this.seed = seed;
+  }
+
+  @Override
+  public int bits() {
+    return 128;
+  }
+
+  @Override
+  public Hasher newHasher() {
+    return new Murmur3_128Hasher(seed);
+  }
+
+  @Override
+  public String toString() {
+    return "Hashing.murmur3_128(" + seed + ")";
+  }
+
+  @Override
+  public boolean equals(@CheckForNull Object object) {
+    if (object instanceof Murmur3_128HashFunction) {
+      Murmur3_128HashFunction other = (Murmur3_128HashFunction) object;
+      return seed == other.seed;
+    }
+    return false;
+  }
+
+  @Override
+  public int hashCode() {
+    return getClass().hashCode() ^ seed;
+  }
+
+  private static final class Murmur3_128Hasher extends AbstractStreamingHasher {
+    private static final int CHUNK_SIZE = 16;
+    private static final long C1 = 0x87c37b91114253d5L;
+    private static final long C2 = 0x4cf5ad432745937fL;
+    private long h1;
+    private long h2;
+    private int length;
+
+    Murmur3_128Hasher(int seed) {
+      super(CHUNK_SIZE);
+      this.h1 = seed;
+      this.h2 = seed;
+      this.length = 0;
+    }
+
+    @Override
+    protected void process(ByteBuffer bb) {
+      long k1 = bb.getLong();
+      long k2 = bb.getLong();
+      bmix64(k1, k2);
+      length += CHUNK_SIZE;
+    }
+
+    private void bmix64(long k1, long k2) {
+      h1 ^= mixK1(k1);
+
+      h1 = Long.rotateLeft(h1, 27);
+      h1 += h2;
+      h1 = h1 * 5 + 0x52dce729;
+
+      h2 ^= mixK2(k2);
+
+      h2 = Long.rotateLeft(h2, 31);
+      h2 += h1;
+      h2 = h2 * 5 + 0x38495ab5;
+    }
+
+    @Override
+    protected void processRemaining(ByteBuffer bb) {
+      long k1 = 0;
+      long k2 = 0;
+      length += bb.remaining();
+      switch (bb.remaining()) {
+        case 15:
+          k2 ^= (long) toInt(bb.get(14)) << 48; // fall through
+        case 14:
+          k2 ^= (long) toInt(bb.get(13)) << 40; // fall through
+        case 13:
+          k2 ^= (long) toInt(bb.get(12)) << 32; // fall through
+        case 12:
+          k2 ^= (long) toInt(bb.get(11)) << 24; // fall through
+        case 11:
+          k2 ^= (long) toInt(bb.get(10)) << 16; // fall through
+        case 10:
+          k2 ^= (long) toInt(bb.get(9)) << 8; // fall through
+        case 9:
+          k2 ^= (long) toInt(bb.get(8)); // fall through
+        case 8:
+          k1 ^= bb.getLong();
+          break;
+        case 7:
+          k1 ^= (long) toInt(bb.get(6)) << 48; // fall through
+        case 6:
+          k1 ^= (long) toInt(bb.get(5)) << 40; // fall through
+        case 5:
+          k1 ^= (long) toInt(bb.get(4)) << 32; // fall through
+        case 4:
+          k1 ^= (long) toInt(bb.get(3)) << 24; // fall through
+        case 3:
+          k1 ^= (long) toInt(bb.get(2)) << 16; // fall through
+        case 2:
+          k1 ^= (long) toInt(bb.get(1)) << 8; // fall through
+        case 1:
+          k1 ^= (long) toInt(bb.get(0));
+          break;
+        default:
+          throw new AssertionError("Should never get here.");
+      }
+      h1 ^= mixK1(k1);
+      h2 ^= mixK2(k2);
+    }
+
+    @Override
+    protected HashCode makeHash() {
+      h1 ^= length;
+      h2 ^= length;
+
+      h1 += h2;
+      h2 += h1;
+
+      h1 = fmix64(h1);
+      h2 = fmix64(h2);
+
+      h1 += h2;
+      h2 += h1;
+
+      return HashCode.fromBytesNoCopy(
+          ByteBuffer.wrap(new byte[CHUNK_SIZE])
+              .order(ByteOrder.LITTLE_ENDIAN)
+              .putLong(h1)
+              .putLong(h2)
+              .array());
+    }
+
+    private static long fmix64(long k) {
+      k ^= k >>> 33;
+      k *= 0xff51afd7ed558ccdL;
+      k ^= k >>> 33;
+      k *= 0xc4ceb9fe1a85ec53L;
+      k ^= k >>> 33;
+      return k;
+    }
+
+    private static long mixK1(long k1) {
+      k1 *= C1;
+      k1 = Long.rotateLeft(k1, 31);
+      k1 *= C2;
+      return k1;
+    }
+
+    private static long mixK2(long k2) {
+      k2 *= C2;
+      k2 = Long.rotateLeft(k2, 33);
+      k2 *= C1;
+      return k2;
+    }
+  }
+
+  private static final long serialVersionUID = 0L;
+  private static final int UNSIGNED_MASK = 0xFF;
+
+  /**
+   * Returns the value of the given byte as an integer, when treated as unsigned. That is, returns
+   * {@code value + 256} if {@code value} is negative; {@code value} itself otherwise.
+   *
+   * <p><b>Java 8 users:</b> use {@link Byte#toUnsignedInt(byte)} instead.
+   *
+   * @since 6.0
+   */
+  public static int toInt(byte value) {
+    return value & UNSIGNED_MASK;
+  }
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/hash/PrimitiveSink.java b/iotdb-core/node-commons/src/main/java/com/google/common/hash/PrimitiveSink.java
new file mode 100644
index 0000000..cc08217
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/hash/PrimitiveSink.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed 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 com.google.common.hash;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * An object which can receive a stream of primitive values.
+ *
+ * @author Kevin Bourrillion
+ * @since 12.0 (in 11.0 as {@code Sink})
+ */
+public interface PrimitiveSink {
+  /**
+   * Puts a byte into this sink.
+   *
+   * @param b a byte
+   * @return this instance
+   */
+  PrimitiveSink putByte(byte b);
+
+  /**
+   * Puts an array of bytes into this sink.
+   *
+   * @param bytes a byte array
+   * @return this instance
+   */
+  PrimitiveSink putBytes(byte[] bytes);
+
+  /**
+   * Puts a chunk of an array of bytes into this sink. {@code bytes[off]} is the first byte written,
+   * {@code bytes[off + len - 1]} is the last.
+   *
+   * @param bytes a byte array
+   * @param off the start offset in the array
+   * @param len the number of bytes to write
+   * @return this instance
+   * @throws IndexOutOfBoundsException if {@code off < 0} or {@code off + len > bytes.length} or
+   *     {@code len < 0}
+   */
+  PrimitiveSink putBytes(byte[] bytes, int off, int len);
+
+  /**
+   * Puts the remaining bytes of a byte buffer into this sink. {@code bytes.position()} is the first
+   * byte written, {@code bytes.limit() - 1} is the last. The position of the buffer will be equal
+   * to the limit when this method returns.
+   *
+   * @param bytes a byte buffer
+   * @return this instance
+   * @since 23.0
+   */
+  PrimitiveSink putBytes(ByteBuffer bytes);
+
+  /** Puts a short into this sink. */
+  PrimitiveSink putShort(short s);
+
+  /** Puts an int into this sink. */
+  PrimitiveSink putInt(int i);
+
+  /** Puts a long into this sink. */
+  PrimitiveSink putLong(long l);
+
+  /** Puts a float into this sink. */
+  PrimitiveSink putFloat(float f);
+
+  /** Puts a double into this sink. */
+  PrimitiveSink putDouble(double d);
+
+  /** Puts a boolean into this sink. */
+  PrimitiveSink putBoolean(boolean b);
+
+  /** Puts a character into this sink. */
+  PrimitiveSink putChar(char c);
+
+  /**
+   * Puts each 16-bit code unit from the {@link CharSequence} into this sink.
+   *
+   * <p><b>Warning:</b> This method will produce different output than most other languages do when
+   * running on the equivalent input. For cross-language compatibility, use {@link #putString},
+   * usually with a charset of UTF-8. For other use cases, use {@code putUnencodedChars}.
+   *
+   * @since 15.0 (since 11.0 as putString(CharSequence))
+   */
+  PrimitiveSink putUnencodedChars(CharSequence charSequence);
+
+  /**
+   * Puts a string into this sink using the given charset.
+   *
+   * <p><b>Warning:</b> This method, which reencodes the input before processing it, is useful only
+   * for cross-language compatibility. For other use cases, prefer {@link #putUnencodedChars}, which
+   * is faster, produces the same output across Java releases, and processes every {@code char} in
+   * the input, even if some are invalid.
+   */
+  PrimitiveSink putString(CharSequence charSequence, Charset charset);
+}
diff --git a/iotdb-core/node-commons/src/main/java/com/google/common/primitives/Bytes.java b/iotdb-core/node-commons/src/main/java/com/google/common/primitives/Bytes.java
new file mode 100644
index 0000000..f512365
--- /dev/null
+++ b/iotdb-core/node-commons/src/main/java/com/google/common/primitives/Bytes.java
@@ -0,0 +1,448 @@
+/*
+ * Copyright (C) 2008 The Guava Authors
+ *
+ * Licensed 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 com.google.common.primitives;
+
+import javax.annotation.CheckForNull;
+
+import java.io.Serializable;
+import java.util.AbstractList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.RandomAccess;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkElementIndex;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkPositionIndexes;
+
+/**
+ * Static utility methods pertaining to {@code byte} primitives, that are not already found in
+ * either {@link Byte} or {@link Arrays}, <i>and interpret bytes as neither signed nor unsigned</i>.
+ * The methods which specifically treat bytes as signed or unsigned are found in {@link SignedBytes}
+ * and {@link UnsignedBytes}.
+ *
+ * <p>See the Guava User Guide article on <a
+ * href="https://github.com/google/guava/wiki/PrimitivesExplained">primitive utilities</a>.
+ *
+ * @author Kevin Bourrillion
+ * @since 1.0
+ */
+// TODO(kevinb): how to prevent warning on UnsignedBytes when building GWT
+// javadoc?
+public final class Bytes {
+  private Bytes() {}
+
+  /**
+   * Returns a hash code for {@code value}; equal to the result of invoking {@code ((Byte)
+   * value).hashCode()}.
+   *
+   * <p><b>Java 8 users:</b> use {@link Byte#hashCode(byte)} instead.
+   *
+   * @param value a primitive {@code byte} value
+   * @return a hash code for the value
+   */
+  public static int hashCode(byte value) {
+    return value;
+  }
+
+  /**
+   * Returns {@code true} if {@code target} is present as an element anywhere in {@code array}.
+   *
+   * @param array an array of {@code byte} values, possibly empty
+   * @param target a primitive {@code byte} value
+   * @return {@code true} if {@code array[i] == target} for some value of {@code i}
+   */
+  public static boolean contains(byte[] array, byte target) {
+    for (byte value : array) {
+      if (value == target) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Returns the index of the first appearance of the value {@code target} in {@code array}.
+   *
+   * @param array an array of {@code byte} values, possibly empty
+   * @param target a primitive {@code byte} value
+   * @return the least index {@code i} for which {@code array[i] == target}, or {@code -1} if no
+   *     such index exists.
+   */
+  public static int indexOf(byte[] array, byte target) {
+    return indexOf(array, target, 0, array.length);
+  }
+
+  // TODO(kevinb): consider making this public
+  private static int indexOf(byte[] array, byte target, int start, int end) {
+    for (int i = start; i < end; i++) {
+      if (array[i] == target) {
+        return i;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * Returns the start position of the first occurrence of the specified {@code target} within
+   * {@code array}, or {@code -1} if there is no such occurrence.
+   *
+   * <p>More formally, returns the lowest index {@code i} such that {@code Arrays.copyOfRange(array,
+   * i, i + target.length)} contains exactly the same elements as {@code target}.
+   *
+   * @param array the array to search for the sequence {@code target}
+   * @param target the array to search for as a sub-sequence of {@code array}
+   */
+  public static int indexOf(byte[] array, byte[] target) {
+    checkNotNull(array, "array");
+    checkNotNull(target, "target");
+    if (target.length == 0) {
+      return 0;
+    }
+
+    outer:
+    for (int i = 0; i < array.length - target.length + 1; i++) {
+      for (int j = 0; j < target.length; j++) {
+        if (array[i + j] != target[j]) {
+          continue outer;
+        }
+      }
+      return i;
+    }
+    return -1;
+  }
+
+  /**
+   * Returns the index of the last appearance of the value {@code target} in {@code array}.
+   *
+   * @param array an array of {@code byte} values, possibly empty
+   * @param target a primitive {@code byte} value
+   * @return the greatest index {@code i} for which {@code array[i] == target}, or {@code -1} if no
+   *     such index exists.
+   */
+  public static int lastIndexOf(byte[] array, byte target) {
+    return lastIndexOf(array, target, 0, array.length);
+  }
+
+  // TODO(kevinb): consider making this public
+  private static int lastIndexOf(byte[] array, byte target, int start, int end) {
+    for (int i = end - 1; i >= start; i--) {
+      if (array[i] == target) {
+        return i;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * Returns the values from each provided array combined into a single array. For example, {@code
+   * concat(new byte[] {a, b}, new byte[] {}, new byte[] {c}} returns the array {@code {a, b, c}}.
+   *
+   * @param arrays zero or more {@code byte} arrays
+   * @return a single array containing all the values from the source arrays, in order
+   */
+  public static byte[] concat(byte[]... arrays) {
+    int length = 0;
+    for (byte[] array : arrays) {
+      length += array.length;
+    }
+    byte[] result = new byte[length];
+    int pos = 0;
+    for (byte[] array : arrays) {
+      System.arraycopy(array, 0, result, pos, array.length);
+      pos += array.length;
+    }
+    return result;
+  }
+
+  /**
+   * Returns an array containing the same values as {@code array}, but guaranteed to be of a
+   * specified minimum length. If {@code array} already has a length of at least {@code minLength},
+   * it is returned directly. Otherwise, a new array of size {@code minLength + padding} is
+   * returned, containing the values of {@code array}, and zeroes in the remaining places.
+   *
+   * @param array the source array
+   * @param minLength the minimum length the returned array must guarantee
+   * @param padding an extra amount to "grow" the array by if growth is necessary
+   * @throws IllegalArgumentException if {@code minLength} or {@code padding} is negative
+   * @return an array containing the values of {@code array}, with guaranteed minimum length {@code
+   *     minLength}
+   */
+  public static byte[] ensureCapacity(byte[] array, int minLength, int padding) {
+    checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
+    checkArgument(padding >= 0, "Invalid padding: %s", padding);
+    return (array.length < minLength) ? Arrays.copyOf(array, minLength + padding) : array;
+  }
+
+  /**
+   * Returns an array containing each value of {@code collection}, converted to a {@code byte} value
+   * in the manner of {@link Number#byteValue}.
+   *
+   * <p>Elements are copied from the argument collection as if by {@code collection.toArray()}.
+   * Calling this method is as thread-safe as calling that method.
+   *
+   * @param collection a collection of {@code Number} instances
+   * @return an array containing the same values as {@code collection}, in the same order, converted
+   *     to primitives
+   * @throws NullPointerException if {@code collection} or any of its elements is null
+   * @since 1.0 (parameter was {@code Collection<Byte>} before 12.0)
+   */
+  public static byte[] toArray(Collection<? extends Number> collection) {
+    if (collection instanceof ByteArrayAsList) {
+      return ((ByteArrayAsList) collection).toByteArray();
+    }
+
+    Object[] boxedArray = collection.toArray();
+    int len = boxedArray.length;
+    byte[] array = new byte[len];
+    for (int i = 0; i < len; i++) {
+      // checkNotNull for GWT (do not optimize)
+      array[i] = ((Number) checkNotNull(boxedArray[i])).byteValue();
+    }
+    return array;
+  }
+
+  /**
+   * Returns a fixed-size list backed by the specified array, similar to {@link
+   * Arrays#asList(Object[])}. The list supports {@link List#set(int, Object)}, but any attempt to
+   * set a value to {@code null} will result in a {@link NullPointerException}.
+   *
+   * <p>The returned list maintains the values, but not the identities, of {@code Byte} objects
+   * written to or read from it. For example, whether {@code list.get(0) == list.get(0)} is true for
+   * the returned list is unspecified.
+   *
+   * <p>The returned list is serializable.
+   *
+   * @param backingArray the array to back the list
+   * @return a list view of the array
+   */
+  public static List<Byte> asList(byte... backingArray) {
+    if (backingArray.length == 0) {
+      return Collections.emptyList();
+    }
+    return new ByteArrayAsList(backingArray);
+  }
+
+  private static class ByteArrayAsList extends AbstractList<Byte>
+      implements RandomAccess, Serializable {
+    final byte[] array;
+    final int start;
+    final int end;
+
+    ByteArrayAsList(byte[] array) {
+      this(array, 0, array.length);
+    }
+
+    ByteArrayAsList(byte[] array, int start, int end) {
+      this.array = array;
+      this.start = start;
+      this.end = end;
+    }
+
+    @Override
+    public int size() {
+      return end - start;
+    }
+
+    @Override
+    public boolean isEmpty() {
+      return false;
+    }
+
+    @Override
+    public Byte get(int index) {
+      checkElementIndex(index, size());
+      return array[start + index];
+    }
+
+    @Override
+    public boolean contains(@CheckForNull Object target) {
+      // Overridden to prevent a ton of boxing
+      return (target instanceof Byte) && Bytes.indexOf(array, (Byte) target, start, end) != -1;
+    }
+
+    @Override
+    public int indexOf(@CheckForNull Object target) {
+      // Overridden to prevent a ton of boxing
+      if (target instanceof Byte) {
+        int i = Bytes.indexOf(array, (Byte) target, start, end);
+        if (i >= 0) {
+          return i - start;
+        }
+      }
+      return -1;
+    }
+
+    @Override
+    public int lastIndexOf(@CheckForNull Object target) {
+      // Overridden to prevent a ton of boxing
+      if (target instanceof Byte) {
+        int i = Bytes.lastIndexOf(array, (Byte) target, start, end);
+        if (i >= 0) {
+          return i - start;
+        }
+      }
+      return -1;
+    }
+
+    @Override
+    public Byte set(int index, Byte element) {
+      checkElementIndex(index, size());
+      byte oldValue = array[start + index];
+      // checkNotNull for GWT (do not optimize)
+      array[start + index] = checkNotNull(element);
+      return oldValue;
+    }
+
+    @Override
+    public List<Byte> subList(int fromIndex, int toIndex) {
+      int size = size();
+      checkPositionIndexes(fromIndex, toIndex, size);
+      if (fromIndex == toIndex) {
+        return Collections.emptyList();
+      }
+      return new ByteArrayAsList(array, start + fromIndex, start + toIndex);
+    }
+
+    @Override
+    public boolean equals(@CheckForNull Object object) {
+      if (object == this) {
+        return true;
+      }
+      if (object instanceof ByteArrayAsList) {
+        ByteArrayAsList that = (ByteArrayAsList) object;
+        int size = size();
+        if (that.size() != size) {
+          return false;
+        }
+        for (int i = 0; i < size; i++) {
+          if (array[start + i] != that.array[that.start + i]) {
+            return false;
+          }
+        }
+        return true;
+      }
+      return super.equals(object);
+    }
+
+    @Override
+    public int hashCode() {
+      int result = 1;
+      for (int i = start; i < end; i++) {
+        result = 31 * result + Bytes.hashCode(array[i]);
+      }
+      return result;
+    }
+
+    @Override
+    public String toString() {
+      StringBuilder builder = new StringBuilder(size() * 5);
+      builder.append('[').append(array[start]);
+      for (int i = start + 1; i < end; i++) {
+        builder.append(", ").append(array[i]);
+      }
+      return builder.append(']').toString();
+    }
+
+    byte[] toByteArray() {
+      return Arrays.copyOfRange(array, start, end);
+    }
+
+    private static final long serialVersionUID = 0;
+  }
+
+  /**
+   * Reverses the elements of {@code array}. This is equivalent to {@code
+   * Collections.reverse(Bytes.asList(array))}, but is likely to be more efficient.
+   *
+   * @since 23.1
+   */
+  public static void reverse(byte[] array) {
+    checkNotNull(array);
+    reverse(array, 0, array.length);
+  }
+
+  /**
+   * Reverses the elements of {@code array} between {@code fromIndex} inclusive and {@code toIndex}
+   * exclusive. This is equivalent to {@code
+   * Collections.reverse(Bytes.asList(array).subList(fromIndex, toIndex))}, but is likely to be more
+   * efficient.
+   *
+   * @throws IndexOutOfBoundsException if {@code fromIndex < 0}, {@code toIndex > array.length}, or
+   *     {@code toIndex > fromIndex}
+   * @since 23.1
+   */
+  public static void reverse(byte[] array, int fromIndex, int toIndex) {
+    checkNotNull(array);
+    checkPositionIndexes(fromIndex, toIndex, array.length);
+    for (int i = fromIndex, j = toIndex - 1; i < j; i++, j--) {
+      byte tmp = array[i];
+      array[i] = array[j];
+      array[j] = tmp;
+    }
+  }
+
+  /**
+   * Performs a right rotation of {@code array} of "distance" places, so that the first element is
+   * moved to index "distance", and the element at index {@code i} ends up at index {@code (distance
+   * + i) mod array.length}. This is equivalent to {@code Collections.rotate(Bytes.asList(array),
+   * distance)}, but is somewhat faster.
+   *
+   * <p>The provided "distance" may be negative, which will rotate left.
+   *
+   * @since 32.0.0
+   */
+  public static void rotate(byte[] array, int distance) {
+    rotate(array, distance, 0, array.length);
+  }
+
+  /**
+   * Performs a right rotation of {@code array} between {@code fromIndex} inclusive and {@code
+   * toIndex} exclusive. This is equivalent to {@code
+   * Collections.rotate(Bytes.asList(array).subList(fromIndex, toIndex), distance)}, but is somewhat
+   * faster.
+   *
+   * <p>The provided "distance" may be negative, which will rotate left.
+   *
+   * @throws IndexOutOfBoundsException if {@code fromIndex < 0}, {@code toIndex > array.length}, or
+   *     {@code toIndex > fromIndex}
+   * @since 32.0.0
+   */
+  public static void rotate(byte[] array, int distance, int fromIndex, int toIndex) {
+    // See Ints.rotate for more details about possible algorithms here.
+    checkNotNull(array);
+    checkPositionIndexes(fromIndex, toIndex, array.length);
+    if (array.length <= 1) {
+      return;
+    }
+
+    int length = toIndex - fromIndex;
+    // Obtain m = (-distance mod length), a non-negative value less than "length". This is how many
+    // places left to rotate.
+    int m = -distance % length;
+    m = (m < 0) ? m + length : m;
+    // The current index of what will become the first element of the rotated section.
+    int newFirstIndex = m + fromIndex;
+    if (newFirstIndex == fromIndex) {
+      return;
+    }
+
+    reverse(array, fromIndex, newFirstIndex);
+    reverse(array, newFirstIndex, toIndex);
+    reverse(array, fromIndex, toIndex);
+  }
+}