servlib/bundling/BPQCacheEntry.cc
changeset 66 e1101c5d54a1
parent 64 1296a0283271
child 72 e978673d3bc2
--- a/servlib/bundling/BPQCacheEntry.cc	Wed Oct 26 13:33:11 2011 +0100
+++ b/servlib/bundling/BPQCacheEntry.cc	Fri Jan 06 17:28:36 2012 +0000
@@ -19,55 +19,81 @@
 
 namespace dtn {
 
-int
+bool
 BPQCacheEntry::add_response(Bundle* bundle)
 {
 	if ( ! bundle->is_fragment() ) {
 		log_debug("add complete response to cache entry");
-
-		fragments_.insert_sorted(bundle, BundleList::SORT_FRAG_OFFSET);
-		is_complete_ = true;
-
-	} else if ( bundle->is_fragment() && ! is_complete_ ) {
+	} else {
 		log_debug("add response fragment to cache entry");
-
-		fragments_.insert_sorted(bundle, BundleList::SORT_FRAG_OFFSET);
-		is_complete_ = check_complete();
-
-	} else if ( bundle->is_fragment() && is_complete_ ) {
-		log_debug("ignoring response fragment as cache entry is complete");
-
-	} else {
-		NOTREACHED;
 	}
 
+	fragments_.insert_sorted(bundle, BundleList::SORT_FRAG_OFFSET);
+
+	return is_complete();
+}
+
+//----------------------------------------------------------------------
+int
+BPQCacheEntry::reassemble_fragments(Bundle* new_bundle, Bundle* meta_bundle){
+
+	log_debug("reassembling fragments for bundle id=%u", meta_bundle->bundleid());
+
+	// copy metadata
+	new_bundle->copy_metadata(meta_bundle);
+	new_bundle->set_orig_length(meta_bundle->orig_length());
+	new_bundle->set_frag_offset(0);
+
+	// copy payload
+	BundleList::iterator frag_iter;
+	Bundle* current_fragment;
+
+    for (frag_iter = fragments_.begin();
+		 frag_iter != fragments_.end();
+         ++frag_iter) {
+
+    	current_fragment = *frag_iter;
+    	size_t fraglen = current_fragment->payload().length();
+
+    	new_bundle->mutable_payload()->write_data(	current_fragment->payload(),
+    												0,
+													fraglen,
+													current_fragment->frag_offset());
+    }
+
+    // copy extension blocks
+	BlockInfoVec::const_iterator block_iter;
+
+    for (block_iter =  meta_bundle->recv_blocks().begin();
+    	 block_iter != meta_bundle->recv_blocks().end();
+         ++block_iter) {
+
+    	if (! new_bundle->recv_blocks().has_block( block_iter->type() ) &&
+    		block_iter->type() != BundleProtocol::PRIMARY_BLOCK         &&
+			block_iter->type() != BundleProtocol::PAYLOAD_BLOCK) {
+
+    		log_debug("Adding block(%d) to fragment bundle", block_iter->type());
+
+    		new_bundle->mutable_recv_blocks()->push_back(BlockInfo(*block_iter));
+		}
+    }
 	return BP_SUCCESS;
 }
 
 //----------------------------------------------------------------------
-int
-BPQCacheEntry::reassemble_fragments(Bundle* new_bundle, const Bundle* meta_bundle){
-	//TODO: implement this
-	NOTIMPLEMENTED;
-	return BP_FAIL;
-}
-
-//----------------------------------------------------------------------
 bool
-BPQCacheEntry::check_complete() const
+BPQCacheEntry::is_complete() const
 {
     Bundle* fragment;
     BundleList::iterator iter;
     oasys::ScopeLock l(fragments_.lock(),
-                       "BPQCacheEntry::check_complete");
+                       "BPQCacheEntry::is_complete");
 
     size_t done_up_to = 0;  // running total of completed reassembly
     size_t f_len;
     size_t f_offset;
     size_t f_origlen;
 
-//    size_t total_len = bundle_->payload().length();
-
     int fragi = 0;
     int fragn = fragments_.size();
     (void)fragn; // in case NDEBUG is defined
@@ -149,6 +175,7 @@
             NOTREACHED;
         }
     }
+    l.unlock();
 
     if (done_up_to == total_len_) {
         log_debug("check_completed reassembly complete!");
@@ -160,5 +187,47 @@
     }
 }
 
+//----------------------------------------------------------------------
+
+bool
+BPQCacheEntry::is_fragmented() const
+{
+    Bundle* bundle;
+    BundleList::iterator iter;
+    oasys::ScopeLock l(fragments_.lock(),
+                       "BPQCacheEntry::is_fragmented");
+
+    for (iter = fragments_.begin();
+         iter != fragments_.end();
+         ++iter)
+    {
+        bundle = *iter;
+
+        if (bundle->is_fragment()){
+        	l.unlock();
+        	return true;
+        }
+    }
+
+    return false;
+}
+
+//----------------------------------------------------------------------
+size_t
+BPQCacheEntry::entry_size() const
+{
+	size_t size = 0;
+    BundleList::iterator iter;
+    oasys::ScopeLock l(fragments_.lock(),
+                       "BPQCacheEntry::is_fragmented");
+
+    for (iter = fragments_.begin();
+         iter != fragments_.end();
+         ++iter) {
+        size += (*iter)->payload().length();
+    }
+
+    return size;
+}
 
 } // namespace dtn