Mem_Map_Stream.cpp

Go to the documentation of this file.
00001 // $Id: Mem_Map_Stream.cpp 78399 2007-05-18 02:54:37Z sowayaa $
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, "$Id: Mem_Map_Stream.cpp 78399 2007-05-18 02:54:37Z sowayaa $")
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<ACE_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 ACE_OFF_T
00100 ACEXML_Mem_Map_Stream::seek (ACE_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     }
00120 
00121   // Make sure that the backing store will cover this.
00122   while (this->get_pos_ > this->end_of_mapping_plus1_)
00123     if (this->grow_file_and_remap () == -1)
00124       this->get_pos_ = this->end_of_mapping_plus1_;
00125 
00126   this->recv_pos_ = this->get_pos_;
00127   return this->recv_pos_ - reinterpret_cast<char *> (this->mem_map_.addr ());
00128 }
00129 
00130 Svc_Handler *
00131 ACEXML_Mem_Map_Stream::svc_handler (void)
00132 {
00133   return this->svc_handler_;
00134 }
00135 
00136 size_t
00137 ACEXML_Mem_Map_Stream::available (void) const
00138 {
00139   return this->end_of_mapping_plus1_ - this->get_pos_;
00140 }
00141 
00142 int
00143 ACEXML_Mem_Map_Stream::open (Connector *connector,
00144                              const ACE_INET_Addr &addr)
00145 {
00146   svc_handler_ = 0;
00147 
00148   // Connect to the server at <addr>. If the handler has to be
00149   // connected to the server again, the Caching strategy takes care
00150   // and uses the same connection.
00151   if (connector->connect (svc_handler_,
00152                           addr) == -1)
00153     {
00154 
00155       ACE_ERROR_RETURN ((LM_ERROR,
00156                          "%p %s %d\n",
00157                          "Connect failed",
00158                          addr.get_host_name (),
00159                          addr.get_port_number ()),
00160                         -1);
00161     }
00162   // Create a temporary filename.
00163   ACE_FILE_Addr file (ACE_sap_any_cast (ACE_FILE_Addr &));
00164 
00165   // Create the temporary file via the <ACE_Mem_Map> class API.
00166   if (this->mem_map_.open (file.get_path_name (),
00167                            O_RDWR | O_CREAT | O_APPEND,
00168                            ACE_DEFAULT_FILE_PERMS) == -1)
00169     ACE_ERROR_RETURN ((LM_ERROR,
00170                        "%p\n",
00171                        "open"),
00172                       -1);
00173   // Make sure to unlink this right away so that if this process
00174   // crashes these files will be removed automatically.
00175   else if (ACE_OS::unlink (file.get_path_name ()) == -1)
00176     ACE_ERROR_RETURN ((LM_ERROR,
00177                        "%p\n",
00178                        "unlink"),
00179                       -1);
00180   else
00181     // Initialize all the position pointers to 0.
00182     this->rewind ();
00183 
00184   return 0;
00185 }
00186 
00187 int
00188 ACEXML_Mem_Map_Stream::grow_file_and_remap (void)
00189 {
00190   char buf[8192];
00191 
00192   // Copy the next chunk of bytes from the socket into the temporary
00193   // file.
00194   ACE_Time_Value tv (ACE_DEFAULT_TIMEOUT);
00195   ssize_t bytes = 0;
00196   ssize_t n = 0;
00197   while (1)
00198     {
00199       n = this->svc_handler_->peer ().recv (buf, sizeof buf, 0, &tv);
00200       if (n < 0)
00201         {
00202           if (errno != EWOULDBLOCK)
00203             {
00204               ACE_ERROR ((LM_ERROR, "%p\n", "recv"));
00205             }
00206 
00207           return -1;
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 (static_cast<size_t> (-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 Sun Jan 27 13:04:15 2008 for ACEXML by doxygen 1.3.6