pinconv.go 3.55 KB
Newer Older
Andrew Gillis's avatar
Andrew Gillis committed
1 2 3 4 5 6 7 8 9
// Package pinconv converts pins between the dag-based ipldpinner and the
// datastore-based dspinner.  Once conversion is complete, the pins from the
// source pinner are removed.
package pinconv

import (
	"context"
	"fmt"

10
	cid "github.com/ipfs/go-cid"
Andrew Gillis's avatar
Andrew Gillis committed
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
	ds "github.com/ipfs/go-datastore"
	ipfspinner "github.com/ipfs/go-ipfs-pinner"
	"github.com/ipfs/go-ipfs-pinner/dspinner"
	"github.com/ipfs/go-ipfs-pinner/ipldpinner"
	ipld "github.com/ipfs/go-ipld-format"
)

// ConvertPinsFromIPLDToDS converts pins stored in mdag based storage to pins
// stores in the datastore.  Returns a dspinner loaded with the converted pins,
// and a count of the recursive and direct pins converted.
//
// After pins are stored in datastore, the root pin key is deleted to unlink
// the pin data in the DAGService.
func ConvertPinsFromIPLDToDS(ctx context.Context, dstore ds.Datastore, dserv ipld.DAGService, internal ipld.DAGService) (ipfspinner.Pinner, int, error) {
	const ipldPinPath = "/local/pins"

	dsPinner, err := dspinner.New(ctx, dstore, dserv)
	if err != nil {
		return nil, 0, err
	}

32 33 34 35 36 37 38 39 40 41
	var convCount int
	keyChan := make(chan cid.Cid)

	go func() {
		err = ipldpinner.LoadKeys(ctx, dstore, dserv, internal, true, keyChan)
		close(keyChan)
	}()
	for key := range keyChan {
		dsPinner.PinWithMode(key, ipfspinner.Recursive)
		convCount++
Andrew Gillis's avatar
Andrew Gillis committed
42
	}
43 44
	if err != nil {
		return nil, 0, fmt.Errorf("cannot load recursive keys: %s", err)
Andrew Gillis's avatar
Andrew Gillis committed
45 46
	}

47 48 49 50 51 52 53 54
	keyChan = make(chan cid.Cid)
	go func() {
		err = ipldpinner.LoadKeys(ctx, dstore, dserv, internal, false, keyChan)
		close(keyChan)
	}()
	for key := range keyChan {
		dsPinner.PinWithMode(key, ipfspinner.Direct)
		convCount++
Andrew Gillis's avatar
Andrew Gillis committed
55
	}
56 57
	if err != nil {
		return nil, 0, fmt.Errorf("cannot load direct keys: %s", err)
Andrew Gillis's avatar
Andrew Gillis committed
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
	}

	err = dsPinner.Flush(ctx)
	if err != nil {
		return nil, 0, err
	}

	// Delete root mdag key from datastore to remove old pin storage.
	ipldPinDatastoreKey := ds.NewKey(ipldPinPath)
	if err = dstore.Delete(ipldPinDatastoreKey); err != nil {
		return nil, 0, fmt.Errorf("cannot delete old pin state: %v", err)
	}
	if err = dstore.Sync(ipldPinDatastoreKey); err != nil {
		return nil, 0, fmt.Errorf("cannot sync old pin state: %v", err)
	}

	return dsPinner, convCount, nil
}

// ConvertPinsFromDSToIPLD converts the pins stored in the datastore by
// dspinner, into pins stored in the given internal DAGService by ipldpinner.
// Returns an ipldpinner loaded with the converted pins, and a count of the
// recursive and direct pins converted.
//
// After the pins are stored in the DAGService, the pins and their indexes are
// removed from the dspinner.
func ConvertPinsFromDSToIPLD(ctx context.Context, dstore ds.Datastore, dserv ipld.DAGService, internal ipld.DAGService) (ipfspinner.Pinner, int, error) {
	dsPinner, err := dspinner.New(ctx, dstore, dserv)
	if err != nil {
		return nil, 0, err
	}

	ipldPinner, err := ipldpinner.New(dstore, dserv, internal)
	if err != nil {
		return nil, 0, err
	}

	cids, err := dsPinner.RecursiveKeys(ctx)
	if err != nil {
		return nil, 0, err
	}
	for i := range cids {
		ipldPinner.PinWithMode(cids[i], ipfspinner.Recursive)
		dsPinner.RemovePinWithMode(cids[i], ipfspinner.Recursive)
	}
	convCount := len(cids)

	cids, err = dsPinner.DirectKeys(ctx)
	if err != nil {
		return nil, 0, err
	}
	for i := range cids {
		ipldPinner.PinWithMode(cids[i], ipfspinner.Direct)
		dsPinner.RemovePinWithMode(cids[i], ipfspinner.Direct)
	}
	convCount += len(cids)

	// Save the ipldpinner pins
	err = ipldPinner.Flush(ctx)
	if err != nil {
		return nil, 0, err
	}

	err = dsPinner.Flush(ctx)
	if err != nil {
		return nil, 0, err
	}

	return ipldPinner, convCount, nil
}