コード例 #1
0
ファイル: serving_graph.go プロジェクト: aaijazi/vitess
// UpdateEndPoints is part of the topo.Server interface
func (zkts *Server) UpdateEndPoints(ctx context.Context, cell, keyspace, shard string, tabletType topodatapb.TabletType, addrs *topodatapb.EndPoints, existingVersion int64) error {
	path := zkPathForVtName(cell, keyspace, shard, tabletType)
	data, err := json.MarshalIndent(addrs, "", "  ")
	if err != nil {
		return err
	}

	if existingVersion == -1 {
		// Update or create unconditionally.
		_, err := zk.CreateRecursive(zkts.zconn, path, string(data), 0, zookeeper.WorldACL(zookeeper.PERM_ALL))
		if err != nil {
			if zookeeper.IsError(err, zookeeper.ZNODEEXISTS) {
				// Node already exists - just stomp away. Multiple writers shouldn't be here.
				// We use RetryChange here because it won't update the node unnecessarily.
				f := func(oldValue string, oldStat zk.Stat) (string, error) {
					return string(data), nil
				}
				err = zkts.zconn.RetryChange(path, 0, zookeeper.WorldACL(zookeeper.PERM_ALL), f)
			}
		}
		return err
	}

	// Compare And Set
	if _, err = zkts.zconn.Set(path, string(data), int(existingVersion)); err != nil {
		if zookeeper.IsError(err, zookeeper.ZBADVERSION) {
			err = topo.ErrBadVersion
		} else if zookeeper.IsError(err, zookeeper.ZNONODE) {
			err = topo.ErrNoNode
		}
	}
	return err
}
コード例 #2
0
ファイル: metaconn.go プロジェクト: CowLeo/vitess
// Create implements Conn.
func (conn *MetaConn) Create(path, value string, flags int, aclv []zookeeper.ACL) (pathCreated string, err error) {
	var zconn Conn
	for i := 0; i < maxAttempts; i++ {
		zconn, err = conn.connCache.ConnForPath(path)
		if err != nil {
			return
		}
		path = resolveZkPath(path)
		pathCreated, err = zconn.Create(path, value, flags, aclv)
		if err != nil && zookeeper.IsError(err, zookeeper.ZNONODE) {
			parts := strings.Split(path, "/")
			if len(parts) == 3 && parts[0] == "" && parts[1] == MagicPrefix {
				// We were asked to create a /zk/<cell> path, but /zk doesn't exist.
				// We should create /zk automatically in this case, because it's
				// impossible to create /zk via MetaConn, since there's no cell name.
				_, err = zconn.Create("/"+MagicPrefix, "", 0, zookeeper.WorldACL(zookeeper.PERM_ALL))
				if err != nil {
					if shouldRetry(err) {
						continue
					}
					if !zookeeper.IsError(err, zookeeper.ZNODEEXISTS) {
						return "", err
					}
				}
				// Now try the original path again.
				pathCreated, err = zconn.Create(path, value, flags, aclv)
			}
		}
		if !shouldRetry(err) {
			return
		}
	}
	return
}
コード例 #3
0
ファイル: fakezk.go プロジェクト: CowLeo/vitess
func (conn *zconn) RetryChange(path string, flags int, acl []zookeeper.ACL, changeFunc zk.ChangeFunc) error {
	for {
		oldValue, oldStat, err := conn.Get(path)
		if err != nil && !zookeeper.IsError(err, zookeeper.ZNONODE) {
			return err
		}
		newValue, err := changeFunc(oldValue, oldStat)
		if err != nil {
			return err
		}
		if oldStat == nil {
			_, err := conn.Create(path, newValue, flags, acl)
			if err == nil || !zookeeper.IsError(err, zookeeper.ZNODEEXISTS) {
				return err
			}
			continue
		}
		if newValue == oldValue {
			return nil // Nothing to do.
		}
		_, err = conn.Set(path, newValue, oldStat.Version())
		if err == nil || !zookeeper.IsError(err, zookeeper.ZBADVERSION) && !zookeeper.IsError(err, zookeeper.ZNONODE) {
			return err
		}
	}
}
コード例 #4
0
ファイル: zkutil.go プロジェクト: kingpro/vitess
func DeleteRecursive(zconn Conn, zkPath string, version int) error {
	// version: -1 delete any version of the node at path - only applies to the top node
	err := zconn.Delete(zkPath, version)
	if err == nil {
		return nil
	}
	if !zookeeper.IsError(err, zookeeper.ZNOTEMPTY) {
		return err
	}
	// Remove the ability for other nodes to get created while we are trying to delete.
	// Otherwise, you can enter a race condition, or get starved out from deleting.
	err = zconn.SetACL(zkPath, zookeeper.WorldACL(zookeeper.PERM_ADMIN|zookeeper.PERM_DELETE|zookeeper.PERM_READ), version)
	if err != nil {
		return err
	}
	children, _, err := zconn.Children(zkPath)
	if err != nil {
		return err
	}
	for _, child := range children {
		err := DeleteRecursive(zconn, path.Join(zkPath, child), -1)
		if err != nil && !zookeeper.IsError(err, zookeeper.ZNONODE) {
			return fmt.Errorf("zkutil: recursive delete failed: %v", err)
		}
	}

	err = zconn.Delete(zkPath, version)
	if err != nil && !zookeeper.IsError(err, zookeeper.ZNOTEMPTY) {
		err = fmt.Errorf("zkutil: nodes getting recreated underneath delete (app race condition): %v", zkPath)
	}
	return err
}
コード例 #5
0
ファイル: keyspace.go プロジェクト: ninqing/vitess
func (zkts *Server) UpdateKeyspace(ki *topo.KeyspaceInfo) error {
	keyspacePath := path.Join(globalKeyspacesPath, ki.KeyspaceName())
	data := jscfg.ToJson(ki.Keyspace)
	_, err := zkts.zconn.Set(keyspacePath, data, -1)
	if err != nil {
		if zookeeper.IsError(err, zookeeper.ZNONODE) {
			// The code should be:
			//   err = topo.ErrNoNode
			// Temporary code until we have Keyspace object
			// everywhere:
			_, err = zkts.zconn.Create(keyspacePath, data, 0, zookeeper.WorldACL(zookeeper.PERM_ALL))
			if err != nil {
				if zookeeper.IsError(err, zookeeper.ZNONODE) {
					// the directory doesn't even exist
					err = topo.ErrNoNode
				}
				return err
			}

			event.Dispatch(&events.KeyspaceChange{
				KeyspaceInfo: *ki,
				Status:       "updated (had to create Keyspace object)",
			})
			return nil
		}
		return err
	}

	event.Dispatch(&events.KeyspaceChange{
		KeyspaceInfo: *ki,
		Status:       "updated",
	})
	return nil
}
コード例 #6
0
ファイル: zk.go プロジェクト: Ehuos/gopush-cluster
// Create the persistence node in zookeeper
func (zk *ZK) Create(path string, node string) error {
	// create zk root path
	tpath := ""
	for _, str := range strings.Split(path, "/")[1:] {
		tpath += "/" + str
		Log.Debug("create zookeeper path:%s", tpath)
		_, err := zk.conn.Create(tpath, "", 0, zookeeper.WorldACL(zookeeper.PERM_ALL))
		if err != nil {
			if zookeeper.IsError(err, zookeeper.ZNODEEXISTS) {
				Log.Warn("zk.Create(\"%s\") exists", tpath)
			} else {
				Log.Error("zk.Create(\"%s\") failed (%s)", tpath, err.Error())
				return err
			}
		}
	}

	// create node path
	fpath := path + "/" + node
	Log.Debug("create zookeeper path:%s", fpath)
	_, err := zk.conn.Create(fpath, "", 0, zookeeper.WorldACL(zookeeper.PERM_ALL))
	if err != nil {
		if zookeeper.IsError(err, zookeeper.ZNODEEXISTS) {
			Log.Warn("zk.Create(\"%s\") exists", fpath)
		} else {
			Log.Error("zk.Create(\"%s\") failed (%s)", fpath, err.Error())
			return err
		}
	}

	return nil
}
コード例 #7
0
ファイル: server.go プロジェクト: henryanand/vitess
// PurgeActions removes all queued actions, leaving the action node
// itself in place.
//
// This inherently breaks the locking mechanism of the action queue,
// so this is a rare cleanup action, not a normal part of the flow.
//
// This can be used for tablets, shards and keyspaces.
func (zkts *Server) PurgeActions(zkActionPath string, canBePurged func(data string) bool) error {
	if path.Base(zkActionPath) != "action" {
		return fmt.Errorf("not action path: %v", zkActionPath)
	}

	children, _, err := zkts.zconn.Children(zkActionPath)
	if err != nil {
		return err
	}

	sort.Strings(children)
	// Purge newer items first so the action queues don't try to process something.
	for i := len(children) - 1; i >= 0; i-- {
		actionPath := path.Join(zkActionPath, children[i])
		data, _, err := zkts.zconn.Get(actionPath)
		if err != nil && !zookeeper.IsError(err, zookeeper.ZNONODE) {
			return fmt.Errorf("PurgeActions(%v) err: %v", zkActionPath, err)
		}
		if !canBePurged(data) {
			continue
		}

		err = zk.DeleteRecursive(zkts.zconn, actionPath, -1)
		if err != nil && !zookeeper.IsError(err, zookeeper.ZNONODE) {
			return fmt.Errorf("PurgeActions(%v) err: %v", zkActionPath, err)
		}
	}
	return nil
}
コード例 #8
0
ファイル: zk.go プロジェクト: Brant-Zhang/gopush-cluster
// Create the persistence node in zookeeper
func (zk *ZK) create() error {
	// create zk root path
	tpath := ""
	for _, str := range strings.Split(Conf.ZookeeperPath, "/")[1:] {
		tpath += "/" + str
		Log.Debug("create zookeeper path:%s", tpath)
		_, err := zk.conn.Create(tpath, "", 0, zookeeper.WorldACL(zookeeper.PERM_ALL))
		if err != nil {
			if zookeeper.IsError(err, zookeeper.ZNODEEXISTS) {
				Log.Warn("zk.create(\"%s\") exists", tpath)
			} else {
				Log.Error("zk.create(\"%s\") error(%v)", tpath, err)
				return err
			}
		}
	}
	// create node path
	fpath := fmt.Sprintf("%s/%s", Conf.ZookeeperPath, Conf.ZookeeperNode)
	Log.Debug("create zookeeper path:%s", fpath)
	_, err := zk.conn.Create(fpath, "", 0, zookeeper.WorldACL(zookeeper.PERM_ALL))
	if err != nil {
		if zookeeper.IsError(err, zookeeper.ZNODEEXISTS) {
			Log.Warn("zk.Create(\"%s\") exists", fpath)
		} else {
			Log.Error("zk.Create(\"%s\") error(%v)", fpath, err)
			return err
		}
	}
	return nil
}
コード例 #9
0
ファイル: cache.go プロジェクト: Eric-Chen/vitess
// return a few values that need to be refreshed
func (zkc *ZkCache) refreshSomeValues(zconn zk.Conn, maxToRefresh int) {
	// build a list of a few values we want to refresh
	refreshThreshold := time.Now().Add(-10 * time.Minute)

	// range will randomize the traversal order, so we will not always try
	// the same entries in the same order
	dataEntries := make([]*zkCacheEntry, 0, maxToRefresh)
	childrenEntries := make([]*zkCacheEntry, 0, maxToRefresh)
	zkc.mutex.Lock()
	for _, entry := range zkc.Cache {
		shouldBeDataRefreshed, shouldBeChildrenRefreshed := entry.checkForRefresh(refreshThreshold)
		if shouldBeDataRefreshed {
			dataEntries = append(dataEntries, entry)
		}
		if shouldBeChildrenRefreshed {
			childrenEntries = append(childrenEntries, entry)
		}

		// check if we have enough work to do
		if len(dataEntries) == maxToRefresh || len(childrenEntries) == maxToRefresh {
			break
		}
	}
	zkc.mutex.Unlock()

	// now refresh the values
	for _, entry := range dataEntries {
		data, stat, watch, err := zconn.GetW(entry.node.Path)
		if err == nil {
			zkStat := &zk.ZkStat{}
			zkStat.FromZookeeperStat(stat)
			entry.updateData(data, zkStat, watch)
		} else if zookeeper.IsError(err, zookeeper.ZCLOSING) {
			// connection is closing, no point in asking for more
			relog.Warning("failed to refresh cache: %v (and stopping refresh)", err.Error())
			return
		} else {
			// individual failure
			relog.Warning("failed to refresh cache: %v", err.Error())
		}
	}

	for _, entry := range childrenEntries {
		children, stat, watch, err := zconn.ChildrenW(entry.node.Path)
		if err == nil {
			zkStat := &zk.ZkStat{}
			zkStat.FromZookeeperStat(stat)
			entry.updateChildren(children, zkStat, watch)
		} else if zookeeper.IsError(err, zookeeper.ZCLOSING) {
			// connection is closing, no point in asking for more
			relog.Warning("failed to refresh cache: %v (and stopping refresh)", err.Error())
			return
		} else {
			// individual failure
			relog.Warning("failed to refresh cache: %v", err.Error())
		}
	}
}
コード例 #10
0
ファイル: zkctl.go プロジェクト: littleyang/vitess
func (zkd *Zkd) init(preserveData bool) error {
	log.Infof("zkd.Init")
	for _, path := range zkd.config.DirectoryList() {
		if err := os.MkdirAll(path, 0775); err != nil {
			log.Errorf(err.Error())
			return err
		}
		// FIXME(msolomon) validate permissions?
	}

	configData, err := zkd.makeCfg()
	if err == nil {
		err = ioutil.WriteFile(zkd.config.ConfigFile(), []byte(configData), 0664)
	}
	if err != nil {
		log.Errorf("failed creating %v: %v", zkd.config.ConfigFile(), err)
		return err
	}

	err = zkd.config.WriteMyid()
	if err != nil {
		log.Errorf("failed creating %v: %v", zkd.config.MyidFile(), err)
		return err
	}

	if err = zkd.Start(); err != nil {
		log.Errorf("failed starting, check %v", zkd.config.LogDir())
		return err
	}

	zkAddr := fmt.Sprintf("localhost:%v", zkd.config.ClientPort)
	zk, session, err := zookeeper.Dial(zkAddr, StartWaitTime*time.Second)
	if err != nil {
		return err
	}
	event := <-session
	if event.State != zookeeper.STATE_CONNECTED {
		return err
	}
	defer zk.Close()

	if !preserveData {
		_, err = zk.Create("/zk", "", 0, zookeeper.WorldACL(zookeeper.PERM_ALL))
		if err != nil && !zookeeper.IsError(err, zookeeper.ZNODEEXISTS) {
			return err
		}

		if zkd.config.Global {
			_, err = zk.Create("/zk/global", "", 0, zookeeper.WorldACL(zookeeper.PERM_ALL))
			if err != nil && !zookeeper.IsError(err, zookeeper.ZNODEEXISTS) {
				return err
			}
		}
	}

	return nil
}
コード例 #11
0
ファイル: serving_graph.go プロジェクト: aaijazi/vitess
// DeleteEndPoints is part of the topo.Server interface
func (zkts *Server) DeleteEndPoints(ctx context.Context, cell, keyspace, shard string, tabletType topodatapb.TabletType, existingVersion int64) error {
	path := zkPathForVtName(cell, keyspace, shard, tabletType)
	if err := zkts.zconn.Delete(path, int(existingVersion)); err != nil {
		switch {
		case zookeeper.IsError(err, zookeeper.ZNONODE):
			err = topo.ErrNoNode
		case zookeeper.IsError(err, zookeeper.ZBADVERSION):
			err = topo.ErrBadVersion
		}
		return err
	}
	return nil
}
コード例 #12
0
func (zkts *Server) DeleteReplicationPath(keyspace, shard, repPath string) error {
	replicationPath := path.Join(globalKeyspacesPath, keyspace, "shards", shard, repPath)
	err := zkts.zconn.Delete(replicationPath, -1)
	if err != nil {
		if zookeeper.IsError(err, zookeeper.ZNONODE) {
			err = topo.ErrNoNode
		} else if zookeeper.IsError(err, zookeeper.ZNOTEMPTY) {
			err = topo.ErrNotEmpty
		}
		return err
	}
	return nil
}
コード例 #13
0
ファイル: cache.go プロジェクト: Eric-Chen/vitess
func (entry *zkCacheEntry) checkForRefresh(refreshThreshold time.Time) (shouldBeDataRefreshed, shouldBeChildrenRefreshed bool) {
	entry.mutex.Lock()
	defer entry.mutex.Unlock()

	if entry.dataTime.IsZero() {
		// the entry was never set
		// if we had an error getting it, it means we asked for it,
		// see if we can get a good value
		if entry.dataError != nil {
			if zookeeper.IsError(entry.dataError, zookeeper.ZNONODE) {
				// we had no node, we can try next time a client asks
				entry.dataError = nil
				// at this point, we have both
				// dataTime.IsZero() and
				// entry.dataError = nil, as if we
				// never asked for it
			} else {
				// we had a valid error, let's try again
				shouldBeDataRefreshed = true
			}
		}
	} else {
		// 1. we got a value at some point, then it got stale
		// 2. we got a value a long time ago, refresh it
		shouldBeDataRefreshed = entry.dataError != nil || entry.dataTime.Before(refreshThreshold)
	}

	if entry.childrenTime.IsZero() {
		// the entry was never set
		// if we had an error getting it, it means we asked for it,
		// see if we can get a good value
		if entry.childrenError != nil {
			if zookeeper.IsError(entry.childrenError, zookeeper.ZNONODE) {
				// we had no node, we can try next time a client asks
				entry.childrenError = nil
				// at this point, we have both
				// childrenTime.IsZero() and
				// entry.childrenError = nil, as if we
				// never asked for it
			} else {
				shouldBeChildrenRefreshed = true
				// we had a valid error, let's try again
			}
		}
	} else {
		// 1. we got a value at some point, then it got stale
		// 2. we got a value a long time ago, refresh it
		shouldBeChildrenRefreshed = entry.childrenError != nil || entry.childrenTime.Before(refreshThreshold)
	}
	return
}
コード例 #14
0
ファイル: cell.go プロジェクト: johnvilsack/golang-stuff
func (zkts *Server) UpdateTablet(tablet *topo.TabletInfo, existingVersion int) (int, error) {
	zkTabletPath := TabletPathForAlias(tablet.Alias())
	stat, err := zkts.zconn.Set(zkTabletPath, tablet.Json(), existingVersion)
	if err != nil {
		if zookeeper.IsError(err, zookeeper.ZBADVERSION) {
			err = topo.ErrBadVersion
		} else if zookeeper.IsError(err, zookeeper.ZNONODE) {
			err = topo.ErrNoNode
		}

		return 0, err
	}
	return stat.Version(), nil
}
コード例 #15
0
ファイル: server.go プロジェクト: henryanand/vitess
// StaleActions returns a list of queued actions that have been
// sitting for more than some amount of time.
func (zkts *Server) StaleActions(zkActionPath string, maxStaleness time.Duration, isStale func(data string) bool) ([]string, error) {
	if path.Base(zkActionPath) != "action" {
		return nil, fmt.Errorf("not action path: %v", zkActionPath)
	}

	children, _, err := zkts.zconn.Children(zkActionPath)
	if err != nil {
		return nil, err
	}

	staleActions := make([]string, 0, 16)
	// Purge newer items first so the action queues don't try to process something.
	sort.Strings(children)
	for i := 0; i < len(children); i++ {
		actionPath := path.Join(zkActionPath, children[i])
		data, stat, err := zkts.zconn.Get(actionPath)
		if err != nil && !zookeeper.IsError(err, zookeeper.ZNONODE) {
			return nil, fmt.Errorf("stale action err: %v", err)
		}
		if stat == nil || time.Since(stat.MTime()) <= maxStaleness {
			continue
		}
		if isStale(data) {
			staleActions = append(staleActions, data)
		}
	}
	return staleActions, nil
}
コード例 #16
0
ファイル: global.go プロジェクト: rrudduck/golang-stuff
func (zkts *Server) CreateKeyspace(keyspace string) error {
	keyspacePath := path.Join(globalKeyspacesPath, keyspace)
	pathList := []string{
		keyspacePath,
		path.Join(keyspacePath, "action"),
		path.Join(keyspacePath, "actionlog"),
		path.Join(keyspacePath, "shards"),
	}

	alreadyExists := false
	for _, zkPath := range pathList {
		_, err := zk.CreateRecursive(zkts.zconn, zkPath, "", 0, zookeeper.WorldACL(zookeeper.PERM_ALL))
		if err != nil {
			if zookeeper.IsError(err, zookeeper.ZNODEEXISTS) {
				alreadyExists = true
			} else {
				return fmt.Errorf("error creating keyspace: %v %v", zkPath, err)
			}
		}
	}
	if alreadyExists {
		return topo.ErrNodeExists
	}
	return nil
}
コード例 #17
0
ファイル: keyspace.go プロジェクト: richarwu/vitess
// DeleteKeyspaceShards is part of the topo.Server interface
func (zkts *Server) DeleteKeyspaceShards(ctx context.Context, keyspace string) error {
	shardsPath := path.Join(globalKeyspacesPath, keyspace, "shards")
	if err := zk.DeleteRecursive(zkts.zconn, shardsPath, -1); err != nil && !zookeeper.IsError(err, zookeeper.ZNONODE) {
		return err
	}
	return nil
}
コード例 #18
0
ファイル: cell.go プロジェクト: johnvilsack/golang-stuff
func (zkts *Server) UpdateTabletFields(tabletAlias topo.TabletAlias, update func(*topo.Tablet) error) error {
	zkTabletPath := TabletPathForAlias(tabletAlias)
	f := func(oldValue string, oldStat zk.Stat) (string, error) {
		if oldValue == "" {
			return "", fmt.Errorf("no data for tablet addr update: %v", tabletAlias)
		}

		tablet, err := topo.TabletFromJson(oldValue)
		if err != nil {
			return "", err
		}
		if err := update(tablet); err != nil {
			return "", err
		}
		return jscfg.ToJson(tablet), nil
	}
	err := zkts.zconn.RetryChange(zkTabletPath, 0, zookeeper.WorldACL(zookeeper.PERM_ALL), f)
	if err != nil {
		if zookeeper.IsError(err, zookeeper.ZNONODE) {
			err = topo.ErrNoNode
		}
		return err
	}
	return nil
}
コード例 #19
0
ファイル: tablet.go プロジェクト: cinderalla/vitess
// DeleteTablet is part of the topo.Server interface
func (zkts *Server) DeleteTablet(ctx context.Context, alias topo.TabletAlias) error {
	// We need to find out the keyspace and shard names because
	// those are required in the TabletChange event.
	ti, tiErr := zkts.GetTablet(ctx, alias)

	zkTabletPath := TabletPathForAlias(alias)
	err := zk.DeleteRecursive(zkts.zconn, zkTabletPath, -1)
	if err != nil {
		if zookeeper.IsError(err, zookeeper.ZNONODE) {
			err = topo.ErrNoNode
		}
		return err
	}

	// Only try to log if we have the required information.
	if tiErr == nil {
		// We only want to copy the identity info for the tablet (alias, etc.).
		// The rest has just been deleted, so it should be blank.
		event.Dispatch(&events.TabletChange{
			Tablet: topo.Tablet{
				Alias:    ti.Tablet.Alias,
				Keyspace: ti.Tablet.Keyspace,
				Shard:    ti.Tablet.Shard,
			},
			Status: "deleted",
		})
	}
	return nil
}
コード例 #20
0
ファイル: plugin_zktopo.go プロジェクト: chinna1986/vitess
func getActions(wr *wrangler.Wrangler, zconn zk.Conn, actionPath string) ([]*actionnode.ActionNode, error) {
	actions, _, err := zconn.Children(actionPath)
	if err != nil {
		return nil, fmt.Errorf("getActions failed: %v %v", actionPath, err)
	}
	sort.Strings(actions)
	wg := sync.WaitGroup{}
	mu := sync.Mutex{}
	nodes := make([]*actionnode.ActionNode, 0, len(actions))
	for _, action := range actions {
		wg.Add(1)
		go func(action string) {
			defer wg.Done()
			actionNodePath := path.Join(actionPath, action)
			data, _, err := zconn.Get(actionNodePath)
			if err != nil && !zookeeper.IsError(err, zookeeper.ZNONODE) {
				wr.Logger().Warningf("getActions: %v %v", actionNodePath, err)
				return
			}
			actionNode, err := actionnode.ActionNodeFromJson(data, actionNodePath)
			if err != nil {
				wr.Logger().Warningf("getActions: %v %v", actionNodePath, err)
				return
			}
			mu.Lock()
			nodes = append(nodes, actionNode)
			mu.Unlock()
		}(action)
	}
	wg.Wait()

	return nodes, nil
}
コード例 #21
0
ファイル: zkutil.go プロジェクト: qinbo/vitess
// Create a path and any pieces required, think mkdir -p.
// Intermediate znodes are always created empty.
func CreateRecursive(zconn Conn, zkPath, value string, flags int, aclv []zookeeper.ACL) (pathCreated string, err error) {
	parts := strings.Split(zkPath, "/")
	if parts[1] != "zk" {
		return "", fmt.Errorf("zkutil: non zk path: %v", zkPath)
	}

	pathCreated, err = zconn.Create(zkPath, value, flags, aclv)
	if zookeeper.IsError(err, zookeeper.ZNONODE) {
		_, err = CreateRecursive(zconn, path.Dir(zkPath), "", flags, aclv)
		if err != nil && !zookeeper.IsError(err, zookeeper.ZNODEEXISTS) {
			return "", err
		}
		pathCreated, err = zconn.Create(zkPath, value, flags, aclv)
	}
	return
}
コード例 #22
0
ファイル: keyspace.go プロジェクト: ninqing/vitess
func (zkts *Server) CreateKeyspace(keyspace string, value *topo.Keyspace) error {
	keyspacePath := path.Join(globalKeyspacesPath, keyspace)
	pathList := []string{
		keyspacePath,
		path.Join(keyspacePath, "action"),
		path.Join(keyspacePath, "actionlog"),
		path.Join(keyspacePath, "shards"),
	}

	alreadyExists := false
	for i, zkPath := range pathList {
		c := ""
		if i == 0 {
			c = jscfg.ToJson(value)
		}
		_, err := zk.CreateRecursive(zkts.zconn, zkPath, c, 0, zookeeper.WorldACL(zookeeper.PERM_ALL))
		if err != nil {
			if zookeeper.IsError(err, zookeeper.ZNODEEXISTS) {
				alreadyExists = true
			} else {
				return fmt.Errorf("error creating keyspace: %v %v", zkPath, err)
			}
		}
	}
	if alreadyExists {
		return topo.ErrNodeExists
	}

	event.Dispatch(&events.KeyspaceChange{
		KeyspaceInfo: *topo.NewKeyspaceInfo(keyspace, value),
		Status:       "created",
	})
	return nil
}
コード例 #23
0
ファイル: tablet.go プロジェクト: BobbWu/vitess
// UpdateTabletFields is part of the topo.Server interface
func (zkts *Server) UpdateTabletFields(ctx context.Context, tabletAlias *topodatapb.TabletAlias, update func(*topodatapb.Tablet) error) (*topodatapb.Tablet, error) {
	// Store the last tablet value so we can log it if the change succeeds.
	var lastTablet *topodatapb.Tablet

	zkTabletPath := TabletPathForAlias(tabletAlias)
	f := func(oldValue string, oldStat zk.Stat) (string, error) {
		if oldValue == "" {
			return "", fmt.Errorf("no data for tablet addr update: %v", tabletAlias)
		}

		tablet := &topodatapb.Tablet{}
		if err := json.Unmarshal([]byte(oldValue), tablet); err != nil {
			return "", err
		}
		if err := update(tablet); err != nil {
			return "", err
		}
		lastTablet = tablet
		data, err := json.MarshalIndent(tablet, "", "  ")
		if err != nil {
			return "", err
		}
		return string(data), nil
	}
	err := zkts.zconn.RetryChange(zkTabletPath, 0, zookeeper.WorldACL(zookeeper.PERM_ALL), f)
	if err != nil {
		if zookeeper.IsError(err, zookeeper.ZNONODE) {
			err = topo.ErrNoNode
		}
		return nil, err
	}
	return lastTablet, nil
}
コード例 #24
0
ファイル: fakezk.go プロジェクト: CowLeo/vitess
// NewConnFromFile returns a fake zk.Conn implementation, that is seeded
// with the json data extracted from the input file.
func NewConnFromFile(filename string) zk.Conn {
	result := &zconn{
		root: &node{
			_stat:    _stat{name: "/"},
			children: make(map[string]*node),
		},
		existWatches: make(map[string][]chan zookeeper.Event)}
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		panic(fmt.Errorf("NewConnFromFile failed to read file %v: %v", filename, err))
	}
	values := make(map[string]interface{})
	if err := json.Unmarshal(data, &values); err != nil {
		panic(fmt.Errorf("NewConnFromFile failed to json.Unmarshal file %v: %v", filename, err))
	}
	for k, v := range values {
		jv, err := json.Marshal(v)
		if err != nil {
			panic(fmt.Errorf("NewConnFromFile failed to json.Marshal value %v: %v", k, err))
		}

		// CreateRecursive will work for a leaf node where the parent
		// doesn't exist, but not for a node in the middle of a tree
		// that already exists. So have to use 'Set' as a backup.
		if _, err := zk.CreateRecursive(result, k, string(jv), 0, nil); err != nil {
			if zookeeper.IsError(err, zookeeper.ZNODEEXISTS) {
				_, err = result.Set(k, string(jv), -1)
			}
			if err != nil {
				panic(fmt.Errorf("NewConnFromFile failed to zk.CreateRecursive value %v: %v", k, err))
			}
		}
	}
	return result
}
コード例 #25
0
ファイル: shard.go プロジェクト: BobbWu/vitess
// CreateShard is part of the topo.Server interface
func (zkts *Server) CreateShard(ctx context.Context, keyspace, shard string, value *topodatapb.Shard) error {
	shardPath := path.Join(globalKeyspacesPath, keyspace, "shards", shard)
	pathList := []string{
		shardPath,
		path.Join(shardPath, "action"),
		path.Join(shardPath, "actionlog"),
	}

	data, err := json.MarshalIndent(value, "", "  ")
	if err != nil {
		return err
	}

	alreadyExists := false
	for i, zkPath := range pathList {
		c := ""
		if i == 0 {
			c = string(data)
		}
		_, err := zk.CreateRecursive(zkts.zconn, zkPath, c, 0, zookeeper.WorldACL(zookeeper.PERM_ALL))
		if err != nil {
			if zookeeper.IsError(err, zookeeper.ZNODEEXISTS) {
				alreadyExists = true
			} else {
				return fmt.Errorf("error creating shard: %v %v", zkPath, err)
			}
		}
	}
	if alreadyExists {
		return topo.ErrNodeExists
	}
	return nil
}
コード例 #26
0
ファイル: zkcmd.go プロジェクト: ZhuoRoger/vitess
func cmdWait(args []string) {
	if len(args) != 1 {
		log.Fatalf("wait: can only wait for one path")
	}
	zkPath := args[0]
	isDir := zkPath[len(zkPath)-1] == '/'
	zkPath = fixZkPath(zkPath)

	var wait <-chan zookeeper.Event
	var err error
	if isDir {
		_, _, wait, err = zconn.ChildrenW(zkPath)
	} else {
		_, _, wait, err = zconn.GetW(zkPath)
	}
	if err != nil {
		if zookeeper.IsError(err, zookeeper.ZNONODE) {
			_, wait, err = zconn.ExistsW(zkPath)
		} else {
			log.Fatalf("wait: error %v: %v", zkPath, err)
		}
	} else {
		if *exitIfExists {
			fmt.Printf("already exists: %v\n", zkPath)
			return
		}
	}
	event := <-wait
	fmt.Printf("event: %v\n", event)
}
コード例 #27
0
ファイル: timeid.go プロジェクト: kooxiv/gopush-cluster
// PubMIDLock public message mid lock, make sure that get the unique mid
func PubMIDLock() (bool, string, error) {
	prefix := "p"
	splitSign := "@"
	pathCreated, err := zk.Create(fmt.Sprintf("%s/%s%s", Conf.ZKPIDPath, prefix, splitSign),
		"0", zookeeper.EPHEMERAL|zookeeper.SEQUENCE, zookeeper.WorldACL(zookeeper.PERM_ALL))
	if err != nil {
		return false, pathCreated, fmt.Errorf("zk.Create(%s/%s%s) error(%v)", Conf.ZKPIDPath, prefix, splitSign, err)
	}

	for {
		childrens, stat, err := zk.Children(Conf.ZKPIDPath)
		if err != nil {
			return false, pathCreated, fmt.Errorf("zk.Children(%s) error(%v)", Conf.ZKPIDPath, err)
		}

		// If node isn`t exist
		if childrens == nil || stat == nil {
			return false, pathCreated, fmt.Errorf("node(%s) is not existent", Conf.ZKPIDPath)
		}

		var realQueue []string
		for _, children := range childrens {
			tmp := strings.Split(children, splitSign)
			if prefix == tmp[0] {
				realQueue = append(realQueue, children)
			}
		}

		// Sort sequence nodes
		sort.Strings(realQueue)

		tmp := strings.Split(pathCreated, "/")
		posReal := sort.StringSlice(realQueue).Search(tmp[len(tmp)-1])

		// If does not get lock
		if posReal > 0 {
			// Watch the last one
			watchPath := fmt.Sprintf("%s/%s", Conf.ZKPIDPath, realQueue[posReal-1])
			_, watch, err := zk.ExistsW(watchPath)
			if err != nil || zookeeper.IsError(err, zookeeper.ZNONODE) {
				return false, pathCreated, fmt.Errorf("zk.ExistsW(%s) error(%v) or no node", watchPath, err)
			}

			// Watch the lower node
			watchNode := <-watch
			switch watchNode.Type {
			case zookeeper.EVENT_DELETED:
			default:
				return false, pathCreated, fmt.Errorf("zookeeper watch errCode:%d", watchNode.Type)
			}

			return false, pathCreated, nil
		} else {
			return true, pathCreated, nil
		}
	}

	// Never get here
	return false, pathCreated, fmt.Errorf("never get here")
}
コード例 #28
0
ファイル: cell.go プロジェクト: johnvilsack/golang-stuff
func (zkts *Server) CreateTablet(tablet *topo.Tablet) error {
	zkTabletPath := TabletPathForAlias(tablet.Alias())

	// Create /zk/<cell>/vt/tablets/<uid>
	_, err := zk.CreateRecursive(zkts.zconn, zkTabletPath, tablet.Json(), 0, zookeeper.WorldACL(zookeeper.PERM_ALL))
	if err != nil {
		if zookeeper.IsError(err, zookeeper.ZNODEEXISTS) {
			err = topo.ErrNodeExists
		}
		return err
	}

	// Create /zk/<cell>/vt/tablets/<uid>/action
	tap := path.Join(zkTabletPath, "action")
	_, err = zkts.zconn.Create(tap, "", 0, zookeeper.WorldACL(zookeeper.PERM_ALL))
	if err != nil {
		return err
	}

	// Create /zk/<cell>/vt/tablets/<uid>/actionlog
	talp := path.Join(zkTabletPath, "actionlog")
	_, err = zkts.zconn.Create(talp, "", 0, zookeeper.WorldACL(zookeeper.PERM_ALL))
	if err != nil {
		return err
	}

	return nil
}
コード例 #29
0
ファイル: shard.go プロジェクト: haoqoo/vitess
// CreateShard is part of the topo.Server interface
func (zkts *Server) CreateShard(ctx context.Context, keyspace, shard string, value *pb.Shard) error {
	shardPath := path.Join(globalKeyspacesPath, keyspace, "shards", shard)
	pathList := []string{
		shardPath,
		path.Join(shardPath, "action"),
		path.Join(shardPath, "actionlog"),
	}

	alreadyExists := false
	for i, zkPath := range pathList {
		c := ""
		if i == 0 {
			c = jscfg.ToJSON(value)
		}
		_, err := zk.CreateRecursive(zkts.zconn, zkPath, c, 0, zookeeper.WorldACL(zookeeper.PERM_ALL))
		if err != nil {
			if zookeeper.IsError(err, zookeeper.ZNODEEXISTS) {
				alreadyExists = true
			} else {
				return fmt.Errorf("error creating shard: %v %v", zkPath, err)
			}
		}
	}
	if alreadyExists {
		return topo.ErrNodeExists
	}

	event.Dispatch(&events.ShardChange{
		ShardInfo: *topo.NewShardInfo(keyspace, shard, value, -1),
		Status:    "created",
	})
	return nil
}
コード例 #30
0
ファイル: replication_graph.go プロジェクト: richarwu/vitess
// UpdateShardReplicationFields is part of the topo.Server interface
func (zkts *Server) UpdateShardReplicationFields(ctx context.Context, cell, keyspace, shard string, update func(*pb.ShardReplication) error) error {
	// create the parent directory to be sure it's here
	zkDir := path.Join("/zk", cell, "vt", "replication", keyspace)
	if _, err := zk.CreateRecursive(zkts.zconn, zkDir, "", 0, zookeeper.WorldACL(zookeeper.PERM_ALL)); err != nil && !zookeeper.IsError(err, zookeeper.ZNODEEXISTS) {
		return err
	}

	// now update the data
	zkPath := shardReplicationPath(cell, keyspace, shard)
	f := func(oldValue string, oldStat zk.Stat) (string, error) {
		sr := &pb.ShardReplication{}
		if oldValue != "" {
			if err := json.Unmarshal([]byte(oldValue), sr); err != nil {
				return "", err
			}
		}

		if err := update(sr); err != nil {
			return "", err
		}
		data, err := json.MarshalIndent(sr, "", "  ")
		if err != nil {
			return "", err
		}
		return string(data), nil
	}
	err := zkts.zconn.RetryChange(zkPath, 0, zookeeper.WorldACL(zookeeper.PERM_ALL), f)
	if err != nil {
		if zookeeper.IsError(err, zookeeper.ZNONODE) {
			err = topo.ErrNoNode
		}
		return err
	}
	return nil
}