Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

ACE_RMCast_Partial_Message Class Reference

Represent a partially received message in the ACE_RMCast_Reassembly module. More...

#include <RMCast_Partial_Message.h>

Collaboration diagram for ACE_RMCast_Partial_Message:

Collaboration graph
[legend]
List of all members.

Public Methods

 ACE_RMCast_Partial_Message (ACE_UINT32 message_size)
 Constructor, reserve enough memory for the complete message. More...

 ~ACE_RMCast_Partial_Message (void)
 Destructor. More...

int fragment_received (ACE_UINT32 message_size, ACE_UINT32 offset, ACE_Message_Block *mb)
 Process a fragment. More...

int is_complete (void) const
 Return 1 if the message is complete. More...

ACE_Message_Blockmessage_body (void)
 Return the body of the message, the memory is *not* owned by the caller. More...


Private Methods

int insert_hole (size_t i, ACE_UINT32 start, ACE_UINT32 end)
 Insert a new hole into the list. More...

int remove_hole (size_t i)
 Remove a hole from the list. More...


Private Attributes

ACE_Message_Block message_body_
 Maintain the message storage. More...

Holehole_list_
size_t max_hole_count_
size_t hole_count_

Detailed Description

Represent a partially received message in the ACE_RMCast_Reassembly module.

This class provides temporary storage for the fragments as they are received in the ACE_RMCast_Reassembly module. It also keeps track of what portions of the message are still missing.

Definition at line 36 of file RMCast_Partial_Message.h.


Constructor & Destructor Documentation

ACE_RMCast_Partial_Message::ACE_RMCast_Partial_Message ACE_UINT32    message_size
 

Constructor, reserve enough memory for the complete message.

Definition at line 12 of file RMCast_Partial_Message.cpp.

References ACE_NEW, ACE_RMCAST_DEFAULT_HOLE_COUNT, ACE_RMCast_Partial_Message::Hole::end, hole_list_, message_body_, ACE_Message_Block::size, ACE_RMCast_Partial_Message::Hole::start, and ACE_Message_Block::wr_ptr.

00013   :  max_hole_count_ (ACE_RMCAST_DEFAULT_HOLE_COUNT),
00014      hole_count_ (1)
00015 {
00016   ACE_NEW (this->hole_list_,
00017            ACE_RMCast_Partial_Message::Hole[this->max_hole_count_]);
00018   this->hole_list_[0].start = 0;
00019   this->hole_list_[0].end = message_size;
00020 
00021   this->message_body_.size (message_size);
00022   this->message_body_.wr_ptr (message_size);
00023 }

ACE_RMCast_Partial_Message::~ACE_RMCast_Partial_Message void   
 

Destructor.

Definition at line 26 of file RMCast_Partial_Message.cpp.

References hole_list_.

00027 {
00028   delete[] this->hole_list_;
00029 }


Member Function Documentation

int ACE_RMCast_Partial_Message::fragment_received ACE_UINT32    message_size,
ACE_UINT32    offset,
ACE_Message_Block   mb
 

Process a fragment.

A fragment starting at <offset> has been received, copy the fragment contents and update the list of holes.

Definition at line 32 of file RMCast_Partial_Message.cpp.

References ACE_Message_Block::cont, ACE_RMCast_Partial_Message::Hole::end, hole_count_, hole_list_, insert_hole, ACE_Message_Block::length, ACE_OS_String::memcpy, message_body_, ACE_Message_Block::rd_ptr, remove_hole, ACE_RMCast_Partial_Message::Hole::start, and ACE_Message_Block::wr_ptr.

Referenced by ACE_RMCast_Reassembly::data.

00035 {
00036   if (this->message_body_.length () != message_size)
00037     {
00038       //      ACE_DEBUG ((LM_DEBUG,
00039       //                  "Partial_Message::fragment_received - "
00040       //                  "invalid message length\n"));
00041       return -1;
00042     }
00043 
00044   // Just copy the data...
00045   char *rd_ptr = this->message_body_.rd_ptr () + offset;
00046   size_t total_length = 0;
00047   {
00048     for (const ACE_Message_Block *i = mb; i != 0; i = i->cont ())
00049       {
00050         if (rd_ptr + i->length () > this->message_body_.wr_ptr ())
00051           {
00052             //            ACE_DEBUG ((LM_DEBUG,
00053             //                        "Partial_Message::fragment_received - "
00054             //                        "invalid payload length\n"));
00055             return -1;
00056           }
00057         ACE_OS::memcpy (rd_ptr, i->rd_ptr (), i->length ());
00058         rd_ptr       += i->length ();
00059         total_length += i->length ();
00060       }
00061   }
00062 
00063   // The algorithm works like this:
00064   //
00065   //   For each hole we determine if there is an intersection between
00066   //   the hole and the incoming fragment.  If there is none we do
00067   //   nothing (actually since the holes are ordered we can stop the
00068   //   iteration if the
00069 
00070   ACE_UINT32 start = offset;
00071   ACE_UINT32 end   = ACE_static_cast (ACE_UINT32,
00072                                       offset + total_length);
00073 
00074   while (start != end && this->hole_count_ != 0)
00075     {
00076       for (size_t i = 0; i < this->hole_count_; ++i)
00077         {
00078           Hole& hole = this->hole_list_[i];
00079 
00080           // First check if the new data insersects the hole...
00081           if (end <= hole.start)
00082             return 0;
00083           if (start >= hole.end)
00084             {
00085               if (i == this->hole_count_ - 1)
00086                 return 0;
00087               else
00088                 continue;
00089             }
00090 
00091           // The hole and the new fragment intersect, we have to
00092           // update the hole list.
00093           //
00094           // There are only three cases for the <start> value:
00095           // start < hole.start
00096           // start == hole.start
00097           // hole.start < start < hole.end
00098           //
00099           // But the code for both start == hole.start and start <
00100           // hole.start is identical....
00101 
00102           if (start <= hole.start)
00103             {
00104               if (end < hole.end)
00105                 {
00106                   // NOTE: hole.start < end, because of previous test
00107 
00108                   // In this case we shrink the hole, but it is not
00109                   // removed!
00110                   hole.start = end;
00111                   return 0;
00112                 }
00113               else // end >= hole.end
00114                 {
00115                   start = hole.end;
00116                   // We remove the hole, and continue the iteration...
00117                   if (this->remove_hole (i) == -1)
00118                     return -1;
00119                   break;
00120                 }
00121             }
00122           else // hole.start < start < hole.end
00123             {
00124               if (end >= hole.end)
00125                 {
00126                   // Just adjust the size of the hole...
00127                   ACE_UINT32 tmp = hole.end;
00128                   hole.end = start;
00129                   start = tmp;
00130                   break;
00131                 }
00132               else // if (end < hole.end)
00133                 {
00134                   // Nasty, we need to insert a new hole...
00135                   if (this->insert_hole (i, end, hole.end) == -1)
00136                     return -1;
00137                   // and change the old hole...
00138                   // NOTE: we have to refetch it because the array may
00139                   // have been reallocated!
00140                   this->hole_list_[i].end = start;
00141                   return 0;
00142                 }
00143             }
00144         }
00145     }
00146   return 0;
00147   // @@ OLD COMMENTS, the algorithm has changed since!
00148   // There are several cases:
00149   //
00150   // 1) The fragment is completely contained in data already received,
00151   //    nothing changes in this case.
00152   //
00153   // 2) Part of the fragment is contained in data already received and
00154   //    part is new data:
00155   //    2.1) The new data closes a hole, remove it from the list
00156   //    2.2) The beginning of the new fragment is the new data, reduce
00157   //    the size of the hole
00158   //    2.3) The end of the new fragment is the new data, increment
00159   //    the size of the received block
00160   //
00161   // 3) The fragment is completely contained in a hole
00162   //    3.1) It closes the hole, remove it from the list
00163   //    3.2) It starts at the beginning of a hole, grow the received
00164   //    block
00165   //    3.3) It ends at the end of a hole, reduce the hole size
00166   //    3.4) It is in the middle of a hole, insert a new hole
00167   //
00168 }

int ACE_RMCast_Partial_Message::insert_hole size_t    i,
ACE_UINT32    start,
ACE_UINT32    end
[private]
 

Insert a new hole into the list.

The class keeps an array to represent the missing portions of the message. This method inserts a new hole, i.e. a new element in the array at index . The <start> and <end> arguments represent the offsets of the missing portion of the message.

Definition at line 171 of file RMCast_Partial_Message.cpp.

References ACE_NEW_RETURN, ACE_RMCast_Partial_Message::Hole::end, hole_count_, hole_list_, max_hole_count_, and ACE_RMCast_Partial_Message::Hole::start.

Referenced by fragment_received.

00174 {
00175   //  ACE_DEBUG ((LM_DEBUG,
00176   //              "Partial_Message::insert_hole %d = [%d,%d]\n",
00177   //              i, start, end));
00178   if (this->hole_count_ + 1 > this->max_hole_count_)
00179     {
00180       this->max_hole_count_ *= 2;
00181       Hole *tmp;
00182       ACE_NEW_RETURN (tmp, Hole[this->max_hole_count_], -1);
00183       for (size_t j = 0; j != this->hole_count_; ++j)
00184         {
00185           tmp[j] = this->hole_list_[j];
00186         }
00187       delete[] this->hole_list_;
00188       this->hole_list_ = tmp;
00189     }
00190   if (this->hole_count_ != 0)
00191     {
00192       for (size_t j = this->hole_count_ - 1; j >= i + 1; --j)
00193         {
00194           this->hole_list_[j+1] = this->hole_list_[j];
00195         }
00196     }
00197 
00198   this->hole_list_[i + 1].start = start;
00199   this->hole_list_[i + 1].end   = end;
00200   this->hole_count_++;
00201 
00202   return 0;
00203 }

ACE_INLINE int ACE_RMCast_Partial_Message::is_complete void    const
 

Return 1 if the message is complete.

Definition at line 4 of file RMCast_Partial_Message.i.

References ACE_RMCast_Partial_Message::Hole::end, hole_count_, hole_list_, and ACE_RMCast_Partial_Message::Hole::start.

Referenced by ACE_RMCast_Reassembly::data.

00005 {
00006   return (this->hole_count_ == 0)
00007     || (this->hole_count_ == 1
00008         && this->hole_list_[0].start == this->hole_list_[0].end);
00009 }

ACE_INLINE ACE_Message_Block * ACE_RMCast_Partial_Message::message_body void   
 

Return the body of the message, the memory is *not* owned by the caller.

Definition at line 12 of file RMCast_Partial_Message.i.

References message_body_.

Referenced by ACE_RMCast_Reassembly::data.

00013 {
00014   return &this->message_body_;
00015 }

int ACE_RMCast_Partial_Message::remove_hole size_t    i [private]
 

Remove a hole from the list.

Definition at line 206 of file RMCast_Partial_Message.cpp.

References hole_count_, and hole_list_.

Referenced by fragment_received.

00207 {
00208   //  ACE_DEBUG ((LM_DEBUG,
00209   //              "Partial_Message::remove_hole %d\n",
00210   //              i));
00211   for (size_t j = i; j != this->hole_count_ - 1; ++j)
00212     this->hole_list_[j] = this->hole_list_[j + 1];
00213 
00214   this->hole_count_--;
00215   return 0;
00216 }


Member Data Documentation

size_t ACE_RMCast_Partial_Message::hole_count_ [private]
 

Definition at line 93 of file RMCast_Partial_Message.h.

Referenced by fragment_received, insert_hole, is_complete, and remove_hole.

Hole* ACE_RMCast_Partial_Message::hole_list_ [private]
 

Definition at line 91 of file RMCast_Partial_Message.h.

Referenced by ACE_RMCast_Partial_Message, fragment_received, insert_hole, is_complete, remove_hole, and ~ACE_RMCast_Partial_Message.

size_t ACE_RMCast_Partial_Message::max_hole_count_ [private]
 

Definition at line 92 of file RMCast_Partial_Message.h.

Referenced by insert_hole.

ACE_Message_Block ACE_RMCast_Partial_Message::message_body_ [private]
 

Maintain the message storage.

Definition at line 78 of file RMCast_Partial_Message.h.

Referenced by ACE_RMCast_Partial_Message, fragment_received, and message_body.


The documentation for this class was generated from the following files:
Generated on Mon Jun 16 13:14:06 2003 for ACE_RMCast by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002