summaryrefslogtreecommitdiff
path: root/ACE/ace/Mem_Map.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/ace/Mem_Map.cpp')
-rw-r--r--ACE/ace/Mem_Map.cpp372
1 files changed, 372 insertions, 0 deletions
diff --git a/ACE/ace/Mem_Map.cpp b/ACE/ace/Mem_Map.cpp
new file mode 100644
index 00000000000..112b4dfce9c
--- /dev/null
+++ b/ACE/ace/Mem_Map.cpp
@@ -0,0 +1,372 @@
+// $Id$
+
+// Defines the member functions for the memory mapping facility.
+
+#include "ace/Mem_Map.h"
+#if !defined (__ACE_INLINE__)
+#include "ace/Mem_Map.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/OS_NS_sys_stat.h"
+#include "ace/OS_NS_fcntl.h"
+#include "ace/OS_NS_string.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_WIN32) \
+ && (!defined(ACE_HAS_WINNT4) || (ACE_HAS_WINNT4 == 0))
+# define ACE_USE_MAPPING_NAME 1
+#endif /* ACE_WIN32 */
+
+#if defined (ACE_USE_MAPPING_NAME)
+#include "ace/SString.h"
+#endif /* ACE_USE_MAPPING_NAME */
+
+ACE_RCSID(ace, Mem_Map, "Mem_Map.cpp,v 4.39 2003/11/01 11:15:13 dhinton Exp")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Mem_Map)
+
+#if defined (ACE_USE_MAPPING_NAME)
+// Gets a mapping object name from a file name. TODO: The file name
+// is used as the key to the mapping. We should try to avoid mapping
+// the same object name to different files (there is a mapping object
+// name length limitation).
+
+static void
+to_mapping_name (ACE_TCHAR *mapobjname,
+ const ACE_TCHAR *filename,
+ size_t len)
+{
+ --len;
+ size_t i = 0;
+
+ while (*filename && i < len)
+ {
+ if (*filename == ACE_LIB_TEXT ('\\'))
+ // Can't use backslash in mapping object name.
+ mapobjname[i] = ACE_LIB_TEXT ('.');
+ else
+ mapobjname[i] = *filename;
+ ++filename;
+ ++i;
+ }
+
+ mapobjname[i] = 0;
+}
+#endif /* ACE_USE_MAPPING_NAME */
+
+void
+ACE_Mem_Map::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Mem_Map::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("base_addr_ = %x"), this->base_addr_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nfilename_ = %s"), this->filename_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nlength_ = %d"), this->length_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nhandle_ = %d"), this->handle_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nfile_mapping_ = %d"), this->file_mapping_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nclose_handle_ = %d"), this->close_handle_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+int
+ACE_Mem_Map::close (void)
+{
+ ACE_TRACE ("ACE_Mem_Map::close");
+
+ this->unmap ();
+
+ return this->close_handle ();
+}
+
+ACE_Mem_Map::~ACE_Mem_Map (void)
+{
+ ACE_TRACE ("ACE_Mem_Map::~ACE_Mem_Map");
+
+ this->close ();
+}
+
+// This function does the dirty work of actually calling ACE_OS::mmap
+// to map the file into memory.
+
+int
+ACE_Mem_Map::map_it (ACE_HANDLE handle,
+ ssize_t length_request,
+ int prot,
+ int share,
+ void *addr,
+ off_t offset,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_TRACE ("ACE_Mem_Map::map_it");
+
+#if defined (ACE_LACKS_AUTO_MMAP_REPLACEMENT)
+ // If the system does not replace any previous mappings, then
+ // unmap() before (potentially) mapping to the same location.
+ int const unmap_result = this->unmap ();
+ if (unmap_result != 0)
+ return unmap_result;
+#endif /* ACE_LACKS_AUTO_MMAP_REPLACEMENT */
+
+ this->base_addr_ = addr;
+ this->handle_ = handle;
+
+ ACE_LOFF_T const result = ACE_OS::filesize (this->handle_);
+
+ // At this point we know <result> is not negative...
+ size_t const current_file_length = static_cast<size_t> (result);
+
+ // Flag to indicate if we need to extend the back store
+ bool extend_backing_store = false;
+
+ // File length requested by user
+ size_t requested_file_length = 0;
+
+ // Check <length_request>
+ if (length_request == -1)
+ // Set length to file_request.
+ this->length_ = current_file_length - offset;
+ else
+ {
+ // File length implicitly requested by user
+ requested_file_length = length_request + offset;
+
+ // Check to see if we need to extend the backing store
+ if (requested_file_length > current_file_length)
+ {
+ // If the length of the mapped region is less than the
+ // length of the file then we force a complete new remapping
+ // by setting the descriptor to ACE_INVALID_HANDLE (closing
+ // down the descriptor if necessary).
+ this->close_filemapping_handle ();
+
+ // Remember to extend the backing store
+ extend_backing_store = true;
+ }
+
+ // Set length to length_request
+ this->length_ = length_request;
+ }
+
+ // Check if we need to extend the backing store.
+ if (extend_backing_store)
+ {
+ // Remember than write increases the size by one.
+ off_t null_byte_position;
+ if (requested_file_length > 0)
+ // This will make the file size <requested_file_length>
+ null_byte_position =
+ static_cast<off_t> (requested_file_length - 1);
+ else
+ // This will make the file size 1
+ null_byte_position = 0;
+
+ if (ACE_OS::pwrite (this->handle_,
+ "",
+ 1,
+ null_byte_position) == -1)
+ return -1;
+ }
+
+#if defined (ACE_HAS_LYNXOS_BROKEN_MMAP)
+ // Set flag that indicates whether PROT_WRITE has been enabled.
+ write_enabled_ = ACE_BIT_ENABLED (prot, PROT_WRITE);
+#endif /* ACE_HAS_LYNXOS_BROKEN_MMAP */
+
+#if defined (ACE_USE_MAPPING_NAME)
+ if (ACE_BIT_ENABLED (share, MAP_SHARED))
+ {
+# if defined(__MINGW32__)
+ const int max_mapping_name_length = 32;
+# else
+ const int max_mapping_name_length = 31;
+# endif /* __MINGW32__ */
+ ACE_TCHAR file_mapping_name[max_mapping_name_length + 1];
+ to_mapping_name (file_mapping_name,
+ filename_,
+ max_mapping_name_length + 1);
+
+ this->base_addr_ = ACE_OS::mmap (this->base_addr_,
+ this->length_,
+ prot,
+ share,
+ this->handle_,
+ offset,
+ &this->file_mapping_,
+ sa,
+ file_mapping_name);
+ }
+ else
+#endif /* ACE_USE_MAPPING_NAME */
+ this->base_addr_ = ACE_OS::mmap (this->base_addr_,
+ this->length_,
+ prot,
+ share,
+ this->handle_,
+ offset,
+ &this->file_mapping_,
+ sa);
+
+ return this->base_addr_ == MAP_FAILED ? -1 : 0;
+}
+
+int
+ACE_Mem_Map::open (const ACE_TCHAR *file_name,
+ int flags,
+ int mode,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_TRACE ("ACE_Mem_Map::open");
+
+#if defined(INTEGRITY) || defined (__QNXNTO__)
+ this->handle_ = ACE_OS::shm_open (file_name, flags, mode, sa);
+#elif defined (ACE_OPENVMS)
+ ACE_OSCALL (::open (file_name, flags, mode, "shr=get,put,upd"), ACE_HANDLE, -1, this->handle_);
+#else
+ this->handle_ = ACE_OS::open (file_name, flags, mode, sa);
+#endif /* INTEGRITY */
+
+ if (this->handle_ == ACE_INVALID_HANDLE)
+ return -1;
+ else
+ {
+ ACE_OS::strsncpy (this->filename_,
+ file_name,
+ MAXPATHLEN);
+
+ this->close_handle_ = true;
+ return 0;
+ }
+}
+
+int
+ACE_Mem_Map::map (const ACE_TCHAR *file_name,
+ ssize_t len,
+ int flags,
+ int mode,
+ int prot,
+ int share,
+ void *addr,
+ off_t offset,
+ LPSECURITY_ATTRIBUTES sa)
+{
+ ACE_TRACE ("ACE_Mem_Map::map");
+ this->length_ = 0;
+
+ if (this->open (file_name,
+ flags,
+ mode,
+ sa) == -1)
+ return -1;
+ else
+ return this->map_it (this->handle (),
+ len,
+ prot,
+ share,
+ addr,
+ offset,
+ sa);
+}
+
+ACE_Mem_Map::ACE_Mem_Map (void)
+ : base_addr_ (MAP_FAILED),
+ length_ (0),
+ handle_ (ACE_INVALID_HANDLE),
+ file_mapping_ (ACE_INVALID_HANDLE),
+ close_handle_ (false)
+{
+ ACE_TRACE ("ACE_Mem_Map::ACE_Mem_Map");
+ ACE_OS::memset (this->filename_, 0, sizeof this->filename_);
+}
+
+// Map a file specified by FILE_NAME.
+
+ACE_Mem_Map::ACE_Mem_Map (const ACE_TCHAR *file_name,
+ ssize_t len,
+ int flags,
+ int mode,
+ int prot,
+ int share,
+ void *addr,
+ off_t offset,
+ LPSECURITY_ATTRIBUTES sa)
+ : base_addr_ (MAP_FAILED),
+ length_ (0),
+ handle_ (ACE_INVALID_HANDLE),
+ file_mapping_ (ACE_INVALID_HANDLE),
+ close_handle_ (false)
+{
+ ACE_TRACE ("ACE_Mem_Map::ACE_Mem_Map");
+ if (this->map (file_name,
+ len,
+ flags,
+ mode,
+ prot,
+ share,
+ addr,
+ offset,
+ sa) < 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Mem_Map::ACE_Mem_Map")));
+}
+
+// Map a file from an open file descriptor HANDLE. This function will
+// lookup the length of the file if it is not given.
+
+ACE_Mem_Map::ACE_Mem_Map (ACE_HANDLE handle,
+ ssize_t len,
+ int prot,
+ int share,
+ void *addr,
+ off_t offset,
+ LPSECURITY_ATTRIBUTES sa)
+ : base_addr_ (MAP_FAILED),
+ length_ (0),
+ handle_ (ACE_INVALID_HANDLE),
+ file_mapping_ (ACE_INVALID_HANDLE),
+ close_handle_ (false)
+{
+ ACE_TRACE ("ACE_Mem_Map::ACE_Mem_Map");
+
+ ACE_OS::memset (this->filename_,
+ 0,
+ sizeof this->filename_);
+ if (this->map (handle,
+ len,
+ prot,
+ share,
+ addr,
+ offset,
+ sa) < 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_Mem_Map::ACE_Mem_Map")));
+}
+
+// Close down and remove the file from the file system.
+
+int
+ACE_Mem_Map::remove (void)
+{
+ ACE_TRACE ("ACE_Mem_Map::remove");
+
+ ACE_OS::ftruncate (this->handle_, 0);
+ this->close ();
+
+ if (this->filename_[0] != '\0')
+#if defined (__QNXNTO__)
+ return ACE_OS::shm_unlink (this->filename_);
+#else
+ return ACE_OS::unlink (this->filename_);
+#endif /* __QNXNTO__ */
+
+ else
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL