servlib/bundling/FragmentState.cc
changeset 0 2b3e5ec03512
equal deleted inserted replaced
-1:000000000000 0:2b3e5ec03512
       
     1 /*
       
     2  *    Copyright 2004-2006 Intel Corporation
       
     3  * 
       
     4  *    Licensed under the Apache License, Version 2.0 (the "License");
       
     5  *    you may not use this file except in compliance with the License.
       
     6  *    You may obtain a copy of the License at
       
     7  * 
       
     8  *        http://www.apache.org/licenses/LICENSE-2.0
       
     9  * 
       
    10  *    Unless required by applicable law or agreed to in writing, software
       
    11  *    distributed under the License is distributed on an "AS IS" BASIS,
       
    12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    13  *    See the License for the specific language governing permissions and
       
    14  *    limitations under the License.
       
    15  */
       
    16 
       
    17 #ifdef HAVE_CONFIG_H
       
    18 #  include <dtn-config.h>
       
    19 #endif
       
    20 
       
    21 #include "Bundle.h"
       
    22 #include "FragmentState.h"
       
    23 
       
    24 namespace dtn {
       
    25 
       
    26 //----------------------------------------------------------------------
       
    27 void
       
    28 FragmentState::add_fragment(Bundle* fragment)
       
    29 {
       
    30     fragments_.insert_sorted(fragment, BundleList::SORT_FRAG_OFFSET);
       
    31 }
       
    32 
       
    33 //----------------------------------------------------------------------
       
    34 bool
       
    35 FragmentState::erase_fragment(Bundle* fragment) 
       
    36 {
       
    37     return fragments_.erase(fragment);
       
    38 }
       
    39 
       
    40 //----------------------------------------------------------------------
       
    41 bool
       
    42 FragmentState::check_completed() const
       
    43 {
       
    44     Bundle* fragment;
       
    45     BundleList::iterator iter;
       
    46     oasys::ScopeLock l(fragments_.lock(),
       
    47                        "FragmentState::check_completed");
       
    48     
       
    49     size_t done_up_to = 0;  // running total of completed reassembly
       
    50     size_t f_len;
       
    51     size_t f_offset;
       
    52     size_t f_origlen;
       
    53 
       
    54     size_t total_len = bundle_->payload().length();
       
    55     
       
    56     int fragi = 0;
       
    57     int fragn = fragments_.size();
       
    58     (void)fragn; // in case NDEBUG is defined
       
    59 
       
    60     for (iter = fragments_.begin();
       
    61          iter != fragments_.end();
       
    62          ++iter, ++fragi)
       
    63     {
       
    64         fragment = *iter;
       
    65 
       
    66         f_len = fragment->payload().length();
       
    67         f_offset = fragment->frag_offset();
       
    68         f_origlen = fragment->orig_length();
       
    69         
       
    70         ASSERT(fragment->is_fragment());
       
    71         
       
    72         if (f_origlen != total_len) {
       
    73             PANIC("check_completed: error fragment orig len %zu != total %zu",
       
    74                   f_origlen, total_len);
       
    75             // XXX/demmer deal with this
       
    76         }
       
    77 
       
    78         if (done_up_to == f_offset) {
       
    79             /*
       
    80              * fragment is adjacent to the bytes so far
       
    81              * bbbbbbbbbb
       
    82              *           fff
       
    83              */
       
    84             log_debug("check_completed fragment %d/%d: "
       
    85                       "offset %zu len %zu total %zu done_up_to %zu: "
       
    86                       "(perfect fit)",
       
    87                       fragi, fragn, f_offset, f_len, f_origlen, done_up_to);
       
    88             done_up_to += f_len;
       
    89         }
       
    90 
       
    91         else if (done_up_to < f_offset) {
       
    92             /*
       
    93              * there's a gap
       
    94              * bbbbbbb ffff
       
    95              */
       
    96             log_debug("check_completed fragment %d/%d: "
       
    97                       "offset %zu len %zu total %zu done_up_to %zu: "
       
    98                       "(found a hole)",
       
    99                       fragi, fragn, f_offset, f_len, f_origlen, done_up_to);
       
   100             return false;
       
   101 
       
   102         }
       
   103 
       
   104         else if (done_up_to > (f_offset + f_len)) {
       
   105             /* fragment is completely redundant, skip
       
   106              * bbbbbbbbbb
       
   107              *      fffff
       
   108              */
       
   109             log_debug("check_completed fragment %d/%d: "
       
   110                       "offset %zu len %zu total %zu done_up_to %zu: "
       
   111                       "(redundant fragment)",
       
   112                       fragi, fragn, f_offset, f_len, f_origlen, done_up_to);
       
   113             continue;
       
   114         }
       
   115         
       
   116         else if (done_up_to > f_offset) {
       
   117             /*
       
   118              * there's some overlap, so reduce f_len accordingly
       
   119              * bbbbbbbbbb
       
   120              *      fffffff
       
   121              */
       
   122             log_debug("check_completed fragment %d/%d: "
       
   123                       "offset %zu len %zu total %zu done_up_to %zu: "
       
   124                       "(overlapping fragment, reducing len to %zu)",
       
   125                       fragi, fragn, f_offset, f_len, f_origlen, done_up_to,
       
   126                       (f_len - (done_up_to - f_offset)));
       
   127             
       
   128             f_len -= (done_up_to - f_offset);
       
   129             done_up_to += f_len;
       
   130         }
       
   131 
       
   132         else {
       
   133             // all cases should be covered above
       
   134             NOTREACHED;
       
   135         }
       
   136     }
       
   137 
       
   138     if (done_up_to == total_len) {
       
   139         log_debug("check_completed reassembly complete!");
       
   140         return true;
       
   141     } else {
       
   142         log_debug("check_completed reassembly not done (got %zu/%zu)",
       
   143                   done_up_to, total_len);
       
   144         return false;
       
   145     }
       
   146 }
       
   147 
       
   148 } // namespace dtn
       
   149