Skip to content

Commit b4f5d85

Browse files
committed
implements transport component of raft - initial working set(#180)
1 parent 7ddd142 commit b4f5d85

File tree

9 files changed

+1964
-56
lines changed

9 files changed

+1964
-56
lines changed

cluster/store/store.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,14 @@ func (s *store) newRaftNode() error {
8282
conf := s.newDefaultConfig()
8383

8484
// setup Raft communication
85-
t := newTransport(s.conf)
86-
85+
ls, err := newListener(s.conf)
86+
if err != nil {
87+
return err
88+
}
89+
t, err := newTransport(s.conf, ls, newDialOption(s.conf))
90+
if err != nil {
91+
return err
92+
}
8793
// create the snapshot store. This allows the Raft to truncate the log.
8894
snapshots, err := newSnapshotStore(s.conf)
8995
if err != nil {

cluster/store/store_log.go

+5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"github.com/ByteStorage/FlyDB/config"
66
"github.com/ByteStorage/FlyDB/lib/datastore"
7+
"github.com/hashicorp/raft"
78
)
89

910
// DataStoreFactory is a function type that creates a new instance of a raft.LogStore.
@@ -21,6 +22,10 @@ var datastoreFactories = make(map[string]DataStoreFactory)
2122
func Init() error {
2223
// Register the "memory" DataStoreFactory implementation with the name "memory"
2324
_ = Register("memory", datastore.NewLogInMemStorage)
25+
// Register the "memory" DataStoreFactory implementation with the name "memory"
26+
_ = Register("inMemory", func(conf config.Config) (datastore.DataStore, error) {
27+
return raft.NewInmemStore(), nil
28+
})
2429
// Register the "bolt" DataStoreFactory implementation with the name "boltdb"
2530
_ = Register("boltdb", datastore.NewLogBoltDbStorage)
2631
// Register the "flydb" DataStoreFactory implementation with the name "flydb"

cluster/store/store_transport.go

+99-10
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import (
88
raftPB "github.com/ByteStorage/FlyDB/lib/proto/raft"
99
"github.com/hashicorp/raft"
1010
"google.golang.org/grpc"
11+
"google.golang.org/grpc/credentials/insecure"
1112
"io"
13+
"net"
1214
"sync"
1315
"time"
1416
)
@@ -41,24 +43,49 @@ type appendFuture struct {
4143
type Transport struct {
4244
//implement me
4345
localAddr raft.ServerAddress
44-
consumer chan raft.RPC
4546
clients map[raft.ServerAddress]*ClientConn
46-
server *grpc.Server
47-
heartbeatFn func(raft.RPC)
47+
server *TransportServer
4848
dialOptions []grpc.DialOption
4949
heartbeatTimeout time.Duration
5050
sync.RWMutex
5151
}
52+
type TransportServer struct {
53+
server *grpc.Server
54+
consumer chan raft.RPC
55+
heartbeatFn func(raft.RPC)
56+
serverQuit chan struct{}
57+
raftPB.UnsafeRaftServiceServer
58+
}
5259

5360
// NewTransport returns a new transport, it needs start a grpc server
54-
func newTransport(conf config.Config) raft.Transport {
61+
func newTransport(conf config.Config, l net.Listener, do []grpc.DialOption) (*Transport, error) {
62+
s := grpc.NewServer()
63+
ts := &TransportServer{
64+
server: s,
65+
consumer: make(chan raft.RPC),
66+
serverQuit: make(chan struct{}),
67+
}
68+
raftPB.RegisterRaftServiceServer(s, ts)
69+
70+
go func() {
71+
if err := s.Serve(l); err != nil {
72+
panic(err)
73+
}
74+
}()
75+
5576
return &Transport{
5677
localAddr: conf.LocalAddress,
57-
dialOptions: []grpc.DialOption{grpc.WithInsecure()},
78+
dialOptions: do,
5879
heartbeatTimeout: conf.HeartbeatTimeout,
59-
consumer: make(chan raft.RPC),
80+
server: ts,
6081
clients: map[raft.ServerAddress]*ClientConn{},
61-
}
82+
}, nil
83+
}
84+
func newListener(conf config.Config) (net.Listener, error) {
85+
return net.Listen("tcp", string(conf.LocalAddress))
86+
}
87+
func newDialOption(conf config.Config) []grpc.DialOption {
88+
return []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
6289
}
6390

6491
// AppendEntriesPipeline returns an interface that can be used to pipeline
@@ -152,7 +179,7 @@ func (t *Transport) TimeoutNow(id raft.ServerID, target raft.ServerAddress, args
152179
// Consumer returns a channel that can be used to
153180
// consume and respond to RPC requests.
154181
func (t *Transport) Consumer() <-chan raft.RPC {
155-
return t.consumer
182+
return t.server.consumer
156183
}
157184

158185
// LocalAddr is used to return our local address to distinguish from our peers.
@@ -177,7 +204,7 @@ func (t *Transport) DecodePeer(p []byte) raft.ServerAddress {
177204
func (t *Transport) SetHeartbeatHandler(handler func(rpc raft.RPC)) {
178205
t.RWMutex.RLock()
179206
defer t.RWMutex.RUnlock()
180-
t.heartbeatFn = handler
207+
t.server.heartbeatFn = handler
181208
}
182209

183210
func (t *Transport) getPeer(target raft.ServerAddress) (raftPB.RaftServiceClient, error) {
@@ -198,8 +225,8 @@ func (t *Transport) getPeer(target raft.ServerAddress) (raftPB.RaftServiceClient
198225
if err != nil {
199226
return nil, err
200227
}
201-
c.conn = conn
202228
c.client = raftPB.NewRaftServiceClient(conn)
229+
c.conn = conn
203230
}
204231
}
205232

@@ -290,3 +317,65 @@ func (af *appendFuture) processMessage(r *raftPipeline) {
290317
close(af.done)
291318
r.doneCh <- af
292319
}
320+
321+
func (t *TransportServer) AppendEntries(ctx context.Context, req *raftPB.AppendEntriesRequest) (*raftPB.AppendEntriesResponse, error) {
322+
resp, err := t.sendRPC(encoding.DecodeAppendEntriesRequest(req), nil)
323+
if err != nil {
324+
return nil, err
325+
}
326+
return encoding.EncodeAppendEntriesResponse(resp.(*raft.AppendEntriesResponse)), nil
327+
}
328+
func (t *TransportServer) RequestVote(ctx context.Context, req *raftPB.RequestVoteRequest) (*raftPB.RequestVoteResponse, error) {
329+
resp, err := t.sendRPC(encoding.DecodeRequestVoteRequest(req), nil)
330+
if err != nil {
331+
return nil, err
332+
}
333+
return encoding.EncodeRequestVoteResponse(resp.(*raft.RequestVoteResponse)), nil
334+
}
335+
func (t *TransportServer) AppendEntriesPipeline(server raftPB.RaftService_AppendEntriesPipelineServer) error {
336+
return nil
337+
}
338+
func (t *TransportServer) TimeoutNow(ctx context.Context, in *raftPB.TimeoutNowRequest) (*raftPB.TimeoutNowResponse, error) {
339+
resp, err := t.sendRPC(encoding.DecodeTimeoutNowRequest(in), nil)
340+
if err != nil {
341+
return nil, err
342+
}
343+
return encoding.EncodeTimeoutNowResponse(resp.(*raft.TimeoutNowResponse)), nil
344+
}
345+
func (t *TransportServer) InstallSnapshot(ctx context.Context, req *raftPB.InstallSnapshotRequest) (*raftPB.InstallSnapshotResponse, error) {
346+
resp, err := t.sendRPC(encoding.DecodeInstallSnapshotRequest(req), nil)
347+
if err != nil {
348+
return nil, err
349+
}
350+
return encoding.EncodeInstallSnapshotResponse(resp.(*raft.InstallSnapshotResponse)), nil
351+
}
352+
353+
func (t *TransportServer) sendRPC(command interface{}, data io.Reader) (interface{}, error) {
354+
ch := make(chan raft.RPCResponse, 1)
355+
rpc := raft.RPC{
356+
Command: command,
357+
RespChan: ch,
358+
Reader: data,
359+
}
360+
if isHeartbeat(command) {
361+
fn := t.heartbeatFn
362+
if fn != nil {
363+
fn(rpc)
364+
}
365+
} else {
366+
t.consumer <- rpc
367+
}
368+
resp := <-ch
369+
if resp.Error != nil {
370+
return nil, resp.Error
371+
}
372+
return resp.Response, nil
373+
}
374+
func (t *TransportServer) Close() {
375+
t.server.GracefulStop()
376+
return
377+
}
378+
func (t *Transport) Close() {
379+
t.server.server.GracefulStop()
380+
return
381+
}

0 commit comments

Comments
 (0)