diff --git a/engine/src/main/java/com/arcadedb/database/Database.java b/engine/src/main/java/com/arcadedb/database/Database.java index c87b6abee5..e6dd5b1113 100644 --- a/engine/src/main/java/com/arcadedb/database/Database.java +++ b/engine/src/main/java/com/arcadedb/database/Database.java @@ -55,10 +55,11 @@ public interface Database extends AutoCloseable { */ String getCurrentUserName(); + /** + * Returns true if there is a transaction active. A transaction is active if it is in the following states: `{BEGUN, COMMIT_1ST_PHASE, COMMIT_2ND_PHASE}`. + */ boolean isTransactionActive(); - boolean checkTransactionIsActive(boolean createTx); - /** * Executes a lambda in the transaction scope. If there is an active transaction, then the current transaction is parked and a new sub-transaction is begun. * diff --git a/engine/src/main/java/com/arcadedb/database/DatabaseComparator.java b/engine/src/main/java/com/arcadedb/database/DatabaseComparator.java index a42c27ad46..2b7c522a09 100644 --- a/engine/src/main/java/com/arcadedb/database/DatabaseComparator.java +++ b/engine/src/main/java/com/arcadedb/database/DatabaseComparator.java @@ -21,10 +21,8 @@ import com.arcadedb.exception.ArcadeDBException; import com.arcadedb.schema.DocumentType; -import java.io.IOException; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; +import java.io.*; +import java.util.*; /** * Compares 2 databases if are identical. diff --git a/engine/src/main/java/com/arcadedb/database/DatabaseInternal.java b/engine/src/main/java/com/arcadedb/database/DatabaseInternal.java index f947f81862..7fe8578891 100644 --- a/engine/src/main/java/com/arcadedb/database/DatabaseInternal.java +++ b/engine/src/main/java/com/arcadedb/database/DatabaseInternal.java @@ -65,6 +65,8 @@ enum CALLBACK_EVENT { void checkPermissionsOnFile(int fileId, SecurityDatabaseUser.ACCESS access); + boolean checkTransactionIsActive(boolean createTx); + long getResultSetLimit(); long getReadTimeout(); diff --git a/engine/src/main/java/com/arcadedb/database/EmbeddedDatabase.java b/engine/src/main/java/com/arcadedb/database/EmbeddedDatabase.java index f81bfcf713..bcb57d3af9 100644 --- a/engine/src/main/java/com/arcadedb/database/EmbeddedDatabase.java +++ b/engine/src/main/java/com/arcadedb/database/EmbeddedDatabase.java @@ -943,7 +943,7 @@ public void transaction(final TransactionScope txBlock) { @Override public boolean transaction(final TransactionScope txBlock, final boolean joinCurrentTx) { - return transaction(txBlock, joinCurrentTx, configuration.getValueAsInteger(GlobalConfiguration.TX_RETRIES)); + return transaction(txBlock, joinCurrentTx, configuration.getValueAsInteger(GlobalConfiguration.TX_RETRIES), null, null); } @Override diff --git a/engine/src/main/java/com/arcadedb/schema/DocumentType.java b/engine/src/main/java/com/arcadedb/schema/DocumentType.java index 721b3fef2a..15190be981 100644 --- a/engine/src/main/java/com/arcadedb/schema/DocumentType.java +++ b/engine/src/main/java/com/arcadedb/schema/DocumentType.java @@ -594,8 +594,7 @@ public boolean isSubTypeOf(final String type) { return false; } - protected void recordFileChanges(final Callable callback) { - schema.recordFileChanges(callback); - schema.saveConfiguration(); + protected RET recordFileChanges(final Callable callback) { + return schema.recordFileChanges(callback); } } diff --git a/engine/src/main/java/com/arcadedb/schema/EmbeddedSchema.java b/engine/src/main/java/com/arcadedb/schema/EmbeddedSchema.java index 8d4d771afd..75419a72c7 100644 --- a/engine/src/main/java/com/arcadedb/schema/EmbeddedSchema.java +++ b/engine/src/main/java/com/arcadedb/schema/EmbeddedSchema.java @@ -1332,6 +1332,21 @@ protected RET recordFileChanges(final Callable callback) { } } - return database.getWrappedDatabaseInstance().recordFileChanges(callback); + final boolean madeDirty = !dirtyConfiguration; + if (madeDirty) + dirtyConfiguration = true; + + boolean executed = false; + try { + final RET result = database.getWrappedDatabaseInstance().recordFileChanges(callback); + executed = true; + saveConfiguration(); + return result; + + } finally { + if (!executed && madeDirty) + // ROLLBACK THE DIRTY STATUS + dirtyConfiguration = false; + } } } diff --git a/server/src/main/java/com/arcadedb/server/ha/ReplicatedDatabase.java b/server/src/main/java/com/arcadedb/server/ha/ReplicatedDatabase.java index fcb23645d6..2b5d68d78e 100644 --- a/server/src/main/java/com/arcadedb/server/ha/ReplicatedDatabase.java +++ b/server/src/main/java/com/arcadedb/server/ha/ReplicatedDatabase.java @@ -652,7 +652,9 @@ public RET recordFileChanges(final Callable callback) { final List fileChanges = proxied.getFileManager().getRecordedChanges(); - if (fileChanges.isEmpty() && proxied.getSchema().getEmbedded().getVersion() == schemaVersionBefore) + if (fileChanges.isEmpty() &&// + !proxied.getSchema().getEmbedded().isDirty() && // + proxied.getSchema().getEmbedded().getVersion() == schemaVersionBefore) // NO CHANGES return null; diff --git a/server/src/main/java/com/arcadedb/server/ha/ReplicatedDocumentType.java b/server/src/main/java/com/arcadedb/server/ha/ReplicatedDocumentType.java deleted file mode 100644 index 2548c8b292..0000000000 --- a/server/src/main/java/com/arcadedb/server/ha/ReplicatedDocumentType.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright © 2021-present Arcade Data Ltd (info@arcadedata.com) - * - * 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.arcadedb.server.ha; - -import com.arcadedb.database.DatabaseInternal; -import com.arcadedb.index.Index; -import com.arcadedb.index.lsm.LSMTreeIndexAbstract; -import com.arcadedb.schema.DocumentType; -import com.arcadedb.schema.EmbeddedSchema; -import com.arcadedb.schema.Property; -import com.arcadedb.schema.Type; - -public class ReplicatedDocumentType extends DocumentType { - public ReplicatedDocumentType(EmbeddedSchema schema, String name) { - super(schema, name); - } - - @Override - public Property createProperty(String propertyName, Type propertyType) { - return (((DatabaseInternal) schema.getDatabase()).getWrappedDatabaseInstance()).recordFileChanges(() -> super.createProperty(propertyName, propertyType)); - } - - @Override - public Property createProperty(String propertyName, Class propertyType) { - return (((DatabaseInternal) schema.getDatabase()).getWrappedDatabaseInstance()).recordFileChanges(() -> super.createProperty(propertyName, propertyType)); - } - - @Override - public Property createProperty(String propertyName, String propertyType) { - return (((DatabaseInternal) schema.getDatabase()).getWrappedDatabaseInstance()).recordFileChanges(() -> super.createProperty(propertyName, propertyType)); - } - - @Override - public Property getOrCreateProperty(String propertyName, Type propertyType) { - return (((DatabaseInternal) schema.getDatabase()).getWrappedDatabaseInstance()).recordFileChanges( - () -> super.getOrCreateProperty(propertyName, propertyType)); - } - - @Override - public Property getOrCreateProperty(String propertyName, Class propertyType) { - return (((DatabaseInternal) schema.getDatabase()).getWrappedDatabaseInstance()).recordFileChanges( - () -> super.getOrCreateProperty(propertyName, propertyType)); - } - - @Override - public Property getOrCreateProperty(String propertyName, String propertyType) { - return (((DatabaseInternal) schema.getDatabase()).getWrappedDatabaseInstance()).recordFileChanges( - () -> super.getOrCreateProperty(propertyName, propertyType)); - } - - @Override - public Index createTypeIndex(EmbeddedSchema.INDEX_TYPE indexType, boolean unique, String... propertyNames) { - return (((DatabaseInternal) schema.getDatabase()).getWrappedDatabaseInstance()).recordFileChanges( - () -> super.createTypeIndex(indexType, unique, propertyNames)); - } - - @Override - public Index createTypeIndex(EmbeddedSchema.INDEX_TYPE indexType, boolean unique, String[] propertyNames, int pageSize) { - return (((DatabaseInternal) schema.getDatabase()).getWrappedDatabaseInstance()).recordFileChanges( - () -> super.createTypeIndex(indexType, unique, propertyNames, pageSize)); - } - - @Override - public Index createTypeIndex(EmbeddedSchema.INDEX_TYPE indexType, boolean unique, String[] propertyNames, int pageSize, Index.BuildIndexCallback callback) { - return (((DatabaseInternal) schema.getDatabase()).getWrappedDatabaseInstance()).recordFileChanges( - () -> super.createTypeIndex(indexType, unique, propertyNames, pageSize, callback)); - } - - @Override - public Index createTypeIndex(EmbeddedSchema.INDEX_TYPE indexType, boolean unique, String[] propertyNames, int pageSize, - LSMTreeIndexAbstract.NULL_STRATEGY nullStrategy, Index.BuildIndexCallback callback) { - return (((DatabaseInternal) schema.getDatabase()).getWrappedDatabaseInstance()).recordFileChanges( - () -> super.createTypeIndex(indexType, unique, propertyNames, pageSize, nullStrategy, callback)); - } - - @Override - public Index getOrCreateTypeIndex(EmbeddedSchema.INDEX_TYPE indexType, boolean unique, String... propertyNames) { - return (((DatabaseInternal) schema.getDatabase()).getWrappedDatabaseInstance()).recordFileChanges( - () -> super.getOrCreateTypeIndex(indexType, unique, propertyNames)); - } - - @Override - public Index getOrCreateTypeIndex(EmbeddedSchema.INDEX_TYPE indexType, boolean unique, String[] propertyNames, int pageSize) { - return (((DatabaseInternal) schema.getDatabase()).getWrappedDatabaseInstance()).recordFileChanges( - () -> super.getOrCreateTypeIndex(indexType, unique, propertyNames, pageSize)); - } - - @Override - public Index getOrCreateTypeIndex(EmbeddedSchema.INDEX_TYPE indexType, boolean unique, String[] propertyNames, int pageSize, - Index.BuildIndexCallback callback) { - return (((DatabaseInternal) schema.getDatabase()).getWrappedDatabaseInstance()).recordFileChanges( - () -> super.getOrCreateTypeIndex(indexType, unique, propertyNames, pageSize, callback)); - } - - @Override - public Index getOrCreateTypeIndex(EmbeddedSchema.INDEX_TYPE indexType, boolean unique, String[] propertyNames, int pageSize, - LSMTreeIndexAbstract.NULL_STRATEGY nullStrategy, Index.BuildIndexCallback callback) { - return (((DatabaseInternal) schema.getDatabase()).getWrappedDatabaseInstance()).recordFileChanges( - () -> super.getOrCreateTypeIndex(indexType, unique, propertyNames, pageSize, nullStrategy, callback)); - } -} diff --git a/server/src/test/java/com/arcadedb/server/ha/ReplicationChangeSchema.java b/server/src/test/java/com/arcadedb/server/ha/ReplicationChangeSchema.java index c0ef345ffb..49f500bccb 100644 --- a/server/src/test/java/com/arcadedb/server/ha/ReplicationChangeSchema.java +++ b/server/src/test/java/com/arcadedb/server/ha/ReplicationChangeSchema.java @@ -29,12 +29,12 @@ public void testReplication() { final Database database0 = getServerDatabase(0, getDatabaseName()); final VertexType type0 = database0.getSchema().createVertexType("RuntimeVertex0"); - type0.createProperty("id", Type.STRING); + type0.createProperty("nameNotFoundInDictionary", Type.STRING); final Database database1 = getServerDatabase(1, getDatabaseName()); Assertions.assertNotNull(database1.getSchema().getType("RuntimeVertex0")); - Assertions.assertNotNull(database1.getSchema().getType("RuntimeVertex0").getProperty("id")); + Assertions.assertNotNull(database1.getSchema().getType("RuntimeVertex0").getProperty("nameNotFoundInDictionary")); try { database1.getSchema().createVertexType("RuntimeVertex1");