Esempio n. 1
0
func (c *CfgMetaKv) delUnlocked(key string, cas uint64) error {
	path := c.keyToPath(key)

	if cfgMetaKvSplitKeys[key] {
		return metakv.RecursiveDelete(path + "/")
	}

	rev, err := c.cfgMem.GetRev(key, cas)
	if err != nil {
		return err
	}

	err = metakv.Delete(path, rev)
	if err != nil {
		return err
	}

	return c.cfgMem.Del(key, 0)
}
Esempio n. 2
0
func (c *CfgMetaKv) delUnlocked(key string, cas uint64) error {
    keys := []string{}
    if strings.HasPrefix(key, CfgNodeDefsKey(NODE_DEFS_WANTED)) {
        m := c.cfgMem.GetKeyWithPrefix(CfgNodeDefsKey(NODE_DEFS_WANTED))
        for k,_ := range m {
            keys = append(keys, k)
        }
    } else {
        keys = append(keys, key)
    }
    // is this fine ? I dont think so.
    for _,key := range keys {
        rev, err := c.cfgMem.GetRev(key, cas)
            if err != nil {
                return err
            }
        err = metakv.Delete(c.makeKey(key), rev)
            if err != nil {
                return c.cfgMem.Del(key, 0)
            }
    }
    return err
}
Esempio n. 3
0
// set() splits a nodeDefs into multiple child metakv entries and must
// be invoked with c.m.Lock()'ed.
func (a *cfgMetaKvNodeDefsSplitHandler) set(
	c *CfgMetaKv, key string, val []byte, cas uint64) (uint64, error) {
	path := c.keyToPath(key)

	curEntry := c.splitEntries[key]

	if cas != 0 && cas != curEntry.cas {
		log.Printf("cfg_metakv: Set split, key: %v, cas mismatch: %x != %x",
			key, 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 !reflect.DeepEqual(curNodeDefs.NodeDefs[k], v) {
				updated[k] = true
			}
		}
	}

	if curNodeDefs.NodeDefs != nil {
		for k, _ := range curNodeDefs.NodeDefs {
			if nd.NodeDefs[k] == nil {
				removed[k] = true
			}
		}
	}

	log.Printf("cfg_metakv: Set split, key: %v,"+
		" added: %v, removed: %v, updated: %v",
		key, added, removed, updated)

LOOP:
	for k, v := range nd.NodeDefs {
		if c.nodeUUID != "" && c.nodeUUID != v.UUID {
			// If we have a nodeUUID, only add/update our
			// nodeDef, where other nodes will each add/update
			// only their own nodeDef's.
			log.Printf("cfg_metakv: Set split, key: %v,"+
				" skipping other node UUID: %v, self nodeUUID: %s",
				key, v.UUID, c.nodeUUID)

			continue LOOP
		}

		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
		}

		break LOOP
	}

	// Remove composite children entries from metakv only if
	// caller was attempting removals only.  This should work as
	// the caller usually has read-compute-write logic that only
	// removes node defs and does not add/update node defs in the
	// same read-compute-write code path.
	//
	if len(added) <= 0 && len(updated) <= 0 && len(removed) > 0 {
		for nodeDefUUID := range removed {
			childPath := path + "/" + nodeDefUUID

			log.Printf("cfg_metakv: Set delete, childPath: %v", childPath)

			err = metakv.Delete(childPath, nil)
			if err != nil {
				return 0, err
			}
		}
	}

	casResult := c.lastSplitCAS + 1
	c.lastSplitCAS = casResult
	return casResult, err
}
Esempio n. 4
0
func (c *CfgMetaKv) delRawLOCKED(key string, cas uint64) error {
	path := c.keyToPath(key)

	return metakv.Delete(path, nil) // TODO: Handle rev better.
}
Esempio n. 5
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)
}