func Dial(node string, keyspace string, timeout time.Duration) (*CassConnection, error) { // resolve the address addr, err := net.ResolveTCPAddr("tcp", node) if err != nil { return nil, err } // get a socket sock, err := thrift.NewTNonblockingSocketAddr(addr) if err != nil { return nil, err } sock.SetTimeout(int64(timeout)) // build the client transport := thriftutils.NewTFramedTransport(sock) protocolFactory := thrift.NewTBinaryProtocolFactoryDefault() cli := cassandra.NewCassandraClientFactory(transport, protocolFactory) // connect, with a timeout of `timeout` ch := make(chan bool, 1) go func() { err = transport.Open() ch <- true }() timedOut := false select { case <-time.After(timeout): timedOut = true case <-ch: } if timedOut { return nil, ErrorConnectionTimeout } // get the version and check for min version and what not ver, err := cli.DescribeVersion() if err != nil { transport.Close() return nil, err } log.Print("Opened new connection, protocol version: ", ver) return &CassConnection{sock, transport, cli, node, keyspace, protocolFactory}, nil }
func newConnection(node, keyspace string, timeout int, authentication map[string]string) (*connection, error) { addr, err := net.ResolveTCPAddr("tcp", node) if err != nil { return nil, err } c := &connection{node: node} c.socket, err = thrift.NewTNonblockingSocketAddr(addr) if err != nil { return nil, err } // socket not open yet, so no error expected. it expects nanos, we have milis, so it's 1e6 c.socket.SetTimeout(int64(timeout) * 1e6) c.transport = thrift.NewTFramedTransport(c.socket) protocolFactory := thrift.NewTBinaryProtocolFactoryDefault() c.client = cassandra.NewCassandraClientFactory(c.transport, protocolFactory) // simulate timeout support for the underlying Dial() in .Open(). needless to say this sucks // restore sanity to this for Go v1 with the new DialTimeout() func ch := make(chan bool, 1) go func() { err = c.transport.Open() ch <- true }() timedOut := false select { case <-time.After(time.Duration(timeout) * time.Millisecond): timedOut = true case <-ch: } if timedOut { return nil, ErrorConnectionTimeout } if err != nil { return nil, err } version, err := c.client.DescribeVersion() if err != nil { c.close() return nil, err } versionComponents := strings.Split(version, ".") if len(versionComponents) < 1 { return nil, ErrorInvalidThriftVersion } majorVersion, err := strconv.Atoi(versionComponents[0]) if err != nil { return nil, ErrorInvalidThriftVersion } if majorVersion < LOWEST_COMPATIBLE_VERSION { return nil, ErrorWrongThriftVersion } if len(authentication) > 0 { ar := cassandra.NewAuthenticationRequest() ar.Credentials = thrift.NewTMap(thrift.STRING, thrift.STRING, 1) for k, v := range authentication { ar.Credentials.Set(k, v) } autE, auzE, err := c.client.Login(ar) if autE != nil { return nil, ErrorAuthenticationFailed } if auzE != nil { return nil, ErrorAuthorizationFailed } if err != nil { return nil, err } } ire, err := c.client.SetKeyspace(keyspace) if err != nil { c.close() return nil, err } if ire != nil { c.close() return nil, ErrorSetKeyspace } c.keyspace = keyspace return c, nil }
func newConnection(node, keyspace string, timeout int) (*connection, error) { addr, err := net.ResolveTCPAddr("tcp", node) if err != nil { return nil, err } c := &connection{node: node} c.socket, err = thrift.NewTNonblockingSocketAddr(addr) if err != nil { return nil, err } // socket not open yet, so no error expected. it expects nanos, we have milis, so it's 1e6 c.socket.SetTimeout(int64(timeout) * 1e6) c.transport = thrift.NewTFramedTransport(c.socket) protocolFactory := thrift.NewTBinaryProtocolFactoryDefault() c.client = cassandra.NewCassandraClientFactory(c.transport, protocolFactory) // simulate timeout support for the underlying Dial() in .Open(). needless to say this sucks // restore sanity to this for Go v1 with the new DialTimeout() func ch := make(chan bool, 1) go func() { err = c.transport.Open() ch <- true }() timedOut := false select { case <-time.After(time.Duration(timeout) * time.Millisecond): timedOut = true case <-ch: } if timedOut { return nil, ErrorConnectionTimeout } if err != nil { return nil, err } version, err := c.client.DescribeVersion() if err != nil { c.close() return nil, err } versionComponents := strings.Split(version, ".") if len(versionComponents) < 1 { return nil, errors.New(fmt.Sprint("Cannot parse the Thrift API version number: ", version)) } majorVersion, err := strconv.Atoi(versionComponents[0]) if err != nil { return nil, errors.New(fmt.Sprint("Cannot parse the Thrift API version number: ", version)) } if majorVersion < LOWEST_COMPATIBLE_VERSION { return nil, errors.New(fmt.Sprint("Unsupported Thrift API version, lowest supported is ", LOWEST_COMPATIBLE_VERSION, ", server reports ", majorVersion)) } ire, err := c.client.SetKeyspace(keyspace) if err != nil { c.close() return nil, err } if ire != nil { c.close() return nil, errors.New("Cannot set the keyspace") } c.keyspace = keyspace return c, nil }