Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions console/src/main/java/com/arcadedb/console/Console.java
Original file line number Diff line number Diff line change
Expand Up @@ -217,23 +217,23 @@ private void executeBegin() {
if (localDatabase != null)
localDatabase.begin();
else
remoteDatabase.command("SQL", "begin");
remoteDatabase.begin();
}

private void executeCommit() {
checkDatabaseIsOpen();
if (localDatabase != null)
localDatabase.commit();
else
remoteDatabase.command("SQL", "commit");
remoteDatabase.commit();
}

private void executeRollback() {
checkDatabaseIsOpen();
if (localDatabase != null)
localDatabase.rollback();
else
remoteDatabase.command("SQL", "rollback");
remoteDatabase.rollback();
}

private void executeClose() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ protected int[] getServerToCheck() {
protected void deleteDatabaseFolders() {
if (databases != null)
for (int i = 0; i < databases.length; ++i) {
if (databases[i] != null)
if (databases[i] != null && databases[i].isOpen())
databases[i].drop();
}

Expand All @@ -322,7 +322,7 @@ protected void deleteDatabaseFolders() {
Assertions.assertTrue(DatabaseFactory.getActiveDatabaseInstances().isEmpty(), "Found active databases: " + DatabaseFactory.getActiveDatabaseInstances());

for (int i = 0; i < getServerCount(); ++i)
FileUtils.deleteRecursively(new File(getDatabasePath(i)));
FileUtils.deleteRecursively(new File(GlobalConfiguration.SERVER_DATABASE_DIRECTORY.getValueAsString() + i + "/"));
FileUtils.deleteRecursively(new File(GlobalConfiguration.SERVER_ROOT_PATH.getValueAsString() + "/replication"));
}

Expand Down
100 changes: 63 additions & 37 deletions console/src/test/java/com/arcadedb/console/RemoteConsoleIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
*/
package com.arcadedb.console;

import com.arcadedb.GlobalConfiguration;
import com.arcadedb.remote.RemoteException;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
Expand All @@ -30,6 +32,11 @@ public class RemoteConsoleIT extends BaseGraphServerTest {
private static final String URL_WRONGPASSWD = "remote:localhost/console root wrong";
private static Console console;

public void setTestConfiguration() {
super.setTestConfiguration();
GlobalConfiguration.SERVER_HTTP_TX_EXPIRE_TIMEOUT.setValue(3);
}

@Test
public void testConnect() throws IOException {
Assertions.assertTrue(console.parse("connect " + URL, false));
Expand Down Expand Up @@ -64,12 +71,7 @@ public void testCreateType() throws IOException {
Assertions.assertTrue(console.parse("create document type Person2", false));

final StringBuilder buffer = new StringBuilder();
console.setOutput(new ConsoleOutput() {
@Override
public void onOutput(final String output) {
buffer.append(output);
}
});
console.setOutput(output -> buffer.append(output));
Assertions.assertTrue(console.parse("info types", false));
Assertions.assertTrue(buffer.toString().contains("Person2"));
Assertions.assertTrue(console.parse("drop type Person2", false));
Expand All @@ -82,45 +84,64 @@ public void testInsertAndSelectRecord() throws IOException {
Assertions.assertTrue(console.parse("insert into Person2 set name = 'Jay', lastname='Miner'", false));

final StringBuilder buffer = new StringBuilder();
console.setOutput(new ConsoleOutput() {
@Override
public void onOutput(final String output) {
buffer.append(output);
}
});
console.setOutput(output -> buffer.append(output));
Assertions.assertTrue(console.parse("select from Person2", false));
Assertions.assertTrue(buffer.toString().contains("Jay"));
Assertions.assertTrue(console.parse("drop type Person2", false));
}
//
// @Test
// public void testInsertAndRollback() throws IOException {
// Assertions.assertTrue(console.parse("connect " + URL));
// Assertions.assertTrue(console.parse("begin"));
// Assertions.assertTrue(console.parse("create document type Person"));
// Assertions.assertTrue(console.parse("insert into Person set name = 'Jay', lastname='Miner'"));
// Assertions.assertTrue(console.parse("rollback"));
//
// final StringBuilder buffer = new StringBuilder();
// console.setOutput(new ConsoleOutput() {
// @Override
// public void onOutput(final String output) {
// buffer.append(output);
// }
// });
// Assertions.assertTrue(console.parse("select from Person"));
// Assertions.assertFalse(buffer.toString().contains("Jay"));
// }

@Test
public void testInsertAndRollback() throws IOException {
Assertions.assertTrue(console.parse("connect " + URL, false));
Assertions.assertTrue(console.parse("begin", false));
Assertions.assertTrue(console.parse("create document type Person", false));
Assertions.assertTrue(console.parse("insert into Person set name = 'Jay', lastname='Miner'", false));
Assertions.assertTrue(console.parse("rollback", false));

final StringBuilder buffer = new StringBuilder();
console.setOutput(output -> buffer.append(output));
Assertions.assertTrue(console.parse("select from Person", false));
Assertions.assertFalse(buffer.toString().contains("Jay"));
}

@Test
public void testInsertAndCommit() throws IOException {
Assertions.assertTrue(console.parse("connect " + URL, false));
Assertions.assertTrue(console.parse("begin", false));
Assertions.assertTrue(console.parse("create document type Person", false));
Assertions.assertTrue(console.parse("insert into Person set name = 'Jay', lastname='Miner'", false));
Assertions.assertTrue(console.parse("commit", false));

final StringBuilder buffer = new StringBuilder();
console.setOutput(output -> buffer.append(output));
Assertions.assertTrue(console.parse("select from Person", false));
Assertions.assertTrue(buffer.toString().contains("Jay"));
}

@Test
public void testTransactionExpired() throws IOException, InterruptedException {
Assertions.assertTrue(console.parse("connect " + URL, false));
Assertions.assertTrue(console.parse("begin", false));
Assertions.assertTrue(console.parse("create document type Person", false));
Assertions.assertTrue(console.parse("insert into Person set name = 'Jay', lastname='Miner'", false));
Thread.sleep(5000);
try {
Assertions.assertTrue(console.parse("commit", false));
Assertions.fail();
} catch (Exception e) {
// EXPECTED
}

final StringBuilder buffer = new StringBuilder();
console.setOutput(output -> buffer.append(output));
Assertions.assertTrue(console.parse("select from Person", false));
Assertions.assertFalse(buffer.toString().contains("Jay"));
}

@Test
public void testHelp() throws IOException {
final StringBuilder buffer = new StringBuilder();
console.setOutput(new ConsoleOutput() {
@Override
public void onOutput(final String output) {
buffer.append(output);
}
});
console.setOutput(output -> buffer.append(output));
Assertions.assertTrue(console.parse("?", false));
Assertions.assertTrue(buffer.toString().contains("quit"));
}
Expand Down Expand Up @@ -155,4 +176,9 @@ public void endTest() {
if (console != null)
console.close();
}

@AfterAll
public static void afterAll() {
GlobalConfiguration.SERVER_HTTP_TX_EXPIRE_TIMEOUT.setValue(GlobalConfiguration.SERVER_HTTP_TX_EXPIRE_TIMEOUT.getDefValue());
}
}
3 changes: 3 additions & 0 deletions engine/src/main/java/com/arcadedb/GlobalConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,9 @@ public Object call(final Object value) {
SERVER_HTTP_AUTOINCREMENT_PORT("arcadedb.server.httpAutoIncrementPort",
"True to increment the TCP/IP port number used for incoming HTTP in case the configured is not available", Boolean.class, true),

SERVER_HTTP_TX_EXPIRE_TIMEOUT("arcadedb.server.httpTxExpireTimeout",
"Timeout in seconds for a HTTP transaction to expire. This timeout is computed from the latest command against the transaction", Long.class, 30),

// SERVER SECURITY
SERVER_SECURITY_ALGORITHM("arcadedb.server.securityAlgorithm", "Default encryption algorithm used for passwords hashing", String.class,
"PBKDF2WithHmacSHA256"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
*/
public class DatabaseContext extends ThreadLocal<Map<String, DatabaseContext.DatabaseContextTL>> {
public DatabaseContextTL init(final DatabaseInternal database) {
return init(database, null);
}

public DatabaseContextTL init(final DatabaseInternal database, final TransactionContext firstTransaction) {
Map<String, DatabaseContextTL> map = get();

final String key = database.getDatabasePath();
Expand Down Expand Up @@ -57,7 +61,7 @@ public DatabaseContextTL init(final DatabaseInternal database) {
}

if (current.transactions.isEmpty())
current.transactions.add(new TransactionContext(database.getWrappedDatabaseInstance()));
current.transactions.add(firstTransaction != null ? firstTransaction : new TransactionContext(database.getWrappedDatabaseInstance()));

return current;
}
Expand Down
47 changes: 23 additions & 24 deletions engine/src/main/java/com/arcadedb/database/EmbeddedDatabase.java
Original file line number Diff line number Diff line change
Expand Up @@ -246,30 +246,6 @@ private void openInternal() {
}
}

private void checkForRecovery() throws IOException {
lockFile = new File(databasePath + "/database.lck");

if (lockFile.exists()) {
lockDatabase();

// RECOVERY
LogManager.instance().log(this, Level.WARNING, "Database '%s' was not closed properly last time", null, name);

if (mode == PaginatedFile.MODE.READ_ONLY)
throw new DatabaseMetadataException("Database needs recovery but has been open in read only mode");

executeCallbacks(CALLBACK_EVENT.DB_NOT_CLOSED);

transactionManager.checkIntegrity();
} else {
if (mode == PaginatedFile.MODE.READ_WRITE) {
lockFile.createNewFile();
lockDatabase();
} else
lockFile = null;
}
}

@Override
public void drop() {
checkDatabaseIsOpen();
Expand Down Expand Up @@ -1580,4 +1556,27 @@ private void internalClose(final boolean drop) {
DatabaseFactory.removeActiveDatabaseInstance(databasePath);
}

private void checkForRecovery() throws IOException {
lockFile = new File(databasePath + "/database.lck");

if (lockFile.exists()) {
lockDatabase();

// RECOVERY
LogManager.instance().log(this, Level.WARNING, "Database '%s' was not closed properly last time", null, name);

if (mode == PaginatedFile.MODE.READ_ONLY)
throw new DatabaseMetadataException("Database needs recovery but has been open in read only mode");

executeCallbacks(CALLBACK_EVENT.DB_NOT_CLOSED);

transactionManager.checkIntegrity();
} else {
if (mode == PaginatedFile.MODE.READ_WRITE) {
lockFile.createNewFile();
lockDatabase();
} else
lockFile = null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ protected int[] getServerToCheck() {
protected void deleteDatabaseFolders() {
if (databases != null)
for (int i = 0; i < databases.length; ++i) {
if (databases[i] != null)
if (databases[i] != null && databases[i].isOpen())
((ServerDatabase) databases[i]).getWrappedDatabaseInstance().drop();
}

Expand All @@ -345,7 +345,7 @@ protected void deleteDatabaseFolders() {
Assertions.assertTrue(DatabaseFactory.getActiveDatabaseInstances().isEmpty(), "Found active databases: " + DatabaseFactory.getActiveDatabaseInstances());

for (int i = 0; i < getServerCount(); ++i)
FileUtils.deleteRecursively(new File(getDatabasePath(i)));
FileUtils.deleteRecursively(new File(GlobalConfiguration.SERVER_DATABASE_DIRECTORY.getValueAsString() + i + "/"));
FileUtils.deleteRecursively(new File(GlobalConfiguration.SERVER_ROOT_PATH.getValueAsString() + "/replication"));
}

Expand Down
29 changes: 29 additions & 0 deletions network/src/main/java/com/arcadedb/network/http/HttpUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2021 Arcade Data Ltd
*
* 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 com.arcadedb.network.http;

/**
* @author Luca Garulli (l.garulli@arcadedata.com)
**/
public class HttpUtils {
public static final String ARCADEDB_SESSION_ID = "arcadedb-session-id";
}
Loading