next up previous contents index
Next: SortedTable.h Up: The Sources Previous: PersistentStorage.cc

MMap.h

// MMap.h -- mmap() system call wrapper class
// 11/4/97
// 11/29/97 modified for private mappings of /dev/zero

#ifndef __MMAP_H
#define __MMAP_H
#pragma interface "MMap.h"

#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>

/*
  MMap -- wrapper class for the system call mmap()

  This wrapper class provides a simple interface to the system call mmap().
  The object contains:
  int         fd -- the file descriptor of the file to be mapped
  const char *fileName -- the name of the file to be mapped
  size_t      length -- the length of the mapped region in bytes
  off_t       offset -- the offset of the mapped region in the file
  int         prot -- the protection mode of the mapping
  int         flags -- the flags of the mapping
  void       *paddr -- the address of the mapped region in the main memory
 */
class MMap {
protected:
  int fd;  // file descriptor
  char *fileName; // file name
  size_t length; // length of the mapped region in bytes
  off_t offset;  // offset of the mapped region in the file
  int prot; // protection mode of mmap
  int flags; // mmap flags
  void *paddr; // mapped addr in main memory

public:
  // constructors
  
  /*
    MMap(fd) -- constructor by a file descriptor

    parameters:
    int FD -- the file descriptor 
    int p -- the protection mode
   */
  MMap(int FD = -1, int p = PROT_READ | PROT_WRITE): 
    fd(FD), 
    fileName(0), 
    prot(p), 
    flags(MAP_SHARED), 
    paddr(0) {}

  /*
    MMap(MMap &) -- constructor by another MMap object

    parameter:
    MMap &m -- the MMap object, whose mapping is not inherited
   */
  MMap(MMap &m): 
    fd(m.fd), 
    fileName(0), 
    prot(m.prot), 
    flags(m.flags), 
    paddr(0) {}

  /*
    MMap(file) -- general constructor by a file name

    parameters:
    const char *file -- the file name for mapping
    int p -- the protection mode
   */
  MMap(const char *file, int p = PROT_READ | PROT_WRITE) : paddr(0) {
    struct stat st;
    static const char DevZero[] = "/dev/zero";
    if (file == 0) { 
      fd = -1; 
      return; 
    } 
    if (strcmp(file, DevZero) != 0) {
      if (stat(file, &st) != 0) { 
        fd = -1; 
        return; 
      }
      if (!S_ISREG(st.st_mode)) { 
        fd = -1; 
        return; 
      }
      if (st.st_size <= 0) { 
        fd = -1; 
        return; 
      }
    }
    if (p & PROT_WRITE) {
      if ((fd = open(file, O_RDWR)) == -1) { 
        fd = -1; 
        return; 
      }
    } else {
      if ((fd = open(file, O_RDONLY)) == -1) { 
        fd = -1; 
        return; 
      }
    }
    fileName = new char[strlen(file) + 1];
    strcpy(fileName, file);
    prot = p;
    if (strcmp(file, DevZero) != 0) {
      flags = MAP_SHARED;
    } else {
      flags = MAP_PRIVATE; 
    }
  }

  /*
    assignment operater with another MMap object

    parameter:
    MMap &m -- another MMap object, whose mapping is not inherited
   */
  MMap &operator=(MMap &m) { 
    fd = m.fd;
    fileName = 0;
    prot = m.prot; 
    flags = m.flags; 
    paddr = 0;
    return *this;
  }

  /* 
     ~MMap() -- destructor
     
     This destructor unmaps the existing mapping.
   */
  ~MMap() {
    if (fd != -1 && paddr != 0) {
      this->unmap();
      if (fileName) {
        close(fd);
      }
    }
  }

  /* 
     map -- map a region to the main memory
     
     parameters:
     off_t  off -- the offset of the beginning of the region in the file
     size_t len -- the length of the region in bytes

     return value:
     void * -- the address of the mapped region in the main memory,
               0 when mapping failed
   */
  void *map(off_t off, size_t len) {
    if (fd == -1) 
      return 0; 
    if (paddr != 0) // already mapped
      munmap(paddr, length); // unmap the previous mapping
    
    paddr = mmap(0, len, prot, flags, fd, off);
    if ((int)paddr == -1) { 
      paddr = 0; 
      return 0; 
    }
    offset = off;
    length = len; 
    return paddr;
  }

  /*
    unmap -- unmap the region

    parameter: none

    return value:
    int -- -1 when unmapping failed
   */
  int unmap() {
    if (fd == -1) 
      return -1; 
    if (paddr == 0)
      return -1; 
    if (munmap(paddr, length) != 0) {
      return -1;
    } else {
      paddr = 0;
      return 0;
    }
  }

  /*
    sync -- synchronize the memory with the file

    parameter:
    int syncflags -- MS_SYNC for synchronous operation,
                     MS_ASYNC for asynchronous operation

    return value:
    int -- -1 when synchronization failed
   */
  int sync(int syncflags = MS_SYNC) {
    if (fd == -1) 
      return -1; 
    if (paddr == 0) 
      return -1;
    if (msync(paddr, length, syncflags) != 0)
      return -1; 
    else
      return 0;
  }

  // accessors

  // get the file descriptor
  int getFd() { 
    return fd; 
  }

  // get the file name
  const char *getFileName() { 
    return fileName; 
  }

  // get the address of the mapped region in the main memory
  inline void *getAddr() { 
    return paddr; 
  }

  // get the length of the mapped region
  inline size_t getLength() { 
    return paddr ? length : -1; 
  }

  // get the offset of the mapped region in the file
  inline off_t getOffset() { 
    return paddr ? offset : -1; 
  }
};

#endif // __MMAP_H



Mori Tetsuya / t2y3141592@gmail.com