|
@@ -22,6 +22,8 @@ import (
|
|
|
"github.com/coreos/etcd/pkg/types"
|
|
"github.com/coreos/etcd/pkg/types"
|
|
|
"github.com/coreos/etcd/storage/backend"
|
|
"github.com/coreos/etcd/storage/backend"
|
|
|
"github.com/coreos/etcd/store"
|
|
"github.com/coreos/etcd/store"
|
|
|
|
|
+
|
|
|
|
|
+ "github.com/coreos/go-semver/semver"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
const (
|
|
@@ -35,6 +37,7 @@ const (
|
|
|
var (
|
|
var (
|
|
|
membersBucketName = []byte("members")
|
|
membersBucketName = []byte("members")
|
|
|
membersRemovedBuckedName = []byte("members_removed")
|
|
membersRemovedBuckedName = []byte("members_removed")
|
|
|
|
|
+ clusterBucketName = []byte("cluster")
|
|
|
|
|
|
|
|
StoreMembersPrefix = path.Join(storePrefix, "members")
|
|
StoreMembersPrefix = path.Join(storePrefix, "members")
|
|
|
storeRemovedMembersPrefix = path.Join(storePrefix, "removed_members")
|
|
storeRemovedMembersPrefix = path.Join(storePrefix, "removed_members")
|
|
@@ -63,6 +66,15 @@ func mustDeleteMemberFromBackend(be backend.Backend, id types.ID) {
|
|
|
tx.Unlock()
|
|
tx.Unlock()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+func mustSaveClusterVersionToBackend(be backend.Backend, ver *semver.Version) {
|
|
|
|
|
+ ckey := backendClusterVersionKey()
|
|
|
|
|
+
|
|
|
|
|
+ tx := be.BatchTx()
|
|
|
|
|
+ tx.Lock()
|
|
|
|
|
+ defer tx.Unlock()
|
|
|
|
|
+ tx.UnsafePut(clusterBucketName, ckey, []byte(ver.String()))
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func mustSaveMemberToStore(s store.Store, m *Member) {
|
|
func mustSaveMemberToStore(s store.Store, m *Member) {
|
|
|
b, err := json.Marshal(m.RaftAttributes)
|
|
b, err := json.Marshal(m.RaftAttributes)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
@@ -105,6 +117,12 @@ func mustUpdateMemberAttrInStore(s store.Store, m *Member) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+func mustSaveClusterVersionToStore(s store.Store, ver *semver.Version) {
|
|
|
|
|
+ if _, err := s.Set(StoreClusterVersionKey(), false, ver.String(), store.TTLOptionSet{ExpireTime: store.Permanent}); err != nil {
|
|
|
|
|
+ plog.Panicf("save cluster version should never fail: %v", err)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// nodeToMember builds member from a key value node.
|
|
// nodeToMember builds member from a key value node.
|
|
|
// the child nodes of the given node MUST be sorted by key.
|
|
// the child nodes of the given node MUST be sorted by key.
|
|
|
func nodeToMember(n *store.NodeExtern) (*Member, error) {
|
|
func nodeToMember(n *store.NodeExtern) (*Member, error) {
|
|
@@ -137,18 +155,27 @@ func backendMemberKey(id types.ID) []byte {
|
|
|
return []byte(id.String())
|
|
return []byte(id.String())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func mustCreateBackendMemberBucket(be backend.Backend) {
|
|
|
|
|
|
|
+func backendClusterVersionKey() []byte {
|
|
|
|
|
+ return []byte("clusterVersion")
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func mustCreateBackendBuckets(be backend.Backend) {
|
|
|
tx := be.BatchTx()
|
|
tx := be.BatchTx()
|
|
|
tx.Lock()
|
|
tx.Lock()
|
|
|
defer tx.Unlock()
|
|
defer tx.Unlock()
|
|
|
tx.UnsafeCreateBucket(membersBucketName)
|
|
tx.UnsafeCreateBucket(membersBucketName)
|
|
|
tx.UnsafeCreateBucket(membersRemovedBuckedName)
|
|
tx.UnsafeCreateBucket(membersRemovedBuckedName)
|
|
|
|
|
+ tx.UnsafeCreateBucket(clusterBucketName)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func MemberStoreKey(id types.ID) string {
|
|
func MemberStoreKey(id types.ID) string {
|
|
|
return path.Join(StoreMembersPrefix, id.String())
|
|
return path.Join(StoreMembersPrefix, id.String())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+func StoreClusterVersionKey() string {
|
|
|
|
|
+ return path.Join(storePrefix, "version")
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func MemberAttributesStorePath(id types.ID) string {
|
|
func MemberAttributesStorePath(id types.ID) string {
|
|
|
return path.Join(MemberStoreKey(id), attributesSuffix)
|
|
return path.Join(MemberStoreKey(id), attributesSuffix)
|
|
|
}
|
|
}
|