diff -r 000000000000 -r 2b3e5ec03512 servlib/bundling/FragmentState.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlib/bundling/FragmentState.cc Thu Apr 21 14:57:45 2011 +0100 @@ -0,0 +1,149 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "Bundle.h" +#include "FragmentState.h" + +namespace dtn { + +//---------------------------------------------------------------------- +void +FragmentState::add_fragment(Bundle* fragment) +{ + fragments_.insert_sorted(fragment, BundleList::SORT_FRAG_OFFSET); +} + +//---------------------------------------------------------------------- +bool +FragmentState::erase_fragment(Bundle* fragment) +{ + return fragments_.erase(fragment); +} + +//---------------------------------------------------------------------- +bool +FragmentState::check_completed() const +{ + Bundle* fragment; + BundleList::iterator iter; + oasys::ScopeLock l(fragments_.lock(), + "FragmentState::check_completed"); + + 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 + + for (iter = fragments_.begin(); + iter != fragments_.end(); + ++iter, ++fragi) + { + fragment = *iter; + + f_len = fragment->payload().length(); + f_offset = fragment->frag_offset(); + f_origlen = fragment->orig_length(); + + ASSERT(fragment->is_fragment()); + + if (f_origlen != total_len) { + PANIC("check_completed: error fragment orig len %zu != total %zu", + f_origlen, total_len); + // XXX/demmer deal with this + } + + if (done_up_to == f_offset) { + /* + * fragment is adjacent to the bytes so far + * bbbbbbbbbb + * fff + */ + log_debug("check_completed fragment %d/%d: " + "offset %zu len %zu total %zu done_up_to %zu: " + "(perfect fit)", + fragi, fragn, f_offset, f_len, f_origlen, done_up_to); + done_up_to += f_len; + } + + else if (done_up_to < f_offset) { + /* + * there's a gap + * bbbbbbb ffff + */ + log_debug("check_completed fragment %d/%d: " + "offset %zu len %zu total %zu done_up_to %zu: " + "(found a hole)", + fragi, fragn, f_offset, f_len, f_origlen, done_up_to); + return false; + + } + + else if (done_up_to > (f_offset + f_len)) { + /* fragment is completely redundant, skip + * bbbbbbbbbb + * fffff + */ + log_debug("check_completed fragment %d/%d: " + "offset %zu len %zu total %zu done_up_to %zu: " + "(redundant fragment)", + fragi, fragn, f_offset, f_len, f_origlen, done_up_to); + continue; + } + + else if (done_up_to > f_offset) { + /* + * there's some overlap, so reduce f_len accordingly + * bbbbbbbbbb + * fffffff + */ + log_debug("check_completed fragment %d/%d: " + "offset %zu len %zu total %zu done_up_to %zu: " + "(overlapping fragment, reducing len to %zu)", + fragi, fragn, f_offset, f_len, f_origlen, done_up_to, + (f_len - (done_up_to - f_offset))); + + f_len -= (done_up_to - f_offset); + done_up_to += f_len; + } + + else { + // all cases should be covered above + NOTREACHED; + } + } + + if (done_up_to == total_len) { + log_debug("check_completed reassembly complete!"); + return true; + } else { + log_debug("check_completed reassembly not done (got %zu/%zu)", + done_up_to, total_len); + return false; + } +} + +} // namespace dtn +