Mem_Map_Stream.cpp

Go to the documentation of this file.
00001 // Mem_Map_Stream.cpp,v 1.15 2006/04/20 09:55:37 jwillemsen Exp
00002 
00003 #include "ace/FILE_Addr.h"
00004 #include "ace/OS_NS_unistd.h"
00005 #include "ACEXML/common/Mem_Map_Stream.h"
00006 
00007 ACE_RCSID(common, Mem_Map_Stream, "Mem_Map_Stream.cpp,v 1.15 2006/04/20 09:55:37 jwillemsen Exp")
00008 
00009 ACEXML_Mem_Map_Stream::ACEXML_Mem_Map_Stream (void)
00010   : svc_handler_ (0)
00011 {
00012 
00013 }
00014 
00015 ACE_SOCK_Stream &
00016 ACEXML_Mem_Map_Stream::stream (void)
00017 {
00018   return svc_handler_->peer ();
00019 }
00020 
00021 ssize_t
00022 ACEXML_Mem_Map_Stream::send_n (const void *buf, size_t size,
00023                                ACE_Time_Value *tv)
00024 {
00025   return svc_handler_->peer ().send_n (buf, size, 0, tv);
00026 }
00027 
00028 int
00029 ACEXML_Mem_Map_Stream::eof (void) const
00030 {
00031   return this->get_pos_ >= this->end_of_mapping_plus1_;
00032 }
00033 
00034 int
00035 ACEXML_Mem_Map_Stream::get_char (void)
00036 {
00037   if (this->eof () && this->grow_file_and_remap () == -1)
00038     return EOF;
00039   return *this->get_pos_++;
00040 }
00041 
00042 void
00043 ACEXML_Mem_Map_Stream::rewind (void)
00044 {
00045   this->recv_pos_ = reinterpret_cast<char *> (this->mem_map_.addr ());
00046   this->get_pos_ = this->recv_pos_;
00047   this->end_of_mapping_plus1_ = this->recv_pos_ + this->mem_map_.size ();
00048 }
00049 
00050 int
00051 ACEXML_Mem_Map_Stream::peek_char (size_t offset)
00052 {
00053   // We may need to iterate if the size of <n> is large.
00054   while (this->get_pos_ + offset >= this->end_of_mapping_plus1_)
00055     if (this->grow_file_and_remap () == -1)
00056       return EOF;
00057 
00058   return this->get_pos_[offset];
00059 }
00060 
00061 const char *
00062 ACEXML_Mem_Map_Stream::recv (void) const
00063 {
00064   return this->recv_pos_;
00065 }
00066 
00067 const char *
00068 ACEXML_Mem_Map_Stream::recv (size_t &len)
00069 {
00070   if (this->eof () && this->grow_file_and_remap () == -1)
00071     {
00072       len = 0;
00073       return 0;
00074     }
00075   const char *s = this->recv_pos_;
00076   this->seek (static_cast<off_t> (len), SEEK_CUR);
00077   len = this->get_pos_ - s;
00078   return s;
00079 }
00080 
00081 size_t
00082 ACEXML_Mem_Map_Stream::recv_len (void) const
00083 {
00084   return this->get_pos_ - this->recv_pos_;
00085 }
00086 
00087 const char *
00088 ACEXML_Mem_Map_Stream::peek_str (size_t offset,
00089                                  size_t size)
00090 {
00091   // We will iterate if the size of <offset> is large.
00092   while (this->get_pos_ + (offset + size) > this->end_of_mapping_plus1_)
00093     if (this->grow_file_and_remap () == -1)
00094       return 0;
00095 
00096   return &this->get_pos_[offset];
00097 }
00098 
00099 off_t
00100 ACEXML_Mem_Map_Stream::seek (off_t offset, int whence)
00101 {
00102   switch (whence)
00103     {
00104     case SEEK_SET:
00105       this->get_pos_ =
00106         reinterpret_cast<char *> (this->mem_map_.addr ())
00107         + offset;
00108       break;
00109 
00110     case SEEK_CUR:
00111       this->get_pos_ += offset;
00112       break;
00113 
00114     case SEEK_END:
00115       this->get_pos_ =
00116         this->end_of_mapping_plus1_ + offset;
00117       // @@ Not sure how to implement this (yet).
00118       ACE_NOTSUP_RETURN (-1);
00119       break;
00120     }
00121 
00122   // Make sure that the backing store will cover this.
00123   while (this->get_pos_ > this->end_of_mapping_plus1_)
00124     if (this->grow_file_and_remap () == -1)
00125       this->get_pos_ = this->end_of_mapping_plus1_;
00126 
00127   this->recv_pos_ = this->get_pos_;
00128   return this->recv_pos_ - reinterpret_cast<char *> (this->mem_map_.addr ());
00129 }
00130 
00131 Svc_Handler *
00132 ACEXML_Mem_Map_Stream::svc_handler (void)
00133 {
00134   return this->svc_handler_;
00135 }
00136 
00137 size_t
00138 ACEXML_Mem_Map_Stream::available (void) const
00139 {
00140   return this->end_of_mapping_plus1_ - this->get_pos_;
00141 }
00142 
00143 int
00144 ACEXML_Mem_Map_Stream::open (Connector *connector,
00145                              const ACE_INET_Addr &addr)
00146 {
00147   svc_handler_ = 0;
00148 
00149   // Connect to the server at <addr>. If the handler has to be
00150   // connected to the server again, the Caching strategy takes care
00151   // and uses the same connection.
00152   if (connector->connect (svc_handler_,
00153                           addr) == -1)
00154     {
00155 
00156       ACE_ERROR_RETURN ((LM_ERROR,
00157                          "%p %s %d\n",
00158                          "Connect failed",
00159                          addr.get_host_name (),
00160                          addr.get_port_number ()),
00161                         -1);
00162     }
00163   // Create a temporary filename.
00164   ACE_FILE_Addr file (ACE_sap_any_cast (ACE_FILE_Addr &));
00165 
00166   // Create the temporary file via the <ACE_Mem_Map> class API.
00167   if (this->mem_map_.open (file.get_path_name (),
00168                            O_RDWR | O_CREAT | O_APPEND,
00169                            ACE_DEFAULT_FILE_PERMS) == -1)
00170     ACE_ERROR_RETURN ((LM_ERROR,
00171                        "%p\n",
00172                        "open"),
00173                       -1);
00174   // Make sure to unlink this right away so that if this process
00175   // crashes these files will be removed automatically.
00176   else if (ACE_OS::unlink (file.get_path_name ()) == -1)
00177     ACE_ERROR_RETURN ((LM_ERROR,
00178                        "%p\n",
00179                        "unlink"),
00180                       -1);
00181   else
00182     // Initialize all the position pointers to 0.
00183     this->rewind ();
00184 
00185   return 0;
00186 }
00187 
00188 int
00189 ACEXML_Mem_Map_Stream::grow_file_and_remap (void)
00190 {
00191   char buf[8192];
00192 
00193   // Copy the next chunk of bytes from the socket into the temporary
00194   // file.
00195   ACE_Time_Value tv (ACE_DEFAULT_TIMEOUT);
00196   ssize_t bytes = 0;
00197   ssize_t n = 0;
00198   while (1)
00199     {
00200       n = this->svc_handler_->peer ().recv (buf, sizeof buf, 0, &tv);
00201       if (n == -1)
00202         {
00203           if (errno != EWOULDBLOCK)
00204             {
00205               ACE_ERROR ((LM_ERROR, "%p\n", "recv"));
00206               return -1;
00207             }
00208         }
00209       bytes += n;
00210       if (n == 0 && !bytes)
00211         return -1;
00212       else if (n == 0)
00213         break;
00214       else if (ACE::write_n (this->mem_map_.handle (), buf, n) != n)
00215         ACE_ERROR_RETURN ((LM_ERROR,
00216                            "%p\n",
00217                            "write_n"),
00218                           -1);
00219     }
00220 
00221 //   ssize_t n = this->svc_handler_->peer ().recv (buf, sizeof buf, 0, &tv);
00222 //   if (n == -1)
00223 //     {
00224 //       ACE_ERROR ((LM_ERROR, "%p\n", "recv"));
00225 //       return -1;
00226 //     }
00227 //   else if (n == 0)
00228 //     return -1;
00229 //   else if (ACE::write_n (this->mem_map_.handle (), buf, n) != n)
00230 //         ACE_ERROR_RETURN ((LM_ERROR,
00231 //                            "%p\n",
00232 //                            "write_n"),
00233 //                           -1);
00234 
00235   // Grow the memory-mapping to encompass the entire temporary file.
00236   if (this->mem_map_.map (-1,
00237                           PROT_RDWR,
00238                           ACE_MAP_PRIVATE,
00239                           (void*)0) == -1)
00240     ACE_ERROR_RETURN ((LM_ERROR,
00241                        "%p\n",
00242                        "map"),
00243                       -1);
00244   // MAP_FAILED is used as a "first time in" flag.
00245   if (this->recv_pos_ == MAP_FAILED)
00246     {
00247       this->recv_pos_ = reinterpret_cast<char *> (this->mem_map_.addr ());
00248       this->get_pos_ = this->recv_pos_;
00249     }
00250 
00251   this->end_of_mapping_plus1_ =
00252     reinterpret_cast<char *> (this->mem_map_.addr ())
00253     + this->mem_map_.size ();
00254 
00255   return 0;
00256 }
00257 
00258 ACEXML_Mem_Map_Stream::~ACEXML_Mem_Map_Stream (void)
00259 {
00260   // Remove the mapping and the file.
00261   this->mem_map_.remove ();
00262   delete this->svc_handler_;
00263 }
00264 

Generated on Thu Nov 9 11:45:37 2006 for ACEXML by doxygen 1.3.6