func (c *CfgMetaKv) SetKey(key string, val []byte) ( uint64, error) { rev, err := c.cfgMem.GetRev(key, 0) if err != nil { return 0, err } if rev == nil { err = metakv.Add(c.makeKey(key), val) } else { err = metakv.Set(c.makeKey(key), val, rev) } if err == nil { cas, err = c.cfgMem.Set(key, val, CAS_FORCE) if err != nil { return 0, err } } }
func (c *CfgMetaKv) Set(key string, val []byte, cas uint64) ( uint64, error) { log.Printf("cfg_metakv: Set, key: %v, cas: %x", key, cas) path := c.keyToPath(key) c.m.Lock() defer c.m.Unlock() if cfgMetaKvSplitKeys[key] { curEntry := c.splitEntries[key] if cas != 0 && cas != curEntry.cas { return 0, &CfgCASError{} } var curNodeDefs NodeDefs if curEntry.data != nil && len(curEntry.data) > 0 { err := json.Unmarshal(curEntry.data, &curNodeDefs) if err != nil { return 0, err } } var nd NodeDefs err := json.Unmarshal(val, &nd) if err != nil { return 0, err } // Analyze which children were added, removed, updated. // added := map[string]bool{} removed := map[string]bool{} updated := map[string]bool{} for k, v := range nd.NodeDefs { if curNodeDefs.NodeDefs == nil || curNodeDefs.NodeDefs[k] == nil { added[k] = true } else { if curNodeDefs.NodeDefs[k].UUID != v.UUID { updated[k] = true } } } if curNodeDefs.NodeDefs != nil { for k, _ := range curNodeDefs.NodeDefs { if nd.NodeDefs[k] == nil { removed[k] = true } } } // Update metakv with child entries. // if len(added) > 0 || len(updated) > 0 { for k, v := range nd.NodeDefs { childNodeDefs := NodeDefs{ UUID: nd.UUID, NodeDefs: map[string]*NodeDef{}, ImplVersion: nd.ImplVersion, } childNodeDefs.NodeDefs[k] = v val, err = json.Marshal(childNodeDefs) if err != nil { return 0, err } childPath := path + "/" + k log.Printf("cfg_metakv: Set split key: %v, childPath: %v", key, childPath) err = metakv.Set(childPath, val, nil) if err != nil { return 0, err } } } // Remove composite children entries from metakv only if // caller was attempting removals only. This should work as // the caller usually has read-modify-write logic that only // removes node defs and does not add/update node defs in the // same read-modify-write code path. // if len(added) <= 0 && len(updated) <= 0 && len(removed) > 0 { for nodeDefUUID := range removed { err = metakv.Delete(path+"/"+nodeDefUUID, nil) if err != nil { return 0, err } } } casResult := c.lastSplitCAS + 1 c.lastSplitCAS = casResult return casResult, err } rev, err := c.cfgMem.GetRev(key, cas) if err != nil { return 0, err } if rev == nil { err = metakv.Add(path, val) } else { err = metakv.Set(path, val, rev) } if err != nil { return 0, err } return c.cfgMem.Set(key, val, CFG_CAS_FORCE) }