funcs.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763
  1. /*
  2. *
  3. * Copyright 2018 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. // Package channelz defines APIs for enabling channelz service, entry
  19. // registration/deletion, and accessing channelz data. It also defines channelz
  20. // metric struct formats.
  21. //
  22. // All APIs in this package are experimental.
  23. package channelz
  24. import (
  25. "errors"
  26. "sort"
  27. "sync"
  28. "sync/atomic"
  29. "time"
  30. "google.golang.org/grpc/grpclog"
  31. "google.golang.org/grpc/internal"
  32. )
  33. const (
  34. defaultMaxTraceEntry int32 = 30
  35. )
  36. var (
  37. // IDGen is the global channelz entity ID generator. It should not be used
  38. // outside this package except by tests.
  39. IDGen IDGenerator
  40. db dbWrapper
  41. // EntryPerPage defines the number of channelz entries to be shown on a web page.
  42. EntryPerPage = int64(50)
  43. curState int32
  44. maxTraceEntry = defaultMaxTraceEntry
  45. )
  46. // TurnOn turns on channelz data collection.
  47. func TurnOn() {
  48. if !IsOn() {
  49. db.set(newChannelMap())
  50. IDGen.Reset()
  51. atomic.StoreInt32(&curState, 1)
  52. }
  53. }
  54. func init() {
  55. internal.ChannelzTurnOffForTesting = func() {
  56. atomic.StoreInt32(&curState, 0)
  57. }
  58. }
  59. // IsOn returns whether channelz data collection is on.
  60. func IsOn() bool {
  61. return atomic.LoadInt32(&curState) == 1
  62. }
  63. // SetMaxTraceEntry sets maximum number of trace entry per entity (i.e. channel/subchannel).
  64. // Setting it to 0 will disable channel tracing.
  65. func SetMaxTraceEntry(i int32) {
  66. atomic.StoreInt32(&maxTraceEntry, i)
  67. }
  68. // ResetMaxTraceEntryToDefault resets the maximum number of trace entry per entity to default.
  69. func ResetMaxTraceEntryToDefault() {
  70. atomic.StoreInt32(&maxTraceEntry, defaultMaxTraceEntry)
  71. }
  72. func getMaxTraceEntry() int {
  73. i := atomic.LoadInt32(&maxTraceEntry)
  74. return int(i)
  75. }
  76. // dbWarpper wraps around a reference to internal channelz data storage, and
  77. // provide synchronized functionality to set and get the reference.
  78. type dbWrapper struct {
  79. mu sync.RWMutex
  80. DB *channelMap
  81. }
  82. func (d *dbWrapper) set(db *channelMap) {
  83. d.mu.Lock()
  84. d.DB = db
  85. d.mu.Unlock()
  86. }
  87. func (d *dbWrapper) get() *channelMap {
  88. d.mu.RLock()
  89. defer d.mu.RUnlock()
  90. return d.DB
  91. }
  92. // GetTopChannels returns a slice of top channel's ChannelMetric, along with a
  93. // boolean indicating whether there's more top channels to be queried for.
  94. //
  95. // The arg id specifies that only top channel with id at or above it will be included
  96. // in the result. The returned slice is up to a length of the arg maxResults or
  97. // EntryPerPage if maxResults is zero, and is sorted in ascending id order.
  98. func GetTopChannels(id int64, maxResults int64) ([]*ChannelMetric, bool) {
  99. return db.get().GetTopChannels(id, maxResults)
  100. }
  101. // GetServers returns a slice of server's ServerMetric, along with a
  102. // boolean indicating whether there's more servers to be queried for.
  103. //
  104. // The arg id specifies that only server with id at or above it will be included
  105. // in the result. The returned slice is up to a length of the arg maxResults or
  106. // EntryPerPage if maxResults is zero, and is sorted in ascending id order.
  107. func GetServers(id int64, maxResults int64) ([]*ServerMetric, bool) {
  108. return db.get().GetServers(id, maxResults)
  109. }
  110. // GetServerSockets returns a slice of server's (identified by id) normal socket's
  111. // SocketMetric, along with a boolean indicating whether there's more sockets to
  112. // be queried for.
  113. //
  114. // The arg startID specifies that only sockets with id at or above it will be
  115. // included in the result. The returned slice is up to a length of the arg maxResults
  116. // or EntryPerPage if maxResults is zero, and is sorted in ascending id order.
  117. func GetServerSockets(id int64, startID int64, maxResults int64) ([]*SocketMetric, bool) {
  118. return db.get().GetServerSockets(id, startID, maxResults)
  119. }
  120. // GetChannel returns the ChannelMetric for the channel (identified by id).
  121. func GetChannel(id int64) *ChannelMetric {
  122. return db.get().GetChannel(id)
  123. }
  124. // GetSubChannel returns the SubChannelMetric for the subchannel (identified by id).
  125. func GetSubChannel(id int64) *SubChannelMetric {
  126. return db.get().GetSubChannel(id)
  127. }
  128. // GetSocket returns the SocketInternalMetric for the socket (identified by id).
  129. func GetSocket(id int64) *SocketMetric {
  130. return db.get().GetSocket(id)
  131. }
  132. // GetServer returns the ServerMetric for the server (identified by id).
  133. func GetServer(id int64) *ServerMetric {
  134. return db.get().GetServer(id)
  135. }
  136. // RegisterChannel registers the given channel c in the channelz database with
  137. // ref as its reference name, and adds it to the child list of its parent
  138. // (identified by pid). pid == nil means no parent.
  139. //
  140. // Returns a unique channelz identifier assigned to this channel.
  141. //
  142. // If channelz is not turned ON, the channelz database is not mutated.
  143. func RegisterChannel(c Channel, pid *Identifier, ref string) *Identifier {
  144. id := IDGen.genID()
  145. var parent int64
  146. isTopChannel := true
  147. if pid != nil {
  148. isTopChannel = false
  149. parent = pid.Int()
  150. }
  151. if !IsOn() {
  152. return newIdentifer(RefChannel, id, pid)
  153. }
  154. cn := &channel{
  155. refName: ref,
  156. c: c,
  157. subChans: make(map[int64]string),
  158. nestedChans: make(map[int64]string),
  159. id: id,
  160. pid: parent,
  161. trace: &channelTrace{createdTime: time.Now(), events: make([]*TraceEvent, 0, getMaxTraceEntry())},
  162. }
  163. db.get().addChannel(id, cn, isTopChannel, parent)
  164. return newIdentifer(RefChannel, id, pid)
  165. }
  166. // RegisterSubChannel registers the given subChannel c in the channelz database
  167. // with ref as its reference name, and adds it to the child list of its parent
  168. // (identified by pid).
  169. //
  170. // Returns a unique channelz identifier assigned to this subChannel.
  171. //
  172. // If channelz is not turned ON, the channelz database is not mutated.
  173. func RegisterSubChannel(c Channel, pid *Identifier, ref string) (*Identifier, error) {
  174. if pid == nil {
  175. return nil, errors.New("a SubChannel's parent id cannot be nil")
  176. }
  177. id := IDGen.genID()
  178. if !IsOn() {
  179. return newIdentifer(RefSubChannel, id, pid), nil
  180. }
  181. sc := &subChannel{
  182. refName: ref,
  183. c: c,
  184. sockets: make(map[int64]string),
  185. id: id,
  186. pid: pid.Int(),
  187. trace: &channelTrace{createdTime: time.Now(), events: make([]*TraceEvent, 0, getMaxTraceEntry())},
  188. }
  189. db.get().addSubChannel(id, sc, pid.Int())
  190. return newIdentifer(RefSubChannel, id, pid), nil
  191. }
  192. // RegisterServer registers the given server s in channelz database. It returns
  193. // the unique channelz tracking id assigned to this server.
  194. //
  195. // If channelz is not turned ON, the channelz database is not mutated.
  196. func RegisterServer(s Server, ref string) *Identifier {
  197. id := IDGen.genID()
  198. if !IsOn() {
  199. return newIdentifer(RefServer, id, nil)
  200. }
  201. svr := &server{
  202. refName: ref,
  203. s: s,
  204. sockets: make(map[int64]string),
  205. listenSockets: make(map[int64]string),
  206. id: id,
  207. }
  208. db.get().addServer(id, svr)
  209. return newIdentifer(RefServer, id, nil)
  210. }
  211. // RegisterListenSocket registers the given listen socket s in channelz database
  212. // with ref as its reference name, and add it to the child list of its parent
  213. // (identified by pid). It returns the unique channelz tracking id assigned to
  214. // this listen socket.
  215. //
  216. // If channelz is not turned ON, the channelz database is not mutated.
  217. func RegisterListenSocket(s Socket, pid *Identifier, ref string) (*Identifier, error) {
  218. if pid == nil {
  219. return nil, errors.New("a ListenSocket's parent id cannot be 0")
  220. }
  221. id := IDGen.genID()
  222. if !IsOn() {
  223. return newIdentifer(RefListenSocket, id, pid), nil
  224. }
  225. ls := &listenSocket{refName: ref, s: s, id: id, pid: pid.Int()}
  226. db.get().addListenSocket(id, ls, pid.Int())
  227. return newIdentifer(RefListenSocket, id, pid), nil
  228. }
  229. // RegisterNormalSocket registers the given normal socket s in channelz database
  230. // with ref as its reference name, and adds it to the child list of its parent
  231. // (identified by pid). It returns the unique channelz tracking id assigned to
  232. // this normal socket.
  233. //
  234. // If channelz is not turned ON, the channelz database is not mutated.
  235. func RegisterNormalSocket(s Socket, pid *Identifier, ref string) (*Identifier, error) {
  236. if pid == nil {
  237. return nil, errors.New("a NormalSocket's parent id cannot be 0")
  238. }
  239. id := IDGen.genID()
  240. if !IsOn() {
  241. return newIdentifer(RefNormalSocket, id, pid), nil
  242. }
  243. ns := &normalSocket{refName: ref, s: s, id: id, pid: pid.Int()}
  244. db.get().addNormalSocket(id, ns, pid.Int())
  245. return newIdentifer(RefNormalSocket, id, pid), nil
  246. }
  247. // RemoveEntry removes an entry with unique channelz tracking id to be id from
  248. // channelz database.
  249. //
  250. // If channelz is not turned ON, this function is a no-op.
  251. func RemoveEntry(id *Identifier) {
  252. if !IsOn() {
  253. return
  254. }
  255. db.get().removeEntry(id.Int())
  256. }
  257. // TraceEventDesc is what the caller of AddTraceEvent should provide to describe
  258. // the event to be added to the channel trace.
  259. //
  260. // The Parent field is optional. It is used for an event that will be recorded
  261. // in the entity's parent trace.
  262. type TraceEventDesc struct {
  263. Desc string
  264. Severity Severity
  265. Parent *TraceEventDesc
  266. }
  267. // AddTraceEvent adds trace related to the entity with specified id, using the
  268. // provided TraceEventDesc.
  269. //
  270. // If channelz is not turned ON, this will simply log the event descriptions.
  271. func AddTraceEvent(l grpclog.DepthLoggerV2, id *Identifier, depth int, desc *TraceEventDesc) {
  272. // Log only the trace description associated with the bottom most entity.
  273. switch desc.Severity {
  274. case CtUnknown, CtInfo:
  275. l.InfoDepth(depth+1, withParens(id)+desc.Desc)
  276. case CtWarning:
  277. l.WarningDepth(depth+1, withParens(id)+desc.Desc)
  278. case CtError:
  279. l.ErrorDepth(depth+1, withParens(id)+desc.Desc)
  280. }
  281. if getMaxTraceEntry() == 0 {
  282. return
  283. }
  284. if IsOn() {
  285. db.get().traceEvent(id.Int(), desc)
  286. }
  287. }
  288. // channelMap is the storage data structure for channelz.
  289. // Methods of channelMap can be divided in two two categories with respect to locking.
  290. // 1. Methods acquire the global lock.
  291. // 2. Methods that can only be called when global lock is held.
  292. // A second type of method need always to be called inside a first type of method.
  293. type channelMap struct {
  294. mu sync.RWMutex
  295. topLevelChannels map[int64]struct{}
  296. servers map[int64]*server
  297. channels map[int64]*channel
  298. subChannels map[int64]*subChannel
  299. listenSockets map[int64]*listenSocket
  300. normalSockets map[int64]*normalSocket
  301. }
  302. func newChannelMap() *channelMap {
  303. return &channelMap{
  304. topLevelChannels: make(map[int64]struct{}),
  305. channels: make(map[int64]*channel),
  306. listenSockets: make(map[int64]*listenSocket),
  307. normalSockets: make(map[int64]*normalSocket),
  308. servers: make(map[int64]*server),
  309. subChannels: make(map[int64]*subChannel),
  310. }
  311. }
  312. func (c *channelMap) addServer(id int64, s *server) {
  313. c.mu.Lock()
  314. s.cm = c
  315. c.servers[id] = s
  316. c.mu.Unlock()
  317. }
  318. func (c *channelMap) addChannel(id int64, cn *channel, isTopChannel bool, pid int64) {
  319. c.mu.Lock()
  320. cn.cm = c
  321. cn.trace.cm = c
  322. c.channels[id] = cn
  323. if isTopChannel {
  324. c.topLevelChannels[id] = struct{}{}
  325. } else {
  326. c.findEntry(pid).addChild(id, cn)
  327. }
  328. c.mu.Unlock()
  329. }
  330. func (c *channelMap) addSubChannel(id int64, sc *subChannel, pid int64) {
  331. c.mu.Lock()
  332. sc.cm = c
  333. sc.trace.cm = c
  334. c.subChannels[id] = sc
  335. c.findEntry(pid).addChild(id, sc)
  336. c.mu.Unlock()
  337. }
  338. func (c *channelMap) addListenSocket(id int64, ls *listenSocket, pid int64) {
  339. c.mu.Lock()
  340. ls.cm = c
  341. c.listenSockets[id] = ls
  342. c.findEntry(pid).addChild(id, ls)
  343. c.mu.Unlock()
  344. }
  345. func (c *channelMap) addNormalSocket(id int64, ns *normalSocket, pid int64) {
  346. c.mu.Lock()
  347. ns.cm = c
  348. c.normalSockets[id] = ns
  349. c.findEntry(pid).addChild(id, ns)
  350. c.mu.Unlock()
  351. }
  352. // removeEntry triggers the removal of an entry, which may not indeed delete the entry, if it has to
  353. // wait on the deletion of its children and until no other entity's channel trace references it.
  354. // It may lead to a chain of entry deletion. For example, deleting the last socket of a gracefully
  355. // shutting down server will lead to the server being also deleted.
  356. func (c *channelMap) removeEntry(id int64) {
  357. c.mu.Lock()
  358. c.findEntry(id).triggerDelete()
  359. c.mu.Unlock()
  360. }
  361. // c.mu must be held by the caller
  362. func (c *channelMap) decrTraceRefCount(id int64) {
  363. e := c.findEntry(id)
  364. if v, ok := e.(tracedChannel); ok {
  365. v.decrTraceRefCount()
  366. e.deleteSelfIfReady()
  367. }
  368. }
  369. // c.mu must be held by the caller.
  370. func (c *channelMap) findEntry(id int64) entry {
  371. var v entry
  372. var ok bool
  373. if v, ok = c.channels[id]; ok {
  374. return v
  375. }
  376. if v, ok = c.subChannels[id]; ok {
  377. return v
  378. }
  379. if v, ok = c.servers[id]; ok {
  380. return v
  381. }
  382. if v, ok = c.listenSockets[id]; ok {
  383. return v
  384. }
  385. if v, ok = c.normalSockets[id]; ok {
  386. return v
  387. }
  388. return &dummyEntry{idNotFound: id}
  389. }
  390. // c.mu must be held by the caller
  391. // deleteEntry simply deletes an entry from the channelMap. Before calling this
  392. // method, caller must check this entry is ready to be deleted, i.e removeEntry()
  393. // has been called on it, and no children still exist.
  394. // Conditionals are ordered by the expected frequency of deletion of each entity
  395. // type, in order to optimize performance.
  396. func (c *channelMap) deleteEntry(id int64) {
  397. var ok bool
  398. if _, ok = c.normalSockets[id]; ok {
  399. delete(c.normalSockets, id)
  400. return
  401. }
  402. if _, ok = c.subChannels[id]; ok {
  403. delete(c.subChannels, id)
  404. return
  405. }
  406. if _, ok = c.channels[id]; ok {
  407. delete(c.channels, id)
  408. delete(c.topLevelChannels, id)
  409. return
  410. }
  411. if _, ok = c.listenSockets[id]; ok {
  412. delete(c.listenSockets, id)
  413. return
  414. }
  415. if _, ok = c.servers[id]; ok {
  416. delete(c.servers, id)
  417. return
  418. }
  419. }
  420. func (c *channelMap) traceEvent(id int64, desc *TraceEventDesc) {
  421. c.mu.Lock()
  422. child := c.findEntry(id)
  423. childTC, ok := child.(tracedChannel)
  424. if !ok {
  425. c.mu.Unlock()
  426. return
  427. }
  428. childTC.getChannelTrace().append(&TraceEvent{Desc: desc.Desc, Severity: desc.Severity, Timestamp: time.Now()})
  429. if desc.Parent != nil {
  430. parent := c.findEntry(child.getParentID())
  431. var chanType RefChannelType
  432. switch child.(type) {
  433. case *channel:
  434. chanType = RefChannel
  435. case *subChannel:
  436. chanType = RefSubChannel
  437. }
  438. if parentTC, ok := parent.(tracedChannel); ok {
  439. parentTC.getChannelTrace().append(&TraceEvent{
  440. Desc: desc.Parent.Desc,
  441. Severity: desc.Parent.Severity,
  442. Timestamp: time.Now(),
  443. RefID: id,
  444. RefName: childTC.getRefName(),
  445. RefType: chanType,
  446. })
  447. childTC.incrTraceRefCount()
  448. }
  449. }
  450. c.mu.Unlock()
  451. }
  452. type int64Slice []int64
  453. func (s int64Slice) Len() int { return len(s) }
  454. func (s int64Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
  455. func (s int64Slice) Less(i, j int) bool { return s[i] < s[j] }
  456. func copyMap(m map[int64]string) map[int64]string {
  457. n := make(map[int64]string)
  458. for k, v := range m {
  459. n[k] = v
  460. }
  461. return n
  462. }
  463. func min(a, b int64) int64 {
  464. if a < b {
  465. return a
  466. }
  467. return b
  468. }
  469. func (c *channelMap) GetTopChannels(id int64, maxResults int64) ([]*ChannelMetric, bool) {
  470. if maxResults <= 0 {
  471. maxResults = EntryPerPage
  472. }
  473. c.mu.RLock()
  474. l := int64(len(c.topLevelChannels))
  475. ids := make([]int64, 0, l)
  476. cns := make([]*channel, 0, min(l, maxResults))
  477. for k := range c.topLevelChannels {
  478. ids = append(ids, k)
  479. }
  480. sort.Sort(int64Slice(ids))
  481. idx := sort.Search(len(ids), func(i int) bool { return ids[i] >= id })
  482. count := int64(0)
  483. var end bool
  484. var t []*ChannelMetric
  485. for i, v := range ids[idx:] {
  486. if count == maxResults {
  487. break
  488. }
  489. if cn, ok := c.channels[v]; ok {
  490. cns = append(cns, cn)
  491. t = append(t, &ChannelMetric{
  492. NestedChans: copyMap(cn.nestedChans),
  493. SubChans: copyMap(cn.subChans),
  494. })
  495. count++
  496. }
  497. if i == len(ids[idx:])-1 {
  498. end = true
  499. break
  500. }
  501. }
  502. c.mu.RUnlock()
  503. if count == 0 {
  504. end = true
  505. }
  506. for i, cn := range cns {
  507. t[i].ChannelData = cn.c.ChannelzMetric()
  508. t[i].ID = cn.id
  509. t[i].RefName = cn.refName
  510. t[i].Trace = cn.trace.dumpData()
  511. }
  512. return t, end
  513. }
  514. func (c *channelMap) GetServers(id, maxResults int64) ([]*ServerMetric, bool) {
  515. if maxResults <= 0 {
  516. maxResults = EntryPerPage
  517. }
  518. c.mu.RLock()
  519. l := int64(len(c.servers))
  520. ids := make([]int64, 0, l)
  521. ss := make([]*server, 0, min(l, maxResults))
  522. for k := range c.servers {
  523. ids = append(ids, k)
  524. }
  525. sort.Sort(int64Slice(ids))
  526. idx := sort.Search(len(ids), func(i int) bool { return ids[i] >= id })
  527. count := int64(0)
  528. var end bool
  529. var s []*ServerMetric
  530. for i, v := range ids[idx:] {
  531. if count == maxResults {
  532. break
  533. }
  534. if svr, ok := c.servers[v]; ok {
  535. ss = append(ss, svr)
  536. s = append(s, &ServerMetric{
  537. ListenSockets: copyMap(svr.listenSockets),
  538. })
  539. count++
  540. }
  541. if i == len(ids[idx:])-1 {
  542. end = true
  543. break
  544. }
  545. }
  546. c.mu.RUnlock()
  547. if count == 0 {
  548. end = true
  549. }
  550. for i, svr := range ss {
  551. s[i].ServerData = svr.s.ChannelzMetric()
  552. s[i].ID = svr.id
  553. s[i].RefName = svr.refName
  554. }
  555. return s, end
  556. }
  557. func (c *channelMap) GetServerSockets(id int64, startID int64, maxResults int64) ([]*SocketMetric, bool) {
  558. if maxResults <= 0 {
  559. maxResults = EntryPerPage
  560. }
  561. var svr *server
  562. var ok bool
  563. c.mu.RLock()
  564. if svr, ok = c.servers[id]; !ok {
  565. // server with id doesn't exist.
  566. c.mu.RUnlock()
  567. return nil, true
  568. }
  569. svrskts := svr.sockets
  570. l := int64(len(svrskts))
  571. ids := make([]int64, 0, l)
  572. sks := make([]*normalSocket, 0, min(l, maxResults))
  573. for k := range svrskts {
  574. ids = append(ids, k)
  575. }
  576. sort.Sort(int64Slice(ids))
  577. idx := sort.Search(len(ids), func(i int) bool { return ids[i] >= startID })
  578. count := int64(0)
  579. var end bool
  580. for i, v := range ids[idx:] {
  581. if count == maxResults {
  582. break
  583. }
  584. if ns, ok := c.normalSockets[v]; ok {
  585. sks = append(sks, ns)
  586. count++
  587. }
  588. if i == len(ids[idx:])-1 {
  589. end = true
  590. break
  591. }
  592. }
  593. c.mu.RUnlock()
  594. if count == 0 {
  595. end = true
  596. }
  597. s := make([]*SocketMetric, 0, len(sks))
  598. for _, ns := range sks {
  599. sm := &SocketMetric{}
  600. sm.SocketData = ns.s.ChannelzMetric()
  601. sm.ID = ns.id
  602. sm.RefName = ns.refName
  603. s = append(s, sm)
  604. }
  605. return s, end
  606. }
  607. func (c *channelMap) GetChannel(id int64) *ChannelMetric {
  608. cm := &ChannelMetric{}
  609. var cn *channel
  610. var ok bool
  611. c.mu.RLock()
  612. if cn, ok = c.channels[id]; !ok {
  613. // channel with id doesn't exist.
  614. c.mu.RUnlock()
  615. return nil
  616. }
  617. cm.NestedChans = copyMap(cn.nestedChans)
  618. cm.SubChans = copyMap(cn.subChans)
  619. // cn.c can be set to &dummyChannel{} when deleteSelfFromMap is called. Save a copy of cn.c when
  620. // holding the lock to prevent potential data race.
  621. chanCopy := cn.c
  622. c.mu.RUnlock()
  623. cm.ChannelData = chanCopy.ChannelzMetric()
  624. cm.ID = cn.id
  625. cm.RefName = cn.refName
  626. cm.Trace = cn.trace.dumpData()
  627. return cm
  628. }
  629. func (c *channelMap) GetSubChannel(id int64) *SubChannelMetric {
  630. cm := &SubChannelMetric{}
  631. var sc *subChannel
  632. var ok bool
  633. c.mu.RLock()
  634. if sc, ok = c.subChannels[id]; !ok {
  635. // subchannel with id doesn't exist.
  636. c.mu.RUnlock()
  637. return nil
  638. }
  639. cm.Sockets = copyMap(sc.sockets)
  640. // sc.c can be set to &dummyChannel{} when deleteSelfFromMap is called. Save a copy of sc.c when
  641. // holding the lock to prevent potential data race.
  642. chanCopy := sc.c
  643. c.mu.RUnlock()
  644. cm.ChannelData = chanCopy.ChannelzMetric()
  645. cm.ID = sc.id
  646. cm.RefName = sc.refName
  647. cm.Trace = sc.trace.dumpData()
  648. return cm
  649. }
  650. func (c *channelMap) GetSocket(id int64) *SocketMetric {
  651. sm := &SocketMetric{}
  652. c.mu.RLock()
  653. if ls, ok := c.listenSockets[id]; ok {
  654. c.mu.RUnlock()
  655. sm.SocketData = ls.s.ChannelzMetric()
  656. sm.ID = ls.id
  657. sm.RefName = ls.refName
  658. return sm
  659. }
  660. if ns, ok := c.normalSockets[id]; ok {
  661. c.mu.RUnlock()
  662. sm.SocketData = ns.s.ChannelzMetric()
  663. sm.ID = ns.id
  664. sm.RefName = ns.refName
  665. return sm
  666. }
  667. c.mu.RUnlock()
  668. return nil
  669. }
  670. func (c *channelMap) GetServer(id int64) *ServerMetric {
  671. sm := &ServerMetric{}
  672. var svr *server
  673. var ok bool
  674. c.mu.RLock()
  675. if svr, ok = c.servers[id]; !ok {
  676. c.mu.RUnlock()
  677. return nil
  678. }
  679. sm.ListenSockets = copyMap(svr.listenSockets)
  680. c.mu.RUnlock()
  681. sm.ID = svr.id
  682. sm.RefName = svr.refName
  683. sm.ServerData = svr.s.ChannelzMetric()
  684. return sm
  685. }
  686. // IDGenerator is an incrementing atomic that tracks IDs for channelz entities.
  687. type IDGenerator struct {
  688. id int64
  689. }
  690. // Reset resets the generated ID back to zero. Should only be used at
  691. // initialization or by tests sensitive to the ID number.
  692. func (i *IDGenerator) Reset() {
  693. atomic.StoreInt64(&i.id, 0)
  694. }
  695. func (i *IDGenerator) genID() int64 {
  696. return atomic.AddInt64(&i.id, 1)
  697. }