changeset 24367:1909f2d7a36e

Backed out changeset 4e746afab617 The fix for this problem is not as simple as it would appear...
author John W. Eaton <jwe@octave.org>
date Wed, 06 Dec 2017 13:55:23 -0500
parents 8bf013efffa3
children 77d976a84d0a
files NEWS libinterp/corefcn/load-path.cc libinterp/corefcn/load-path.h
diffstat 3 files changed, 76 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Wed Dec 06 09:05:32 2017 -0800
+++ b/NEWS	Wed Dec 06 13:55:23 2017 -0500
@@ -66,10 +66,6 @@
  ** An initial implementation of alpha transparency has been made for
     patch and surface objects.  Printing to svg and pdf is supported.
 
- ** All directories are now converted to absolute names when they are
-    added to the load path.  This change was made for compatibility with
-    Matlab, which was changed similarly in release 2016b.
-
  ** The following statistical functions have been moved from core
     Octave to the statistics package available from Octave Forge.
 
--- a/libinterp/corefcn/load-path.cc	Wed Dec 06 09:05:32 2017 -0800
+++ b/libinterp/corefcn/load-path.cc	Wed Dec 06 13:55:23 2017 -0500
@@ -497,7 +497,7 @@
       {
         for (const auto& di : dir_info_list)
           {
-            std::string dname = di.dir_name;
+            std::string dname = sys::env::make_absolute (di.dir_name);
 
             size_t dname_len = dname.length ();
 
@@ -543,7 +543,7 @@
       {
         for (const auto& di : dir_info_list)
           {
-            std::string dname = di.dir_name;
+            std::string dname = sys::env::make_absolute (di.dir_name);
 
             size_t dname_len = dname.length ();
 
@@ -1123,8 +1123,59 @@
         std::string msg = fs.error ();
         warning ("load_path: %s: %s", dir_name.c_str (), msg.c_str ());
       }
-    else if (fs.mtime () + fs.time_resolution () > dir_time_last_checked)
-      initialize ();
+    else
+      {
+        if (is_relative)
+          {
+            try
+              {
+                std::string abs_name = sys::env::make_absolute (dir_name);
+
+                const_abs_dir_cache_iterator p = abs_dir_cache.find (abs_name);
+
+                if (p != abs_dir_cache.end ())
+                  {
+                    // The directory is in the cache of all directories we have
+                    // visited (indexed by absolute name).  If it is out of date,
+                    // initialize it.  Otherwise, copy the info from the cache.
+                    // By doing that, we avoid unnecessary calls to stat that can
+                    // slow things down tremendously for large directories.
+                    const dir_info& di = p->second;
+
+                    if (fs.mtime () + fs.time_resolution ()
+                        > di.dir_time_last_checked)
+                      initialize ();
+                    else
+                      {
+                        // Copy over info from cache, but leave dir_name and
+                        // is_relative unmodified.
+                        this->abs_dir_name = di.abs_dir_name;
+                        this->dir_mtime = di.dir_mtime;
+                        this->dir_time_last_checked = di.dir_time_last_checked;
+                        this->all_files = di.all_files;
+                        this->fcn_files = di.fcn_files;
+                        this->private_file_map = di.private_file_map;
+                        this->method_file_map = di.method_file_map;
+                        this->package_dir_map = di.package_dir_map;
+                      }
+                  }
+                else
+                  {
+                    // We haven't seen this directory before.
+                    initialize ();
+                  }
+              }
+            catch (const execution_exception&)
+              {
+                // Skip updating if we don't know where we are,
+                // but don't treat it as an error.
+                interpreter::recover_from_exception ();
+              }
+          }
+        // Absolute path, check timestamp to see whether it requires re-caching
+        else if (fs.mtime () + fs.time_resolution () > dir_time_last_checked)
+          initialize ();
+      }
   }
 
   bool
@@ -1151,9 +1202,7 @@
   void
   load_path::dir_info::initialize (void)
   {
-    // We only handle absolute directory names.
-
-    dir_name = sys::env::make_absolute (dir_name);
+    is_relative = ! sys::env::absolute_pathname (dir_name);
 
     dir_time_last_checked = sys::time (static_cast<time_t> (0));
 
@@ -1169,11 +1218,23 @@
 
         get_file_list (dir_name);
 
-        // FIXME: nothing is ever removed from this cache of directory
-        // information, so there could be some resource problems.
-        // Perhaps it should be pruned from time to time.
-
-        abs_dir_cache[dir_name] = *this;
+        try
+          {
+            std::string abs_name = sys::env::make_absolute (dir_name);
+
+            // FIXME: nothing is ever removed from this cache of
+            // directory information, so there could be some resource
+            // problems.  Perhaps it should be pruned from time to time.
+
+            abs_dir_cache[abs_name] = *this;
+          }
+        catch (const execution_exception&)
+          {
+            // Skip updating if we don't know where we are but don't treat
+            // it as an error.
+
+            interpreter::recover_from_exception ();
+          }
       }
     else
       {
--- a/libinterp/corefcn/load-path.h	Wed Dec 06 09:05:32 2017 -0800
+++ b/libinterp/corefcn/load-path.h	Wed Dec 06 13:55:23 2017 -0500
@@ -252,8 +252,8 @@
       dir_info (void) = default;
 
       dir_info (const std::string& d)
-        : dir_name (d), abs_dir_name (), dir_mtime (),
-          dir_time_last_checked (), all_files (), fcn_files (),
+        : dir_name (d), abs_dir_name (), is_relative (false),
+          dir_mtime (), dir_time_last_checked (), all_files (), fcn_files (),
           private_file_map (), method_file_map (), package_dir_map ()
       {
         initialize ();
@@ -269,6 +269,7 @@
 
       std::string dir_name;
       std::string abs_dir_name;
+      bool is_relative;
       sys::time dir_mtime;
       sys::time dir_time_last_checked;
       string_vector all_files;