Exemple #1
0
// NewSession wraps an existing Node.
func NewSession(cfg ClusterConfig) (*Session, error) {
	// Check that hosts in the ClusterConfig is not empty
	if len(cfg.Hosts) < 1 {
		return nil, ErrNoHosts
	}

	s := &Session{
		cons:     cfg.Consistency,
		prefetch: 0.25,
		cfg:      cfg,
		pageSize: cfg.PageSize,
		stmtsLRU: &preparedLRU{lru: lru.New(cfg.MaxPreparedStmts)},
		quit:     make(chan struct{}),
	}

	s.nodeEvents = newEventDebouncer("NodeEvents", s.handleNodeEvent)
	s.schemaEvents = newEventDebouncer("SchemaEvents", s.handleSchemaEvent)

	s.routingKeyInfoCache.lru = lru.New(cfg.MaxRoutingKeyInfo)

	s.hostSource = &ringDescriber{
		session:   s,
		closeChan: make(chan bool),
	}

	if cfg.PoolConfig.HostSelectionPolicy == nil {
		cfg.PoolConfig.HostSelectionPolicy = RoundRobinHostPolicy()
	}
	s.pool = cfg.PoolConfig.buildPool(s)

	s.policy = cfg.PoolConfig.HostSelectionPolicy
	s.executor = &queryExecutor{
		pool:   s.pool,
		policy: cfg.PoolConfig.HostSelectionPolicy,
	}

	if err := s.init(); err != nil {
		// TODO(zariel): dont wrap this error in fmt.Errorf, return a typed error
		s.Close()
		return nil, fmt.Errorf("gocql: unable to create session: %v", err)
	}

	if s.pool.Size() == 0 {
		// TODO(zariel): move this to init
		s.Close()
		return nil, ErrNoConnectionsStarted
	}

	return s, nil
}
Exemple #2
0
func initStmtsLRU(max int) {
	if stmtsLRU.lru != nil {
		stmtsLRU.Max(max)
	} else {
		stmtsLRU.lru = lru.New(max)
	}
}
Exemple #3
0
// NewSession wraps an existing Node.
func NewSession(cfg ClusterConfig) (*Session, error) {
	//Check that hosts in the ClusterConfig is not empty
	if len(cfg.Hosts) < 1 {
		return nil, ErrNoHosts
	}

	//Adjust the size of the prepared statements cache to match the latest configuration
	stmtsLRU.Lock()
	initStmtsLRU(cfg.MaxPreparedStmts)
	stmtsLRU.Unlock()

	s := &Session{
		cons:     cfg.Consistency,
		prefetch: 0.25,
		cfg:      cfg,
		pageSize: cfg.PageSize,
	}

	pool, err := cfg.PoolConfig.buildPool(s)
	if err != nil {
		return nil, err
	}
	s.pool = pool

	// See if there are any connections in the pool
	if pool.Size() == 0 {
		s.Close()
		return nil, ErrNoConnectionsStarted
	}

	s.routingKeyInfoCache.lru = lru.New(cfg.MaxRoutingKeyInfo)

	// I think it might be a good idea to simplify this and make it always discover
	// hosts, maybe with more filters.
	if cfg.DiscoverHosts {
		s.hostSource = &ringDescriber{
			session:    s,
			dcFilter:   cfg.Discovery.DcFilter,
			rackFilter: cfg.Discovery.RackFilter,
			closeChan:  make(chan bool),
		}
	}

	if !cfg.disableControlConn {
		s.control = createControlConn(s)
		s.control.reconnect(false)

		// need to setup host source to check for rpc_address in system.local
		localHasRPCAddr, err := checkSystemLocal(s.control)
		if err != nil {
			log.Printf("gocql: unable to verify if system.local table contains rpc_address, falling back to connection address: %v", err)
		}

		if cfg.DiscoverHosts {
			s.hostSource.localHasRpcAddr = localHasRPCAddr
		}
	}

	if cfg.DiscoverHosts {
		s.hostSource.refreshRing()
		go s.hostSource.run(cfg.Discovery.Sleep)
	}

	return s, nil
}
Exemple #4
0
// NewSession wraps an existing Node.
func NewSession(cfg ClusterConfig) (*Session, error) {
	//Check that hosts in the ClusterConfig is not empty
	if len(cfg.Hosts) < 1 {
		return nil, ErrNoHosts
	}

	s := &Session{
		cons:     cfg.Consistency,
		prefetch: 0.25,
		cfg:      cfg,
		pageSize: cfg.PageSize,
		stmtsLRU: &preparedLRU{lru: lru.New(cfg.MaxPreparedStmts)},
	}

	connCfg, err := connConfig(s)
	if err != nil {
		s.Close()
		return nil, fmt.Errorf("gocql: unable to create session: %v", err)
	}
	s.connCfg = connCfg

	s.nodeEvents = newEventDeouncer("NodeEvents", s.handleNodeEvent)
	s.schemaEvents = newEventDeouncer("SchemaEvents", s.handleSchemaEvent)

	s.routingKeyInfoCache.lru = lru.New(cfg.MaxRoutingKeyInfo)

	// I think it might be a good idea to simplify this and make it always discover
	// hosts, maybe with more filters.
	s.hostSource = &ringDescriber{
		session:   s,
		closeChan: make(chan bool),
	}

	pool := cfg.PoolConfig.buildPool(s)
	if cfg.PoolConfig.HostSelectionPolicy == nil {
		cfg.PoolConfig.HostSelectionPolicy = RoundRobinHostPolicy()
	}

	s.pool = pool
	s.policy = cfg.PoolConfig.HostSelectionPolicy
	s.executor = &queryExecutor{
		pool:   pool,
		policy: cfg.PoolConfig.HostSelectionPolicy,
	}

	var hosts []*HostInfo

	if !cfg.disableControlConn {
		s.control = createControlConn(s)
		if err := s.control.connect(cfg.Hosts); err != nil {
			s.Close()
			return nil, fmt.Errorf("gocql: unable to create session: %v", err)
		}

		// need to setup host source to check for broadcast_address in system.local
		localHasRPCAddr, _ := checkSystemLocal(s.control)
		s.hostSource.localHasRpcAddr = localHasRPCAddr

		var err error
		if cfg.DisableInitialHostLookup {
			// TODO: we could look at system.local to get token and other metadata
			// in this case.
			hosts, err = addrsToHosts(cfg.Hosts, cfg.Port)
		} else {
			hosts, _, err = s.hostSource.GetHosts()
		}

		if err != nil {
			s.Close()
			return nil, fmt.Errorf("gocql: unable to create session: %v", err)
		}
	} else {
		// we dont get host info
		hosts, err = addrsToHosts(cfg.Hosts, cfg.Port)
	}

	for _, host := range hosts {
		if s.cfg.HostFilter == nil || s.cfg.HostFilter.Accept(host) {
			if existingHost, ok := s.ring.addHostIfMissing(host); ok {
				existingHost.update(host)
			}

			s.handleNodeUp(net.ParseIP(host.Peer()), host.Port(), false)
		}
	}

	if cfg.ReconnectInterval > 0 {
		go s.reconnectDownedHosts(cfg.ReconnectInterval)
	}

	// TODO(zariel): we probably dont need this any more as we verify that we
	// can connect to one of the endpoints supplied by using the control conn.
	// See if there are any connections in the pool
	if s.pool.Size() == 0 {
		s.Close()
		return nil, ErrNoConnectionsStarted
	}

	s.useSystemSchema = hosts[0].Version().Major >= 3

	return s, nil
}
Exemple #5
0
// NewSession wraps an existing Node.
func NewSession(cfg ClusterConfig) (*Session, error) {
	//Check that hosts in the ClusterConfig is not empty
	if len(cfg.Hosts) < 1 {
		return nil, ErrNoHosts
	}

	//Adjust the size of the prepared statements cache to match the latest configuration
	stmtsLRU.Lock()
	initStmtsLRU(cfg.MaxPreparedStmts)
	stmtsLRU.Unlock()

	s := &Session{
		cons:     cfg.Consistency,
		prefetch: 0.25,
		cfg:      cfg,
		pageSize: cfg.PageSize,
	}

	connCfg, err := connConfig(s)
	if err != nil {
		s.Close()
		return nil, fmt.Errorf("gocql: unable to create session: %v", err)
	}
	s.connCfg = connCfg

	s.nodeEvents = newEventDeouncer("NodeEvents", s.handleNodeEvent)

	s.routingKeyInfoCache.lru = lru.New(cfg.MaxRoutingKeyInfo)

	// I think it might be a good idea to simplify this and make it always discover
	// hosts, maybe with more filters.
	s.hostSource = &ringDescriber{
		session:   s,
		closeChan: make(chan bool),
	}

	s.pool = cfg.PoolConfig.buildPool(s)

	var hosts []*HostInfo

	if !cfg.disableControlConn {
		s.control = createControlConn(s)
		if err := s.control.connect(cfg.Hosts); err != nil {
			s.Close()
			return nil, err
		}

		// need to setup host source to check for broadcast_address in system.local
		localHasRPCAddr, _ := checkSystemLocal(s.control)
		s.hostSource.localHasRpcAddr = localHasRPCAddr
		hosts, _, err = s.hostSource.GetHosts()
		if err != nil {
			s.Close()
			return nil, err
		}

	} else {
		// we dont get host info
		hosts = make([]*HostInfo, len(cfg.Hosts))
		for i, hostport := range cfg.Hosts {
			// TODO: remove duplication
			addr, portStr, err := net.SplitHostPort(JoinHostPort(hostport, cfg.Port))
			if err != nil {
				s.Close()
				return nil, fmt.Errorf("NewSession: unable to parse hostport of addr %q: %v", hostport, err)
			}

			port, err := strconv.Atoi(portStr)
			if err != nil {
				s.Close()
				return nil, fmt.Errorf("NewSession: invalid port for hostport of addr %q: %v", hostport, err)
			}

			hosts[i] = &HostInfo{peer: addr, port: port, state: NodeUp}
		}
	}

	for _, host := range hosts {
		s.handleNodeUp(net.ParseIP(host.Peer()), host.Port(), false)
	}

	// TODO(zariel): we probably dont need this any more as we verify that we
	// can connect to one of the endpoints supplied by using the control conn.
	// See if there are any connections in the pool
	if s.pool.Size() == 0 {
		s.Close()
		return nil, ErrNoConnectionsStarted
	}

	return s, nil
}