Download presentation
Presentation is loading. Please wait.
1
Serialization 2: Valuetype Code
CDROutputStreams May 30, 2002
2
Review Valuetypes are encoded as a value tag plus optional codebase and repository ID strings Chunks are never nested (so close before any value tag) Chunks cannot split primitives, arrays of primitives, strings, wstrings, or indirections Chunks may span fragments
3
CDROutputStreams CDROutputStream_1_0 is original CDROutputStream, containing most valuetype code CDROutputStream_1_1 and 1_2 override certain methods to better handle fragmentation CDROutputStream_1_1 does not handle chunking with fragmentation at all (thus we don't really support this)
4
CDROutputStream_1_0 vars
int end_flag int chunkedValueNestingLevel int end_flag_position int end_flag_index int blockSizeIndex UNUSED int blockSizePosition boolean mustChunk boolean inBlock
5
End tag variables end_flag chunkedValueNestingLevel end_flag_position
end_flag_index end_flag and chunkedValueNestingLevel track how many valuetypes enclose the one that we're currently working on. end_flag includes all, but chunkedValueNestingLevel includes only chunked valuetypes (interop resolution 3526) end_flag_position tracks the stream position of the last end tag written while end_flag_index is the last buffer index. If we're writing a new end tag at the same position AND index, then we can perform end tag compaction NOTE: end tags are ONLY written for custom marshaled valuetypes
6
Chunking variables (non-frag)
blockSizeIndex UNUSED blockSizePosition mustChunk inBlock inBlock tells us if we're currently writing data within a chunk mustChunk tells recursive calls to write_value that they also need to use chunking, even if the valuetypes wouldn't normally be custom marshaled blockSizePosition tracks the stream position of the last chunk length reserved. This is necessary since we have to go back and write the chunk length when we can compute it – at the beginning, it is merely reserved as a CORBA long of value 0
7
Valuetype code 1 (write_value)
handle null and indirections without closing chunk saves mustChunk as method local oldMustChunk if inBlock end_block write value tag, codebase, rep id(s) if mustChunk or custom marshaled mustChunk = true end_flag-- customValueNestingLevel-- start_block write the data writeEndTag restores mustChunk if mustChunk
8
Valuetype code 2 (block methods)
start_block saves space for long chunk length inBlock = true blockSizePosition = get_offset blockSizeIndex = bbwi.index end_block if !inBlock return inBlock = false if get_offset == blockSizePosition back up blockSizeIndex = blockSizePosition = -1 return writes chunk length in saved position
9
Valuetype code 3 (end tag methods)
writeEndTag(boolean chunked) if chunked if get_offset == end_flag_position if bbwi.index == end_flag_index end tag compaction else new fragment, just write new end tag writeNestingLevel end_flag_index = bbwi.index end_flag_position = get_offset chunkedValueNestingLevel++ end_flag++ writeNestinglevel Writes either end_flag or chunkedValueNestingLevel depending on ORB version
10
Example 1 custom marshaled valuetype A contains
valuetype B which contains nothing CORBA long Marshaling code does the following: 1. Writes valuetag for A [write_value] 2. Writes codebase & repId for A [write_value] 3. Opens a chunk (writes a CORBA long) [start_block] 4. Closes chunk since beginning B. Thus, backs up 4 bytes, erasing the chunk length. 0 length chunks are illegal! [end_block] 5. Writes valuetag for B [write_value] 6. Writes codebase & repId for B [write_value] 7. Opens a chunk since mustChunk is true [start_block] 8. Closes chunk since B is finished. Since it wrote no data, we back up over the chunk again, erasing it. [end_block] 9. Writes an end tag of -2 showing that the first nested custom marshaled type ends here. [writeEndTag] 10. Opens new chunk to continue A's data (mustChunk is still true) [write_value] 11. Back in A's marshaling code, so writes A's long. [write_value] 12. Closes chunk, going back to update the chunk length to be 4 [end_block] 13. Writes an end tag of -1 [writeEndTag] 14. mustChunk is now false, so does not open new chunk [write_value]
11
Chunking & Fragmentation 1
CDROutputStream_1_2 Variables: boolean primitiveAcrossFragmentedChunk boolean specialChunk Methods: handleSpecialChunkBegin(int data length) handleSpecialChunkEnd checkPrimitiveAcrossFragmentedChunk
12
Chunking and Fragmentation 2
Before “special” writes (arrays of primitives, string/wstring data, indirections), call handleSpecialChunkBegin with the total size in bytes of desired data Afterwards, call handleSpecialChunkEnd Primitives are overridden in 1_2 to call checkPrimitiveAcrossFragmentedChunk after writing, but don't use handleSpecialChunk methods (ABLE TO REUSE?)
13
Chunking and Fragmentation 3
CDROutputStream_1_2 handleSpecialChunkBegin(int data length) if inBlock and data length + bbwi.index > bbwi.buflen writes chunk length including data length specialChunk = true grow(alignment boundary, data size) local handleChunk = inBlock && !specialChunk if (handleChunk) writes chunk length (including data size) buffermanager.overflow if fragmented update fragmentOffset if handleChunk primitiveAcrossFragmentedChunk = true handleSpecialChunkEnd if inBlock and specialChunk inBlock = false blockSizeIndex = blockSizePosition = -1 start_block specialChunk = false
14
Example 2 custom marshaled valuetype A contains
octet array N of length 1024 ORB fragment size 1024, GIOP 1.2. Let's say we actually begin marshaling valuetype A at index 512 with a repository ID of 16 chars and no codebase URL. (Note that CORBA strings have a null appended, so length will be written as 17.) 1. Writes valuetag for A [write_value] -> = 516 2. Writes repId for A [write_value] -> = 537 3. Opens a chunk (writes a CORBA long) [start_block] -> = 544 (3 bytes of alignment) 4. write_octet_array calls handleSpecialChunkBegin(2048) which 4a. Writes chunk length as 2048 4b. Sets specialChunk to true 5. write_octet_array calls internalWriteOctetArray (**) 6. Writes = 480 bytes 7. Calls alignAndReserve which calls grow 7a. handleChunk = inBlock && !specialChunk = false 7b. !handleChunk so doesn't touch chunk length, doesn't open new chunk 8. Now in next fragment at index 16 (GIOP 1.2 fragment header first) 9. internalWriteOctetArray continues to write remaining = 544 bytes 10. handleSpecialChunkEnd called which starts a new chunk
15
Chunking and Fragmenation 4
CDROutputStream_1_2 grow(alignment boundary, data size) local handleChunk = inBlock && !specialChunk if (handleChunk) writes chunk length (including data size) buffermanager.overflow if fragmented update fragmentOffset if handleChunk primitiveAcrossFragmentedChunk = true checkPrimitiveAcrossFragmentedChunk if primitiveAcrossFragmentedChunk primitiveAcrossFragmentedChunk = false inBlock = false blockSizeIndex = blockSizePosition = -1 start_block
16
Example 3 GIOP 1.2 in a custom valuetype. Already have a chunk open (specialChunk is false). Fragment size 1024, and we're currently at index 1021 and want to write a CORBA long (4 bytes). Will want 3 bytes of alignment plus 4 bytes of data, but that won't all fit in this fragment. 1. alignAndReserve(4, 4) advances the index to 1024 and calls grow(4, 4) 2. handleChunk = inBlock && !specialChunk = true 3. Writes chunk length as current length (through index 1024) plus 4 (This works since GIOP 1.2 fragment header ends on 16 byte boundary) 4. Fragments, primitiveAcrossFragmentedChunk -> true 5. GIOP 1.2 fragment header is written (ends at byte 16) 6. write_long actually writes the bytes of the long 7. write_long calls checkPrimitiveAcrossFragmentedChunk 8. checkPrimitiveAcrossFragmentedChunk 8a. primitiveAcrossFragmentedChunk -> false 8b. opens new chunk (start_block) NOTE: This allows the write_xxxx_array methods to still call the individual write_xxxx methods without mangling the variables, and was a fast fix. Could probably reuse specialChunk if the array methods called internal write methods instead which themselves don't call handleSpecialChunkBegin/End.
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.