| 1018 | } |
| 1019 | |
| 1020 | func (f *VFSFile) Open() error { |
| 1021 | f.logger.Debug("opening file") |
| 1022 | |
| 1023 | // Try to get restore plan. For write-enabled VFS, we can create a new database |
| 1024 | // if no LTX files exist yet. |
| 1025 | infos, err := f.waitForRestorePlan() |
| 1026 | if err != nil { |
| 1027 | // If write mode is enabled and no files exist, we can create a new database |
| 1028 | if f.writeEnabled && errors.Is(err, ErrTxNotAvailable) { |
| 1029 | f.logger.Info("no existing database found, creating new database") |
| 1030 | return f.openNewDatabase() |
| 1031 | } |
| 1032 | return err |
| 1033 | } |
| 1034 | |
| 1035 | pageSize, err := detectPageSizeFromInfos(f.ctx, f.client, infos) |
| 1036 | if err != nil { |
| 1037 | f.logger.Error("cannot detect page size", "error", err) |
| 1038 | return fmt.Errorf("detect page size: %w", err) |
| 1039 | } |
| 1040 | f.pageSize = pageSize |
| 1041 | |
| 1042 | // Initialize page cache. Convert byte size to number of pages. |
| 1043 | cacheEntries := f.CacheSize / int(pageSize) |
| 1044 | if cacheEntries < 1 { |
| 1045 | cacheEntries = 1 |
| 1046 | } |
| 1047 | cache, err := lru.New[uint32, []byte](cacheEntries) |
| 1048 | if err != nil { |
| 1049 | return fmt.Errorf("create page cache: %w", err) |
| 1050 | } |
| 1051 | f.cache = cache |
| 1052 | |
| 1053 | // Determine the current position based off the latest LTX file. |
| 1054 | var pos ltx.Pos |
| 1055 | if len(infos) > 0 { |
| 1056 | pos = ltx.Pos{TXID: infos[len(infos)-1].MaxTXID} |
| 1057 | } |
| 1058 | f.pos = pos |
| 1059 | |
| 1060 | // Initialize write support TXID tracking |
| 1061 | if f.writeEnabled { |
| 1062 | f.expectedTXID = pos.TXID |
| 1063 | f.pendingTXID = pos.TXID + 1 |
| 1064 | f.logger.Debug("write support enabled", "expectedTXID", f.expectedTXID, "pendingTXID", f.pendingTXID) |
| 1065 | |
| 1066 | // Initialize write buffer file for durability (discards any existing buffer) |
| 1067 | if err := f.initWriteBuffer(); err != nil { |
| 1068 | return fmt.Errorf("initialize write buffer: %w", err) |
| 1069 | } |
| 1070 | } |
| 1071 | |
| 1072 | // Build the page index so we can lookup individual pages. |
| 1073 | if err := f.buildIndex(f.ctx, infos); err != nil { |
| 1074 | f.logger.Error("cannot build index", "error", err) |
| 1075 | return fmt.Errorf("cannot build index: %w", err) |
| 1076 | } |
| 1077 | |