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 }