]> git.ipfire.org Git - thirdparty/squid.git/blob - src/sbuf/MemBlob.cc
5020b97099b3facced4b478d2cd6e1c6c7aa856b
[thirdparty/squid.git] / src / sbuf / MemBlob.cc
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