github.com/tsuna/gohbase@v0.0.0-20250731002811-4ffcadfba63e/region/new.go (about)

     1  // Copyright (C) 2016  The GoHBase Authors.  All rights reserved.
     2  // This file is part of GoHBase.
     3  // Use of this source code is governed by the Apache License 2.0
     4  // that can be found in the COPYING file.
     5  
     6  //go:build !testing
     7  
     8  package region
     9  
    10  import (
    11  	"context"
    12  	"fmt"
    13  	"log/slog"
    14  	"net"
    15  	"time"
    16  
    17  	"github.com/tsuna/gohbase/compression"
    18  	"github.com/tsuna/gohbase/hrpc"
    19  )
    20  
    21  // NewClient creates a new RegionClient.
    22  func NewClient(addr string, ctype ClientType, queueSize int, flushInterval time.Duration,
    23  	effectiveUser string, readTimeout time.Duration, codec compression.Codec,
    24  	dialer func(ctx context.Context, network, addr string) (net.Conn, error),
    25  	slogger *slog.Logger) hrpc.RegionClient {
    26  	c := &client{
    27  		addr:          addr,
    28  		ctype:         ctype,
    29  		rpcQueueSize:  queueSize,
    30  		flushInterval: flushInterval,
    31  		effectiveUser: effectiveUser,
    32  		readTimeout:   readTimeout,
    33  		rpcs:          make(chan []hrpc.Call),
    34  		done:          make(chan struct{}),
    35  		sent:          make(map[uint32]hrpc.Call),
    36  		logger:        slogger,
    37  	}
    38  
    39  	if codec != nil {
    40  		c.compressor = &compressor{Codec: codec}
    41  	}
    42  
    43  	if dialer != nil {
    44  		c.dialer = dialer
    45  	} else {
    46  		var d net.Dialer
    47  		c.dialer = d.DialContext
    48  	}
    49  
    50  	return c
    51  }
    52  
    53  func (c *client) Dial(ctx context.Context) error {
    54  	c.dialOnce.Do(func() {
    55  		conn, err := c.dialer(ctx, "tcp", c.addr)
    56  		if err != nil {
    57  			c.fail(fmt.Errorf("failed to dial RegionServer: %s", err))
    58  			return
    59  		}
    60  
    61  		c.connM.Lock()
    62  		c.conn = conn
    63  		c.connM.Unlock()
    64  
    65  		// time out send hello if it take long
    66  		if deadline, ok := ctx.Deadline(); ok {
    67  			if err = c.conn.SetWriteDeadline(deadline); err != nil {
    68  				c.fail(fmt.Errorf("failed to set write deadline: %s", err))
    69  				return
    70  			}
    71  		}
    72  		if err := c.sendHello(); err != nil {
    73  			c.fail(fmt.Errorf("failed to send hello to RegionServer: %s", err))
    74  			return
    75  		}
    76  		// reset write deadline
    77  		if err = c.conn.SetWriteDeadline(time.Time{}); err != nil {
    78  			c.fail(fmt.Errorf("failed to set write deadline: %s", err))
    79  			return
    80  		}
    81  
    82  		if c.ctype == RegionClient {
    83  			go c.processRPCs() // Batching goroutine
    84  		}
    85  		go c.receiveRPCs() // Reader goroutine
    86  	})
    87  
    88  	select {
    89  	case <-c.done:
    90  		return ErrClientClosed
    91  	default:
    92  		return nil
    93  	}
    94  }