Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delete reuse space #1539

Open
wants to merge 34 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
907c803
first version of compress pages after a delete
lvca Dec 19, 2023
4d20a47
chore: additional check on page pointer
lvca Dec 19, 2023
d98bd7f
Merge branch 'main' into delete-reuse-space
lvca Dec 19, 2023
9e844dc
Fixed issue with compacting holes
lvca Dec 21, 2023
9ef2d04
Merge branch 'main' into delete-reuse-space
lvca Dec 21, 2023
db521f1
Merge branch 'main' into delete-reuse-space
lvca Dec 21, 2023
1f52172
Fixed move of records in update
lvca Dec 22, 2023
2c3f38e
Fixed compression of page
lvca Dec 24, 2023
9a10ece
Fixed last issue with update in multi page record
lvca Dec 27, 2023
9b1f696
Merge branch 'main' into delete-reuse-space
lvca Dec 27, 2023
e776e8f
Merge branch 'main' into delete-reuse-space
lvca Dec 27, 2023
63fc946
Merge branch 'main' into delete-reuse-space
lvca Dec 27, 2023
b4a15e8
Merge branch 'main' into delete-reuse-space
lvca Dec 27, 2023
577e787
feat: deleted extra space from multi-page records when on update the …
lvca Dec 27, 2023
88f04f8
Merge branch 'main' into delete-reuse-space
lvca Dec 27, 2023
0c04f56
Merge branch 'main' into delete-reuse-space
lvca Feb 8, 2024
b027497
Merge branch 'main' into delete-reuse-space
lvca Feb 29, 2024
b3a8193
Merge branch 'main' into delete-reuse-space
lvca Mar 9, 2024
4428c52
Merge branch 'main' into delete-reuse-space
lvca Mar 15, 2024
1bb9b0e
Merge branch 'main' into delete-reuse-space
lvca Apr 1, 2024
e7f11cc
Merge branch 'main' into delete-reuse-space
lvca Apr 2, 2024
e2273c6
Merge branch 'main' into delete-reuse-space
lvca Apr 5, 2024
c7fac0a
test: added new test case that creates and delete multiple times a graph
lvca Apr 5, 2024
dc49c4b
test: added check database after test
lvca Apr 5, 2024
3e74734
Merge branch 'main' into delete-reuse-space
lvca Apr 5, 2024
e3d289e
fix: vertex delete left space allocated
lvca Apr 5, 2024
a3751f9
Merge branch 'main' into delete-reuse-space
lvca Apr 8, 2024
979e1a9
Merge branch 'main' into delete-reuse-space
lvca Apr 11, 2024
95c44f1
fix: fixed issue after merge
lvca Apr 11, 2024
c5fe163
Merge branch 'main' into delete-reuse-space
lvca May 4, 2024
a5aa1b2
Merge branch 'main' into delete-reuse-space
lvca Jun 24, 2024
29f4ffd
Merge branch 'main' into delete-reuse-space
lvca Aug 19, 2024
8fc2271
Merge branch 'main' into delete-reuse-space
lvca Sep 5, 2024
e0483e5
Merge branch 'main' into delete-reuse-space
lvca Oct 20, 2024
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
17 changes: 17 additions & 0 deletions engine/src/main/java/com/arcadedb/database/TransactionContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import com.arcadedb.GlobalConfiguration;
import com.arcadedb.engine.BasePage;
import com.arcadedb.engine.Bucket;
import com.arcadedb.engine.ComponentFile;
import com.arcadedb.engine.ImmutablePage;
import com.arcadedb.engine.LocalBucket;
Expand All @@ -37,6 +38,8 @@
import com.arcadedb.index.IndexInternal;
import com.arcadedb.index.lsm.LSMTreeIndexAbstract;
import com.arcadedb.log.LogManager;
import com.arcadedb.schema.LocalSchema;
import com.arcadedb.schema.Schema;

import java.io.*;
import java.util.*;
Expand Down Expand Up @@ -572,6 +575,20 @@ public TransactionPhase1 commit1stPhase(final boolean isLeader) {
final List<MutablePage> pages = new ArrayList<>();
final PageManager pageManager = database.getPageManager();

// COMPRESS PAGES BEFORE SAVING THEM
final LocalSchema localSchema = database.getSchema().getEmbedded();

for (MutablePage page : modifiedPages.values()) {
final LocalBucket bucket = localSchema.getBucketById(page.getPageId().getFileId(), false);
if (bucket != null)
bucket.compressPage(page);
}
for (MutablePage page : newPages.values()) {
final LocalBucket bucket = localSchema.getBucketById(page.getPageId().getFileId(), false);
if (bucket != null)
bucket.compressPage(page);
}

for (final Iterator<MutablePage> it = modifiedPages.values().iterator(); it.hasNext(); ) {
final MutablePage p = it.next();

Expand Down
423 changes: 313 additions & 110 deletions engine/src/main/java/com/arcadedb/engine/LocalBucket.java

Large diffs are not rendered by default.

17 changes: 14 additions & 3 deletions engine/src/main/java/com/arcadedb/schema/LocalSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -284,12 +284,23 @@ public Bucket getBucketByName(final String name) {

@Override
public LocalBucket getBucketById(final int id) {
return getBucketById(id, true);
}

public LocalBucket getBucketById(final int id, final boolean throwExceptionIfNotFound) {
if (id < 0 || id >= files.size())
throw new SchemaException("Bucket with id '" + id + "' was not found");
if (throwExceptionIfNotFound)
throw new SchemaException("Bucket with id '" + id + "' was not found");
else
return null;

final Component p = files.get(id);
if (!(p instanceof LocalBucket))
throw new SchemaException("Bucket with id '" + id + "' was not found");
if (!(p instanceof LocalBucket)) {
if (throwExceptionIfNotFound)
throw new SchemaException("Bucket with id '" + id + "' was not found");
else
return null;
}
return (LocalBucket) p;
}

Expand Down
8 changes: 6 additions & 2 deletions engine/src/test/java/com/arcadedb/AsyncTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ public void testSyncScanAndAsyncUpdate() {

database.scanType(TYPE_NAME, true, record -> {
callbackInvoked.incrementAndGet();
database.async().updateRecord(record.modify().set("updated", true), newRecord -> updatedRecords.incrementAndGet());
record.modify().set("updated", true).save();
updatedRecords.incrementAndGet();
return true;
});

Expand All @@ -84,7 +85,10 @@ public void testSyncScanAndAsyncUpdate() {
assertThat(callbackInvoked.get()).isEqualTo(TOT);
assertThat(updatedRecords.get()).isEqualTo(TOT);

final ResultSet resultSet = database.query("sql", "select count(*) as count from " + TYPE_NAME + " where updated = true");
ResultSet resultSet = database.query("sql", "select from " + TYPE_NAME + " where updated <> true");
Assertions.assertFalse(resultSet.hasNext());

resultSet = database.query("sql", "select count(*) as count from " + TYPE_NAME + " where updated = true");

assertThat(resultSet.hasNext()).isTrue();
assertThat(((Number) resultSet.next().getProperty("count")).intValue()).isEqualTo(TOT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,8 @@ private int updateRecords(final Database database, final int threadId) {
}

private int deleteRecords(final Database database, final int threadId) {
// if (true)
// return 0;
if (totalTransactionRecords.get() == 0)
return 0;

Expand Down
22 changes: 11 additions & 11 deletions engine/src/test/java/com/arcadedb/database/CheckDatabaseTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ public void checkBrokenDeletedEdges() {
assertThat(row.<String>getProperty("operation")).isEqualTo("check database");
assertThat((Long) row.getProperty("autoFix")).isEqualTo(0);
assertThat((Long) row.getProperty("totalActiveVertices")).isEqualTo(TOTAL);
assertThat((Long) row.getProperty("totalAllocatedEdges")).isEqualTo(TOTAL - 1);
assertThat((Long) row.getProperty("totalAllocatedEdges")).isEqualTo(TOTAL - 2);
assertThat((Long) row.getProperty("totalActiveEdges")).isEqualTo(TOTAL - 2);
assertThat((Long) row.getProperty("totalDeletedRecords")).isEqualTo(1);
assertThat(((Collection) row.getProperty("corruptedRecords")).size()).isEqualTo(0);
Expand Down Expand Up @@ -214,16 +214,16 @@ public void checkBrokenDeletedVertex() {
assertThat(result.hasNext()).isTrue();
Result row = result.next();

assertThat(row.<String>getProperty("operation")).isEqualTo("check database");
assertThat((Long) row.getProperty("autoFix")).isEqualTo((TOTAL - 1) * 2);
assertThat((Long) row.getProperty("totalActiveVertices")).isEqualTo(TOTAL - 1);
assertThat((Long) row.getProperty("totalAllocatedEdges")).isEqualTo(TOTAL - 1);
assertThat((Long) row.getProperty("totalActiveEdges")).isEqualTo(0);
assertThat((Long) row.getProperty("totalDeletedRecords")).isEqualTo(TOTAL);
assertThat(((Collection) row.getProperty("corruptedRecords")).size()).isEqualTo(TOTAL - 1);
assertThat((Long) row.getProperty("missingReferenceBack")).isEqualTo(0);
assertThat((Long) row.getProperty("invalidLinks")).isEqualTo((TOTAL - 1) * 2);
assertThat(((Collection) row.getProperty("warnings")).size()).isEqualTo((TOTAL - 1) * 2);
Assertions.assertEquals("check database", row.getProperty("operation"));
Assertions.assertEquals((TOTAL - 1L) * 2L, (Long) row.getProperty("autoFix"));
Assertions.assertEquals(TOTAL - 1L, (Long) row.getProperty("totalActiveVertices"));
Assertions.assertEquals(0L, (Long) row.getProperty("totalAllocatedEdges"));
Assertions.assertEquals(0L, (Long) row.getProperty("totalActiveEdges"));
Assertions.assertEquals(1, (Long) row.getProperty("totalDeletedRecords"));
Assertions.assertEquals(TOTAL - 1L, ((Collection) row.getProperty("corruptedRecords")).size());
Assertions.assertEquals(0L, (Long) row.getProperty("missingReferenceBack"));
Assertions.assertEquals((TOTAL - 1L) * 2L, (Long) row.getProperty("invalidLinks"));
Assertions.assertEquals((TOTAL - 1L) * 2L, ((Collection) row.getProperty("warnings")).size());

result = database.command("sql", "check database");
assertThat(result.hasNext()).isTrue();
Expand Down
87 changes: 87 additions & 0 deletions engine/src/test/java/com/arcadedb/engine/RandomDeleteTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.arcadedb.engine;

import com.arcadedb.database.Database;
import com.arcadedb.database.DatabaseFactory;
import com.arcadedb.database.RID;
import com.arcadedb.database.Record;
import com.arcadedb.graph.MutableVertex;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.util.*;

public class RandomDeleteTest {
private final static int TOT_RECORDS = 100_000;
private final static String TYPE = "Product";
private static final int CYCLES = 20;

@Test
public void testSmallRecords() {
try (DatabaseFactory databaseFactory = new DatabaseFactory("databases/randomDeleteTest")) {
if (databaseFactory.exists())
databaseFactory.open().drop();

try (Database db = databaseFactory.create()) {
db.getSchema().createVertexType(TYPE, 1);

db.transaction(() -> {
List<RID> rids = insert(db);
Assertions.assertEquals(TOT_RECORDS, db.countType(TYPE, true));

// DELETE FROM 1 TO N
for (int i = 0; i < TOT_RECORDS; i++)
db.deleteRecord(rids.get(i).asVertex());

Assertions.assertEquals(0, db.countType(TYPE, true));

// DELETE RANDOMLY X TIMES
for (int cycle = 0; cycle < CYCLES; cycle++) {
rids = insert(db);
checkRecords(db, rids);

for (int deleted = 0; deleted < TOT_RECORDS; ) {
final int i = new Random().nextInt(TOT_RECORDS);
final RID rid = rids.get(i);
if (rid != null) {
db.deleteRecord(rid.asVertex());
rids.set(i, null);
++deleted;
}
}
}

Assertions.assertEquals(0, db.countType(TYPE, true));

});
} finally {
if (databaseFactory.exists())
databaseFactory.open().drop();
}
}
}

private void checkRecords(Database db, List<RID> rids) {
for (int i = 0; i < rids.size(); i++)
Assertions.assertNotNull(rids.get(i).asVertex());

final List<RID> found = new ArrayList<>();
for (Iterator<Record> it = db.iterateType(TYPE, true); it.hasNext(); )
found.add(it.next().asVertex().getIdentity());

Assertions.assertEquals(rids, found);

Assertions.assertEquals(rids.size(), db.countType(TYPE, true));
}

private static List<RID> insert(final Database db) {
final List<RID> rids = new ArrayList<>(TOT_RECORDS);
for (int i = 0; i < TOT_RECORDS; i++) {
final MutableVertex v = db.newVertex(TYPE)//
.set("id", i)//
.save();

rids.add(v.getIdentity());
}
return rids;
}
}
Loading