Bug 847479 - Add a helper class for a buffer mapped from a file. r=nfroyd
authorMike Hommey <mh+mozilla@glandium.org>
Wed, 06 Mar 2013 07:29:13 +0100
changeset 123911 c6b328fb4f3ec9f8e0efec2f9a543a6f40b9d1b9
parent 123910 0effb755bdbebf01a94d0a3886679cc84766397c
child 123912 2244aa90a7b32e82c0218dbf24aa0a8a5b6daf48
push id1401
push userpastithas@mozilla.com
push dateThu, 07 Mar 2013 07:26:45 +0000
treeherderfx-team@ee4879719f78 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnfroyd
bugs847479
milestone22.0a1
Bug 847479 - Add a helper class for a buffer mapped from a file. r=nfroyd
mozglue/linker/szip.cpp
--- a/mozglue/linker/szip.cpp
+++ b/mozglue/linker/szip.cpp
@@ -9,132 +9,151 @@
 #include <fcntl.h>
 #include <errno.h>
 #include "mozilla/Assertions.h"
 #include "mozilla/Scoped.h"
 #include "SeekableZStream.h"
 #include "Utils.h"
 #include "Logging.h"
 
+class FileBuffer: public MappedPtr
+{
+public:
+  bool Init(const char *name, bool writable_ = false)
+  {
+    fd = open(name, writable_ ? O_RDWR | O_CREAT | O_TRUNC : O_RDONLY, 0666);
+    if (fd == -1)
+      return false;
+    writable = writable_;
+    return true;
+  }
+
+  bool Resize(size_t size)
+  {
+    if (writable) {
+      if (ftruncate(fd, size) == -1)
+        return false;
+    }
+    Assign(mmap(NULL, size, PROT_READ | (writable ? PROT_WRITE : 0),
+                writable ? MAP_SHARED : MAP_PRIVATE, fd, 0), size);
+    return this != MAP_FAILED;
+  }
+
+  int getFd()
+  {
+    return fd;
+  }
+
+private:
+  AutoCloseFD fd;
+  bool writable;
+};
+
 static const size_t CHUNK = 16384;
 
 /* Generate a seekable compressed stream. */
 
 int main(int argc, char* argv[])
 {
   if (argc != 3 || !argv[1] || !argv[2] || (strcmp(argv[1], argv[2]) == 0)) {
     log("usage: %s file_to_compress out_file", argv[0]);
     return 1;
   }
 
-  AutoCloseFD origFd;
-  origFd = open(argv[1], O_RDONLY);
-  if (origFd == -1) {
+  FileBuffer origBuf;
+  if (!origBuf.Init(argv[1])) {
     log("Couldn't open %s: %s", argv[1], strerror(errno));
     return 1;
   }
 
   struct stat st;
-  int ret = fstat(origFd, &st);
+  int ret = fstat(origBuf.getFd(), &st);
   if (ret == -1) {
-    log("Couldn't seek %s: %s", argv[1], strerror(errno));
+    log("Couldn't stat %s: %s", argv[1], strerror(errno));
     return 1;
   }
 
   size_t origSize = st.st_size;
   log("Size = %lu", origSize);
   if (origSize == 0) {
     log("Won't compress %s: it's empty", argv[1]);
     return 1;
   }
 
   /* Mmap the original file */
-  MappedPtr origBuf;
-  origBuf.Assign(mmap(NULL, origSize, PROT_READ, MAP_PRIVATE, origFd, 0), origSize);
-  if (origBuf == MAP_FAILED) {
+  if (!origBuf.Resize(origSize)) {
     log("Couldn't mmap %s: %s", argv[1], strerror(errno));
     return 1;
   }
 
   /* Create the compressed file */
-  AutoCloseFD outFd;
-  outFd = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0666);
-  if (outFd == -1) {
+  FileBuffer outBuf;
+  if (!outBuf.Init(argv[2], true)) {
     log("Couldn't open %s: %s", argv[2], strerror(errno));
     return 1;
   }
 
   /* Expected total number of chunks */
   size_t nChunks = ((origSize + CHUNK - 1) / CHUNK);
 
   /* The first chunk is going to be stored after the header and the offset
    * table */
   size_t offset = sizeof(SeekableZStreamHeader) + nChunks * sizeof(uint32_t);
 
   /* Give enough room for the header and the offset table, and map them */
-  ret = ftruncate(outFd, offset);
-  MOZ_ASSERT(ret == 0);
-  MappedPtr headerMap;
-  headerMap.Assign(mmap(NULL, offset, PROT_READ | PROT_WRITE, MAP_SHARED,
-                        outFd, 0), offset);
-  if (headerMap == MAP_FAILED) {
-    log("Couldn't mmap %s: %s", argv[1], strerror(errno));
+  if (!outBuf.Resize(origSize)) {
+    log("Couldn't mmap %s: %s", argv[2], strerror(errno));
     return 1;
   }
 
-  SeekableZStreamHeader *header = new (headerMap) SeekableZStreamHeader;
+  SeekableZStreamHeader *header = new (outBuf) SeekableZStreamHeader;
   le_uint32 *entry = reinterpret_cast<le_uint32 *>(&header[1]);
 
   /* Initialize header */
   header->chunkSize = CHUNK;
   header->totalSize = offset;
 
-  /* Seek at the end of the output file, where we're going to append
-   * compressed streams */
-  lseek(outFd, offset, SEEK_SET);
-
   /* Initialize zlib structure */
   z_stream zStream;
   memset(&zStream, 0, sizeof(zStream));
-
-  /* Compression buffer */
-  mozilla::ScopedDeleteArray<Bytef> outBuf;
-  outBuf = new Bytef[CHUNK * 2];
+  zStream.avail_out = origSize - offset;
+  zStream.next_out = static_cast<Bytef*>(outBuf) + offset;
 
   Bytef *origData = static_cast<Bytef*>(origBuf);
   size_t avail = 0;
-  while (origSize) {
-    avail = std::min(origSize, CHUNK);
+  size_t size = origSize;
+  while (size) {
+    avail = std::min(size, CHUNK);
 
     /* Compress chunk */
     ret = deflateInit(&zStream, 9);
     MOZ_ASSERT(ret == Z_OK);
     zStream.avail_in = avail;
     zStream.next_in = origData;
-    zStream.avail_out = CHUNK * 2;
-    zStream.next_out = outBuf;
     ret = deflate(&zStream, Z_FINISH);
     MOZ_ASSERT(ret == Z_STREAM_END);
     ret = deflateEnd(&zStream);
     MOZ_ASSERT(ret == Z_OK);
     MOZ_ASSERT(zStream.avail_out > 0);
 
-    /* Write chunk */
-    size_t len = write(outFd, outBuf, 2 * CHUNK - zStream.avail_out);
-    MOZ_ASSERT(len == 2 * CHUNK - zStream.avail_out);
+    size_t len = origSize - offset - zStream.avail_out;
 
     /* Adjust headers */
     header->totalSize += len;
     *entry++ = offset;
     header->nChunks++;
 
     /* Prepare for next iteration */
-    origSize -= avail;
+    size -= avail;
     origData += avail;
     offset += len;
   }
   header->lastChunkSize = avail;
+  if (!outBuf.Resize(offset)) {
+    log("Error resizing %s: %s", argv[2], strerror(errno));
+    return 1;
+  }
 
   MOZ_ASSERT(header->nChunks == nChunks);
   log("Compressed size is %lu", offset);
 
   return 0;
 }