From: g0dil Date: Thu, 2 Oct 2008 08:19:02 +0000 (+0000) Subject: Packets: More annotation documentation X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=226247520d34c4ec0539bfebf485d7cd46adcd70;p=senf.git Packets: More annotation documentation git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@922 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Packets/Mainpage.dox b/Packets/Mainpage.dox index 817a455..a164bd1 100644 --- a/Packets/Mainpage.dox +++ b/Packets/Mainpage.dox @@ -660,6 +660,77 @@ to define variants in a different way giving other names to the special members (\c has_\e name or \c init_\e name etc.). This must be documented with the composite or protocol parser which defines the variant. + + \section packet_usage_annotation Annotations + + Sometimes we need to store additional data with a packet. Data, which is not part of the packet + itself but gives us some information about the packet: A timestamp, the interface the packet was + received on or other processing related information. + + This type of information can be stored using the annotation interface. + + \code + struct Timestamp { + senf::ClockService::clock_t value; + }; + + senf::EthernetPacket packet (senf::EthernetPacket::create(senf::noinit)); + sock.read(packet.data(), 0u); + packet.annotation().value = senf::ClockService::now(); + \endcode + + In the same way, the annotation can be used later + + \code + if (senf::ClockService::now() - packet.annotation().value + > senf::ClockService::seconds(1)) { + // Ouch ... this packet is to old + // ... + } + \endcode + + It is very important to define a specific structure (or class) type for each type of + annotation. \e Never directly store a fundamental type as an annotation: The name of the type is + used to look up the annotation, so you can store only one annotation for each built-in type. \c + typedef does not help since \c typedef does not introduce new type names, it only defines an + alias. + + Of course, the annotation structure can be arbitrary. However, one very important caveat: If the + annotation is not a POD type, it needs to inherit from senf::ComplexAnnotation. A type is POD, + if it is really just a bunch of bytes: No (non-static) members, no constructor or destructor and + no base classes and all it's members must be POD too. So the following annotation is complex + since \c std::string is not POD + + \code + struct ReadInfo : senf::ComplexAnnotation + { + std::string interface; + senf::ClockService::clock_t timestamp; + }; + + // ... + + packet.annotation().interface = "eth0"; + packet.annotation().timestamp = senf::ClockService::now(); + + // Or store a reference to the annotation for easier access + + ReadInfo & info (packet.annotation()); + + if (info.interface == "eth0") { + // ... + } + \endcode + + You should use annotations economically: Every annotation type used in your program will + allocate an annotation slot in \e all packet data structures. So don't use hundreds of different + annotation types if this is not really necessary: Reuse annotation types where possible or + aggregate data into larger annotation structures. The best solution is to use annotations only + for a small number of packet specific informations. If you really need to manage a train-load of + data together with the packet consider some other way (e.g. place the packet into another class + which holds that data). + + \see senf::Packet::annotation() */ /** \page packet_new Defining new Packet types diff --git a/Packets/Packet.hh b/Packets/Packet.hh index e2e3c3f..124e8bd 100644 --- a/Packets/Packet.hh +++ b/Packets/Packet.hh @@ -358,6 +358,16 @@ namespace senf { used). Additionally, non-complex small annotations require no additional memory management (\c new / \c delete). + + \idea Pool the annotation vectors: In the destructor + swap the vector into a vector graveyard (swapping + two vectors is an O(1) no allocation operation). In + the constructor, if there is a vector in the + graveyard, swap it in from there. Of course, it + would be better to do away with the vector and just + allocate the space together with the packet but + that looks quite complicated to do ... especially + considering that the packetimpl itself uses a pool. */ ///@} diff --git a/senf.dict b/senf.dict index 1e116ff..b34ca69 100644 --- a/senf.dict +++ b/senf.dict @@ -62,6 +62,7 @@ checksumPresent CIDR classsenf ClientSocketHandle +ClockService cloneable CloneSource cmd @@ -72,6 +73,7 @@ CommandOverload CommandParser CommunicationPolicy CommunicationPolicyBase +ComplexAnnotation ConcretePacket conf config @@ -435,6 +437,7 @@ ratestuffer RawINetProtocol RawV rdynamic +ReadInfo refcount regex registerEvent