]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (C) 1996-2025 The Squid Software Foundation and contributors | |
3 | * | |
4 | * Squid software is distributed under GPLv2+ license and includes | |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
7 | */ | |
8 | ||
9 | #include "squid.h" | |
10 | #include "base/TextException.h" | |
11 | #include "debug/Stream.h" | |
12 | #include "sbuf/MemBlob.h" | |
13 | #include "sbuf/Stats.h" | |
14 | ||
15 | #include <iostream> | |
16 | ||
17 | InstanceIdDefinitions(MemBlob, "blob"); | |
18 | ||
19 | /* MemBlobStats */ | |
20 | ||
21 | MemBlobStats& | |
22 | MemBlobStats::operator += (const MemBlobStats& s) | |
23 | { | |
24 | alloc+=s.alloc; | |
25 | live+=s.live; | |
26 | append+=s.append; | |
27 | liveBytes+=s.liveBytes; | |
28 | ||
29 | return *this; | |
30 | } | |
31 | ||
32 | std::ostream& | |
33 | MemBlobStats::dump(std::ostream &os) const | |
34 | { | |
35 | os << | |
36 | "MemBlob created: " << alloc << | |
37 | "\nMemBlob alive: " << live << | |
38 | "\nMemBlob append calls: " << append << | |
39 | "\nMemBlob currently allocated size: " << liveBytes << | |
40 | "\nlive MemBlob mean current allocation size: " << | |
41 | (static_cast<double>(liveBytes)/(live?live:1)) << std::endl; | |
42 | return os; | |
43 | } | |
44 | ||
45 | static auto & | |
46 | WriteableStats() | |
47 | { | |
48 | static const auto stats = new MemBlobStats(); | |
49 | return *stats; | |
50 | } | |
51 | ||
52 | const MemBlobStats & | |
53 | MemBlob::GetStats() | |
54 | { | |
55 | return WriteableStats(); | |
56 | } | |
57 | ||
58 | /* MemBlob */ | |
59 | ||
60 | MemBlob::MemBlob(const MemBlob::size_type reserveSize) : | |
61 | mem(nullptr), capacity(0), size(0) // will be set by memAlloc | |
62 | { | |
63 | debugs(MEMBLOB_DEBUGSECTION,9, "constructed, this=" | |
64 | << static_cast<void*>(this) << " id=" << id | |
65 | << " reserveSize=" << reserveSize); | |
66 | memAlloc(reserveSize); | |
67 | } | |
68 | ||
69 | MemBlob::MemBlob(const char *buffer, const MemBlob::size_type bufSize) : | |
70 | mem(nullptr), capacity(0), size(0) // will be set by memAlloc | |
71 | { | |
72 | debugs(MEMBLOB_DEBUGSECTION,9, "constructed, this=" | |
73 | << static_cast<void*>(this) << " id=" << id | |
74 | << " buffer=" << static_cast<const void*>(buffer) | |
75 | << " bufSize=" << bufSize); | |
76 | memAlloc(bufSize); | |
77 | append(buffer, bufSize); | |
78 | } | |
79 | ||
80 | MemBlob::~MemBlob() | |
81 | { | |
82 | if (mem || capacity) | |
83 | memFreeBuf(capacity, mem); | |
84 | auto &stats = WriteableStats(); | |
85 | stats.liveBytes -= capacity; | |
86 | --stats.live; | |
87 | SBufStats::RecordMemBlobSizeAtDestruct(capacity); | |
88 | ||
89 | debugs(MEMBLOB_DEBUGSECTION,9, "destructed, this=" | |
90 | << static_cast<void*>(this) << " id=" << id | |
91 | << " capacity=" << capacity | |
92 | << " size=" << size); | |
93 | } | |
94 | ||
95 | /** Allocate an available space area of at least minSize bytes in size. | |
96 | * Must be called by constructors and only by constructors. | |
97 | */ | |
98 | void | |
99 | MemBlob::memAlloc(const size_type minSize) | |
100 | { | |
101 | size_t actualAlloc = minSize; | |
102 | ||
103 | Must(!mem); | |
104 | mem = static_cast<char*>(memAllocBuf(actualAlloc, &actualAlloc)); | |
105 | Must(mem); | |
106 | ||
107 | capacity = actualAlloc; | |
108 | size = 0; | |
109 | debugs(MEMBLOB_DEBUGSECTION, 8, | |
110 | id << " memAlloc: requested=" << minSize << | |
111 | ", received=" << capacity); | |
112 | auto &stats = WriteableStats(); | |
113 | ++stats.live; | |
114 | ++stats.alloc; | |
115 | stats.liveBytes += capacity; | |
116 | } | |
117 | ||
118 | void | |
119 | MemBlob::appended(const size_type n) | |
120 | { | |
121 | Must(willFit(n)); | |
122 | size += n; | |
123 | ++WriteableStats().append; | |
124 | } | |
125 | ||
126 | void | |
127 | MemBlob::append(const char *source, const size_type n) | |
128 | { | |
129 | if (n > 0) { // appending zero bytes is allowed but only affects the stats | |
130 | Must(willFit(n)); | |
131 | Must(source); | |
132 | memmove(mem + size, source, n); | |
133 | size += n; | |
134 | } | |
135 | ++WriteableStats().append; | |
136 | } | |
137 | ||
138 | void | |
139 | MemBlob::syncSize(const size_type n) | |
140 | { | |
141 | debugs(MEMBLOB_DEBUGSECTION, 7, n << " was: " << size); | |
142 | Must(LockCount() <= 1); | |
143 | Must(n <= size); | |
144 | size = n; | |
145 | } | |
146 | ||
147 | void | |
148 | MemBlob::consume(const size_type rawN) | |
149 | { | |
150 | if (rawN && size) { | |
151 | Must(LockCount() <= 1); | |
152 | const auto n = std::min(rawN, size); | |
153 | size -= n; | |
154 | if (size) | |
155 | memmove(mem, mem + n, size); | |
156 | } | |
157 | } | |
158 | ||
159 | std::ostream& | |
160 | MemBlob::dump(std::ostream &os) const | |
161 | { | |
162 | os << "id @" << (void *)this | |
163 | << "mem:" << static_cast<void*>(mem) | |
164 | << ",capacity:" << capacity | |
165 | << ",size:" << size | |
166 | << ",refs:" << LockCount() << "; "; | |
167 | return os; | |
168 | } | |
169 |