shard.go 2.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
package flatfs

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"strings"
)

12
type ShardIdV1 struct {
13
	funName string
14 15
	param   int
	fun     ShardFunc
16 17
}

18 19 20 21 22 23 24 25
const PREFIX = "/repo/flatfs/shard"

func (f *ShardIdV1) String() string {
	return fmt.Sprintf("%s/v1/%s/%d", PREFIX, f.funName, f.param)
}

func (f *ShardIdV1) Func() ShardFunc {
	return f.fun
26 27
}

28
func ParseShardFunc(str string) (*ShardIdV1, error) {
29 30 31 32 33 34
	str = strings.TrimSpace(str)
	parts := strings.Split(str, "/")
	// ignore prefix for now
	if len(parts) > 3 {
		parts = parts[len(parts)-3:]
	}
35 36 37 38 39 40
	if len(parts) == 3 {
		version := parts[0]
		if version != "v1" {
			return nil, fmt.Errorf("expected 'v1' for version string got: %s\n", version)
		}
		parts = parts[1:]
41
	}
42 43
	if len(parts) != 2 {
		return nil, fmt.Errorf("invalid shard identifier: %s", str)
44
	}
45 46 47 48
	
	id := &ShardIdV1 {funName: parts[0]}

	param, err := strconv.Atoi(parts[1])
49
	if err != nil {
50
		return nil, fmt.Errorf("invalid parameter: %v", err)
51
	}
52 53 54
	id.param = param

	switch id.funName {
55
	case "prefix":
56
		id.fun = Prefix(param)
57
	case "suffix":
58
		id.fun = Suffix(param)
59
	case "next-to-last":
60
		id.fun = NextToLast(param)
61
	default:
62
		return nil, fmt.Errorf("expected 'prefix', 'suffix' or 'next-to-last' got: %s", id.funName)
63 64
	}

65
	return id, nil
66 67
}

68
func ReadShardFunc(dir string) (*ShardIdV1, error) {
69
	buf, err := ioutil.ReadFile(filepath.Join(dir, "SHARDING"))
70
	if os.IsNotExist(err) {
71
		return nil, ShardingFileMissing
72
	} else if err != nil {
73
		return nil, err
74
	}
75
	return ParseShardFunc(string(buf))
76 77 78
}

func WriteShardFunc(dir, str string) error {
79
	id, err := ParseShardFunc(str)
80 81 82
	if err != nil {
		return err
	}
83 84 85 86 87
	file, err := os.Create(filepath.Join(dir, "SHARDING"))
	if err != nil {
		return err
	}
	defer file.Close()
88
	_, err = file.WriteString(id.String())
89 90 91 92 93 94 95
	if err != nil {
		return err
	}
	_, err = file.WriteString("\n")
	if err != nil {
		return err
	}
96 97 98 99 100 101
	if str == IPFS_DEF_SHARD {
		err := ioutil.WriteFile(filepath.Join(dir, "_README"), []byte(README_IPFS_DEF_SHARD), 0444)
		if err != nil {
			return err
		}
	}
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
	return nil
}

func Prefix(prefixLen int) ShardFunc {
	padding := strings.Repeat("_", prefixLen)
	return func(noslash string) string {
		return (noslash + padding)[:prefixLen]
	}
}

func Suffix(suffixLen int) ShardFunc {
	padding := strings.Repeat("_", suffixLen)
	return func(noslash string) string {
		str := padding + noslash
		return str[len(str)-suffixLen:]
	}
}

func NextToLast(suffixLen int) ShardFunc {
	padding := strings.Repeat("_", suffixLen+1)
	return func(noslash string) string {
		str := padding + noslash
		offset := len(str) - suffixLen - 1
		return str[offset : offset+suffixLen]
	}
}