PacketImpl.cc
Go to the documentation of this file.
1 //
2 // Copyright (c) 2020 Fraunhofer Institute for Applied Information Technology (FIT)
3 // Network Research Group (NET)
4 // Schloss Birlinghoven, 53754 Sankt Augustin, GERMANY
5 // Contact: support@wiback.org
6 //
7 // This file is part of the SENF code tree.
8 // It is licensed under the 3-clause BSD License (aka New BSD License).
9 // See LICENSE.txt in the top level directory for details or visit
10 // https://opensource.org/licenses/BSD-3-Clause
11 //
12 
13 
17 #include "PacketImpl.ih"
18 
19 // Custom includes
20 #include <iterator>
21 #include <map>
22 #include <set>
23 #include <string>
24 #include <boost/format.hpp>
25 #include <senf/Utils/String.hh>
26 #include "Packets.hh"
27 
28 #ifndef SENF_DISABLE_CONSOLE
29 #include <senf/Utils/Console.hh>
30 #endif
31 
32 //#include "PacketImpl.mpp"
33 #define prefix_
34 //-/////////////////////////////////////////////////////////////////////////////////////////////////
35 
36 //-/////////////////////////////////////////////////////////////////////////////////////////////////
37 // senf::detail::PacketImpl
38 
39 #ifdef SENF_DEBUG
40 senf::detail::PacketImpl::size_type senf::detail::PacketImpl::maxPreallocHigh_ (0);
41 #ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
42 senf::detail::PacketImpl::size_type senf::detail::PacketImpl::maxPreallocHeapcount_ (0);
43 #endif
44 #endif
45 
46 #ifndef SENF_DISABLE_CONSOLE
47 
48 namespace {
49 
50  struct ConsoleDirRegistration
51  {
52  ConsoleDirRegistration()
53  {
54  namespace fty = senf::console::factory;
55 
57  .add("memoryStatus",
58  fty::Command(&ConsoleDirRegistration::memoryStatus));
60  .add("dumpAnnotationRegistry",
61  fty::Command(&senf::dumpPacketAnnotationRegistry));
63  .add("pktHandleCount",
64  fty::Command(&ConsoleDirRegistration::pktCount));
65  }
66 
67  static void memoryStatus(std::ostream & os)
68  {
69  os << "SENF_PACKET_PREALLOC_INTERPRETERS = " << SENF_PACKET_PREALLOC_INTERPRETERS << "\n"
70 #ifdef SENF_PACKET_NO_HEAP_INTERPRETERS
71  << "SENF_PACKET_NO_HEAP_INTERPRETERS\n"
72 #endif
73 #ifdef SENF_PACKET_ALTERNATIVE_PREALLOC
74  << "SENF_PACKET_ALTERNATIVE_PREALLOC\n"
75 #endif
76 #ifdef SENF_DEBUG
77  << "maxPreallocHigh = " << senf::detail::PacketImpl::maxPreallocHigh() << "\n"
78 #ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
79  << "maxPreallocHeapcount = " << senf::detail::PacketImpl::maxPreallocHeapcount() << "\n"
80 #endif
81  << "# of live Packets = " << senf::pool_alloc_mixin<senf::detail::PacketImpl>::allocCounter() << "\n"
82 #endif
83  ;
84  }
85 
86  static void pktCount(std::ostream & os)
87  {
88  os << senf::Packet::pktCount() << std::endl;
89  }
90 
91  static ConsoleDirRegistration instance_;
92  };
93 
94  ConsoleDirRegistration ConsoleDirRegistration::instance_;
95 
96 }
97 
98 #endif
99 
100 #ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
101 
102 prefix_ void senf::detail::PacketImpl::destroySelf()
103 {
104  // We increment refcount_ to ensure, release() won't call delete again
105  ++refcount_;
106  interpreter_list::iterator b (interpreters_.begin());
107  interpreter_list::iterator e (interpreters_.end());
108  while (b!=e) {
110  PacketInterpreterBase * p (&(*i));
111  interpreters_.erase(i);
112  p->releaseImpl();
113  if (preallocHeapcount_ == 0)
114  break;
115  }
116 }
117 
118 #endif
119 
121 {
122  SENF_ASSERT(refcount_ >= 1, "Internal failure: Releasing dead PacketImpl ??");
123  // uah ... we need to be extremely careful here. If refcount_ is 1, we want to commit suicide,
124  // however the destructor will remove all PacketInterpreters from the list and will thereby
125  // decrement refcount -> only decrement refcount_ when *not* calling delete (otherwise
126  // the assert above will fail)
127  if (refcount_ == 1) {
128  delete this;
129  return true;
130  } else {
131  -- refcount_;
132  return false;
133  }
134 }
135 
136 // interpreter chain
137 
139 {
140  os << "PacketImpl @" << this << "-" << static_cast<void*>(static_cast<byte*>(static_cast<void*>(this+1))-1)
141  << " refcount=" << refcount()
142 #ifdef SENF_PACKET_ALTERNATIVE_PREALLOC
143  << " preallocHigh=" << preallocHigh_
144 #endif
145 #ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
146  << " preallocHeapcount=" << preallocHeapcount_
147 #endif
148  << std::endl;
149  std::set<void*> used;
150  for (interpreter_list::iterator i (interpreters_.begin()), i_end (interpreters_.end());
151  i != i_end; ++i)
152  used.insert(&(*i));
153  std::set<void*> free;
154  {
155  PreallocSlot * p (preallocFree_);
156 #ifdef SENF_PACKET_ALTERNATIVE_PREALLOC
157  while (p)
158 #else
159  while (p != prealloc_ + SENF_PACKET_PREALLOC_INTERPRETERS)
160 #endif
161  {
162  free.insert(p);
163 #ifdef SENF_PACKET_ALTERNATIVE_PREALLOC
164  p = p->nextFree_;
165 #else
166  p += p->nextOffset_ + 1;
167 #endif
168  }
169  }
170  for (unsigned i (0); i <
171 #ifdef SENF_PACKET_ALTERNATIVE_PREALLOC
172  preallocHigh_
173 #else
174  SENF_PACKET_PREALLOC_INTERPRETERS
175 #endif
176  ; ++i) {
177  void * p (&(prealloc_[i]));
178  if (free.count(p))
179  os << " free @" << p << std::endl;
180  else if (! used.count(p))
181  os << " unlinked @" << p
182  << " refcount=" << static_cast<PacketInterpreterBase*>(p)->refcount() << std::endl;
183  }
184 }
185 
187 {
188  interpreters_.push_back(*p);
189  p->assignImpl(this);
190 }
191 
193 {
194  interpreters_.push_front(*p);
195  p->assignImpl(this);
196 }
197 
199  PacketInterpreterBase * before)
200 {
201  interpreter_list::iterator i (interpreter_list::s_iterator_to(*before));
202  interpreters_.insert(i, *p);
203  p->assignImpl(this);
204 }
205 
206 // Data container
207 
209 {
210  PacketInterpreterBase * n (next(static_cast<PacketInterpreterBase*>(self)));
211  if (n)
212  truncateInterpreters(n);
213  iterator first (boost::next(begin(),self->begin_));
214  data_.erase(first, boost::next(begin(),self->end_));
215  updateIterators(self,self->begin_,-self->size());
216 }
217 
218 // private members
219 
220 prefix_ void senf::detail::PacketImpl::eraseInterpreters(interpreter_list::iterator b,
222 {
223  while (b!=e) {
225  PacketInterpreterBase * p (&(*i));
226  interpreters_.erase(i);
227  p->releaseImpl();
228  }
229 }
230 
231 prefix_ void senf::detail::PacketImpl::updateIterators(PacketData * self, difference_type pos,
232  difference_type n)
233 {
234  // I hate to change the PacketData representation from here, I would have preferred to let
235  // PacketData have authority over this but trying that just get's to convoluted so I choose the
236  // simple solution and made PacketImpl a friend of PacketData.
237 
238  interpreter_list::iterator i (interpreters_.begin());
239 
240  // There are three types of packets
241  // a) Those which come before 'self' in the interpreter chain
242  // b) 'self'
243  // c) Those that come afterwards
244  // For a), the change must be inside the packet since 'self' must be within those packets
245  // For b), the change must also be within since that's the packet we are changing
246  // For c), the change must be outside the packet (we don't allow an upper packet to mess with
247  // the the data owned by a packet further down the chain). It can be before or after the
248  // packet.
249 
250  // a)
251  for (; &(*i) != static_cast<PacketInterpreterBase*>(self); ++i) i->end_ += n;
252 
253  // b)
254  i->end_ += n;
255 
256  // c)
257  interpreter_list::iterator const i_end (interpreters_.end());
258  if (++i != i_end)
259  if (pos <= difference_type(i->begin_))
260  // pos is before the packet, it must then be before all further packets ...
261  for (; i != i_end; ++i) {
262  i->begin_ += n;
263  i->end_ += n;
264  }
265  // else pos is after the packet and we don't need to change anything ...
266 }
267 
268 // Annotations
269 
271 {
272  for (AnnotationRegistry::iterator i (AnnotationRegistry::instance().begin());
273  i != AnnotationRegistry::instance().end(); ++i) {
274  void * antn (annotation(*i));
275  if (antn)
276  AnnotationRegistry::instance().dump(*i, os, antn);
277  }
278 }
279 
281 {
282  ::memset(simpleAnnotations_, 0, sizeof(simpleAnnotations_));
283 #ifndef SENF_PACKET_NO_COMPLEX_ANNOTATIONS
284  complexAnnotations_.clear();
285 #endif
286 }
287 
289 {
290  std::copy(&other.simpleAnnotations_[0], &other.simpleAnnotations_[0] +
291  sizeof(simpleAnnotations_)/sizeof(simpleAnnotations_[0]), simpleAnnotations_);
292 #ifndef SENF_PACKET_NO_COMPLEX_ANNOTATIONS
293  complexAnnotations_.assign(
294  other.complexAnnotations_.begin(), other.complexAnnotations_.end());
295 #endif
296 }
297 
298 #ifndef SENF_PACKET_NO_COMPLEX_ANNOTATIONS
299 
300 prefix_ void * senf::detail::PacketImpl::complexAnnotation(AnnotationRegistry::key_type key)
301 {
302  SENF_ASSERT( key < 0, "complexAnnotation called with invalid key");
303  return (ComplexAnnotations::size_type(-key-1) >= complexAnnotations_.size()
304  || complexAnnotations_.is_null(-key-1))
305  ? 0 : complexAnnotations_[-key-1].get();
306 }
307 
308 #endif
309 
310 //-/////////////////////////////////////////////////////////////////////////////////////////////////
311 // senf::detail::AnnotationRegistry
312 
313 prefix_ void senf::detail::AnnotationRegistry::dump(key_type key, std::ostream & os,
314  void * annotation)
315  const
316 {
317  Registry::const_iterator i (registry_.find(key));
318  if (i != registry_.end()) {
319  os << fieldName(i->second->v_name());
320  i->second->v_dump(os, annotation);
321  os << "\n";
322  }
323 }
324 
325 prefix_ void senf::detail::AnnotationRegistry::dumpRegistrations(std::ostream & os)
326  const
327 {
328  boost::format fmt ("%-56.56s %-4.4s %-7.7s %5d\n");
329  os << "SENF_PACKET_ANNOTATION_SLOTS = " << SENF_PACKET_ANNOTATION_SLOTS << "\n"
330  << "SENF_PACKET_ANNOTATION_SLOTSIZE = " << SENF_PACKET_ANNOTATION_SLOTSIZE << "\n";
331 #ifdef SENF_PACKET_NO_COMPLEX_ANNOTATIONS
332  os << "SENF_PACKET_NO_COMPLEX_ANNOTATIONS defined\n";
333 #endif
334  os << fmt % "TYPE" % "FAST" % "COMPLEX" % "SIZE";
335 
336  for (Index::const_iterator i (index_.begin()), i_end (index_.end()); i != i_end; ++i) {
337  key_type key (i->second);
338  std::string nm (i->first);
339  if (nm.size() > 56) nm.erase(nm.begin(), nm.begin()+nm.size()-32);
340  os << fmt
341  % nm
342  % (key >= 0 ? "yes" : "no")
343  % (isComplex(key) ? "yes" : "no")
344  % size(key);
345  }
346 }
347 
349 {
350  senf::detail::AnnotationRegistry::instance().dumpRegistrations(os);
351 }
352 
353 //-/////////////////////////////////////////////////////////////////////////////////////////////////
354 #undef prefix_
355 //#include "PacketImpl.mpp"
356 
357 
358 // Local Variables:
359 // mode: c++
360 // fill-column: 100
361 // c-file-style: "senf"
362 // indent-tabs-mode: nil
363 // ispell-local-dictionary: "american"
364 // compile-command: "scons -u test"
365 // comment-column: 40
366 // End:
void memDebug(std::ostream &os)
Definition: PacketImpl.cc:138
void copy(ListParser< ListPolicy > const &listParser, OutputIterator result)
Definition: algorithms.hh:58
senf::detail::packet::byte byte
Definition: PacketImpl.hh:117
senf::detail::packet::difference_type difference_type
Definition: PacketImpl.hh:120
static std::int32_t const & pktCount()
Definition: Packet.cc:30
void dumpAnnotations(std::ostream &os)
Definition: PacketImpl.cc:270
std::string fieldName(std::string const &s)
Definition: DumpFormat.cc:28
#define prefix_
Definition: PacketImpl.cc:33
Packets public header.
void prependInterpreter(PacketInterpreterBase *p)
Definition: PacketImpl.cc:192
Internal: Base packet interpreter class.
senf::detail::packet::iterator iterator
Definition: PacketImpl.hh:122
console::ScopedDirectory & packetConsoleDir()
raw_container::const_iterator const_iterator
Definition: PacketTypes.hh:70
Packet data STL-sequence view.
Definition: PacketData.hh:61
raw_container::size_type size_type
Definition: PacketTypes.hh:66
Internal: Packet data storage.
Definition: PacketImpl.hh:112
raw_container::iterator iterator
Definition: PacketTypes.hh:69
static size_type maxPreallocHigh()
senf::detail::packet::size_type size_type
Definition: PacketImpl.hh:119
#define SENF_ASSERT(x, comment)
raw_container::difference_type difference_type
Definition: PacketTypes.hh:67
void assignAnnotations(PacketImpl const &other)
Definition: PacketImpl.cc:288
static size_type maxPreallocHeapcount()
void dumpPacketAnnotationRegistry(std::ostream &os)
Dump annotation registry debug information.
Definition: PacketImpl.cc:348
void appendInterpreter(PacketInterpreterBase *p)
Definition: PacketImpl.cc:186
void clear(PacketData *self)
Definition: PacketImpl.cc:208
NodeType & add(std::string const &name, boost::shared_ptr< NodeType > node)