github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/go-hbase/action.go (about)

     1  package hbase
     2  
     3  import (
     4  	pb "github.com/insionng/yougam/libraries/golang/protobuf/proto"
     5  	"github.com/insionng/yougam/libraries/juju/errors"
     6  	"github.com/insionng/yougam/libraries/ngaut/log"
     7  	"github.com/insionng/yougam/libraries/pingcap/go-hbase/proto"
     8  )
     9  
    10  type action interface {
    11  	ToProto() pb.Message
    12  }
    13  
    14  func (c *client) innerCall(table, row []byte, action action, useCache bool) (*call, error) {
    15  	region, err := c.LocateRegion(table, row, useCache)
    16  	if err != nil {
    17  		return nil, errors.Trace(err)
    18  	}
    19  
    20  	conn, err := c.getClientConn(region.Server)
    21  	if err != nil {
    22  		return nil, errors.Trace(err)
    23  	}
    24  
    25  	regionSpecifier := &proto.RegionSpecifier{
    26  		Type:  proto.RegionSpecifier_REGION_NAME.Enum(),
    27  		Value: []byte(region.Name),
    28  	}
    29  
    30  	var cl *call
    31  	switch a := action.(type) {
    32  	case *Get:
    33  		cl = newCall(&proto.GetRequest{
    34  			Region: regionSpecifier,
    35  			Get:    a.ToProto().(*proto.Get),
    36  		})
    37  	case *Put, *Delete:
    38  		cl = newCall(&proto.MutateRequest{
    39  			Region:   regionSpecifier,
    40  			Mutation: a.ToProto().(*proto.MutationProto),
    41  		})
    42  
    43  	case *CoprocessorServiceCall:
    44  		cl = newCall(&proto.CoprocessorServiceRequest{
    45  			Region: regionSpecifier,
    46  			Call:   a.ToProto().(*proto.CoprocessorServiceCall),
    47  		})
    48  	default:
    49  		return nil, errors.Errorf("Unknown action - %T - %v", action, action)
    50  	}
    51  
    52  	err = conn.call(cl)
    53  	if err != nil {
    54  		// If failed, remove bad server conn cache.
    55  		cachedKey := cachedConnKey(region.Server, ClientService)
    56  		delete(c.cachedConns, cachedKey)
    57  		return nil, errors.Trace(err)
    58  	}
    59  
    60  	return cl, nil
    61  }
    62  
    63  func (c *client) innerDo(table, row []byte, action action, useCache bool) (pb.Message, error) {
    64  	// Try to create and send a new resuqest call.
    65  	cl, err := c.innerCall(table, row, action, useCache)
    66  	if err != nil {
    67  		log.Warnf("inner call failed - %v", errors.ErrorStack(err))
    68  		return nil, errors.Trace(err)
    69  	}
    70  
    71  	// Wait and receive the result.
    72  	return <-cl.responseCh, nil
    73  }
    74  
    75  func (c *client) do(table, row []byte, action action, useCache bool) (pb.Message, error) {
    76  	var (
    77  		result pb.Message
    78  		err    error
    79  	)
    80  
    81  LOOP:
    82  	for i := 0; i < c.maxRetries; i++ {
    83  		result, err = c.innerDo(table, row, action, useCache)
    84  		if err == nil {
    85  			switch r := result.(type) {
    86  			case *exception:
    87  				err = errors.New(r.msg)
    88  				// If get an execption response, clean old region cache.
    89  				c.CleanRegionCache(table)
    90  			default:
    91  				break LOOP
    92  			}
    93  		}
    94  
    95  		useCache = false
    96  		log.Warnf("Retrying action for the %d time(s), error - %v", i+1, errors.ErrorStack(err))
    97  		retrySleep(i + 1)
    98  	}
    99  
   100  	return result, errors.Trace(err)
   101  }