@@ -32,7 +32,7 @@ type sessionBuilder func(ctx context.Context, opts ...sessionBuilderOption) (*se
3232type balancerNotifier interface {
3333 grpc.ClientConnInterface
3434
35- OnDiscovery (onDiscovery func (ctx context.Context , endpoints []endpoint.Info ))
35+ OnUpdate (onDiscovery func (ctx context.Context , endpoints []endpoint.Info ))
3636}
3737
3838func New (balancer balancerNotifier , config config.Config ) * Client {
@@ -55,6 +55,7 @@ func newClient(
5555 cc : balancer ,
5656 build : builder ,
5757 index : make (map [* session ]sessionInfo ),
58+ nodes : make (map [uint32 ]map [* session ]struct {}),
5859 idle : list .New (),
5960 waitq : list .New (),
6061 limit : config .SizeLimit (),
@@ -67,7 +68,7 @@ func newClient(
6768 done : make (chan struct {}),
6869 }
6970 if balancer != nil {
70- balancer .OnDiscovery (c .onDiscovery )
71+ balancer .OnUpdate (c .updateNodes )
7172 }
7273 if idleThreshold := config .IdleThreshold (); idleThreshold > 0 {
7374 c .spawnedGoroutines .Add (1 )
@@ -88,6 +89,7 @@ type Client struct {
8889 // read-write fields
8990 mu xsync.Mutex
9091 index map [* session ]sessionInfo
92+ nodes map [uint32 ]map [* session ]struct {}
9193 createInProgress int // KIKIMR-9163: in-create-process counter
9294 limit int // Upper bound for Client size.
9395 idle * list.List // list<*session>
@@ -118,7 +120,7 @@ func withCreateSessionOnClose(onClose func(s *session)) createSessionOption {
118120 }
119121}
120122
121- func (c * Client ) onDiscovery (ctx context.Context , endpoints []endpoint.Info ) {
123+ func (c * Client ) updateNodes (ctx context.Context , endpoints []endpoint.Info ) {
122124 nodeIDs := make ([]uint32 , len (endpoints ))
123125 for i , e := range endpoints {
124126 nodeIDs [i ] = e .NodeID ()
@@ -127,26 +129,17 @@ func (c *Client) onDiscovery(ctx context.Context, endpoints []endpoint.Info) {
127129 return nodeIDs [i ] < nodeIDs [j ]
128130 })
129131 c .mu .WithLock (func () {
130- touched := make (map [* session ]struct {}, len (c .index ))
131- for e := c .idle .Front (); e != nil ; e = e .Next () {
132- s := e .Value .(* session )
133- nodeID := s .NodeID ()
132+ for nodeID := range c .nodes {
134133 if sort .Search (len (nodeIDs ), func (i int ) bool {
135134 return nodeIDs [i ] >= nodeID
136135 }) == len (nodeIDs ) {
137- c .internalPoolAsyncCloseSession (ctx , s )
138- }
139- touched [s ] = struct {}{}
140- }
141- for s := range c .index {
142- if _ , has := touched [s ]; has {
143- continue
144- }
145- nodeID := s .NodeID ()
146- if sort .Search (len (nodeIDs ), func (i int ) bool {
147- return nodeIDs [i ] >= nodeID
148- }) == len (nodeIDs ) {
149- s .SetStatus (options .SessionClosing )
136+ for s := range c .nodes [nodeID ] {
137+ if c .index [s ].idle != nil {
138+ c .internalPoolAsyncCloseSession (ctx , s )
139+ } else {
140+ s .SetStatus (options .SessionClosing )
141+ }
142+ }
150143 }
151144 }
152145 })
@@ -256,13 +249,51 @@ func (c *Client) createSession(ctx context.Context, opts ...createSessionOption)
256249 }
257250}
258251
252+ func (c * Client ) appendSessionToNodes (s * session ) {
253+ c .mu .WithLock (func () {
254+ nodeID := s .NodeID ()
255+ sessions , has := c .nodes [nodeID ]
256+ if ! has {
257+ sessions = make (map [* session ]struct {})
258+ }
259+ sessions [s ] = struct {}{}
260+ c .nodes [nodeID ] = sessions
261+ })
262+ }
263+
264+ func (c * Client ) removeSessionFromNodes (s * session ) {
265+ c .mu .WithLock (func () {
266+ nodeID := s .NodeID ()
267+ sessions , has := c .nodes [nodeID ]
268+ if ! has {
269+ sessions = make (map [* session ]struct {})
270+ }
271+ delete (sessions , s )
272+ if len (sessions ) == 0 {
273+ delete (c .nodes , nodeID )
274+ } else {
275+ c .nodes [nodeID ] = sessions
276+ }
277+ })
278+ }
279+
259280func (c * Client ) CreateSession (ctx context.Context , opts ... table.Option ) (_ table.ClosableSession , err error ) {
260281 if c == nil {
261282 return nil , xerrors .WithStackTrace (errNilClient )
262283 }
263284 var s * session
285+ createSession := func (ctx context.Context ) (* session , error ) {
286+ s , err = c .createSession (ctx ,
287+ withCreateSessionOnCreate (c .appendSessionToNodes ),
288+ withCreateSessionOnClose (c .removeSessionFromNodes ),
289+ )
290+ if err != nil {
291+ return nil , xerrors .WithStackTrace (err )
292+ }
293+ return s , nil
294+ }
264295 if ! c .config .AutoRetry () {
265- s , err = c . createSession (ctx )
296+ s , err = createSession (ctx )
266297 if err != nil {
267298 return nil , xerrors .WithStackTrace (err )
268299 }
@@ -272,7 +303,7 @@ func (c *Client) CreateSession(ctx context.Context, opts ...table.Option) (_ tab
272303 err = retry .Retry (
273304 ctx ,
274305 func (ctx context.Context ) (err error ) {
275- s , err = c . createSession (ctx )
306+ s , err = createSession (ctx )
276307 if err != nil {
277308 return xerrors .WithStackTrace (err )
278309 }
@@ -328,40 +359,45 @@ func (c *Client) internalPoolCreateSession(ctx context.Context) (s *session, err
328359 })
329360 }()
330361
331- s , err = c .createSession (meta .WithAllowFeatures (ctx ,
332- meta .HintSessionBalancer ,
333- ), withCreateSessionOnCreate (func (s * session ) {
334- c .mu .WithLock (func () {
335- c .index [s ] = sessionInfo {
336- touched : timeutil .Now (),
337- }
338- trace .TableOnPoolSessionAdd (c .config .Trace (), s )
339- trace .TableOnPoolStateChange (c .config .Trace (), len (c .index ), "append" )
340- })
341- }), withCreateSessionOnClose (func (s * session ) {
342- c .mu .WithLock (func () {
343- info , has := c .index [s ]
344- if ! has {
345- panic ("session not found in pool" )
346- }
362+ s , err = c .createSession (
363+ meta .WithAllowFeatures (ctx ,
364+ meta .HintSessionBalancer ,
365+ ),
366+ withCreateSessionOnCreate (c .appendSessionToNodes ),
367+ withCreateSessionOnClose (c .removeSessionFromNodes ),
368+ withCreateSessionOnCreate (func (s * session ) {
369+ c .mu .WithLock (func () {
370+ c .index [s ] = sessionInfo {
371+ touched : timeutil .Now (),
372+ }
373+ trace .TableOnPoolSessionAdd (c .config .Trace (), s )
374+ trace .TableOnPoolStateChange (c .config .Trace (), len (c .index ), "append" )
375+ })
376+ }), withCreateSessionOnClose (func (s * session ) {
377+ c .mu .WithLock (func () {
378+ info , has := c .index [s ]
379+ if ! has {
380+ panic ("session not found in pool" )
381+ }
347382
348- delete (c .index , s )
383+ delete (c .index , s )
349384
350- trace .TableOnPoolSessionRemove (c .config .Trace (), s )
351- trace .TableOnPoolStateChange (c .config .Trace (), len (c .index ), "remove" )
385+ trace .TableOnPoolSessionRemove (c .config .Trace (), s )
386+ trace .TableOnPoolStateChange (c .config .Trace (), len (c .index ), "remove" )
352387
353- if ! c .isClosed () {
354- c .internalPoolNotify (nil )
355- }
388+ if ! c .isClosed () {
389+ c .internalPoolNotify (nil )
390+ }
356391
357- if info .idle != nil {
358- c .idle .Remove (info .idle )
359- }
360- })
361- }))
392+ if info .idle != nil {
393+ c .idle .Remove (info .idle )
394+ }
395+ })
396+ }))
362397 if err != nil {
363398 return nil , xerrors .WithStackTrace (err )
364399 }
400+
365401 return s , nil
366402}
367403
0 commit comments