func (c *Conn) UseKeyspace(keyspace string) error { q := &writeQueryFrame{statement: `USE "` + keyspace + `"`} q.params.consistency = Any framer, err := c.exec(context.Background(), q, nil) if err != nil { return err } resp, err := framer.parseFrame() if err != nil { return err } switch x := resp.(type) { case *resultKeyspaceFrame: case error: return x default: return NewErrProtocol("unknown frame in response to USE: %v", x) } c.currentKeyspace = keyspace return nil }
func (c *controlConn) registerEvents(conn *Conn) error { var events []string if !c.session.cfg.Events.DisableTopologyEvents { events = append(events, "TOPOLOGY_CHANGE") } if !c.session.cfg.Events.DisableNodeStatusEvents { events = append(events, "STATUS_CHANGE") } if !c.session.cfg.Events.DisableSchemaEvents { events = append(events, "SCHEMA_CHANGE") } if len(events) == 0 { return nil } framer, err := conn.exec(context.Background(), &writeRegisterFrame{ events: events, }, nil) if err != nil { return err } frame, err := framer.parseFrame() if err != nil { return err } else if _, ok := frame.(*readyFrame); !ok { return fmt.Errorf("unexpected frame in response to register: got %T: %v\n", frame, frame) } return nil }
func (c *controlConn) writeFrame(w frameWriter) (frame, error) { conn := c.conn.Load().(*Conn) if conn == nil { return nil, errNoControl } framer, err := conn.exec(context.Background(), w, nil) if err != nil { return nil, err } return framer.parseFrame() }
// Connect establishes a connection to a Cassandra node. func Connect(host *HostInfo, addr string, cfg *ConnConfig, errorHandler ConnErrorHandler, session *Session) (*Conn, error) { var ( err error conn net.Conn ) dialer := &net.Dialer{ Timeout: cfg.Timeout, } if cfg.tlsConfig != nil { // the TLS config is safe to be reused by connections but it must not // be modified after being used. conn, err = tls.DialWithDialer(dialer, "tcp", addr, cfg.tlsConfig) } else { conn, err = dialer.Dial("tcp", addr) } if err != nil { return nil, err } c := &Conn{ conn: conn, r: bufio.NewReader(conn), cfg: cfg, calls: make(map[int]*callReq), timeout: cfg.Timeout, version: uint8(cfg.ProtoVersion), addr: conn.RemoteAddr().String(), errorHandler: errorHandler, compressor: cfg.Compressor, auth: cfg.Authenticator, quit: make(chan struct{}), session: session, streams: streams.New(cfg.ProtoVersion), host: host, } if cfg.Keepalive > 0 { c.setKeepalive(cfg.Keepalive) } var ( ctx context.Context cancel func() ) if c.timeout > 0 { ctx, cancel = context.WithTimeout(context.Background(), c.timeout) } else { ctx, cancel = context.WithCancel(context.Background()) } defer cancel() frameTicker := make(chan struct{}, 1) startupErr := make(chan error) go func() { for range frameTicker { err := c.recv() if err != nil { select { case startupErr <- err: case <-ctx.Done(): } return } } }() go func() { defer close(frameTicker) err := c.startup(ctx, frameTicker) select { case startupErr <- err: case <-ctx.Done(): } }() select { case err := <-startupErr: if err != nil { c.Close() return nil, err } case <-ctx.Done(): c.Close() return nil, errors.New("gocql: no response to connection startup within timeout") } go c.serve() return c, nil }