func makeSomeUniqueKeys(N, K uint) (rawKeys [][]byte, bKeys []gh.BytesKey) { rng := xr.MakeSimpleRNG() rawKeys = make([][]byte, N) bKeys = make([]gh.BytesKey, N) keyMap := make(map[uint64]bool) for i := uint(0); i < N; i++ { var bKey gh.BytesKey key := make([]byte, K) for { rng.NextBytes(key) bKey, _ = gh.NewBytesKey(key) hc := bKey.Hashcode() _, ok := keyMap[hc] if !ok { // value is not in the map keyMap[hc] = true break } } rawKeys[i] = key bKeys[i] = bKey } return }
func (rc *RegCluster) AddMember(member *ClientInfo) (err error) { // verify no existing member has the same name name := member.GetName() rc.mu.RLock() // <------------------------------------ _, ok := rc.MembersByName[name] rc.mu.RUnlock() // <------------------------------------ if ok { // DEBUG fmt.Printf("AddMember: ATTEMPT TO ADD EXISTING MEMBER %s\n", name) // END err = ClusterMemberNameInUse } if err == nil { var ( entry interface{} bKey ha.BytesKey ) // check for entry in HAMT rc.mu.RLock() // <--------------------------------- bKey, err = ha.NewBytesKey(rc.ID) entry, err = rc.MembersByID.Find(bKey) rc.mu.RUnlock() // <------------------------------- if err == nil { if entry != nil { err = ClusterMemberIDInUse } } if err == nil { rc.mu.Lock() // <------------------ index := len(rc.Members) // DEBUG _ = index // we might want to use this rc.Members = append(rc.Members, member) rc.MembersByName[name] = member bKey, err = ha.NewBytesKey(member.GetNodeID().Value()) if err == nil { err = rc.MembersByID.Insert(bKey, member) } rc.mu.Unlock() // <---------------------------- } } return }
// Add an item to the map. This should be idempotent: adding a key // that is already in the map should have no effect at all. // func (m *IDMapHAMT) Insert(key []byte, value interface{}) (err error) { bKey, err := gh.NewBytesKey(key) if err == nil { // XXX A very coarse lock m.mu.Lock() defer m.mu.Unlock() err = m.h.Insert(bKey, value) } return }
func (m *IDMapHAMT) Delete(key []byte) (err error) { bKey, err := gh.NewBytesKey(key) if err == nil { // XXX A very coarse lock m.mu.Lock() defer m.mu.Unlock() err = m.h.Delete(bKey) } return }
func (reg *Registry) AddCluster(cluster *RegCluster) (index int, err error) { var bKey, cKey ha.BytesKey if cluster == nil { err = NilCluster } else { name := cluster.Name id := cluster.ID // []byte // convert ID into a HAMT BytesKey bKey, err = ha.NewBytesKey(id) if err == nil { reg.mu.Lock() defer reg.mu.Unlock() if _, ok := reg.ClustersByName[name]; ok { err = NameAlreadyInUse } else { var whatever interface{} whatever, err = reg.ClustersByID.Find(bKey) if err == nil && whatever != nil { err = IDAlreadyInUse } } if err == nil { index = len(reg.Clusters) reg.Clusters = append(reg.Clusters, cluster) reg.ClustersByName[name] = cluster cKey, err = ha.NewBytesKey(cluster.GetNodeID().Value()) if err == nil { err = reg.ClustersByID.Insert(cKey, cluster) } } } } if err != nil { index = -1 } return }
// Return the value associated with the key or nil if there is no // such value. func (m *IDMapHAMT) Find(key []byte) (value interface{}, err error) { bKey, err := gh.NewBytesKey(key) if err == nil { // XXX A very coarse lock m.mu.RLock() defer m.mu.RUnlock() value, err = m.h.Find(bKey) if err == gh.NotFound { err = nil value = nil } } return }
func doGetMsg(h *InHandler) { var ( cluster *RegCluster err error ) defer func() { h.errOut = err }() // Examine incoming message ------------------------------------- getMsg := h.msgIn clusterID := getMsg.GetClusterID() whichRequested := xu.NewBitMap64(getMsg.GetWhich()) // Take appropriate action -------------------------------------- var tokens []*XLRegMsg_Token whichReturned := xu.NewBitMap64(0) // Put the type assertion within the critical section because on // 2013-12-04 I observed a panic with the error message saying // that the assertion failed because kluster was nil, which should // be impossible. // convert clusterID into a BytesKey bKey, err := ha.NewBytesKey(clusterID) if err == nil { var kluster interface{} h.reg.mu.RLock() // <-- LOCK -------------------------- kluster, err = h.reg.ClustersByID.Find(bKey) if kluster == nil { msg := fmt.Sprintf("doGetMsg: can't find cluster with ID %s", hex.EncodeToString(clusterID)) // DEBUG h.reg.Logger.Printf("%s\n", msg) // END err = e.New(msg) } else { cluster = kluster.(*RegCluster) } h.reg.mu.RUnlock() // <-- UNLOCK ---------------------- } if err == nil { size := cluster.Size() // actual size, not MaxSize if size > MAX_CLUSTER_SIZE { // yes, should be impossible size = MAX_CLUSTER_SIZE } // XXX UNDESIRABLE CAST weHave := xu.LowNMap(uint(size)) whichToSend := whichRequested.Intersection(weHave) for i := uint32(0); i < size; i++ { // XXX UNDESIRABLE CAST if whichToSend.Test(uint(i)) { // they want this one member := cluster.Members[i] token, err := member.Token() if err == nil { tokens = append(tokens, token) // XXX UNDESIRABLE CAST whichReturned = whichReturned.Set(uint(i)) } else { break } } } } if err == nil { // Prepare reply to client -------------------------------------- op := XLRegMsg_ClusterMembers h.msgOut = &XLRegMsg{ Op: &op, ClusterID: clusterID, Which: &whichReturned.Bits, Tokens: tokens, } // Set exit state ----------------------------------------------- h.exitState = JOIN_RCVD // the JOIN is intentional ! } }
func doJoinMsg(h *InHandler) { var err error defer func() { h.errOut = err }() // Examine incoming message ------------------------------------- var ( cluster *RegCluster clusterName string clusterID []byte clusterMaxSize uint32 endPointCount uint32 ) joinMsg := h.msgIn // Take appropriate action -------------------------------------- // Accept either cluster name or id. If it's just the name, // attempt to retrieve the ID; it's an error if it does not exist // in the registry. . In either case use the ID to retrieve the size. clusterName = joinMsg.GetClusterName() // will be "" if absent clusterID = joinMsg.GetClusterID() // will be nil if absent if clusterID != nil { h.reg.Logger.Printf("JOIN: cluster %x, new member %s\n", clusterID, h.thisClient.GetName()) } else { h.reg.Logger.Printf("JOIN: cluster %s, new member %s\n", clusterName, h.thisClient.GetName()) } if clusterID == nil && clusterName == "" { // if neither is present, we will use any cluster already // associated with this connection if h.cluster != nil { cluster = h.cluster } else { err = MissingClusterNameOrID } } else if clusterID != nil { var kluster interface{} // convert the clusterID into a HAMT BytesKey bKey, err := ha.NewBytesKey(clusterID) if err == nil { // if an ID has Leen defined, we will try to use that h.reg.mu.RLock() kluster, err = h.reg.ClustersByID.Find(bKey) h.reg.mu.RUnlock() if kluster == nil { msg := fmt.Sprintf("can't find cluster with ID %s", hex.EncodeToString(clusterID)) // DEBUG h.reg.Logger.Printf("%s\n", msg) // END err = e.New(msg) } else { cluster = kluster.(*RegCluster) } } } else { // we have no ID and clusterName is not nil, so we will try to use that var ok bool h.reg.mu.RLock() if cluster, ok = h.reg.ClustersByName[clusterName]; !ok { err = CantFindClusterByName } h.reg.mu.RUnlock() } if err == nil { // if we get here, cluster is not nil err = cluster.AddMember(h.thisClient) } if err == nil { h.reg.Logger.Printf("cluster %x, new member %s\n", cluster.ID, h.thisClient.GetName()) // Prepare reply to client ---------------------------------- h.cluster = cluster clusterID = cluster.ID clusterAttrs := cluster.Attrs clusterMaxSize = h.cluster.maxSize endPointCount = h.cluster.epCount op := XLRegMsg_JoinReply h.msgOut = &XLRegMsg{ Op: &op, ClusterID: clusterID, ClusterAttrs: &clusterAttrs, ClusterMaxSize: &clusterMaxSize, EndPointCount: &endPointCount, } // Set exit state ------------------------------------------- h.exitState = JOIN_RCVD } if err != nil { h.reg.Logger.Printf("cluster %x, new member %s, ERROR %s\n", cluster.ID, h.thisClient.GetName(), err.Error()) } }
func (s *XLSuite) TestRegClusterMaker(c *C) { if VERBOSITY > 0 { fmt.Println("\nTEST_REG_CLUSTER_MAKER") } var err error rng := xr.MakeSimpleRNG() // Generate a random cluster epCount := uint32(1 + rng.Intn(3)) // so from 1 to 3 maxSize := uint32(2 + rng.Intn(6)) // so from 2 to 7 cl := s.makeARegCluster(c, rng, epCount, maxSize) c.Assert(cl.MaxSize(), Equals, maxSize) c.Assert(cl.Size(), Equals, maxSize) // // Verify that member names are unique within the cluster ids := make([][]byte, maxSize) names := make([]string, maxSize) nameMap := make(map[string]uint32) for i := uint32(0); i < maxSize; i++ { member := cl.Members[i] names[i] = member.GetName() // fmt.Printf("member[%d]: %s\n", i, names[i]) // DEBUG nameMap[names[i]] = i // collect IDs while we are at it id := member.GetNodeID().Value() // returns a clone of the nodeID ids[i] = id } // if the names are not unique, map will be smaller c.Assert(maxSize, Equals, uint32(len(nameMap))) // verify that the RegCluster.MembersByName index is correct for i := uint32(0); i < maxSize; i++ { name := names[i] member := cl.MembersByName[name] c.Assert(name, Equals, member.GetName()) } // verify that the RegCluster.MembersByID index is correct count := uint32(0) // number of successful type assertions for i := uint32(0); i < maxSize; i++ { id := ids[i] var bKey ha.BytesKey bKey, err = ha.NewBytesKey(id) c.Assert(err, IsNil) mbr, err := cl.MembersByID.Find(bKey) c.Assert(err, IsNil) var member *ClientInfo // verify that the type assertion succeeds if m, ok := mbr.(*ClientInfo); ok { member = m mID := member.GetNodeID().Value() c.Assert(len(id), Equals, len(mID)) for j := uint(0); j < uint(len(id)); j++ { c.Assert(id[j], Equals, mID[j]) } count++ } } c.Assert(maxSize, Equals, count) }