Bug 727960 - When extracting libraries, reuse cached library if it is newer than the apk. r=tglek
authorMike Hommey <mh+mozilla@glandium.org>
Wed, 22 Feb 2012 08:12:15 +0100
changeset 87356 1419f0146049aa9a5a59ba350ff1435733123e70
parent 87355 b8c9749cfff715824e35fd0349155311beab6e67
child 87357 013b99c7ae65f7d1fc5250a2dcca42e331d7c14d
push idunknown
push userunknown
push dateunknown
reviewerstglek
bugs727960
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 727960 - When extracting libraries, reuse cached library if it is newer than the apk. r=tglek
mozglue/linker/ElfLoader.cpp
mozglue/linker/Mappable.cpp
mozglue/linker/Mappable.h
--- a/mozglue/linker/ElfLoader.cpp
+++ b/mozglue/linker/ElfLoader.cpp
@@ -227,17 +227,17 @@ ElfLoader::Load(const char *path, int fl
     Zip::Stream s;
     if (zip && zip->GetStream(subpath, &s)) {
       /* When the MOZ_LINKER_EXTRACT environment variable is set to "1",
        * compressed libraries are going to be (temporarily) extracted as
        * files, in the directory pointed by the MOZ_LINKER_CACHE
        * environment variable. */
       const char *extract = getenv("MOZ_LINKER_EXTRACT");
       if (extract && !strncmp(extract, "1", 2 /* Including '\0' */))
-        mappable = MappableExtractFile::Create(name, &s);
+        mappable = MappableExtractFile::Create(name, zip, &s);
       if (!mappable) {
         if (s.GetType() == Zip::Stream::DEFLATE) {
           mappable = MappableDeflate::Create(name, zip, &s);
         } else if (s.GetType() == Zip::Stream::STORE) {
           mappable = MappableSeekableZStream::Create(name, zip, &s);
         }
       }
     }
--- a/mozglue/linker/Mappable.cpp
+++ b/mozglue/linker/Mappable.cpp
@@ -7,29 +7,31 @@
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <cstring>
 #include <cstdlib>
 #include "Mappable.h"
 #ifdef ANDROID
 #include <linux/ashmem.h>
 #endif
+#include <sys/stat.h>
 #include "ElfLoader.h"
 #include "SeekableZStream.h"
 #include "Logging.h"
 
 #ifndef PAGE_SIZE
 #define PAGE_SIZE 4096
 #endif
 
 #ifndef PAGE_MASK
 #define PAGE_MASK (~ (PAGE_SIZE - 1))
 #endif
 
-MappableFile *MappableFile::Create(const char *path)
+Mappable *
+MappableFile::Create(const char *path)
 {
   int fd = open(path, O_RDONLY);
   if (fd != -1)
     return new MappableFile(fd);
   return NULL;
 }
 
 void *
@@ -57,28 +59,37 @@ MappableFile::mmap(const void *addr, siz
 
 void
 MappableFile::finalize()
 {
   /* Close file ; equivalent to close(fd.forget()) */
   fd = -1;
 }
 
-MappableExtractFile *
-MappableExtractFile::Create(const char *name, Zip::Stream *stream)
+Mappable *
+MappableExtractFile::Create(const char *name, Zip *zip, Zip::Stream *stream)
 {
   const char *cachePath = getenv("MOZ_LINKER_CACHE");
   if (!cachePath || !*cachePath) {
     log("Warning: MOZ_LINKER_EXTRACT is set, but not MOZ_LINKER_CACHE; "
         "not extracting");
     return NULL;
   }
   AutoDeleteArray<char> path = new char[strlen(cachePath) + strlen(name) + 2];
   sprintf(path, "%s/%s", cachePath, name);
-  debug("Extracting to %s", (char *)path);
+  struct stat cacheStat;
+  if (stat(path, &cacheStat) == 0) {
+    struct stat zipStat;
+    stat(zip->GetName(), &zipStat);
+    if (cacheStat.st_mtime > zipStat.st_mtime) {
+      debug("Reusing %s", static_cast<char *>(path));
+      return MappableFile::Create(path);
+    }
+  }
+  debug("Extracting to %s", static_cast<char *>(path));
   AutoCloseFD fd = open(path, O_TRUNC | O_RDWR | O_CREAT | O_NOATIME,
                               S_IRUSR | S_IWUSR);
   if (fd == -1) {
     log("Couldn't open %s to decompress library", path.get());
     return NULL;
   }
   AutoUnlinkFile file = path.forget();
   if (stream->GetType() == Zip::Stream::DEFLATE) {
@@ -241,17 +252,17 @@ private:
   _MappableBuffer(int fd, void *buf, size_t length)
   : MappedPtr(buf, length), fd(fd) { }
 
   /* File descriptor for the temporary file or ashmem */
   AutoCloseFD fd;
 };
 
 
-MappableDeflate *
+Mappable *
 MappableDeflate::Create(const char *name, Zip *zip, Zip::Stream *stream)
 {
   MOZ_ASSERT(stream->GetType() == Zip::Stream::DEFLATE);
   _MappableBuffer *buf = _MappableBuffer::Create(name, stream->GetUncompressedSize());
   if (buf)
     return new MappableDeflate(buf, zip, stream);
   return NULL;
 }
@@ -319,17 +330,17 @@ void
 MappableDeflate::finalize()
 {
   /* Free decompression buffer */
   buffer = NULL;
   /* Remove reference to Zip archive */
   zip = NULL;
 }
 
-MappableSeekableZStream *
+Mappable *
 MappableSeekableZStream::Create(const char *name, Zip *zip,
                                 Zip::Stream *stream)
 {
   MOZ_ASSERT(stream->GetType() == Zip::Stream::STORE);
   AutoDeletePtr<MappableSeekableZStream> mappable =
     new MappableSeekableZStream(zip);
 
   if (pthread_mutex_init(&mappable->mutex, NULL))
--- a/mozglue/linker/Mappable.h
+++ b/mozglue/linker/Mappable.h
@@ -67,17 +67,17 @@ public:
 class MappableFile: public Mappable
 {
 public:
   ~MappableFile() { }
 
   /**
    * Create a MappableFile instance for the given file path.
    */
-  static MappableFile *Create(const char *path);
+  static Mappable *Create(const char *path);
 
   /* Inherited from Mappable */
   virtual void *mmap(const void *addr, size_t length, int prot, int flags, off_t offset);
   virtual void finalize();
 
 protected:
   MappableFile(int fd): fd(fd) { }
 
@@ -94,24 +94,18 @@ class MappableExtractFile: public Mappab
 {
 public:
   ~MappableExtractFile();
 
   /**
    * Create a MappableExtractFile instance for the given Zip stream. The name
    * argument is used to create the cache file in the cache directory.
    */
-  static MappableExtractFile *Create(const char *name, Zip::Stream *stream);
+  static Mappable *Create(const char *name, Zip *zip, Zip::Stream *stream);
 
-  /**
-   * Returns the path of the extracted file.
-   */
-  char *GetPath() {
-    return path;
-  }
 private:
   MappableExtractFile(int fd, char *path)
   : MappableFile(fd), path(path), pid(getpid()) { }
 
   /**
    * AutoUnlinkFile keeps track or a file name and removes (unlinks) the file
    * when the instance is destroyed.
    */
@@ -143,17 +137,17 @@ class MappableDeflate: public Mappable
 public:
   ~MappableDeflate();
 
   /**
    * Create a MappableDeflate instance for the given Zip stream. The name
    * argument is used for an appropriately named temporary file, and the Zip
    * instance is given for the MappableDeflate to keep a reference of it.
    */
-  static MappableDeflate *Create(const char *name, Zip *zip, Zip::Stream *stream);
+  static Mappable *Create(const char *name, Zip *zip, Zip::Stream *stream);
 
   /* Inherited from Mappable */
   virtual void *mmap(const void *addr, size_t length, int prot, int flags, off_t offset);
   virtual void finalize();
 
 private:
   MappableDeflate(_MappableBuffer *buf, Zip *zip, Zip::Stream *stream);
 
@@ -177,17 +171,17 @@ public:
   ~MappableSeekableZStream();
 
   /**
    * Create a MappableSeekableZStream instance for the given Zip stream. The
    * name argument is used for an appropriately named temporary file, and the
    * Zip instance is given for the MappableSeekableZStream to keep a reference
    * of it.
    */
-  static MappableSeekableZStream *Create(const char *name, Zip *zip,
+  static Mappable *Create(const char *name, Zip *zip,
                                          Zip::Stream *stream);
 
   /* Inherited from Mappable */
   virtual void *mmap(const void *addr, size_t length, int prot, int flags, off_t offset);
   virtual void munmap(void *addr, size_t length);
   virtual void finalize();
   virtual bool ensure(const void *addr);
   virtual void stats(const char *when, const char *name) const;