-
Notifications
You must be signed in to change notification settings - Fork 0
/
bootstrap.go
134 lines (115 loc) · 3.22 KB
/
bootstrap.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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package reg
// xlReg_go/bootstrap.go
import (
"crypto/rsa"
"fmt"
xcl "github.com/jddixon/xlCluster_go"
xi "github.com/jddixon/xlNodeID_go"
xn "github.com/jddixon/xlNode_go"
xt "github.com/jddixon/xlTransport_go"
"sync"
)
var _ = fmt.Print
// The bootstrap process enables the caller to join an xlReg cluster
// and learn information about the cluster's other members. Once the
// bootstrapper has learned that information, it is done.
// As implemented so far, this is an ephemeral client, meaning that it
// neither saves nor restores its Node; keys and such are generated for
// each instance.
// For practical use, it is essential that the PktLayer create its
// Node when NewPktLayer() is first called, but then save its
// configuration. This is conventionally written to LFS/.xlattice/config.
// On subsequent runs the client reads its configuration file rather than
// regenerating keys, etc.
//
type Bootstrapper struct {
DoneCh chan error
mu sync.RWMutex // ever used ??? XXX
MemberMaker
}
func NewBootstrapper(
// properties of the prospective cluster member
name, lfs string, ckPriv, skPriv *rsa.PrivateKey, attrs uint64,
// reg server properties
serverName string, serverID *xi.NodeID, serverEnd xt.EndPointI,
serverCK, serverSK *rsa.PublicKey,
// cluster attributes
clusterName string, clusterAttrs uint64, clusterID *xi.NodeID,
size, epCount uint32, e []xt.EndPointI) (bs *Bootstrapper, err error) {
// DEBUG
fmt.Printf("NewBootstrapper: name '%s', lfs '%s'\n", name, lfs)
// END
if lfs == "" {
attrs |= xcl.ATTR_EPHEMERAL
}
nodeID, err := xi.New(nil) // ie, make me a NodeID
if err == nil {
node, err := xn.NewNew(name, nodeID, lfs)
if err == nil {
mn, err := NewMemberMaker(node, attrs,
serverName, serverID, serverEnd, serverCK, serverSK,
clusterName, clusterAttrs, clusterID, size, epCount, e)
if err == nil {
bs = &Bootstrapper{
DoneCh: make(chan error),
MemberMaker: *mn,
}
}
}
}
return
}
// Join the cluster and get the members list.
func (bs *Bootstrapper) JoinCluster() {
mn := &bs.MemberMaker
var (
err error
version1 uint32
)
// join the cluster and get the members list
cnx, version2, err := mn.SessionSetup(version1)
_ = version2 // not yet used
if err == nil {
bs.Cnx = cnx
err = mn.MemberAndOK()
if err == nil {
err = mn.JoinAndReply()
if err == nil {
err = mn.GetAndMembers()
}
}
}
// DEBUG
fmt.Printf("JoinCluster for %s done, returning %v\n",
bs.GetName(), err)
// END
bs.DoneCh <- err
}
// Start the bootstrapper running in separate goroutine, so that this function
// is non-blocking.
func (bs *Bootstrapper) Start() {
mn := &bs.MemberMaker
go func() {
var err error
// DEBUG ------------------------------------------
var nilMembers []int
for i := 0; i < len(bs.Members); i++ {
if bs.Members[i] == nil {
nilMembers = append(nilMembers, i)
}
}
if len(nilMembers) > 0 {
fmt.Printf("Bootstrapper.Run() after Get finds nil members: %v\n",
nilMembers)
}
// END --------------------------------------------
if err == nil {
err = mn.ByeAndAck()
}
// END OF RUN ===============================================
if bs.Cnx != nil {
bs.Cnx.Close()
}
bs.DoneCh <- err
}()
}