servlib/bundling/BlockInfo.cc
changeset 0 2b3e5ec03512
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/servlib/bundling/BlockInfo.cc	Thu Apr 21 14:57:45 2011 +0100
@@ -0,0 +1,283 @@
+/*
+ *    Copyright 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <dtn-config.h>
+#endif
+
+#include <oasys/debug/Log.h>
+#include "BlockInfo.h"
+#include "BlockProcessor.h"
+#include "APIBlockProcessor.h"
+#include "BundleProtocol.h"
+#include "SDNV.h"
+
+namespace dtn {
+
+//----------------------------------------------------------------------
+BlockInfo::BlockInfo(BlockProcessor* owner, const BlockInfo* source)
+    : SerializableObject(),
+      owner_(owner),
+      owner_type_(owner->block_type()),
+      source_(source),
+      eid_list_(),
+      contents_(),
+      locals_("BlockInfo constructor"),
+      data_length_(0),
+      data_offset_(0),
+      complete_(false),
+      reloaded_(false)
+{
+    eid_list_.clear();
+}
+
+//----------------------------------------------------------------------
+BlockInfo::BlockInfo(oasys::Builder& builder)
+    : SerializableObject(),
+      owner_(NULL),
+      owner_type_(0),
+      source_(NULL),
+      eid_list_(),
+      contents_(),
+      locals_("BlockInfo constructor"),
+      data_length_(0),
+      data_offset_(0),
+      complete_(false),
+      reloaded_(true)
+{
+    (void)builder;
+}
+
+//----------------------------------------------------------------------
+BlockInfo::BlockInfo(const BlockInfo &bi)
+    : SerializableObject(),
+      owner_(bi.owner_),
+      owner_type_(bi.owner_type_),
+      source_(bi.source_),
+      eid_list_(bi.eid_list_),
+      contents_(bi.contents_),
+      locals_(bi.locals_.object(), "BlockInfo copy constructor"),
+      data_length_(bi.data_length_),
+      data_offset_(bi.data_offset_),
+      complete_(bi.complete_),
+      reloaded_(bi.reloaded_)
+{
+}
+
+//----------------------------------------------------------------------
+BlockInfo::~BlockInfo()
+{
+}
+
+//----------------------------------------------------------------------
+void
+BlockInfo::set_locals(BP_Local* l)
+{
+    locals_ = l; 
+}
+
+//----------------------------------------------------------------------
+int
+BlockInfo::type() const
+{
+    if (owner_->block_type() == BundleProtocol::PRIMARY_BLOCK) {
+        return BundleProtocol::PRIMARY_BLOCK;
+    }
+
+    if (contents_.len() == 0) {
+        if (owner_ != NULL)
+            return owner_->block_type();
+        
+        return BundleProtocol::UNKNOWN_BLOCK;
+    }
+
+    u_char* data = contents_.buf();
+    (void)data;
+    if (owner_ != NULL)
+        ASSERT(contents_.buf()[0] == owner_->block_type()
+               || owner_->block_type() == BundleProtocol::UNKNOWN_BLOCK
+               || owner_->block_type() == BundleProtocol::API_EXTENSION_BLOCK);
+    return contents_.buf()[0];
+}
+
+//----------------------------------------------------------------------
+u_int64_t
+BlockInfo::flags() const
+{
+    if (type() == BundleProtocol::PRIMARY_BLOCK) {
+        return 0x0;
+    }
+    
+    u_int64_t flags;
+    int sdnv_size = SDNV::decode(contents_.buf() + 1, contents_.len() - 1, 
+                                 &flags);
+    ASSERT(sdnv_size > 0);
+    return flags;
+}
+
+//----------------------------------------------------------------------
+void
+BlockInfo::set_flag(u_int64_t flag)
+{
+    size_t sdnv_len = SDNV::encoding_len(flag);
+    ASSERT(contents_.len() >= 1 + sdnv_len);
+    SDNV::encode(flag, contents_.buf() + 1, sdnv_len);
+}
+
+//----------------------------------------------------------------------
+bool
+BlockInfo::last_block() const
+{
+    //check if it's too small to be flagged as last
+    if (contents_.len() < 2) {
+        return false;
+    }
+    
+    u_int64_t flag = flags();
+    return ((flag & BundleProtocol::BLOCK_FLAG_LAST_BLOCK) != 0);
+}
+
+//----------------------------------------------------------------------
+void
+BlockInfo::serialize(oasys::SerializeAction* a)
+{
+    a->process("owner_type", &owner_type_);
+    if (a->action_code() == oasys::Serialize::UNMARSHAL) {
+        // need to re-assign the owner
+        if (owner_type_ == BundleProtocol::API_EXTENSION_BLOCK) {
+            owner_ = APIBlockProcessor::instance();
+        } else {
+            owner_ = BundleProtocol::find_processor(owner_type_);
+        }
+    }
+
+    u_int32_t length = contents_.len();
+    a->process("length", &length);
+    
+    // when we're unserializing, we need to reserve space and set the
+    // length of the contents buffer before we write into it
+    if (a->action_code() == oasys::Serialize::UNMARSHAL) {
+        contents_.reserve(length);
+        contents_.set_len(length);
+    }
+
+    a->process("contents", contents_.buf(), length);
+    a->process("data_length", &data_length_);
+    a->process("data_offset", &data_offset_);
+    a->process("complete", &complete_);
+    a->process("eid_list", &eid_list_);
+}
+
+//----------------------------------------------------------------------
+BlockInfoVec::BlockInfoVec()
+    : oasys::SerializableVector<BlockInfo>(),
+      error_major_(0),
+      error_minor_(0),
+      error_debug_(0)
+{
+}
+
+//----------------------------------------------------------------------
+BlockInfo*
+BlockInfoVec::append_block(BlockProcessor* owner, const BlockInfo* source)
+{
+    push_back(BlockInfo(owner, source));
+    return &back();
+}
+
+//----------------------------------------------------------------------
+const BlockInfo*
+BlockInfoVec::find_block(u_int8_t type) const
+{
+    for (const_iterator iter = begin(); iter != end(); ++iter) {
+        if (iter->type() == type ||
+            iter->owner()->block_type() == type)
+        {
+            return &*iter;
+        }
+    }
+    return false;
+}
+
+//----------------------------------------------------------------------
+LinkBlockSet::Entry::Entry(const LinkRef& link)
+    : blocks_(NULL), link_(link.object(), "LinkBlockSet::Entry")
+{
+}
+
+//----------------------------------------------------------------------
+LinkBlockSet::~LinkBlockSet()
+{
+    for (iterator iter = entries_.begin();
+         iter != entries_.end();
+         ++iter)
+    {
+        delete iter->blocks_;
+        iter->blocks_ = 0;
+    }
+}
+
+//----------------------------------------------------------------------
+BlockInfoVec*
+LinkBlockSet::create_blocks(const LinkRef& link)
+{
+    oasys::ScopeLock l(lock_, "LinkBlockSet::create_blocks");
+    
+    ASSERT(find_blocks(link) == NULL);
+    entries_.push_back(Entry(link));
+    entries_.back().blocks_ = new BlockInfoVec();
+    return entries_.back().blocks_;
+}
+
+//----------------------------------------------------------------------
+BlockInfoVec*
+LinkBlockSet::find_blocks(const LinkRef& link) const
+{
+    oasys::ScopeLock l(lock_, "LinkBlockSet::find_blocks");
+    
+    for (const_iterator iter = entries_.begin();
+         iter != entries_.end();
+         ++iter)
+    {
+        if (iter->link_ == link) {
+            return iter->blocks_;
+        }
+    }
+    return NULL;
+}
+
+//----------------------------------------------------------------------
+void
+LinkBlockSet::delete_blocks(const LinkRef& link)
+{
+    oasys::ScopeLock l(lock_, "LinkBlockSet::delete_blocks");
+    
+    for (iterator iter = entries_.begin();
+         iter != entries_.end();
+         ++iter)
+    {
+        if (iter->link_ == link) {
+            delete iter->blocks_;
+            entries_.erase(iter);
+            return;
+        }
+    }
+    
+    PANIC("LinkBlockVec::delete_blocks: "
+          "no block vector for link *%p", link.object());
+}
+
+} // namespace dtn