dataply 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/index.js CHANGED
@@ -3776,11 +3776,16 @@ var MetadataPageManager = class _MetadataPageManager extends PageManager {
3776
3776
  OFFSET_ROOT_INDEX_ORDER: 126,
3777
3777
  OFFSET_LAST_INSERT_PAGE_ID: 130,
3778
3778
  OFFSET_LAST_ROW_PK: 134,
3779
+ OFFSET_BITMAP_PAGE_ID: 140,
3780
+ OFFSET_FREE_PAGE_ID: 144,
3779
3781
  SIZE_PAGE_COUNT: 4,
3780
3782
  SIZE_PAGE_SIZE: 4,
3781
3783
  SIZE_ROOT_INDEX_PAGE_ID: 4,
3782
3784
  SIZE_ROOT_INDEX_ORDER: 4,
3783
- SIZE_LAST_INSERT_PAGE_ID: 4
3785
+ SIZE_LAST_INSERT_PAGE_ID: 4,
3786
+ SIZE_ROW_PK: 6,
3787
+ SIZE_BITMAP_PAGE_ID: 4,
3788
+ SIZE_FREE_PAGE_ID: 4
3784
3789
  };
3785
3790
  /**
3786
3791
  * Checks if the page type is `MetadataPage`.
@@ -3882,7 +3887,7 @@ var MetadataPageManager = class _MetadataPageManager extends PageManager {
3882
3887
  return bytesToNumber(
3883
3888
  page,
3884
3889
  _MetadataPageManager.CONSTANT.OFFSET_LAST_ROW_PK,
3885
- Row.CONSTANT.SIZE_PK
3890
+ _MetadataPageManager.CONSTANT.SIZE_ROW_PK
3886
3891
  );
3887
3892
  }
3888
3893
  /**
@@ -3894,9 +3899,34 @@ var MetadataPageManager = class _MetadataPageManager extends PageManager {
3894
3899
  return bytesToNumber(
3895
3900
  page,
3896
3901
  _MetadataPageManager.CONSTANT.OFFSET_ROW_COUNT,
3897
- Row.CONSTANT.SIZE_PK
3902
+ _MetadataPageManager.CONSTANT.SIZE_ROW_PK
3903
+ );
3904
+ }
3905
+ /**
3906
+ * Returns the ID of the bitmap page.
3907
+ * @param page Page data
3908
+ * @returns Bitmap page ID
3909
+ */
3910
+ getBitmapPageId(page) {
3911
+ return bytesToNumber(
3912
+ page,
3913
+ _MetadataPageManager.CONSTANT.OFFSET_BITMAP_PAGE_ID,
3914
+ _MetadataPageManager.CONSTANT.SIZE_BITMAP_PAGE_ID
3898
3915
  );
3899
3916
  }
3917
+ /**
3918
+ * Returns the ID of the free page.
3919
+ * @param page Page data
3920
+ * @returns Free page ID
3921
+ */
3922
+ getFreePageId(page) {
3923
+ const id = bytesToNumber(
3924
+ page,
3925
+ _MetadataPageManager.CONSTANT.OFFSET_FREE_PAGE_ID,
3926
+ _MetadataPageManager.CONSTANT.SIZE_FREE_PAGE_ID
3927
+ );
3928
+ return id === 4294967295 ? -1 : id;
3929
+ }
3900
3930
  /**
3901
3931
  * Sets the number of pages stored in the database.
3902
3932
  * @param page Page data
@@ -3997,6 +4027,32 @@ var MetadataPageManager = class _MetadataPageManager extends PageManager {
3997
4027
  Row.CONSTANT.SIZE_PK
3998
4028
  );
3999
4029
  }
4030
+ /**
4031
+ * Sets the ID of the bitmap page.
4032
+ * @param page Page data
4033
+ * @param bitmapPageId Bitmap page ID
4034
+ */
4035
+ setBitmapPageId(page, bitmapPageId) {
4036
+ numberToBytes(
4037
+ bitmapPageId,
4038
+ page,
4039
+ _MetadataPageManager.CONSTANT.OFFSET_BITMAP_PAGE_ID,
4040
+ _MetadataPageManager.CONSTANT.SIZE_BITMAP_PAGE_ID
4041
+ );
4042
+ }
4043
+ /**
4044
+ * Sets the ID of the free page.
4045
+ * @param page Page data
4046
+ * @param pageId Free page ID
4047
+ */
4048
+ setFreePageId(page, pageId) {
4049
+ numberToBytes(
4050
+ pageId,
4051
+ page,
4052
+ _MetadataPageManager.CONSTANT.OFFSET_FREE_PAGE_ID,
4053
+ _MetadataPageManager.CONSTANT.SIZE_FREE_PAGE_ID
4054
+ );
4055
+ }
4000
4056
  };
4001
4057
  var BitmapPageManager = class _BitmapPageManager extends PageManager {
4002
4058
  get pageType() {
@@ -4027,6 +4083,31 @@ var BitmapPageManager = class _BitmapPageManager extends PageManager {
4027
4083
  isEmptyPage(page, index) {
4028
4084
  return bytesToNumber(page, index, 1) === 0;
4029
4085
  }
4086
+ /**
4087
+ * Gets a bit from the bitmap page.
4088
+ * @param page Page data
4089
+ * @param index Bit index
4090
+ * @returns boolean indicating if the bit is set
4091
+ */
4092
+ getBit(page, index) {
4093
+ const bitOffset = Math.floor(index / 8);
4094
+ const offset = _BitmapPageManager.CONSTANT.SIZE_PAGE_HEADER + bitOffset;
4095
+ const value = bytesToNumber(page, offset, 1);
4096
+ return getBit(value, index % 8);
4097
+ }
4098
+ /**
4099
+ * Sets a bit in the bitmap page.
4100
+ * @param page Page data
4101
+ * @param index Bit index
4102
+ * @param flag boolean indicating if the bit is set
4103
+ */
4104
+ setBit(page, index, flag) {
4105
+ const bitOffset = Math.floor(index / 8);
4106
+ const offset = _BitmapPageManager.CONSTANT.SIZE_PAGE_HEADER + bitOffset;
4107
+ const value = bytesToNumber(page, offset, 1);
4108
+ const newValue = setBit(value, index % 8, flag);
4109
+ numberToBytes(newValue, page, offset, 1);
4110
+ }
4030
4111
  };
4031
4112
  var OverflowPageManager = class _OverflowPageManager extends PageManager {
4032
4113
  get pageType() {
@@ -4448,8 +4529,8 @@ var VirtualFileSystem = class {
4448
4529
  * @param position Start position in file
4449
4530
  */
4450
4531
  _writeAsync(handle, buffer, offset, length, position) {
4451
- if (position + length > 100 * 1024 * 1024) {
4452
- return Promise.reject(new Error(`[Safety Limit] File write exceeds 100MB limit at position ${position}`));
4532
+ if (position + length > 512 * 1024 * 1024) {
4533
+ return Promise.reject(new Error(`[Safety Limit] File write exceeds 512MB limit at position ${position}`));
4453
4534
  }
4454
4535
  return new Promise((resolve, reject) => {
4455
4536
  import_node_fs2.default.write(handle, buffer, offset, length, position, (err, bytesWritten) => {
@@ -4627,6 +4708,43 @@ var PageFileSystem = class {
4627
4708
  pageFactory = new PageManagerFactory();
4628
4709
  vfs;
4629
4710
  pageManagerFactory;
4711
+ /**
4712
+ * Updates the bitmap status for a specific page.
4713
+ * @param pageId The ID of the page to update
4714
+ * @param isFree True to mark as free, false to mark as used
4715
+ * @param tx Transaction
4716
+ */
4717
+ async updateBitmap(pageId, isFree, tx) {
4718
+ const metadata = await this.getMetadata(tx);
4719
+ const metadataManager = this.pageFactory.getManager(metadata);
4720
+ const bitmapPageId = metadataManager.getBitmapPageId(metadata);
4721
+ const headerSize = PageManager.CONSTANT.SIZE_PAGE_HEADER;
4722
+ const capacityPerBitmapPage = (this.pageSize - headerSize) * 8;
4723
+ let currentBitmapPageId = bitmapPageId;
4724
+ let targetBitIndex = pageId;
4725
+ while (targetBitIndex >= capacityPerBitmapPage) {
4726
+ const currentBitmapPage = await this.get(currentBitmapPageId, tx);
4727
+ const manager = this.pageFactory.getManager(currentBitmapPage);
4728
+ targetBitIndex -= capacityPerBitmapPage;
4729
+ const nextPageId = manager.getNextPageId(currentBitmapPage);
4730
+ if (nextPageId === -1) {
4731
+ if (!isFree) {
4732
+ throw new Error("Bitmap page not found for reused page");
4733
+ }
4734
+ const newBitmapPageId = await this.appendNewPage(PageManager.CONSTANT.PAGE_TYPE_BITMAP, tx);
4735
+ manager.setNextPageId(currentBitmapPage, newBitmapPageId);
4736
+ await this.setPage(currentBitmapPageId, currentBitmapPage, tx);
4737
+ currentBitmapPageId = newBitmapPageId;
4738
+ } else {
4739
+ currentBitmapPageId = nextPageId;
4740
+ }
4741
+ }
4742
+ await tx.__acquireWriteLock(currentBitmapPageId);
4743
+ const targetBitmapPage = await this.get(currentBitmapPageId, tx);
4744
+ const bitmapManager = this.pageFactory.getManager(targetBitmapPage);
4745
+ bitmapManager.setBit(targetBitmapPage, targetBitIndex, isFree);
4746
+ await this.setPage(currentBitmapPageId, targetBitmapPage, tx);
4747
+ }
4630
4748
  /**
4631
4749
  * VFS 인스턴스를 반환합니다.
4632
4750
  * Transaction 생성 시 사용됩니다.
@@ -4735,12 +4853,28 @@ var PageFileSystem = class {
4735
4853
  }
4736
4854
  /**
4737
4855
  * Appends and inserts a new page.
4738
- * @returns Created page ID
4856
+ * If a free page is available in the free list, it reuses it.
4857
+ * Otherwise, it appends a new page to the end of the file.
4858
+ * @returns Created or reused page ID
4739
4859
  */
4740
4860
  async appendNewPage(pageType = PageManager.CONSTANT.PAGE_TYPE_EMPTY, tx) {
4741
4861
  await tx.__acquireWriteLock(0);
4742
4862
  const metadata = await this.getMetadata(tx);
4743
4863
  const metadataManager = this.pageFactory.getManager(metadata);
4864
+ const freePageId = metadataManager.getFreePageId(metadata);
4865
+ if (freePageId !== -1) {
4866
+ const reusedPageId = freePageId;
4867
+ const reusedPage = await this.get(reusedPageId, tx);
4868
+ const reusedPageManager = this.pageFactory.getManager(reusedPage);
4869
+ const nextFreePageId = reusedPageManager.getNextPageId(reusedPage);
4870
+ metadataManager.setFreePageId(metadata, nextFreePageId);
4871
+ await this.setPage(0, metadata, tx);
4872
+ await this.updateBitmap(reusedPageId, false, tx);
4873
+ const manager2 = this.pageFactory.getManagerFromType(pageType);
4874
+ const newPage2 = manager2.create(this.pageSize, reusedPageId);
4875
+ await this.setPage(reusedPageId, newPage2, tx);
4876
+ return reusedPageId;
4877
+ }
4744
4878
  const pageCount = metadataManager.getPageCount(metadata);
4745
4879
  const newPageIndex = pageCount;
4746
4880
  const newTotalCount = pageCount + 1;
@@ -4805,6 +4939,26 @@ var PageFileSystem = class {
4805
4939
  }
4806
4940
  }
4807
4941
  }
4942
+ /**
4943
+ * Frees the page and marks it as available in the bitmap.
4944
+ * It also adds the page to the linked list of free pages in metadata.
4945
+ * @param pageId Page ID
4946
+ * @param tx Transaction
4947
+ */
4948
+ async setFreePage(pageId, tx) {
4949
+ await tx.__acquireWriteLock(0);
4950
+ await tx.__acquireWriteLock(pageId);
4951
+ const metadata = await this.getMetadata(tx);
4952
+ const metadataManager = this.pageFactory.getManager(metadata);
4953
+ const currentHeadFreePageId = metadataManager.getFreePageId(metadata);
4954
+ const emptyPageManager = this.pageFactory.getManagerFromType(PageManager.CONSTANT.PAGE_TYPE_EMPTY);
4955
+ const emptyPage = emptyPageManager.create(this.pageSize, pageId);
4956
+ emptyPageManager.setNextPageId(emptyPage, currentHeadFreePageId);
4957
+ await this.setPage(pageId, emptyPage, tx);
4958
+ await this.updateBitmap(pageId, true, tx);
4959
+ metadataManager.setFreePageId(metadata, pageId);
4960
+ await this.setPage(0, metadata, tx);
4961
+ }
4808
4962
  /**
4809
4963
  * Closes the page file system.
4810
4964
  */
@@ -4944,8 +5098,7 @@ var RowIdentifierStrategy = class extends SerializeStrategyAsync {
4944
5098
  while (true) {
4945
5099
  const page = await this.pfs.get(pageId, tx);
4946
5100
  const nextPageId = manager.getNextPageId(page);
4947
- manager.setNextPageId(page, -1);
4948
- manager.setRemainingCapacity(page, this.pfs.pageSize - PageManager.CONSTANT.SIZE_PAGE_HEADER);
5101
+ await this.pfs.setFreePage(pageId, tx);
4949
5102
  if (nextPageId === -1) {
4950
5103
  break;
4951
5104
  }
@@ -5337,13 +5490,41 @@ var RowTableEngine = class {
5337
5490
  if (this.rowManager.getDeletedFlag(row)) {
5338
5491
  return;
5339
5492
  }
5493
+ if (this.rowManager.getOverflowFlag(row)) {
5494
+ let overflowPageId = bytesToNumber(this.rowManager.getBody(row));
5495
+ while (overflowPageId !== -1) {
5496
+ const overflowPage = await this.pfs.get(overflowPageId, tx);
5497
+ const manager = this.factory.getManager(overflowPage);
5498
+ const nextPageId = manager.getNextPageId(overflowPage);
5499
+ await this.pfs.setFreePage(overflowPageId, tx);
5500
+ overflowPageId = nextPageId;
5501
+ }
5502
+ }
5340
5503
  this.rowManager.setDeletedFlag(row, true);
5341
5504
  await this.pfs.setPage(pageId, page, tx);
5342
5505
  if (decrementRowCount) {
5343
- const metadataPage = await this.pfs.getMetadata(tx);
5344
- const currentRowCount = this.metadataPageManager.getRowCount(metadataPage);
5345
- this.metadataPageManager.setRowCount(metadataPage, currentRowCount - 1);
5346
- await this.pfs.setMetadata(metadataPage, tx);
5506
+ const metadataPage2 = await this.pfs.getMetadata(tx);
5507
+ const currentRowCount = this.metadataPageManager.getRowCount(metadataPage2);
5508
+ this.metadataPageManager.setRowCount(metadataPage2, currentRowCount - 1);
5509
+ await this.pfs.setMetadata(metadataPage2, tx);
5510
+ }
5511
+ const insertedRowCount = this.dataPageManager.getInsertedRowCount(page);
5512
+ let allDeleted = true;
5513
+ const metadataPage = await this.pfs.getMetadata(tx);
5514
+ const lastInsertPageId = this.metadataPageManager.getLastInsertPageId(metadataPage);
5515
+ if (pageId === lastInsertPageId) {
5516
+ allDeleted = false;
5517
+ } else {
5518
+ for (let i = 0; i < insertedRowCount; i++) {
5519
+ const slotRow = this.dataPageManager.getRow(page, i);
5520
+ if (!this.rowManager.getDeletedFlag(slotRow)) {
5521
+ allDeleted = false;
5522
+ break;
5523
+ }
5524
+ }
5525
+ }
5526
+ if (allDeleted) {
5527
+ await this.pfs.setFreePage(pageId, tx);
5347
5528
  }
5348
5529
  }
5349
5530
  /**
@@ -5648,6 +5829,7 @@ var DataplyAPI = class {
5648
5829
  */
5649
5830
  static InitializeFile(fileHandle, options) {
5650
5831
  const metadataPageManager = new MetadataPageManager();
5832
+ const bitmapPageManager = new BitmapPageManager();
5651
5833
  const dataPageManager = new DataPageManager();
5652
5834
  const metadataPage = new Uint8Array(options.pageSize);
5653
5835
  const dataPage = new Uint8Array(options.pageSize);
@@ -5659,19 +5841,32 @@ var DataplyAPI = class {
5659
5841
  options.pageSize - MetadataPageManager.CONSTANT.SIZE_PAGE_HEADER
5660
5842
  );
5661
5843
  metadataPageManager.setMagicString(metadataPage);
5662
- metadataPageManager.setPageCount(metadataPage, 2);
5663
5844
  metadataPageManager.setPageSize(metadataPage, options.pageSize);
5664
5845
  metadataPageManager.setRootIndexPageId(metadataPage, -1);
5665
- metadataPageManager.setLastInsertPageId(metadataPage, 1);
5846
+ metadataPageManager.setBitmapPageId(metadataPage, 1);
5847
+ metadataPageManager.setLastInsertPageId(metadataPage, 2);
5848
+ metadataPageManager.setPageCount(metadataPage, 3);
5849
+ metadataPageManager.setFreePageId(metadataPage, -1);
5850
+ const bitmapPage = new Uint8Array(options.pageSize);
5851
+ bitmapPageManager.initial(
5852
+ bitmapPage,
5853
+ BitmapPageManager.CONSTANT.PAGE_TYPE_BITMAP,
5854
+ 1,
5855
+ -1,
5856
+ options.pageSize - BitmapPageManager.CONSTANT.SIZE_PAGE_HEADER
5857
+ );
5666
5858
  dataPageManager.initial(
5667
5859
  dataPage,
5668
5860
  DataPageManager.CONSTANT.PAGE_TYPE_DATA,
5669
- 1,
5861
+ 2,
5670
5862
  -1,
5671
5863
  options.pageSize - DataPageManager.CONSTANT.SIZE_PAGE_HEADER
5672
5864
  );
5673
- import_node_fs3.default.appendFileSync(fileHandle, metadataPage);
5674
- import_node_fs3.default.appendFileSync(fileHandle, dataPage);
5865
+ import_node_fs3.default.appendFileSync(fileHandle, new Uint8Array([
5866
+ ...metadataPage,
5867
+ ...bitmapPage,
5868
+ ...dataPage
5869
+ ]));
5675
5870
  }
5676
5871
  /**
5677
5872
  * Opens the database file. If the file does not exist, it initializes it.
@@ -421,11 +421,16 @@ export declare class MetadataPageManager extends PageManager {
421
421
  readonly OFFSET_ROOT_INDEX_ORDER: 126;
422
422
  readonly OFFSET_LAST_INSERT_PAGE_ID: 130;
423
423
  readonly OFFSET_LAST_ROW_PK: 134;
424
+ readonly OFFSET_BITMAP_PAGE_ID: 140;
425
+ readonly OFFSET_FREE_PAGE_ID: 144;
424
426
  readonly SIZE_PAGE_COUNT: 4;
425
427
  readonly SIZE_PAGE_SIZE: 4;
426
428
  readonly SIZE_ROOT_INDEX_PAGE_ID: 4;
427
429
  readonly SIZE_ROOT_INDEX_ORDER: 4;
428
430
  readonly SIZE_LAST_INSERT_PAGE_ID: 4;
431
+ readonly SIZE_ROW_PK: 6;
432
+ readonly SIZE_BITMAP_PAGE_ID: 4;
433
+ readonly SIZE_FREE_PAGE_ID: 4;
429
434
  readonly PAGE_TYPE_UNKNOWN: 0;
430
435
  readonly PAGE_TYPE_EMPTY: 1;
431
436
  readonly PAGE_TYPE_METADATA: 2;
@@ -508,6 +513,18 @@ export declare class MetadataPageManager extends PageManager {
508
513
  * @returns Number of rows
509
514
  */
510
515
  getRowCount(page: MetadataPage): number;
516
+ /**
517
+ * Returns the ID of the bitmap page.
518
+ * @param page Page data
519
+ * @returns Bitmap page ID
520
+ */
521
+ getBitmapPageId(page: MetadataPage): number;
522
+ /**
523
+ * Returns the ID of the free page.
524
+ * @param page Page data
525
+ * @returns Free page ID
526
+ */
527
+ getFreePageId(page: MetadataPage): number;
511
528
  /**
512
529
  * Sets the number of pages stored in the database.
513
530
  * @param page Page data
@@ -555,6 +572,18 @@ export declare class MetadataPageManager extends PageManager {
555
572
  * @param rowCount Number of rows
556
573
  */
557
574
  setRowCount(page: MetadataPage, rowCount: number): void;
575
+ /**
576
+ * Sets the ID of the bitmap page.
577
+ * @param page Page data
578
+ * @param bitmapPageId Bitmap page ID
579
+ */
580
+ setBitmapPageId(page: MetadataPage, bitmapPageId: number): void;
581
+ /**
582
+ * Sets the ID of the free page.
583
+ * @param page Page data
584
+ * @param pageId Free page ID
585
+ */
586
+ setFreePageId(page: MetadataPage, pageId: number): void;
558
587
  }
559
588
  /**
560
589
  * Represents a bitmap page.
@@ -581,6 +610,20 @@ export declare class BitmapPageManager extends PageManager {
581
610
  * @returns boolean indicating if the page is empty
582
611
  */
583
612
  isEmptyPage(page: BitmapPage, index: number): boolean;
613
+ /**
614
+ * Gets a bit from the bitmap page.
615
+ * @param page Page data
616
+ * @param index Bit index
617
+ * @returns boolean indicating if the bit is set
618
+ */
619
+ getBit(page: BitmapPage, index: number): boolean;
620
+ /**
621
+ * Sets a bit in the bitmap page.
622
+ * @param page Page data
623
+ * @param index Bit index
624
+ * @param flag boolean indicating if the bit is set
625
+ */
626
+ setBit(page: BitmapPage, index: number, flag: boolean): void;
584
627
  }
585
628
  /**
586
629
  * Represents an overflow page.
@@ -21,6 +21,13 @@ export declare class PageFileSystem {
21
21
  * @param walPath WAL 파일 경로 (기본값: null)
22
22
  */
23
23
  constructor(fileHandle: number, pageSize: number, pageCacheCapacity: number, walPath?: string | undefined | null);
24
+ /**
25
+ * Updates the bitmap status for a specific page.
26
+ * @param pageId The ID of the page to update
27
+ * @param isFree True to mark as free, false to mark as used
28
+ * @param tx Transaction
29
+ */
30
+ private updateBitmap;
24
31
  /**
25
32
  * VFS 인스턴스를 반환합니다.
26
33
  * Transaction 생성 시 사용됩니다.
@@ -80,7 +87,9 @@ export declare class PageFileSystem {
80
87
  setPage(pageIndex: number, page: Uint8Array, tx: Transaction): Promise<void>;
81
88
  /**
82
89
  * Appends and inserts a new page.
83
- * @returns Created page ID
90
+ * If a free page is available in the free list, it reuses it.
91
+ * Otherwise, it appends a new page to the end of the file.
92
+ * @returns Created or reused page ID
84
93
  */
85
94
  appendNewPage(pageType: number | undefined, tx: Transaction): Promise<number>;
86
95
  /**
@@ -91,6 +100,13 @@ export declare class PageFileSystem {
91
100
  * @param tx Transaction
92
101
  */
93
102
  writePageContent(pageId: number, data: Uint8Array, offset: number | undefined, tx: Transaction): Promise<void>;
103
+ /**
104
+ * Frees the page and marks it as available in the bitmap.
105
+ * It also adds the page to the linked list of free pages in metadata.
106
+ * @param pageId Page ID
107
+ * @param tx Transaction
108
+ */
109
+ setFreePage(pageId: number, tx: Transaction): Promise<void>;
94
110
  /**
95
111
  * Closes the page file system.
96
112
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dataply",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "A lightweight storage engine for Node.js with support for MVCC, WAL.",
5
5
  "license": "MIT",
6
6
  "author": "izure <admin@izure.org>",
@@ -17,7 +17,7 @@
17
17
  "dist/**/*"
18
18
  ],
19
19
  "scripts": {
20
- "test": "jest --runInBand --forceExit",
20
+ "test": "jest -i",
21
21
  "benchmark": "npx tsx benchmark/benchmark.ts",
22
22
  "build": "node build/index.js && tsc"
23
23
  },
package/readme.md CHANGED
@@ -3,7 +3,7 @@
3
3
  # Dataply
4
4
 
5
5
  > [!WARNING]
6
- > **Dataply is currently in Alpha version.** It is experimental and not yet suitable for production use.
6
+ > **Dataply is currently in Alpha version.** It is experimental and not yet suitable for production use. Internal data structures and file formats are subject to change at any time.
7
7
 
8
8
  **Dataply** is a lightweight, high-performance **Record Store** designed for Node.js. It focuses on storing arbitrary data and providing an auto-generated Primary Key (PK) for ultra-fast retrieval, while supporting core enterprise features like MVCC, WAL, and atomic transactions.
9
9
 
@@ -177,9 +177,17 @@ graph TD
177
177
  ```
178
178
 
179
179
  ### 2. Page-Based Storage and VFS Caching
180
+
180
181
  - **Fixed-size Pages**: All data is managed in fixed-size units (default 8KB) called pages.
181
182
  - **VFS Cache**: Minimizes disk I/O by caching frequently accessed pages in memory.
182
183
  - **Dirty Page Tracking**: Tracks modified pages (Dirty) to synchronize them with disk efficiently only at the time of commit.
184
+ - **Detailed Structure**: For technical details on the physical layout, see [structure.md](structure.md).
185
+
186
+ #### Page & Row Layout
187
+ Dataply uses a **Slotted Page** architecture to manage records efficiently:
188
+ - **Pages**: Consists of a 100-byte header (containing `type`, `id`, `checksum`, etc.) and a body where rows are stored. Slot offsets are stored at the end of the page to track row positions.
189
+ - **Rows**: Each row has a 9-byte header (`flags`, `size`, `PK`) followed by the actual data. Large records automatically trigger **Overflow Pages** to handle data exceeding page capacity.
190
+ - **Keys & Identifiers**: Uses a 6-byte **Primary Key (PK)** for logical mapping and a 6-byte **Record Identifier (RID)** (Slot + Page ID) for direct physical addressing.
183
191
 
184
192
  ### 3. MVCC and Snapshot Isolation
185
193
  - **Non-blocking Reads**: Read operations are not blocked by write operations.