Skip to content

Commit

Permalink
feat: Add delete method to SerializeStrategy class.
Browse files Browse the repository at this point in the history
  • Loading branch information
izure1 committed Apr 12, 2024
1 parent 5757755 commit 259b3b7
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 3 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "serializable-bptree",
"version": "3.3.1",
"version": "3.4.0-alpha.0",
"description": "Store the B+tree flexibly, not only in-memory.",
"main": "dist/cjs/index.cjs",
"module": "dist/esm/index.mjs",
Expand Down
10 changes: 10 additions & 0 deletions src/BPTreeAsync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ export class BPTreeAsync<K, V> extends BPTree<K, V> {

if (this.root === node && node.keys.length === 1) {
const keys = node.keys as number[]
this.bufferForNodeDelete(this.root)
this.root = await this.getNode(keys[0])
this.root.parent = 0
this.strategy.head.root = this.root.id
Expand Down Expand Up @@ -255,6 +256,7 @@ export class BPTreeAsync<K, V> extends BPTree<K, V> {

await this._deleteEntry(await this.getNode(node.parent), node.id, guess!)
this.bufferForNodeUpdate(pointer)
this.bufferForNodeDelete(node)
}
else {
if (isPredecessor) {
Expand Down Expand Up @@ -491,6 +493,13 @@ export class BPTreeAsync<K, V> extends BPTree<K, V> {
this._nodeUpdateBuffer.clear()
}

protected async commitNodeDeleteBuffer(): Promise<void> {
for (const node of this._nodeDeleteBuffer.values()) {
await this.strategy.delete(node.id)
}
this._nodeDeleteBuffer.clear()
}

public async keys(condition: BPTreeCondition<V>, filterValues?: Set<K>): Promise<Set<K>> {
for (const k in condition) {
const key = k as keyof BPTreeCondition<V>
Expand Down Expand Up @@ -608,6 +617,7 @@ export class BPTreeAsync<K, V> extends BPTree<K, V> {
await this.commitHeadBuffer()
await this.commitNodeCreateBuffer()
await this.commitNodeUpdateBuffer()
await this.commitNodeDeleteBuffer()
}

public async exists(key: K, value: V): Promise<boolean> {
Expand Down
10 changes: 10 additions & 0 deletions src/BPTreeSync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ export class BPTreeSync<K, V> extends BPTree<K, V> {

if (this.root === node && node.keys.length === 1) {
const keys = node.keys as number[]
this.bufferForNodeDelete(this.root)
this.root = this.getNode(keys[0])
this.root.parent = 0
this.strategy.head.root = this.root.id
Expand Down Expand Up @@ -255,6 +256,7 @@ export class BPTreeSync<K, V> extends BPTree<K, V> {

this._deleteEntry(this.getNode(node.parent), node.id, guess!)
this.bufferForNodeUpdate(pointer)
this.bufferForNodeDelete(node)
}
else {
if (isPredecessor) {
Expand Down Expand Up @@ -491,6 +493,13 @@ export class BPTreeSync<K, V> extends BPTree<K, V> {
this._nodeUpdateBuffer.clear()
}

protected commitNodeDeleteBuffer(): void {
for (const node of this._nodeDeleteBuffer.values()) {
this.strategy.delete(node.id)
}
this._nodeDeleteBuffer.clear()
}

public keys(condition: BPTreeCondition<V>, filterValues?: Set<K>): Set<K> {
for (const k in condition) {
const key = k as keyof BPTreeCondition<V>
Expand Down Expand Up @@ -608,6 +617,7 @@ export class BPTreeSync<K, V> extends BPTree<K, V> {
this.commitHeadBuffer()
this.commitNodeCreateBuffer()
this.commitNodeUpdateBuffer()
this.commitNodeDeleteBuffer()
}

public exists(key: K, value: V): boolean {
Expand Down
5 changes: 5 additions & 0 deletions src/SerializeStrategyAsync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export abstract class SerializeStrategyAsync<K, V> extends SerializeStrategy<K,
abstract id(isLeaf: boolean): Promise<number>
abstract read(id: number): Promise<BPTreeNode<K, V>>
abstract write(id: number, node: BPTreeNode<K, V>): Promise<void>
abstract delete(id: number): Promise<void>
abstract readHead(): Promise<SerializeStrategyHead|null>
abstract writeHead(head: SerializeStrategyHead): Promise<void>

Expand Down Expand Up @@ -52,6 +53,10 @@ export class InMemoryStoreStrategyAsync<K, V> extends SerializeStrategyAsync<K,
this.node[id] = node
}

async delete(id: number): Promise<void> {
delete this.node[id]
}

async readHead(): Promise<SerializeStrategyHead|null> {
if (this.head.root === 0) {
return null
Expand Down
5 changes: 5 additions & 0 deletions src/SerializeStrategySync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export abstract class SerializeStrategySync<K, V> extends SerializeStrategy<K, V
abstract id(isLeaf: boolean): number
abstract read(id: number): BPTreeNode<K, V>
abstract write(id: number, node: BPTreeNode<K, V>): void
abstract delete(id: number): void
abstract readHead(): SerializeStrategyHead|null
abstract writeHead(head: SerializeStrategyHead): void

Expand Down Expand Up @@ -52,6 +53,10 @@ export class InMemoryStoreStrategySync<K, V> extends SerializeStrategySync<K, V>
this.node[id] = node
}

delete(id: number): void {
delete this.node[id]
}

readHead(): SerializeStrategyHead|null {
if (this.head.root === 0) {
return null
Expand Down
10 changes: 8 additions & 2 deletions src/base/BPTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export abstract class BPTree<K, V> {

protected readonly _nodeCreateBuffer: Map<number, BPTreeUnknownNode<K, V>>
protected readonly _nodeUpdateBuffer: Map<number, BPTreeUnknownNode<K, V>>
protected readonly _nodeDeleteBuffer: Map<number, BPTreeUnknownNode<K, V>>

protected readonly verifierMap: Record<
keyof BPTreeCondition<V>,
Expand Down Expand Up @@ -120,6 +121,7 @@ export abstract class BPTree<K, V> {
this._cachedRegexp = new CacheBranchSync()
this._nodeCreateBuffer = new Map()
this._nodeUpdateBuffer = new Map()
this._nodeDeleteBuffer = new Map()
this.nodes = new Map()
this.strategy = strategy
this.comparator = comparator
Expand Down Expand Up @@ -249,14 +251,18 @@ export abstract class BPTree<K, V> {
}
}

protected bufferForNodeCreate(node: BPTreeUnknownNode<K, V>): Deferred<void> {
protected bufferForNodeCreate(node: BPTreeUnknownNode<K, V>): void {
this._nodeCreateBuffer.set(node.id, node)
}

protected bufferForNodeUpdate(node: BPTreeUnknownNode<K, V>): Deferred<void> {
protected bufferForNodeUpdate(node: BPTreeUnknownNode<K, V>): void {
this._nodeUpdateBuffer.set(node.id, node)
}

protected bufferForNodeDelete(node: BPTreeUnknownNode<K, V>): void {
this._nodeDeleteBuffer.set(node.id, node)
}

/**
* Returns the user-defined data stored in the head of the tree.
* This value can be set using the `setHeadData` method. If no data has been previously inserted, the default value is returned, and the default value is `{}`.
Expand Down
7 changes: 7 additions & 0 deletions src/base/SerializeStrategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ export abstract class SerializeStrategy<K, V> {
*/
abstract write(id: number, node: BPTreeNode<K, V>): void|Promise<void>

/**
* This method is called when previously created nodes become no longer needed due to deletion or other processes.
* It can be used to free up space by deleting existing stored nodes.
* @param id This is the ID of the node to be deleted.
*/
abstract delete(id: number): void|Promise<void>

/**
* It is called when the `init` method of the tree instance is called.
* This method should return the information needed to initialize the tree. This information refers to the values stored in the `writeHead` method.
Expand Down
10 changes: 10 additions & 0 deletions test/unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ import {
import {
readFileSync,
writeFileSync,
unlinkSync,
existsSync,
mkdirSync,
} from 'fs'
import {
readFile,
writeFile,
unlink
} from 'fs/promises'
import { join } from 'path'

Expand Down Expand Up @@ -518,6 +520,10 @@ class FileIOStrategySync extends SerializeStrategySync<string, number> {
writeFileSync(this._filePath(id), stringify, 'utf8')
}

delete(id: number): void {
unlinkSync(this._filePath(id))
}

readHead(): SerializeStrategyHead|null {
const filePath = this._filePath('head')
if (!existsSync(filePath)) {
Expand Down Expand Up @@ -566,6 +572,10 @@ class FileIOStrategyAsync extends SerializeStrategyAsync<string, number> {
await writeFile(this._filePath(id), stringify, 'utf8')
}

async delete(id: number): Promise<void> {
await unlink(this._filePath(id))
}

async readHead(): Promise<SerializeStrategyHead|null> {
const filePath = this._filePath('head')
if (!existsSync(filePath)) {
Expand Down

0 comments on commit 259b3b7

Please sign in to comment.