-
Notifications
You must be signed in to change notification settings - Fork 46
/
finger.go
84 lines (66 loc) · 1.9 KB
/
finger.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
57
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
package chord
import (
"fmt"
"github.com/arriqaaq/chord/models"
"math/big"
)
type fingerTable []*fingerEntry
func newFingerTable(node *models.Node, m int) fingerTable {
ft := make([]*fingerEntry, m)
for i := range ft {
ft[i] = newFingerEntry(fingerID(node.Id, i, m), node)
}
return ft
}
// fingerEntry represents a single finger table entry
type fingerEntry struct {
Id []byte // ID hash of (n + 2^i) mod (2^m)
Node *models.Node // RemoteNode that Start points to
}
// newFingerEntry returns an allocated new finger entry with the attributes set
func newFingerEntry(id []byte, node *models.Node) *fingerEntry {
return &fingerEntry{
Id: id,
Node: node,
}
}
// Computes the offset by (n + 2^i) mod (2^m)
func fingerID(n []byte, i int, m int) []byte {
// Convert the ID to a bigint
idInt := (&big.Int{}).SetBytes(n)
// Get the offset
two := big.NewInt(2)
offset := big.Int{}
offset.Exp(two, big.NewInt(int64(i)), nil)
// Sum
sum := big.Int{}
sum.Add(idInt, &offset)
// Get the ceiling
ceil := big.Int{}
ceil.Exp(two, big.NewInt(int64(m)), nil)
// Apply the mod
idInt.Mod(&sum, &ceil)
// Add together
return idInt.Bytes()
}
// called periodically. refreshes finger table entries.
// next stores the index of the next finger to fix.
func (n *Node) fixFinger(next int) int {
nextHash := fingerID(n.Id, next, n.cnf.HashSize)
succ, err := n.findSuccessor(nextHash)
nextNum := (next + 1) % n.cnf.HashSize
if err != nil || succ == nil {
fmt.Println("error: ", err, succ)
fmt.Printf("finger lookup failed %x %x \n", n.Id, nextHash)
// TODO: Check how to handle retry, passing ahead for now
return nextNum
}
finger := newFingerEntry(nextHash, succ)
n.ftMtx.Lock()
n.fingerTable[next] = finger
// aInt := (&big.Int{}).SetBytes(nextHash)
// bInt := (&big.Int{}).SetBytes(finger.Node.Id)
// fmt.Printf("finger entry %d, %d,%d\n", next, aInt, bInt)
n.ftMtx.Unlock()
return nextNum
}