/** * Given the given fragmentation threshold, determine whether the given bundle should be split * into several smaller bundles. If so, this returns true and generates a bunch of bundle received * events for the individual fragments. * * @param bundle Bundle to split into fragments * @param link Bundle to send on the given link * @param max_length Maximum length of the fragment * @return FragmentState that has the list of created fragments for the given bundle. */ public FragmentState proactively_fragment(Bundle bundle, final Link link, int max_length) { int payload_len = bundle.payload().length(); Bundle fragment; FragmentState state = new FragmentState(bundle); int todo = payload_len; int offset = 0; int count = 0; BlockInfoVec first_frag_blocks = new BlockInfoVec(); BlockInfoVec all_frag_blocks = new BlockInfoVec(); BlockInfoVec this_frag_blocks = first_frag_blocks; ListIterator<BlockInfo> entry = bundle.xmit_link_block_set().find_blocks(link).listIterator(); while (entry.hasNext()) { BlockInfo block_info = entry.next(); if ((block_info.type() == bundle_block_type_t.PRIMARY_BLOCK) || (block_info.type() == bundle_block_type_t.PAYLOAD_BLOCK)) { all_frag_blocks.add(block_info); first_frag_blocks.add(block_info); } else if ((block_info.flags() & block_flag_t.BLOCK_FLAG_REPLICATE.getCode()) > 0) { all_frag_blocks.add(block_info); } else { first_frag_blocks.add(block_info); } } do { fragment = create_fragment(bundle, link, this_frag_blocks, offset, max_length); assert (fragment != null) : TAG + ": proactively_fragment() fragment not valid"; state.add_fragment(fragment); offset += fragment.payload().length(); todo -= fragment.payload().length(); this_frag_blocks = all_frag_blocks; ++count; } while (todo > 0); Logger.getInstance() .debug( TAG, String.format( "proactively fragmenting " + "%s byte payload into %s %s byte fragments", payload_len, count, max_length)); String[] hash_key = new String[1]; get_hash_key(fragment, hash_key); fragment_table_.put(hash_key[0], state); return state; }
/** * Prepare function prepare bundle to generate. It adds Primary Block Info at the start of * xmit_blocks and add endpoint eids at the start of dictionary. * * @param bundle Bundle to prepare * @param xmit_blocks Empty xmit_blocks of the blundle * @param source Source endpoint id * @param link Link of the bundle * @param list Owner type * @return Return success message on success */ public int prepare( final Bundle bundle, BlockInfoVec xmit_blocks, final BlockInfo source, final Link link, list_owner_t list) { // There shouldn't already be anything in the xmit_blocks assert (xmit_blocks.size() == 0) : TAG + ": prepare() there shouldn't be anything already in xmit_blocks"; // Add EIDs to start off the dictionary xmit_blocks.dict().add_eid(bundle.dest()); xmit_blocks.dict().add_eid(bundle.source()); xmit_blocks.dict().add_eid(bundle.replyto()); xmit_blocks.dict().add_eid(bundle.custodian()); // make sure to add the primary to the front xmit_blocks.add(0, new BlockInfo(this, source)); return BP_SUCCESS; }
/** * Create a fragment to be sent out on a particular link. * * @param bundle Source Bundle from which we create a fragment. * @param link Link on which we will send the fragment * @param blocks_to_copy Blocks to copy on this fragment. * @param offset The offset relative to this bundle for the for the new fragment * @param max_length Maximum length of the newly created fragment * @return Newly created fragment. */ public Bundle create_fragment( Bundle bundle, final Link link, final BlockInfoVec blocks_to_copy, int offset, int max_length) { int block_length = 0; ListIterator<BlockInfo> entry = blocks_to_copy.listIterator(); BlockInfo block_i; while (entry.hasNext()) { block_i = entry.next(); if (block_i.type() == bundle_block_type_t.PRIMARY_BLOCK) { block_length += block_i.data_length(); } else { block_length += block_i.data_offset(); // data offset is the // starting point of } } if (block_length > max_length) { Logger.getInstance() .error( TAG, String.format( "unable to create a fragment of length %s; minimum length " + "required is %s", max_length, block_length)); return null; } Bundle fragment = new Bundle(location_t.DISK); // copy the metadata into the new fragment (which can be further // fragmented) bundle.copy_metadata(fragment); fragment.set_is_fragment(true); fragment.set_do_not_fragment(false); // initialize the fragment's orig_length and figure out the offset // into the payload if (!bundle.is_fragment()) { fragment.set_orig_length(bundle.payload().length()); fragment.set_frag_offset(offset); } else { fragment.set_orig_length(bundle.orig_length()); fragment.set_frag_offset(bundle.frag_offset() + offset); } // initialize payload int to_copy = Math.min(max_length - block_length, bundle.payload().length() - offset); fragment.payload().set_length(to_copy); fragment.payload().write_data(bundle.payload(), offset, to_copy, 0); BlockInfoVec xmit_blocks = fragment.xmit_link_block_set().create_blocks(link); entry = blocks_to_copy.listIterator(); // reset Iterator while (entry.hasNext()) { block_i = entry.next(); xmit_blocks.add(block_i); } Logger.getInstance() .debug( TAG, String.format( "created %s byte fragment bundle with %s bytes of payload", to_copy + block_length, to_copy)); return fragment; }