Exemplo n.º 1
0
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
            }
    }
}
Exemplo n.º 2
0
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)
}