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

RMCast_Partial_Message.cpp

Go to the documentation of this file.
00001 // $Id: RMCast_Partial_Message.cpp,v 1.1.1.1.64.1 2003/05/05 16:04:55 chad Exp $
00002 
00003 #include "RMCast_Partial_Message.h"
00004 
00005 #if !defined (__ACE_INLINE__)
00006 #include "RMCast_Partial_Message.i"
00007 #endif /* __ACE_INLINE__ */
00008 
00009 ACE_RCSID(ace, RMCast_Partial_Message, "$Id: RMCast_Partial_Message.cpp,v 1.1.1.1.64.1 2003/05/05 16:04:55 chad Exp $")
00010 
00011 
00012 ACE_RMCast_Partial_Message::ACE_RMCast_Partial_Message (ACE_UINT32 message_size)
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 }
00024 
00025 
00026 ACE_RMCast_Partial_Message::~ACE_RMCast_Partial_Message (void)
00027 {
00028   delete[] this->hole_list_;
00029 }
00030 
00031 int
00032 ACE_RMCast_Partial_Message::fragment_received (ACE_UINT32 message_size,
00033                                                ACE_UINT32 offset,
00034                                                ACE_Message_Block *mb)
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 }
00169 
00170 int
00171 ACE_RMCast_Partial_Message::insert_hole (size_t i,
00172                                          ACE_UINT32 start,
00173                                          ACE_UINT32 end)
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 }
00204 
00205 int
00206 ACE_RMCast_Partial_Message::remove_hole (size_t i)
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 }

Generated on Mon Jun 16 13:12:36 2003 for ACE_RMCast by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002