forked from pachyderm/pachyderm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
hash.go
56 lines (48 loc) · 1.43 KB
/
hash.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package pfs
import (
"hash/adler32"
"path"
"strings"
"github.com/pachyderm/pachyderm/src/client/pfs"
)
type Hasher struct {
FileModulus uint64
BlockModulus uint64
}
func NewHasher(fileModulus uint64, blockModulus uint64) *Hasher {
return &Hasher{
FileModulus: fileModulus,
BlockModulus: blockModulus,
}
}
func (s *Hasher) HashFile(file *pfs.File) uint64 {
return uint64(adler32.Checksum([]byte(path.Clean(file.Path)))) % s.FileModulus
}
func (s *Hasher) HashBlock(block *pfs.Block) uint64 {
return uint64(adler32.Checksum([]byte(block.Hash))) % s.BlockModulus
}
// FileInShard checks if a given file belongs in a given shard, using only the
// file's top-level path. That is, for a path like foo/bar/buzz, FileInShard only
// considers foo
func FileInShard(shard *pfs.Shard, file *pfs.File) bool {
if shard == nil || shard.FileModulus == 0 {
// this lets us default to no filtering
return true
}
parts := strings.Split(path.Clean(file.Path), "/")
var topLevelPath string
if len(parts) > 0 {
topLevelPath = parts[0]
}
sharder := &Hasher{FileModulus: shard.FileModulus}
f := &pfs.File{Path: topLevelPath}
return sharder.HashFile(f) == shard.FileNumber
}
func BlockInShard(shard *pfs.Shard, block *pfs.Block) bool {
if shard == nil || shard.BlockModulus == 0 {
// this lets us default to no filtering
return true
}
sharder := &Hasher{BlockModulus: shard.BlockModulus}
return sharder.HashBlock(block) == shard.BlockNumber
}