ibessonov commented on code in PR #6273:
URL: https://github.com/apache/ignite-3/pull/6273#discussion_r2215292971
##
modules/raft/src/main/java/org/apache/ignite/internal/raft/storage/impl/RocksDbSharedLogStorage.java:
##
@@ -162,21 +174,29 @@ public class RocksDbSharedLogStorage implements
LogStorage, Describer {
this.logStorageFactory = logStorageFactory;
this.db = db;
+this.metaHandle = metaHandle;
this.confHandle = confHandle;
this.dataHandle = dataHandle;
this.executor = executor;
+this.raftNodeStorageId = raftNodeStorageId;
this.startPrefix = raftNodeStorageStartPrefix(raftNodeStorageId);
this.endPrefix = raftNodeStorageEndPrefix(raftNodeStorageId);
this.startBound = new Slice(startPrefix);
this.endBound = new Slice(endPrefix);
this.writeOptions = writeOptions;
}
-/**
- * Returns the log factory instance, that created current log storage.
- */
-DefaultLogStorageFactory getLogStorageFactory() {
-return logStorageFactory;
+static byte[] storageCreatedKey(String raftNodeStorageId) {
+return concat(DefaultLogStorageFactory.STORAGE_CREATED_META_PREFIX,
raftNodeStorageId.getBytes(UTF_8));
+}
+
+private static byte[] concat(byte[] a, byte[] b) {
+byte[] result = new byte[a.length + b.length];
+
+System.arraycopy(a, 0, result, 0, a.length);
Review Comment:
I suggest using `copyOf` for the `a`, it is more efficient. I'm almost
certain that we have such `concat` implementation somewhere else, have you
searched for it?
##
modules/raft/src/main/java/org/apache/ignite/internal/raft/storage/impl/MetadataMigration.java:
##
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.raft.storage.impl;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static
org.apache.ignite.internal.raft.storage.impl.DefaultLogStorageFactory.FINISHED_META_MIGRATION_META_KEY;
+import static
org.apache.ignite.internal.raft.storage.impl.RocksDbSharedLogStorageUtils.raftNodeStorageEndPrefix;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.ignite.internal.logger.IgniteLogger;
+import org.apache.ignite.internal.logger.Loggers;
+import org.apache.ignite.internal.util.ArrayUtils;
+import org.rocksdb.ColumnFamilyHandle;
+import org.rocksdb.RocksDB;
+import org.rocksdb.RocksDBException;
+import org.rocksdb.RocksIterator;
+import org.rocksdb.WriteBatch;
+import org.rocksdb.WriteOptions;
+
+/**
+ * Implements migration of log storage metadata. Namely, it finds all log
storages for which at least one key (in either Configuration
+ * or default column families) exists, and marks them as 'created', so support
the invariant that for a log storage on which init()
+ * is called the corresponding 'created' key is in RocksDB.
+ */
+class MetadataMigration {
+private static final IgniteLogger LOG =
Loggers.forClass(MetadataMigration.class);
+
+private final RocksDB db;
+
+private final WriteOptions writeOptions;
+
+private final ColumnFamilyHandle metaHandle;
+private final ColumnFamilyHandle confHandle;
+private final ColumnFamilyHandle dataHandle;
+
+/** Constructor. */
+MetadataMigration(
+RocksDB db,
+WriteOptions writeOptions,
+ColumnFamilyHandle metaHandle,
+ColumnFamilyHandle confHandle,
+ColumnFamilyHandle dataHandle
+) {
+this.db = db;
+this.writeOptions = writeOptions;
+this.metaHandle = metaHandle;
+this.confHandle = confHandle;
+this.dataHandle = dataHandle;
+}
+
+void migrateIfNeeded() throws RocksDBException {
+if (metaMigrationIsFinished()) {
+return;
+}
+
+try (WriteBatch writeBatch = new WriteBatch()) {
+boolean migratingSomething = doMigration(writeBatch);
+
+markMetaMigrationAsFinished(writeBatch);
+
+db.write(writeOptions, writeBatch);
+
+if (migratingSomething) {
+LOG.info("Metadata migration was performed an