finger.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. package chord
  2. import (
  3. "fmt"
  4. "math/big"
  5. "trial/achord/models"
  6. )
  7. type fingerTable []*fingerEntry
  8. func newFingerTable(node *models.Node, m int) fingerTable {
  9. ft := make([]*fingerEntry, m)
  10. for i := range ft {
  11. ft[i] = newFingerEntry(fingerID(node.Id, i, m), node)
  12. }
  13. return ft
  14. }
  15. // fingerEntry represents a single finger table entry
  16. type fingerEntry struct {
  17. Id []byte // ID hash of (n + 2^i) mod (2^m)
  18. Node *models.Node // RemoteNode that Start points to
  19. }
  20. // newFingerEntry returns an allocated new finger entry with the attributes set
  21. func newFingerEntry(id []byte, node *models.Node) *fingerEntry {
  22. return &fingerEntry{
  23. Id: id,
  24. Node: node,
  25. }
  26. }
  27. // Computes the offset by (n + 2^i) mod (2^m)
  28. func fingerID(n []byte, i int, m int) []byte {
  29. // Convert the ID to a bigint
  30. idInt := (&big.Int{}).SetBytes(n)
  31. // Get the offset
  32. two := big.NewInt(2)
  33. offset := big.Int{}
  34. offset.Exp(two, big.NewInt(int64(i)), nil)
  35. // Sum
  36. sum := big.Int{}
  37. sum.Add(idInt, &offset)
  38. // Get the ceiling
  39. ceil := big.Int{}
  40. ceil.Exp(two, big.NewInt(int64(m)), nil)
  41. // Apply the mod
  42. idInt.Mod(&sum, &ceil)
  43. // Add together
  44. return idInt.Bytes()
  45. }
  46. // called periodically. refreshes finger table entries.
  47. // next stores the index of the next finger to fix.
  48. func (n *Node) fixFinger(next int) int {
  49. nextHash := fingerID(n.Id, next, n.cnf.HashSize)
  50. succ, err := n.findSuccessor(nextHash)
  51. nextNum := (next + 1) % n.cnf.HashSize
  52. if err != nil || succ == nil {
  53. fmt.Println("error: ", err, succ)
  54. fmt.Printf("finger lookup failed %x %x \n", n.Id, nextHash)
  55. // TODO: Check how to handle retry, passing ahead for now
  56. return nextNum
  57. }
  58. finger := newFingerEntry(nextHash, succ)
  59. n.ftMtx.Lock()
  60. n.fingerTable[next] = finger
  61. // aInt := (&big.Int{}).SetBytes(nextHash)
  62. // bInt := (&big.Int{}).SetBytes(finger.Node.Id)
  63. // fmt.Printf("finger entry %d, %d,%d\n", next, aInt, bInt)
  64. n.ftMtx.Unlock()
  65. return nextNum
  66. }