Skip to content

Commit 5da50d9

Browse files
committed
Import migration from old branch
1 parent 280b5e7 commit 5da50d9

File tree

8 files changed

+2671
-0
lines changed

8 files changed

+2671
-0
lines changed

fs-repo-11-to-12/Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.PHONY: build clean
2+
3+
build:
4+
go build -mod=vendor
5+
6+
clean:
7+
go clean

fs-repo-11-to-12/go.mod

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module github.com/ipfs/fs-repo-migrations/fs-repo-11-to-12
2+
3+
go 1.15
4+
5+
require (
6+
github.com/ipfs/fs-repo-migrations v1.7.1
7+
github.com/ipfs/go-ipfs v0.8.0
8+
)

fs-repo-11-to-12/go.sum

Lines changed: 1130 additions & 0 deletions
Large diffs are not rendered by default.

fs-repo-11-to-12/main.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package main
2+
3+
import (
4+
migrate "github.com/ipfs/fs-repo-migrations/go-migrate"
5+
mg11 "github.com/ipfs/fs-repo-migrations/ipfs-11-to-12/migration"
6+
)
7+
8+
func main() {
9+
m := mg11.Migration{}
10+
migrate.Main(&m)
11+
}

fs-repo-11-to-12/migration/go.mod

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module github.com/ipfs/fs-repo-migrations/ipfs-8-to-9/migration
2+
3+
go 1.13
4+
5+
require (
6+
github.com/ipfs/fs-repo-migrations v1.4.0
7+
github.com/ipfs/go-cid v0.0.5
8+
github.com/ipfs/go-datastore v0.3.1
9+
github.com/ipfs/go-filestore v0.0.4-0.20200203163551-8cc45055f624
10+
github.com/ipfs/go-ipfs v0.4.22-0.20200130064341-6750ee973e2a
11+
github.com/ipfs/go-ipfs-ds-help v0.1.0
12+
github.com/ipfs/go-log/v2 v2.0.2 // indirect
13+
go.uber.org/atomic v1.5.1 // indirect
14+
go.uber.org/zap v1.13.0 // indirect
15+
golang.org/x/crypto v0.0.0-20200206161412-a0c6ece9d31a // indirect
16+
golang.org/x/lint v0.0.0-20200130185559-910be7a94367 // indirect
17+
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 // indirect
18+
golang.org/x/tools v0.0.0-20200206152323-64a0f23fc32d // indirect
19+
)

fs-repo-11-to-12/migration/go.sum

Lines changed: 911 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
// package mg11 contains the code to perform 11-12 repository migration in
2+
// go-ipfs. This performs a switch to raw multihashes for all keys in the
3+
// go-ipfs datastore (https://github.com/ipfs/go-ipfs/issues/6815).
4+
package mg11
5+
6+
import (
7+
"bufio"
8+
"fmt"
9+
"io"
10+
"os"
11+
"path/filepath"
12+
13+
migrate "github.com/ipfs/fs-repo-migrations/go-migrate"
14+
lock "github.com/ipfs/fs-repo-migrations/ipfs-1-to-2/repolock"
15+
"github.com/ipfs/fs-repo-migrations/mfsr"
16+
"github.com/ipfs/go-filestore"
17+
dshelp "github.com/ipfs/go-ipfs-ds-help"
18+
19+
log "github.com/ipfs/fs-repo-migrations/stump"
20+
ds "github.com/ipfs/go-datastore"
21+
"github.com/ipfs/go-ipfs/plugin/loader"
22+
fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo"
23+
)
24+
25+
const backupFile = "11-to-12-cids.txt"
26+
27+
var migrationPrefixes = []ds.Key{
28+
ds.NewKey("blocks"),
29+
filestore.FilestorePrefix,
30+
}
31+
32+
// Migration implements the migration described above.
33+
type Migration struct{}
34+
35+
// Versions returns the current version string for this migration.
36+
func (m Migration) Versions() string {
37+
return "11-to-12"
38+
}
39+
40+
// Reversible returns true.
41+
func (m Migration) Reversible() bool {
42+
return true
43+
}
44+
45+
// lock the repo
46+
func (m Migration) lock(opts migrate.Options) (io.Closer, error) {
47+
log.VLog("locking repo at %q", opts.Path)
48+
return lock.Lock2(opts.Path)
49+
}
50+
51+
// open the repo
52+
func (m Migration) open(opts migrate.Options) (ds.Batching, error) {
53+
log.VLog(" - loading repo configurations")
54+
plugins, err := loader.NewPluginLoader(opts.Path)
55+
if err != nil {
56+
return nil, fmt.Errorf("error loading plugins: %s", err)
57+
}
58+
59+
if err := plugins.Initialize(); err != nil {
60+
return nil, fmt.Errorf("error initializing plugins: %s", err)
61+
}
62+
63+
if err := plugins.Inject(); err != nil {
64+
return nil, fmt.Errorf("error injecting plugins: %s", err)
65+
}
66+
67+
cfg, err := fsrepo.ConfigAt(opts.Path)
68+
if err != nil {
69+
return nil, err
70+
}
71+
72+
dsc, err := fsrepo.AnyDatastoreConfig(cfg.Datastore.Spec)
73+
if err != nil {
74+
return nil, err
75+
}
76+
77+
return dsc.Create(opts.Path)
78+
}
79+
80+
// Apply runs the migration and writes a log file that can be used by Revert.
81+
func (m Migration) Apply(opts migrate.Options) error {
82+
log.Verbose = opts.Verbose
83+
log.Log("applying %s repo migration", m.Versions())
84+
85+
lk, err := m.lock(opts)
86+
if err != nil {
87+
return err
88+
}
89+
defer lk.Close()
90+
91+
repo := mfsr.RepoPath(opts.Path)
92+
93+
log.VLog(" - verifying version is '11'")
94+
if err := repo.CheckVersion("11"); err != nil {
95+
return err
96+
}
97+
98+
dstore, err := m.open(opts)
99+
if err != nil {
100+
return err
101+
}
102+
defer dstore.Close()
103+
104+
log.VLog(" - starting CIDv1 to raw multihash block migration")
105+
106+
// Prepare backing up of CIDs
107+
backupPath := filepath.Join(opts.Path, backupFile)
108+
log.VLog(" - backup file will be written to %s", backupPath)
109+
_, err = os.Stat(backupPath)
110+
if err != nil {
111+
if !os.IsNotExist(err) {
112+
log.Error(err)
113+
return err
114+
}
115+
} else { // backup file exists
116+
log.Log("WARN: backup file %s already exists. CIDs-Multihash pairs will be appended", backupPath)
117+
}
118+
119+
// If it exists, append to it.
120+
f, err := os.OpenFile(backupPath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
121+
if err != nil {
122+
log.Error(err)
123+
return err
124+
}
125+
defer f.Close()
126+
buf := bufio.NewWriter(f)
127+
128+
swapCh := make(chan Swap, 1000)
129+
130+
writingDone := make(chan struct{})
131+
go func() {
132+
for sw := range swapCh {
133+
// Only write the Old string (a CID). We can derive
134+
// the multihash from it.
135+
fmt.Fprint(buf, sw.Old.String(), "\n")
136+
}
137+
close(writingDone)
138+
}()
139+
140+
// Add all the keys to migrate to the backup file
141+
for _, prefix := range migrationPrefixes {
142+
log.VLog(" - Adding keys in prefix %s to backup file", prefix)
143+
cidSwapper := CidSwapper{Prefix: prefix, Store: dstore, SwapCh: swapCh}
144+
total, err := cidSwapper.Run(true) // DRY RUN
145+
if err != nil {
146+
close(swapCh)
147+
log.Error(err)
148+
return err
149+
}
150+
log.Log("%d CIDv1 keys added to backup file for %s", total, prefix)
151+
}
152+
close(swapCh)
153+
// Wait for our writing to finish before doing the flushing.
154+
<-writingDone
155+
buf.Flush()
156+
157+
// The backup file is ready. Run the migration.
158+
for _, prefix := range migrationPrefixes {
159+
log.VLog(" - Migrating keys in prefix %s", prefix)
160+
cidSwapper := CidSwapper{Prefix: prefix, Store: dstore}
161+
total, err := cidSwapper.Run(false) // NOT a Dry Run
162+
if err != nil {
163+
log.Error(err)
164+
return err
165+
}
166+
log.Log("%d CIDv1 keys in %s have been migrated", total, prefix)
167+
}
168+
169+
if err := repo.WriteVersion("12"); err != nil {
170+
log.Error("failed to write version file")
171+
return err
172+
}
173+
log.Log("updated version file")
174+
175+
return nil
176+
}
177+
178+
// Revert attempts to undo the migration using the log file written by Apply.
179+
func (m Migration) Revert(opts migrate.Options) error {
180+
log.Verbose = opts.Verbose
181+
log.Log("reverting %s repo migration", m.Versions())
182+
183+
lk, err := m.lock(opts)
184+
if err != nil {
185+
return err
186+
}
187+
defer lk.Close()
188+
189+
repo := mfsr.RepoPath(opts.Path)
190+
191+
log.VLog(" - verifying version is '12'")
192+
if err := repo.CheckVersion("12"); err != nil {
193+
return err
194+
}
195+
196+
log.VLog(" - starting raw multihash to CIDv1 block migration")
197+
dstore, err := m.open(opts)
198+
if err != nil {
199+
return err
200+
}
201+
defer dstore.Close()
202+
203+
// Open revert path for reading
204+
backupPath := filepath.Join(opts.Path, backupFile)
205+
log.VLog(" - backup file will be read from %s", backupPath)
206+
f, err := os.Open(backupPath)
207+
if err != nil {
208+
log.Error(err)
209+
return err
210+
}
211+
212+
unswapCh := make(chan Swap, 1000)
213+
scanner := bufio.NewScanner(f)
214+
var scannerErr error
215+
216+
go func() {
217+
defer close(unswapCh)
218+
219+
for scanner.Scan() {
220+
cidPath := ds.NewKey(scanner.Text())
221+
cidKey := ds.NewKey(cidPath.BaseNamespace())
222+
prefix := cidPath.Parent()
223+
cid, err := dsKeyToCid(cidKey)
224+
if err != nil {
225+
log.Error("could not parse cid from backup file: %s", err)
226+
scannerErr = err
227+
break
228+
}
229+
mhashPath := prefix.Child(dshelp.MultihashToDsKey(cid.Hash()))
230+
// This is the original swap object which is what we
231+
// wanted to rebuild. Old is the old path and new is
232+
// the new path and the unswapper will revert this.
233+
sw := Swap{Old: cidPath, New: mhashPath}
234+
unswapCh <- sw
235+
}
236+
if err := scanner.Err(); err != nil {
237+
log.Error(err)
238+
return
239+
}
240+
241+
}()
242+
243+
// The backup file contains prefixed keys, so we do not need to set
244+
// them.
245+
cidSwapper := CidSwapper{Store: dstore}
246+
total, err := cidSwapper.Revert(unswapCh)
247+
if err != nil {
248+
log.Error(err)
249+
return err
250+
}
251+
// Revert will only return after unswapCh is closed, so we know
252+
// scannerErr is safe to read at this point.
253+
if scannerErr != nil {
254+
return err
255+
}
256+
257+
log.Log("%d multihashes reverted to CidV1s", total)
258+
if err := repo.WriteVersion("11"); err != nil {
259+
log.Error("failed to write version file")
260+
return err
261+
}
262+
263+
log.Log("reverted version file to version 11")
264+
err = f.Close()
265+
if err != nil {
266+
log.Error("could not close backup file")
267+
return err
268+
}
269+
err = os.Rename(backupPath, backupPath+".reverted")
270+
if err != nil {
271+
log.Error("could not rename the backup file, but migration worked: %s", err)
272+
return err
273+
}
274+
return nil
275+
}

0 commit comments

Comments
 (0)