servlib/bundling/Bundle.h
changeset 0 2b3e5ec03512
child 11 4dd7e0cb11a7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/servlib/bundling/Bundle.h	Thu Apr 21 14:57:45 2011 +0100
@@ -0,0 +1,362 @@
+/*
+ *    Copyright 2004-2006 Intel Corporation
+ * 
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ * 
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#ifndef _BUNDLE_H_
+#define _BUNDLE_H_
+
+#include <sys/time.h>
+
+#include <oasys/debug/Formatter.h>
+#include <oasys/debug/DebugUtils.h>
+#include <oasys/serialize/Serialize.h>
+#include <oasys/thread/SpinLock.h>
+#include <oasys/util/StringBuffer.h>
+
+#include "BlockInfo.h"
+#include "BundleMappings.h"
+#include "BundlePayload.h"
+#include "BundleTimestamp.h"
+#include "CustodyTimer.h"
+#include "ForwardingLog.h"
+#include "MetadataBlock.h"
+#include "SequenceID.h"
+#include "naming/EndpointID.h"
+
+namespace dtn {
+
+class BundleList;
+class BundleStore;
+class ExpirationTimer;
+class SQLBundleStore;
+
+/**
+ * The internal representation of a bundle.
+ *
+ * Bundles are reference counted, with references generally
+ * correlating one-to-one with each BundleList on which the Bundle
+ * resides.
+ *
+ * However, although the push() methods of the BundleList always add a
+ * reference and a backpointer to the bundle, the pop() methods do not
+ * decremente the reference count. This means that the caller must
+ * explicitly remove it when done with the bundle.
+ *
+ * Note that delref() will delete the Bundle when the reference count
+ * reaches zero, so care must be taken to never use the pointer after
+ * that point.
+ *
+ * The Bundle class maintains a set of back-pointers to each BundleList
+ * it is contained on, and list addition/removal methods maintain the
+ * invariant that the entiries of this set correlate exactly with the
+ * list pointers.
+ */
+class Bundle : public oasys::Formatter, public oasys::SerializableObject
+{
+public:
+    /**
+     * Default constructor to create an empty bundle, initializing all
+     * fields to defaults and allocating a new bundle id.
+     *
+     * For temporary bundles, the location can be set to MEMORY, and
+     * to support the simulator, the location can be overridden to be
+     * BundlePayload::NODATA.
+     */
+    Bundle(BundlePayload::location_t location = BundlePayload::DISK);
+
+    /**
+     * Constructor when re-reading the database.
+     */
+    Bundle(const oasys::Builder&);
+
+    /**
+     * Bundle destructor.
+     */
+    virtual ~Bundle();
+
+    /**
+     * Copy the metadata from one bundle to another (used in
+     * fragmentation).
+     */
+    void copy_metadata(Bundle* new_bundle) const;
+
+    /**
+     * Virtual from formatter.
+     */
+    int format(char* buf, size_t sz) const;
+    
+    /**
+     * Virtual from formatter.
+     */
+    void format_verbose(oasys::StringBuffer* buf);
+    
+    /**
+     * Virtual from SerializableObject
+     */
+    void serialize(oasys::SerializeAction* a);
+
+    /**
+     * Hook for the generic durable table implementation to know what
+     * the key is for the database.
+     */
+    u_int32_t durable_key() { return bundleid_; }
+
+    /**
+     * Hook for the bundle store implementation to count the storage
+     * impact of this bundle. Currently just returns the payload
+     * length but should be extended to include the metadata as well.
+     */
+    size_t durable_size() { return payload_.length(); }
+    
+    /**
+     * Return the bundle's reference count, corresponding to the
+     * number of entries in the mappings set, i.e. the number of
+     * BundleLists that have a reference to this bundle, as well as
+     * any other scopes that are processing the bundle.
+     */
+    int refcount() { return refcount_; }
+
+    /**
+     * Bump up the reference count. Parameters are used for logging.
+     *
+     * @return the new reference count
+     */
+    int add_ref(const char* what1, const char* what2 = "");
+
+    /**
+     * Decrement the reference count. Parameters are used for logging.
+     *
+     * If the reference count becomes zero, the bundle is deleted.
+     *
+     * @return the new reference count
+     */
+    int del_ref(const char* what1, const char* what2 = "");
+
+    /**
+     * Return the number of mappings for this bundle.
+     */
+    size_t num_mappings();
+
+    /**
+     * Return a pointer to the mappings. Requires that the bundle be
+     * locked.
+     */
+    BundleMappings* mappings();
+
+    /**
+     * Return true if the bundle is on the given list. 
+     */
+    bool is_queued_on(const BundleList* l);
+
+    /**
+     * Validate the bundle's fields
+     */
+    bool validate(oasys::StringBuffer* errbuf);
+
+    /**
+     * True if any return receipt fields are set
+     */
+    bool receipt_requested() const
+    {
+        return (receive_rcpt_ || custody_rcpt_ || forward_rcpt_ ||
+                delivery_rcpt_ || deletion_rcpt_);
+    }
+    
+    /**
+     * Values for the bundle priority field.
+     */
+    typedef enum {
+        COS_INVALID   = -1, 		///< invalid
+        COS_BULK      = 0, 		///< lowest priority
+        COS_NORMAL    = 1, 		///< regular priority
+        COS_EXPEDITED = 2, 		///< important
+        COS_RESERVED  = 3  		///< TBD
+    } priority_values_t;
+
+    /**
+     * Pretty printer function for bundle_priority_t.
+     */
+    static const char* prioritytoa(u_int8_t priority) {
+        switch (priority) {
+        case COS_BULK: 		return "BULK";
+        case COS_NORMAL: 	return "NORMAL";
+        case COS_EXPEDITED: 	return "EXPEDITED";
+        default:		return "_UNKNOWN_PRIORITY_";
+        }
+    }
+
+    /// @{ Accessors
+    u_int32_t         bundleid()          const { return bundleid_; }
+    oasys::Lock*      lock()              const { return &lock_; }
+    bool              expired()           const { return expiration_timer_ == NULL; }
+    const EndpointID& source()            const { return source_; }
+    const EndpointID& dest()              const { return dest_; }
+    const EndpointID& custodian()         const { return custodian_; }
+    const EndpointID& replyto()           const { return replyto_; }
+    const EndpointID& prevhop()           const { return prevhop_; }
+    bool              is_fragment()       const { return is_fragment_; }
+    bool              is_admin()          const { return is_admin_; }
+    bool              do_not_fragment()   const { return do_not_fragment_; }
+    bool              custody_requested() const { return custody_requested_; }
+    bool              singleton_dest()    const { return singleton_dest_; }
+    u_int8_t          priority()          const { return priority_; }
+    bool              receive_rcpt()      const { return receive_rcpt_; }
+    bool              custody_rcpt()      const { return custody_rcpt_; }
+    bool              forward_rcpt()      const { return forward_rcpt_; }
+    bool              delivery_rcpt()     const { return delivery_rcpt_; }
+    bool              deletion_rcpt()     const { return deletion_rcpt_; }
+    bool              app_acked_rcpt()    const { return app_acked_rcpt_; }
+    u_int64_t         expiration()        const { return expiration_; }
+    u_int32_t         frag_offset()       const { return frag_offset_; }
+    u_int32_t         orig_length()       const { return orig_length_; }
+    bool              in_datastore()      const { return in_datastore_; }
+    bool              local_custody()     const { return local_custody_; }
+    const std::string& owner()            const { return owner_; }
+    bool              fragmented_incoming() const { return fragmented_incoming_; }
+    const SequenceID& sequence_id()       const { return sequence_id_; }
+    const SequenceID& obsoletes_id()      const { return obsoletes_id_; }
+    const EndpointID& session_eid()       const { return session_eid_; }
+    u_int8_t          session_flags()     const { return session_flags_; }
+    const BundlePayload& payload()        const { return payload_; }
+    const ForwardingLog* fwdlog()         const { return &fwdlog_; }
+    const BundleTimestamp& creation_ts()  const { return creation_ts_; }
+    const BundleTimestamp& extended_id()  const { return extended_id_; }
+    const BlockInfoVec& recv_blocks()     const { return recv_blocks_; }
+    const MetadataVec& recv_metadata()    const { return recv_metadata_; }
+    const LinkMetadataSet& generated_metadata() const { return generated_metadata_; }
+    /// @}
+
+    /// @{ Setters and mutable accessors
+    EndpointID* mutable_source()       { return &source_; }
+    EndpointID* mutable_dest()         { return &dest_; }
+    EndpointID* mutable_replyto()      { return &replyto_; }
+    EndpointID* mutable_custodian()    { return &custodian_; }
+    EndpointID* mutable_prevhop()      { return &prevhop_; }
+    void set_is_fragment(bool t)       { is_fragment_ = t; }
+    void set_is_admin(bool t)          { is_admin_ = t; }
+    void set_do_not_fragment(bool t)   { do_not_fragment_ = t; }
+    void set_custody_requested(bool t) { custody_requested_ = t; }
+    void set_singleton_dest(bool t)    { singleton_dest_ = t; }
+    void set_priority(u_int8_t p)      { priority_ = p; }
+    void set_receive_rcpt(bool t)      { receive_rcpt_ = t; }
+    void set_custody_rcpt(bool t)      { custody_rcpt_ = t; }
+    void set_forward_rcpt(bool t)      { forward_rcpt_ = t; }
+    void set_delivery_rcpt(bool t)     { delivery_rcpt_ = t; }
+    void set_deletion_rcpt(bool t)     { deletion_rcpt_ = t; }
+    void set_app_acked_rcpt(bool t)    { app_acked_rcpt_ = t; }
+    void set_expiration(u_int64_t e)   { expiration_ = e; }
+    void set_frag_offset(u_int32_t o)  { frag_offset_ = o; }
+    void set_orig_length(u_int32_t l)  { orig_length_ = l; }
+    void set_in_datastore(bool t)      { in_datastore_ = t; }
+    void set_local_custody(bool t)     { local_custody_ = t; }
+    void set_owner(const std::string& s) { owner_ = s; }
+    void set_fragmented_incoming(bool t) { fragmented_incoming_ = t; }
+    void set_creation_ts(const BundleTimestamp& ts) { creation_ts_ = ts; }
+    SequenceID* mutable_sequence_id()  { return &sequence_id_; }
+    SequenceID* mutable_obsoletes_id() { return &obsoletes_id_; }
+    EndpointID* mutable_session_eid()  { return &session_eid_; }
+    void set_session_flags(u_int8_t f) { session_flags_ = f; }
+    void test_set_bundleid(u_int32_t id) { bundleid_ = id; }
+    BundlePayload*   mutable_payload() { return &payload_; }
+    ForwardingLog*   fwdlog()          { return &fwdlog_; }
+    ExpirationTimer* expiration_timer(){ return expiration_timer_; }
+    CustodyTimerVec* custody_timers()  { return &custody_timers_; }
+    BlockInfoVec*    api_blocks()      { return &api_blocks_; }
+    LinkBlockSet*    xmit_blocks()     { return &xmit_blocks_; }
+    BlockInfoVec*    mutable_recv_blocks() { return &recv_blocks_; }
+    MetadataVec*     mutable_recv_metadata() { return &recv_metadata_; }
+    LinkMetadataSet* mutable_generated_metadata() {
+        return &generated_metadata_;
+    }
+    void set_expiration_timer(ExpirationTimer* e) {
+        expiration_timer_ = e;
+    }
+    /// @}
+    
+private:
+    /*
+     * Bundle data fields that correspond to data transferred between
+     * nodes according to the bundle protocol.
+     */
+    EndpointID source_;		///< Source eid
+    EndpointID dest_;		///< Destination eid
+    EndpointID custodian_;	///< Current custodian eid
+    EndpointID replyto_;	///< Reply-To eid
+    EndpointID prevhop_;	///< Previous hop eid
+    bool is_fragment_;		///< Fragmentary Bundle
+    bool is_admin_;		///< Administrative record bundle
+    bool do_not_fragment_;	///< Bundle shouldn't be fragmented
+    bool custody_requested_;	///< Custody requested
+    bool singleton_dest_;	///< Destination endpoint is a singleton
+    u_int8_t priority_;		///< Bundle priority
+    bool receive_rcpt_;		///< Hop by hop reception receipt
+    bool custody_rcpt_;		///< Custody xfer reporting
+    bool forward_rcpt_;		///< Hop by hop forwarding reporting
+    bool delivery_rcpt_;	///< End-to-end delivery reporting
+    bool deletion_rcpt_;	///< Bundle deletion reporting
+    bool app_acked_rcpt_;	///< Acknowlege by application reporting
+    BundleTimestamp creation_ts_; ///< Creation timestamp
+    u_int64_t expiration_;	///< Bundle expiration time
+    u_int32_t frag_offset_;	///< Offset of fragment in original bundle
+    u_int32_t orig_length_;	///< Length of original bundle
+    SequenceID sequence_id_;	///< Sequence id vector
+    SequenceID obsoletes_id_;	///< Obsoletes id vector
+    EndpointID session_eid_;	///< Session eid
+    u_int8_t session_flags_;	///< Session flags
+    BundlePayload payload_;	///< Reference to the payload
+    
+    /*
+     * Internal fields and structures for managing the bundle that are
+     * not transmitted over the network.
+     */
+    u_int32_t bundleid_;	   ///< Local bundle identifier
+    mutable oasys::SpinLock lock_; ///< Lock for bundle data that can be
+                                   ///  updated by multiple threads
+    bool in_datastore_;		   ///< Is bundle in persistent store
+    bool local_custody_;	   ///< Does local node have custody
+    std::string owner_;            ///< Declared entity that "owns" this
+                                   ///  bundle, which could be empty
+    BundleTimestamp extended_id_;  ///< Identifier for external routers to
+                                   ///  refer to duplicate bundles
+    ForwardingLog fwdlog_;	   ///< Log of bundle forwarding records
+    ExpirationTimer* expiration_timer_;	///< The expiration timer
+    CustodyTimerVec custody_timers_; ///< Live custody timers for the bundle
+    bool fragmented_incoming_;     ///< Is the bundle an incoming reactive
+                                   ///  fragment
+
+    BlockInfoVec recv_blocks_;	   ///< BP blocks as arrived off the wire
+    BlockInfoVec api_blocks_;	   ///< BP blocks given from local API
+    LinkBlockSet xmit_blocks_;	   ///< Block vector for each link
+
+    MetadataVec     recv_metadata_;      ///< Metadata as arrived in bundle 
+    LinkMetadataSet generated_metadata_; ///< Metadata to be in bundle
+
+    BundleMappings mappings_;      ///< The set of BundleLists that
+                               	   ///  contain the Bundle.
+    
+    int  refcount_;		   ///< Bundle reference count
+    bool freed_;		   ///< Bit indicating whether a bundle
+                                   ///  free event has been posted
+
+    /**
+     * Initialization helper function.
+     */
+    void init(u_int32_t id);
+};
+
+
+} // namespace dtn
+
+#endif /* _BUNDLE_H_ */