Skip to content

Commit ff8d5a6

Browse files
author
rand0x0m
committed
Initial commit.
0 parents  commit ff8d5a6

File tree

10 files changed

+808
-0
lines changed

10 files changed

+808
-0
lines changed

README.md

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# chord-dfs : Minimal DFS implementing part of the Chord algorithm
2+
3+
## Overview
4+
5+
Aims to fully implement the algorithm but for the time it still lacks a lot of features other implementations have. And most notably it doesn't support fingers thus has worst time O(n) time complexity for any call.
6+
7+
## Install
8+
9+
```
10+
go get github.com/rand0x0m/chord-dfs
11+
```
12+
13+
## License
14+
15+
MIT.
16+

client.go

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package chord
2+
3+
func remotePut(server *Info, value string) error {
4+
con, err := setupConnection(server)
5+
6+
if err == nil {
7+
err = con.Call("Node.Put", value, nil)
8+
}
9+
10+
return err
11+
}
12+
13+
func remoteGet(server *Info, key string) (string, error) {
14+
var res string
15+
16+
con, err := setupConnection(server)
17+
if err == nil {
18+
err = con.Call("Node.Get", key, &res)
19+
}
20+
21+
return res, err
22+
}
23+
24+
func remoteDelete(server *Info, key string) error {
25+
con, err := setupConnection(server)
26+
27+
if err == nil {
28+
err = con.Call("Node.Delete", key, nil)
29+
}
30+
31+
return err
32+
}
33+
34+
func remoteSucc(server *Info) (*Info, error) {
35+
var res Info
36+
37+
con, err := setupConnection(server)
38+
if err == nil {
39+
err = con.Call("Node.Successor", struct{}{}, &res)
40+
}
41+
42+
return &res, err
43+
}
44+
45+
func remotePred(server *Info) (*Info, error) {
46+
var res Info
47+
48+
con, err := setupConnection(server)
49+
if err == nil {
50+
err = con.Call("Node.Predecessor", struct{}{}, &res)
51+
}
52+
53+
return &res, err
54+
}
55+
56+
func remoteNotify(server *Info, newPred Info) error {
57+
con, err := setupConnection(server)
58+
59+
if err == nil {
60+
err = con.Call("Node.Notify", newPred, nil)
61+
}
62+
63+
return err
64+
}
65+
66+
func remoteFindPred(server *Info, id string) (*Info, error) {
67+
var pred Info
68+
69+
con, err := setupConnection(server)
70+
if err == nil {
71+
err = con.Call("Node.FindPred", id, &pred)
72+
}
73+
74+
return &pred, err
75+
}
76+
77+
func remoteFindSucc(server *Info, id string) (*Info, error) {
78+
var succ Info
79+
80+
con, err := setupConnection(server)
81+
if err == nil {
82+
err = con.Call("Node.FindSucc", id, &succ)
83+
}
84+
85+
return &succ, err
86+
}

db.go

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package chord
2+
3+
type Db map[string]string
4+
5+
func newDb() Db {
6+
var s Db = make(map[string]string)
7+
8+
return s
9+
}

dfs.go

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package chord
2+
3+
import (
4+
"errors"
5+
"net"
6+
)
7+
8+
type DFS struct {
9+
N *Node
10+
Config *Config
11+
}
12+
13+
type Config struct {
14+
BindAddr *net.TCPAddr
15+
BootstrapAddr *net.TCPAddr
16+
}
17+
18+
func (dfs *DFS) Put(value string) error {
19+
if dfs.N.isBootstrap() {
20+
return errors.New("disconnected")
21+
} else {
22+
succ, err := remoteFindSucc(dfs.N.Info, hashData(value))
23+
if err != nil {
24+
return err
25+
}
26+
return remotePut(succ, value)
27+
}
28+
}
29+
30+
func (dfs *DFS) Get(value string) (string, error) {
31+
key := hashData(value)
32+
if dfs.N.isBootstrap() {
33+
return "", errors.New("disconnected")
34+
} else {
35+
succ, err := remoteFindSucc(dfs.N.Info, key)
36+
if err != nil {
37+
return "", err
38+
}
39+
40+
return remoteGet(succ, key)
41+
}
42+
}
43+
44+
func (dfs *DFS) Delete(value string) error {
45+
key := hashData(value)
46+
if dfs.N.isBootstrap() {
47+
return errors.New("disconnected")
48+
} else {
49+
succ, err := remoteFindSucc(dfs.N.Info, key)
50+
if err != nil {
51+
return err
52+
}
53+
54+
return remoteDelete(succ, key)
55+
}
56+
}
57+
58+
func (dfs *DFS) Shutdown() {
59+
dfs.N.shutdown()
60+
}
61+
62+
func (dfs *DFS) Connect() error {
63+
err := dfs.N.join(*dfs.Config.BootstrapAddr)
64+
if err != nil {
65+
return err
66+
}
67+
68+
return nil
69+
}
70+
71+
func NewDFS(config *Config) (*DFS, error) {
72+
dfs := new(DFS)
73+
dfs.N = NewNode(*config.BindAddr)
74+
dfs.Config = config
75+
76+
if err := dfs.N.listen(); err != nil {
77+
return nil, err
78+
}
79+
80+
return dfs, nil
81+
}

examples/three-nodes-network/main.go

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"net"
6+
"time"
7+
8+
"github.com/rand0x0m/chord"
9+
)
10+
11+
var dfs1, dfs2, dfs3 chord.DFS
12+
13+
var testAddrs = [6]net.TCPAddr{
14+
{IP: net.ParseIP("127.0.0.1"), Port: 5483},
15+
{IP: net.ParseIP("127.0.0.1"), Port: 5484},
16+
{IP: net.ParseIP("127.0.0.1"), Port: 5485},
17+
}
18+
19+
var testValues = [6]string{
20+
"TestValue",
21+
"TestValue87",
22+
"TestValue90",
23+
"TestValue20",
24+
"TestValue6",
25+
"TestValue65",
26+
}
27+
28+
func main() {
29+
30+
dfs1, err := chord.NewDFS(&chord.Config{&testAddrs[0], nil})
31+
if err != nil {
32+
panic(err)
33+
}
34+
35+
dfs2, err := chord.NewDFS(&chord.Config{&testAddrs[1], &testAddrs[0]})
36+
if err != nil {
37+
panic(err)
38+
}
39+
40+
dfs3, err := chord.NewDFS(&chord.Config{&testAddrs[2], &testAddrs[0]})
41+
if err != nil {
42+
panic(err)
43+
}
44+
45+
if err := dfs2.Connect(); err != nil {
46+
panic(0)
47+
}
48+
49+
time.Sleep(5 * time.Second)
50+
51+
if err := dfs3.Connect(); err != nil {
52+
panic(0)
53+
}
54+
55+
time.Sleep(5 * time.Second)
56+
57+
for _, v := range testValues {
58+
err := dfs1.Put(v)
59+
if err != nil {
60+
panic(err)
61+
}
62+
}
63+
64+
for _, v := range testValues {
65+
v, err := dfs1.Get(v)
66+
fmt.Println(v)
67+
if err != nil {
68+
panic(err)
69+
}
70+
}
71+
72+
dfs1.Shutdown()
73+
74+
time.Sleep(3 * time.Second)
75+
76+
dfs2.Shutdown()
77+
78+
time.Sleep(3 * time.Second)
79+
80+
dfs3.Shutdown()
81+
}

info.go

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package chord
2+
3+
import (
4+
"fmt"
5+
"net"
6+
)
7+
8+
type Info struct {
9+
Addr net.TCPAddr
10+
Id string
11+
}
12+
13+
func (i *Info) equal(o *Info) bool {
14+
return i.Id == o.Id
15+
}
16+
17+
func (i *Info) String() string {
18+
return fmt.Sprintf("Network:%v:%v Id:%v", i.Addr.Network(), i.Addr.String(), i.Id)
19+
}
20+
21+
func newNodeInfo(addr net.TCPAddr) *Info {
22+
i := new(Info)
23+
i.Addr = addr
24+
i.Id = hashAddr(addr)
25+
26+
return i
27+
}

0 commit comments

Comments
 (0)