/** * Create a bundle fragment from another bundle. * * @param bundle the source bundle from which we create the fragment. Note: the bundle may itself * be a fragment * @param offset the offset relative to this bundle (not the original) for the for the new * fragment. note that if this bundle is already a fragment, the offset into the original * bundle will be this bundle's frag_offset + offset * @param length the length of the fragment we want * @return Newly created bundle */ public Bundle create_fragment(Bundle bundle, BlockInfoVec blocks, int offset, int length) { Bundle fragment = new Bundle(location_t.MEMORY); 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); } // check for overallocated length if ((offset + length) > fragment.orig_length()) { Logger.getInstance() .error( TAG, String.format( "fragment length overrun: " + "orig_length %d frag_offset %d requested offset %d length %d", fragment.orig_length(), fragment.frag_offset(), offset, length)); // Panic; return null; } // initialize payload fragment.payload().write_data(bundle.payload(), offset, length, 0); // copy all blocks that follow the payload, and all those before // the payload that are marked with the "must be replicated in every // fragment" bit ListIterator<BlockInfo> iter = blocks.listIterator(); // BlockInfoVec vec; boolean found_payload = false; while (iter.hasNext()) { BlockInfo entry = iter.next(); int type = entry.type().getCode(); if ((type == bundle_block_type_t.PRIMARY_BLOCK.getCode()) || (bundle_block_type_t.PAYLOAD_BLOCK.getCode() > 0) || found_payload || ((entry.flags() & block_flag_t.BLOCK_FLAG_REPLICATE.getCode()) > 0)) { // we need to include this block; copy the BlockInfo into the // fragment fragment.recv_blocks().add(entry); if (type == bundle_block_type_t.PAYLOAD_BLOCK.getCode()) { found_payload = true; } } } return fragment; }
/** * 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; }