Attempts migration of the old (LevelDB-based) database type to the new (SQLite-based) type This will attempt to provide a temporary API server during the migration, if `apiAddr` is not empty.
(ctx context.Context, deleteRetention time.Duration)
| 159 | // Attempts migration of the old (LevelDB-based) database type to the new (SQLite-based) type |
| 160 | // This will attempt to provide a temporary API server during the migration, if `apiAddr` is not empty. |
| 161 | func TryMigrateDatabase(ctx context.Context, deleteRetention time.Duration) error { |
| 162 | oldDBDir := locations.Get(locations.LegacyDatabase) |
| 163 | if _, err := os.Lstat(oldDBDir); err != nil { |
| 164 | // No old database |
| 165 | return nil |
| 166 | } |
| 167 | |
| 168 | be, err := backend.OpenLevelDBRO(oldDBDir) |
| 169 | if err != nil { |
| 170 | // Apparently, not a valid old database |
| 171 | return nil |
| 172 | } |
| 173 | defer be.Close() |
| 174 | |
| 175 | sdb, err := sqlite.OpenForMigration(locations.Get(locations.Database)) |
| 176 | if err != nil { |
| 177 | return err |
| 178 | } |
| 179 | defer sdb.Close() |
| 180 | |
| 181 | miscDB := db.NewMiscDB(sdb) |
| 182 | if when, ok, err := miscDB.Time("migrated-from-leveldb-at"); err == nil && ok { |
| 183 | slog.Error("Old-style database present but already migrated; please manually move or remove.", slog.Any("migratedAt", when), slogutil.FilePath(oldDBDir)) |
| 184 | return nil |
| 185 | } |
| 186 | |
| 187 | slog.Info("Migrating old-style database to SQLite; this may take a while...") |
| 188 | t0 := time.Now() |
| 189 | |
| 190 | ll, err := olddb.NewLowlevel(be) |
| 191 | if err != nil { |
| 192 | return err |
| 193 | } |
| 194 | |
| 195 | totFiles, totBlocks := 0, 0 |
| 196 | for _, folder := range ll.ListFolders() { |
| 197 | // Start a writer routine |
| 198 | fis := make(chan protocol.FileInfo, 50) |
| 199 | var writeErr error |
| 200 | var wg sync.WaitGroup |
| 201 | writerDone := make(chan struct{}) |
| 202 | wg.Go(func() { //nolint:contextcheck |
| 203 | defer close(writerDone) |
| 204 | var batch []protocol.FileInfo |
| 205 | files, blocks := 0, 0 |
| 206 | t0 := time.Now() |
| 207 | t1 := time.Now() |
| 208 | |
| 209 | if writeErr = sdb.DropFolder(folder); writeErr != nil { |
| 210 | slog.Error("Failed database drop", slogutil.Error(writeErr)) |
| 211 | return |
| 212 | } |
| 213 | |
| 214 | for fi := range fis { |
| 215 | batch = append(batch, fi) |
| 216 | files++ |
| 217 | blocks += len(fi.Blocks) |
| 218 | if len(batch) == 1000 { |
no test coverage detected