...

Source file src/google.golang.org/grpc/internal/channelz/subchannel.go

Documentation: google.golang.org/grpc/internal/channelz

     1  /*
     2   *
     3   * Copyright 2024 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   */
    18  
    19  package channelz
    20  
    21  import (
    22  	"fmt"
    23  	"sync/atomic"
    24  )
    25  
    26  // SubChannel is the channelz representation of a subchannel.
    27  type SubChannel struct {
    28  	Entity
    29  	// ID is the channelz id of this subchannel.
    30  	ID int64
    31  	// RefName is the human readable reference string of this subchannel.
    32  	RefName       string
    33  	closeCalled   bool
    34  	sockets       map[int64]string
    35  	parent        *Channel
    36  	trace         *ChannelTrace
    37  	traceRefCount int32
    38  
    39  	ChannelMetrics ChannelMetrics
    40  }
    41  
    42  func (sc *SubChannel) String() string {
    43  	return fmt.Sprintf("%s SubChannel #%d", sc.parent, sc.ID)
    44  }
    45  
    46  func (sc *SubChannel) id() int64 {
    47  	return sc.ID
    48  }
    49  
    50  func (sc *SubChannel) Sockets() map[int64]string {
    51  	db.mu.RLock()
    52  	defer db.mu.RUnlock()
    53  	return copyMap(sc.sockets)
    54  }
    55  
    56  func (sc *SubChannel) Trace() *ChannelTrace {
    57  	db.mu.RLock()
    58  	defer db.mu.RUnlock()
    59  	return sc.trace.copy()
    60  }
    61  
    62  func (sc *SubChannel) addChild(id int64, e entry) {
    63  	if v, ok := e.(*Socket); ok && v.SocketType == SocketTypeNormal {
    64  		sc.sockets[id] = v.RefName
    65  	} else {
    66  		logger.Errorf("cannot add a child (id = %d) of type %T to a subChannel", id, e)
    67  	}
    68  }
    69  
    70  func (sc *SubChannel) deleteChild(id int64) {
    71  	delete(sc.sockets, id)
    72  	sc.deleteSelfIfReady()
    73  }
    74  
    75  func (sc *SubChannel) triggerDelete() {
    76  	sc.closeCalled = true
    77  	sc.deleteSelfIfReady()
    78  }
    79  
    80  func (sc *SubChannel) getParentID() int64 {
    81  	return sc.parent.ID
    82  }
    83  
    84  // deleteSelfFromTree tries to delete the subchannel from the channelz entry relation tree, which
    85  // means deleting the subchannel reference from its parent's child list.
    86  //
    87  // In order for a subchannel to be deleted from the tree, it must meet the criteria that, removal of
    88  // the corresponding grpc object has been invoked, and the subchannel does not have any children left.
    89  //
    90  // The returned boolean value indicates whether the channel has been successfully deleted from tree.
    91  func (sc *SubChannel) deleteSelfFromTree() (deleted bool) {
    92  	if !sc.closeCalled || len(sc.sockets) != 0 {
    93  		return false
    94  	}
    95  	sc.parent.deleteChild(sc.ID)
    96  	return true
    97  }
    98  
    99  // deleteSelfFromMap checks whether it is valid to delete the subchannel from the map, which means
   100  // deleting the subchannel from channelz's tracking entirely. Users can no longer use id to query
   101  // the subchannel, and its memory will be garbage collected.
   102  //
   103  // The trace reference count of the subchannel must be 0 in order to be deleted from the map. This is
   104  // specified in the channel tracing gRFC that as long as some other trace has reference to an entity,
   105  // the trace of the referenced entity must not be deleted. In order to release the resource allocated
   106  // by grpc, the reference to the grpc object is reset to a dummy object.
   107  //
   108  // deleteSelfFromMap must be called after deleteSelfFromTree returns true.
   109  //
   110  // It returns a bool to indicate whether the channel can be safely deleted from map.
   111  func (sc *SubChannel) deleteSelfFromMap() (delete bool) {
   112  	return sc.getTraceRefCount() == 0
   113  }
   114  
   115  // deleteSelfIfReady tries to delete the subchannel itself from the channelz database.
   116  // The delete process includes two steps:
   117  //  1. delete the subchannel from the entry relation tree, i.e. delete the subchannel reference from
   118  //     its parent's child list.
   119  //  2. delete the subchannel from the map, i.e. delete the subchannel entirely from channelz. Lookup
   120  //     by id will return entry not found error.
   121  func (sc *SubChannel) deleteSelfIfReady() {
   122  	if !sc.deleteSelfFromTree() {
   123  		return
   124  	}
   125  	if !sc.deleteSelfFromMap() {
   126  		return
   127  	}
   128  	db.deleteEntry(sc.ID)
   129  	sc.trace.clear()
   130  }
   131  
   132  func (sc *SubChannel) getChannelTrace() *ChannelTrace {
   133  	return sc.trace
   134  }
   135  
   136  func (sc *SubChannel) incrTraceRefCount() {
   137  	atomic.AddInt32(&sc.traceRefCount, 1)
   138  }
   139  
   140  func (sc *SubChannel) decrTraceRefCount() {
   141  	atomic.AddInt32(&sc.traceRefCount, -1)
   142  }
   143  
   144  func (sc *SubChannel) getTraceRefCount() int {
   145  	i := atomic.LoadInt32(&sc.traceRefCount)
   146  	return int(i)
   147  }
   148  
   149  func (sc *SubChannel) getRefName() string {
   150  	return sc.RefName
   151  }
   152  

View as plain text