|
7 | 7 | // |
8 | 8 |
|
9 | 9 | import Foundation |
| 10 | +import Bytes |
10 | 11 |
|
11 | 12 | extension DiskPersistence { |
12 | 13 | actor Transaction: AnyDiskTransaction { |
@@ -294,6 +295,66 @@ extension DiskPersistence.Transaction { |
294 | 295 | instanceData: Data, |
295 | 296 | versionData: Data |
296 | 297 | ) { |
| 298 | + |
| 299 | + guard let rootObject = try await rootObject(for: datastoreKey) |
| 300 | + else { throw DatastoreInterfaceError.datastoreKeyNotFound } |
| 301 | + |
| 302 | + let index = try await rootObject.primaryIndex |
| 303 | + |
| 304 | + let pages = try await index.orderedPages |
| 305 | + |
| 306 | + // See https://stackoverflow.com/questions/26678362/how-do-i-insert-an-element-at-the-correct-position-into-a-sorted-array-in-swift/70645571#70645571 |
| 307 | + // guard !pages.isEmpty else { return Cursor(index: index, after: nil) |
| 308 | + |
| 309 | + var bytesForFirstEntry: Bytes? |
| 310 | + |
| 311 | + let middle = pages.count/2 |
| 312 | + pageIterator: for page in pages[middle...] { |
| 313 | + let blocks = try await page.blocks |
| 314 | + |
| 315 | + for try await block in blocks { |
| 316 | + switch block { |
| 317 | + case .complete(let bytes): |
| 318 | + /// We have a complete entry, lets use it and stop scanning |
| 319 | + bytesForFirstEntry = bytes |
| 320 | + break pageIterator |
| 321 | + case .head(let bytes): |
| 322 | + /// We are starting an entry, but will need to go to the next page. |
| 323 | + bytesForFirstEntry = bytes |
| 324 | + case .slice(let bytes): |
| 325 | + /// In the first position, lets skip it. |
| 326 | + guard bytesForFirstEntry != nil else { continue } |
| 327 | + /// In the final position, lets save and continue. |
| 328 | + bytesForFirstEntry?.append(contentsOf: bytes) |
| 329 | + case .tail(let bytes): |
| 330 | + /// In the first position, lets skip it. |
| 331 | + guard bytesForFirstEntry != nil else { continue } |
| 332 | + /// In the final position, lets save and stop. |
| 333 | + bytesForFirstEntry?.append(contentsOf: bytes) |
| 334 | + break pageIterator |
| 335 | + } |
| 336 | + } |
| 337 | + } |
| 338 | + |
| 339 | + // let entry = try DatastorePageEntry(bytes: bytes) |
| 340 | + let firstEntry = DatastorePageEntry(headers: [], content: []) |
| 341 | + // guard entry.headers.count == 2 else { throw cannot decode page } |
| 342 | +// let versionBytes = firstEntry.headers[0] |
| 343 | + let identifierBytes = firstEntry.headers[1] |
| 344 | + |
| 345 | + let firstEntryIdentifier = try JSONDecoder.shared.decode(IdentifierType.self, from: Data(identifierBytes)) |
| 346 | + |
| 347 | + if firstEntryIdentifier < identifier { |
| 348 | + // evaluate [index(after: middle)...] |
| 349 | + } else { |
| 350 | + // evaluate [..<middle] |
| 351 | + } |
| 352 | + // end of page search |
| 353 | + |
| 354 | + // We have the index we could insert the entry as a new page, but it could be located either on the previous page of the specified one, so check the previous page and check every entry from there, continuing to subsequent pages from there. |
| 355 | + // Cursor should include the page _index_ as a hint, as the structure may change between loading the index and writing to it. |
| 356 | + |
| 357 | + |
297 | 358 | preconditionFailure("Unimplemented") |
298 | 359 | } |
299 | 360 |
|
|
0 commit comments