Example #1
func NewCassandraHostList(initialHostList []CassandraHost, useAutodiscovery bool, shutdown chan int) *CassandraHostList {
	up := make(map[string]CassandraHost)
	dwn := make(map[string]CassandraHost)
	var mtx sync.Mutex
	avail := make([]string, 0)
	ret := &CassandraHostList{up, dwn, avail, shutdown, mtx, 0, false}

	for _, val := range initialHostList {
		ret.Down[val.String()] = val

	// TODO: configurable whether or not to poll, poll frequency
	pollForever := config.Get().Settings().PollServersForever
	ret.StartPollingServers(true, pollForever, time.Duration(5)*time.Second) // comb the up list to include only up nodes

	if useAutodiscovery {
		go ret.NodeAutoDiscovery(time.Duration(10) * time.Second) // TODO: make configurable
	return ret
// Process the arguments of a thrift call off the TProtocol and store it for future access
// NOTE: this actually reads from the inbound protocol, so you will have to call the WriteArgs(TProtocol) method to
// write those back to an upstream server or whatever those args were originally meant for
func (p *ArgsRetainingProcessor) ReadArgs(iprot thrift.TProtocol) (success bool, err thrift.TException) {
	// ok, so this may look a little silly/stupid/insane, but, we're doing it this way (using reflect) to
	// generalize over the generated thrift bindings, which are pretty rigid and offer little extensibility
	t1 := time.Now()
	defer func() {
		t := config.Get().Timer("cassbounce.server.cassutils.ArgsRetainingProcessor.ReadArgs")
	// run the constructor which will return for us an interface{}
	args := p.constructor()
	// reflect the type of the interface{} (which is some args instance)
	typ := reflect.TypeOf(args)
	// get its "Read" method
	meth, isValid := typ.MethodByName("Read")
	if !isValid {
		// should never fail, unless the thrift bindings have changed drastically
		log.Print("ArgsRetainingProcessor:ReadArgs error getting valid Read method from ", typ)
	// build args for the "Read" method
	argsArgs := []reflect.Value{reflect.ValueOf(args), reflect.ValueOf(iprot)}
	// call that "Read" method and get its first return value (Read only returns one Value)
	ret := meth.Func.Call(argsArgs)
	// if it is non-nil, then it is (should be) some TProtocolException
	if !ret[0].IsNil() { // there was an error reading the arguments
		// try casting it to the actual TProtocolException
		concreteExc, ok := ret[0].Interface().(thrift.TProtocolException)
		if !ok {
			// should never fail... unless the thrift bindings have changed drastically
			log.Print("ArgsRetainingProcessor:ReadArgs error getting valid TProtocolException from Read method")
		err = concreteExc
	} else {
		p.gotArgs = true
		p.argsTypCache = typ
		p.args = args
	return p.gotArgs, err
Example #3
func main() {

	// global shutdown signal - a number is sent over when services should shut down
	shutdown := make(chan int)

	// settings
	settings := config.NewAppSettings()
	// settings.InitialServerList = initial
	settings.NodeAutodiscovery = *nodeAutodiscovery
	settings.ListenAddress = *listenAddress
	settings.PollServersForever = *pollServers
	settings.PoolRecycleDuration = time.Duration(*poolRecycleDuration) * time.Second
	settings.PoolRecycleJitter = *poolRecycleJitter
	settings.PoolSize = *poolSize
	settings.PoolConnectionAcquireTimeout = time.Duration(*poolConnectionAcquireTimeout) * time.Millisecond
	settings.PoolConnectionAcquireRetries = *poolConnectionAcquireRetries


	// global app
	app := server.New()
	app.ShutdownChan = shutdown

	// host list set up (this must happen after the global app object is set up)
	initial := parseInitialServerList(*initialServerList)
	// this will block until at least one successful connection can be established
	outboundHostList := server.NewCassandraHostList(initial, *nodeAutodiscovery, shutdown)

	// listen forever
	err := app.Listen()

	if err != nil {
		log.Fatal("Could not listen on interface: ", settings.ListenAddress, " error: ", err)