Пример #1
0
func (conn *vtgateConn) GetSrvKeyspace(ctx context.Context, keyspace string) (*topo.SrvKeyspace, error) {
	request := &pb.GetSrvKeyspaceRequest{
		Keyspace: keyspace,
	}
	response := &pb.GetSrvKeyspaceResponse{}
	if err := conn.rpcConn.Call(ctx, "VTGateP3.GetSrvKeyspace", request, response); err != nil {
		return nil, err
	}
	return topo.ProtoToSrvKeyspace(response.SrvKeyspace), nil
}
Пример #2
0
func (conn *vtgateConn) GetSrvKeyspace(ctx context.Context, keyspace string) (*topo.SrvKeyspace, error) {
	request := &pb.GetSrvKeyspaceRequest{
		Keyspace: keyspace,
	}
	response, err := conn.c.GetSrvKeyspace(ctx, request)
	if err != nil {
		return nil, vterrors.FromGRPCError(err)
	}
	return topo.ProtoToSrvKeyspace(response.SrvKeyspace), nil
}
Пример #3
0
// GetSrvKeyspace is part of the topo.Server interface
func (zkts *Server) GetSrvKeyspace(ctx context.Context, cell, keyspace string) (*topo.SrvKeyspace, error) {
	path := zkPathForVtKeyspace(cell, keyspace)
	data, _, err := zkts.zconn.Get(path)
	if err != nil {
		if zookeeper.IsError(err, zookeeper.ZNONODE) {
			err = topo.ErrNoNode
		}
		return nil, err
	}
	srvKeyspace := &pb.SrvKeyspace{}
	if len(data) > 0 {
		if err := json.Unmarshal([]byte(data), srvKeyspace); err != nil {
			return nil, fmt.Errorf("SrvKeyspace unmarshal failed: %v %v", data, err)
		}
	}
	return topo.ProtoToSrvKeyspace(srvKeyspace), nil
}
Пример #4
0
// GetSrvKeyspace implements topo.Server.
func (s *Server) GetSrvKeyspace(ctx context.Context, cellName, keyspace string) (*topo.SrvKeyspace, error) {
	cell, err := s.getCell(cellName)
	if err != nil {
		return nil, err
	}

	resp, err := cell.Get(srvKeyspaceFilePath(keyspace), false /* sort */, false /* recursive */)
	if err != nil {
		return nil, convertError(err)
	}
	if resp.Node == nil {
		return nil, ErrBadResponse
	}

	value := &pb.SrvKeyspace{}
	if err := json.Unmarshal([]byte(resp.Node.Value), value); err != nil {
		return nil, fmt.Errorf("bad serving keyspace data (%v): %q", err, resp.Node.Value)
	}
	return topo.ProtoToSrvKeyspace(value), nil
}
Пример #5
0
// WatchSrvKeyspace is part of the topo.Server interface
func (s *Server) WatchSrvKeyspace(ctx context.Context, cellName, keyspace string) (<-chan *topo.SrvKeyspace, chan<- struct{}, error) {
	cell, err := s.getCell(cellName)
	if err != nil {
		return nil, nil, fmt.Errorf("WatchSrvKeyspace cannot get cell: %v", err)
	}
	filePath := srvKeyspaceFilePath(keyspace)

	notifications := make(chan *topo.SrvKeyspace, 10)
	stopWatching := make(chan struct{})

	// The watch go routine will stop if the 'stop' channel is closed.
	// Otherwise it will try to watch everything in a loop, and send events
	// to the 'watch' channel.
	watch := make(chan *etcd.Response)
	stop := make(chan bool)
	go func() {
		var srvKeyspace *topo.SrvKeyspace
		var modifiedVersion int64

		resp, err := cell.Get(filePath, false /* sort */, false /* recursive */)
		if err != nil || resp.Node == nil {
			// node doesn't exist
		} else {
			if resp.Node.Value != "" {
				sk := &pb.SrvKeyspace{}
				if err := json.Unmarshal([]byte(resp.Node.Value), sk); err != nil {
					log.Warningf("bad SrvKeyspace data (%v): %q", err, resp.Node.Value)
				} else {
					srvKeyspace = topo.ProtoToSrvKeyspace(sk)
					modifiedVersion = int64(resp.Node.ModifiedIndex)
				}
			}
		}

		// re-check for stop here to be safe, in case the
		// getEndPoints took a long time
		select {
		case <-stop:
			return
		case notifications <- srvKeyspace:
		}

		for {
			if _, err := cell.Client.Watch(filePath, uint64(modifiedVersion+1), false /* recursive */, watch, stop); err != nil {
				log.Errorf("Watch on %v failed, waiting for %v to retry: %v", filePath, WatchSleepDuration, err)
				timer := time.After(WatchSleepDuration)
				select {
				case <-stop:
					return
				case <-timer:
				}
			}
		}
	}()

	// This go routine is the main event handling routine:
	// - it will stop if stopWatching is closed.
	// - if it receives a notification from the watch, it will forward it
	// to the notifications channel.
	go func() {
		for {
			select {
			case resp := <-watch:
				var srvKeyspace *topo.SrvKeyspace
				if resp.Node != nil && resp.Node.Value != "" {
					sk := &pb.SrvKeyspace{}
					if err := json.Unmarshal([]byte(resp.Node.Value), sk); err != nil {
						log.Errorf("failed to Unmarshal EndPoints for %v: %v", filePath, err)
						continue
					}
					srvKeyspace = topo.ProtoToSrvKeyspace(sk)
				}
				notifications <- srvKeyspace
			case <-stopWatching:
				close(stop)
				close(notifications)
				return
			}
		}
	}()

	return notifications, stopWatching, nil
}
Пример #6
0
// WatchSrvKeyspace is part of the topo.Server interface
func (zkts *Server) WatchSrvKeyspace(ctx context.Context, cell, keyspace string) (<-chan *topo.SrvKeyspace, chan<- struct{}, error) {
	filePath := zkPathForVtKeyspace(cell, keyspace)

	notifications := make(chan *topo.SrvKeyspace, 10)
	stopWatching := make(chan struct{})

	// waitOrInterrupted will return true if stopWatching is triggered
	waitOrInterrupted := func() bool {
		timer := time.After(WatchSleepDuration)
		select {
		case <-stopWatching:
			close(notifications)
			return true
		case <-timer:
		}
		return false
	}

	go func() {
		for {
			// set the watch
			data, _, watch, err := zkts.zconn.GetW(filePath)
			if err != nil {
				if zookeeper.IsError(err, zookeeper.ZNONODE) {
					// the parent directory doesn't exist
					notifications <- nil
				}

				log.Errorf("Cannot set watch on %v, waiting for %v to retry: %v", filePath, WatchSleepDuration, err)
				if waitOrInterrupted() {
					return
				}
				continue
			}

			// get the initial value, send it, or send nil if no
			// data
			var srvKeyspace *topo.SrvKeyspace
			sendIt := true
			if len(data) > 0 {
				sk := &pb.SrvKeyspace{}
				if err := json.Unmarshal([]byte(data), sk); err != nil {
					log.Errorf("SrvKeyspace unmarshal failed: %v %v", data, err)
					sendIt = false
				} else {
					srvKeyspace = topo.ProtoToSrvKeyspace(sk)
				}
			}
			if sendIt {
				notifications <- srvKeyspace
			}

			// now act on the watch
			select {
			case event, ok := <-watch:
				if !ok {
					log.Warningf("watch on %v was closed, waiting for %v to retry", filePath, WatchSleepDuration)
					if waitOrInterrupted() {
						return
					}
					continue
				}

				if !event.Ok() {
					log.Warningf("received a non-OK event for %v, waiting for %v to retry", filePath, WatchSleepDuration)
					if waitOrInterrupted() {
						return
					}
				}
			case <-stopWatching:
				// user is not interested any more
				close(notifications)
				return
			}
		}
	}()

	return notifications, stopWatching, nil

}