get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/server/ring.go (about)

     1  // Copyright 2018 The NATS Authors
     2  // Licensed under the Apache License, Version 2.0 (the "License");
     3  // you may not use this file except in compliance with the License.
     4  // You may obtain a copy of the License at
     5  //
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package server
    15  
    16  // We wrap to hold onto optional items for /connz.
    17  type closedClient struct {
    18  	ConnInfo
    19  	subs []SubDetail
    20  	user string
    21  	acc  string
    22  }
    23  
    24  // Fixed sized ringbuffer for closed connections.
    25  type closedRingBuffer struct {
    26  	total uint64
    27  	conns []*closedClient
    28  }
    29  
    30  // Create a new ring buffer with at most max items.
    31  func newClosedRingBuffer(max int) *closedRingBuffer {
    32  	rb := &closedRingBuffer{}
    33  	rb.conns = make([]*closedClient, max)
    34  	return rb
    35  }
    36  
    37  // Adds in a new closed connection. If there is no more room,
    38  // remove the oldest.
    39  func (rb *closedRingBuffer) append(cc *closedClient) {
    40  	rb.conns[rb.next()] = cc
    41  	rb.total++
    42  }
    43  
    44  func (rb *closedRingBuffer) next() int {
    45  	return int(rb.total % uint64(cap(rb.conns)))
    46  }
    47  
    48  func (rb *closedRingBuffer) len() int {
    49  	if rb.total > uint64(cap(rb.conns)) {
    50  		return cap(rb.conns)
    51  	}
    52  	return int(rb.total)
    53  }
    54  
    55  func (rb *closedRingBuffer) totalConns() uint64 {
    56  	return rb.total
    57  }
    58  
    59  // This will return a sorted copy of the list which recipient can
    60  // modify. If the contents of the client itself need to be modified,
    61  // meaning swapping in any optional items, a copy should be made. We
    62  // could introduce a new lock and hold that but since we return this
    63  // list inside monitor which allows programatic access, we do not
    64  // know when it would be done.
    65  func (rb *closedRingBuffer) closedClients() []*closedClient {
    66  	dup := make([]*closedClient, rb.len())
    67  	head := rb.next()
    68  	if rb.total <= uint64(cap(rb.conns)) || head == 0 {
    69  		copy(dup, rb.conns[:rb.len()])
    70  	} else {
    71  		fp := rb.conns[head:]
    72  		sp := rb.conns[:head]
    73  		copy(dup, fp)
    74  		copy(dup[len(fp):], sp)
    75  	}
    76  	return dup
    77  }