Update Eagle and gEDA importers.

Remove a throw in the Eagle importer which just threw a wedge
in the works, and return a default modTime when the file hasn't
been set yet.

Give the gEDA importer the multi-file cache management performance
improvements from the kicad_plugin.

Fixes: lp:1752719
* https://bugs.launchpad.net/kicad/+bug/1752719
This commit is contained in:
Jeff Young 2018-03-02 23:44:27 +00:00
parent 33d925f631
commit 8e1d397587
3 changed files with 91 additions and 114 deletions

View File

@ -2061,32 +2061,16 @@ void EAGLE_PLUGIN::centerBoard()
wxDateTime EAGLE_PLUGIN::getModificationTime( const wxString& aPath )
{
// File hasn't been loaded yet.
if( aPath.IsEmpty() )
return wxDateTime::Now();
wxFileName fn( aPath );
// Do not call wxFileName::GetModificationTime() on a non-existent file, because
// if it fails, wx's implementation calls the crap wxLogSysError() which
// eventually infects our UI with an unwanted popup window, so don't let it fail.
if( !fn.IsFileReadable() )
{
wxString msg = wxString::Format(
_( "File \"%s\" is not readable." ),
GetChars( aPath ) );
THROW_IO_ERROR( msg );
}
/*
// update the writable flag while we have a wxFileName, in a network this
// is possibly quite dynamic anyway.
m_writable = fn.IsFileWritable();
*/
wxDateTime modTime = fn.GetModificationTime();
if( !modTime.IsValid() )
modTime.Now();
return modTime;
if( fn.IsFileReadable() )
return fn.GetModificationTime();
else
return wxDateTime( 0.0 );
}
@ -2099,8 +2083,7 @@ void EAGLE_PLUGIN::cacheLib( const wxString& aLibPath )
// Fixes assertions in wxWidgets debug builds for the wxDateTime object. Refresh the
// cache if either of the wxDateTime objects are invalid or the last file modification
// time differs from the current file modification time.
bool load = !m_mod_time.IsValid() || !modtime.IsValid() ||
m_mod_time != modtime;
bool load = !m_mod_time.IsValid() || !modtime.IsValid() || m_mod_time != modtime;
if( aLibPath != m_lib_path || load )
{

View File

@ -140,7 +140,6 @@ class GPCB_FPL_CACHE_ITEM
{
wxFileName m_file_name; ///< The the full file name and path of the footprint to cache.
bool m_writable; ///< Writability status of the footprint file.
wxDateTime m_mod_time; ///< The last file modified time stamp.
std::unique_ptr<MODULE> m_module;
public:
@ -148,9 +147,7 @@ public:
wxString GetName() const { return m_file_name.GetDirs().Last(); }
wxFileName GetFileName() const { return m_file_name; }
bool IsModified() const;
MODULE* GetModule() const { return m_module.get(); }
void UpdateModificationTime() { m_mod_time = m_file_name.GetModificationTime(); }
};
@ -159,20 +156,6 @@ GPCB_FPL_CACHE_ITEM::GPCB_FPL_CACHE_ITEM( MODULE* aModule, const wxFileName& aFi
{
m_file_name = aFileName;
m_writable = true; // temporary init
if( m_file_name.FileExists() )
m_mod_time = m_file_name.GetModificationTime();
else
m_mod_time.Now();
}
bool GPCB_FPL_CACHE_ITEM::IsModified() const
{
if( !m_file_name.FileExists() )
return false;
return m_file_name.GetModificationTime() != m_mod_time;
}
@ -185,9 +168,13 @@ class GPCB_FPL_CACHE
{
GPCB_PLUGIN* m_owner; /// Plugin object that owns the cache.
wxFileName m_lib_path; /// The path of the library.
wxDateTime m_mod_time; /// Footprint library path modified time stamp.
MODULE_MAP m_modules; /// Map of footprint file name per MODULE*.
bool m_cache_dirty; // Stored separately because it's expensive to check
// m_cache_timestamp against all the files.
long long m_cache_timestamp; // A hash of the timestamps for all the footprint
// files.
MODULE* parseMODULE( LINE_READER* aLineReader );
/**
@ -224,7 +211,6 @@ public:
GPCB_FPL_CACHE( GPCB_PLUGIN* aOwner, const wxString& aLibraryPath );
wxString GetPath() const { return m_lib_path.GetPath(); }
wxDateTime GetLastModificationTime() const { return m_mod_time; }
bool IsWritable() const { return m_lib_path.IsOk() && m_lib_path.IsDirWritable(); }
MODULE_MAP& GetModules() { return m_modules; }
@ -238,21 +224,19 @@ public:
void Remove( const wxString& aFootprintName );
wxDateTime GetLibModificationTime() const;
/**
* Function GetTimestamp
* Generate a timestamp representing all source files in the cache (including the
* parent directory).
* Timestamps should not be considered ordered. They either match or they don't.
*/
long long GetTimestamp();
/**
* Function IsModified
* check if the footprint cache has been modified relative to \a aLibPath
* and \a aFootprintName.
*
* @param aLibPath is a path to test the current cache library path against.
* @param aFootprintName is the footprint name in the cache to test. If the footprint
* name is empty, the all the footprint files in the library are
* checked to see if they have been modified.
* @return true if the cache has been modified.
* Return true if the cache is not up-to-date.
*/
bool IsModified( const wxString& aLibPath,
const wxString& aFootprintName = wxEmptyString ) const;
bool IsModified();
/**
* Function IsPath
@ -274,15 +258,8 @@ GPCB_FPL_CACHE::GPCB_FPL_CACHE( GPCB_PLUGIN* aOwner, const wxString& aLibraryPat
{
m_owner = aOwner;
m_lib_path.SetPath( aLibraryPath );
}
wxDateTime GPCB_FPL_CACHE::GetLibModificationTime() const
{
if( !m_lib_path.DirExists() )
return wxDateTime( 0.0 );
return m_lib_path.GetModificationTime();
m_cache_timestamp = 0;
m_cache_dirty = true;
}
@ -295,9 +272,17 @@ void GPCB_FPL_CACHE::Load()
if( !dir.IsOpened() )
{
m_cache_timestamp = 0;
m_cache_dirty = false;
THROW_IO_ERROR( wxString::Format( _( "footprint library path \"%s\" does not exist" ),
m_lib_path.GetPath().GetData() ) );
}
else
{
m_cache_timestamp = m_lib_path.GetModificationTime().GetValue().GetValue();
m_cache_dirty = false;
}
wxString fpFileName;
wxString wildcard = wxT( "*." ) + GedaPcbFootprintLibFileExtension;
@ -333,11 +318,6 @@ void GPCB_FPL_CACHE::Load()
}
} while( dir.GetNext( &fpFileName ) );
// Remember the file modification time of library file when the
// cache snapshot was made, so that in a networked environment we will
// reload the cache as needed.
m_mod_time = GetLibModificationTime();
if( !cacheErrorMsg.IsEmpty() )
THROW_IO_ERROR( cacheErrorMsg );
}
@ -373,49 +353,41 @@ bool GPCB_FPL_CACHE::IsPath( const wxString& aPath ) const
}
bool GPCB_FPL_CACHE::IsModified( const wxString& aLibPath, const wxString& aFootprintName ) const
bool GPCB_FPL_CACHE::IsModified()
{
// The library is modified if the library path got deleted or changed.
if( !m_lib_path.DirExists() || !IsPath( aLibPath ) )
if( m_cache_dirty )
return true;
else
return GetTimestamp() != m_cache_timestamp;
}
// If no footprint was specified, check every file modification time against the time
// it was loaded.
if( aFootprintName.IsEmpty() )
long long GPCB_FPL_CACHE::GetTimestamp()
{
// Avoid expensive GetModificationTime checks if we already know we're dirty
if( m_cache_dirty )
return wxDateTime::Now().GetValue().GetValue();
long long files_timestamp = 0;
if( m_lib_path.DirExists() )
{
files_timestamp = m_lib_path.GetModificationTime().GetValue().GetValue();
for( MODULE_CITER it = m_modules.begin(); it != m_modules.end(); ++it )
{
wxFileName fn = m_lib_path;
fn.SetName( it->second->GetFileName().GetName() );
fn.SetExt( GedaPcbFootprintLibFileExtension );
if( !fn.FileExists() )
{
wxLogTrace( traceFootprintLibrary,
wxT( "Footprint cache file \"%s\" does not exist." ),
fn.GetFullPath().GetData() );
return true;
}
if( it->second->IsModified() )
{
wxLogTrace( traceFootprintLibrary,
wxT( "Footprint cache file \"%s\" has been modified." ),
fn.GetFullPath().GetData() );
return true;
}
wxFileName moduleFile = it->second->GetFileName();
if( moduleFile.FileExists() )
files_timestamp += moduleFile.GetModificationTime().GetValue().GetValue();
}
}
else
{
MODULE_CITER it = m_modules.find( TO_UTF8( aFootprintName ) );
if( it == m_modules.end() || it->second->IsModified() )
return true;
}
// If the new timestamp doesn't match the cache timestamp, then save ourselves the
// expensive calls next time
if( m_cache_timestamp != files_timestamp )
m_cache_dirty = true;
return false;
return files_timestamp;
}
@ -960,9 +932,9 @@ void GPCB_PLUGIN::init( const PROPERTIES* aProperties )
}
void GPCB_PLUGIN::cacheLib( const wxString& aLibraryPath, const wxString& aFootprintName )
void GPCB_PLUGIN::validateCache( const wxString& aLibraryPath, bool checkModified )
{
if( !m_cache || m_cache->IsModified( aLibraryPath, aFootprintName ) )
if( !m_cache || ( checkModified && m_cache->IsModified() ) )
{
// a spectacular episode in memory management:
delete m_cache;
@ -993,7 +965,7 @@ void GPCB_PLUGIN::FootprintEnumerate( wxArrayString& aFootprintNames,
// the library.
try
{
cacheLib( aLibraryPath );
validateCache( aLibraryPath );
}
catch( const IO_ERROR& ioe )
{
@ -1012,14 +984,16 @@ void GPCB_PLUGIN::FootprintEnumerate( wxArrayString& aFootprintNames,
}
MODULE* GPCB_PLUGIN::FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName,
const PROPERTIES* aProperties )
MODULE* GPCB_PLUGIN::doLoadFootprint( const wxString& aLibraryPath,
const wxString& aFootprintName,
const PROPERTIES* aProperties,
bool checkModified )
{
LOCALE_IO toggle; // toggles on, then off, the C locale.
init( aProperties );
cacheLib( aLibraryPath, aFootprintName );
validateCache( aLibraryPath, checkModified );
const MODULE_MAP& mods = m_cache->GetModules();
@ -1035,6 +1009,21 @@ MODULE* GPCB_PLUGIN::FootprintLoad( const wxString& aLibraryPath, const wxString
}
MODULE* GPCB_PLUGIN::LoadEnumeratedFootprint( const wxString& aLibraryPath,
const wxString& aFootprintName,
const PROPERTIES* aProperties )
{
return doLoadFootprint( aLibraryPath, aFootprintName, aProperties, false );
}
MODULE* GPCB_PLUGIN::FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName,
const PROPERTIES* aProperties )
{
return doLoadFootprint( aLibraryPath, aFootprintName, aProperties, true );
}
void GPCB_PLUGIN::FootprintDelete( const wxString& aLibraryPath, const wxString& aFootprintName,
const PROPERTIES* aProperties )
{
@ -1042,7 +1031,7 @@ void GPCB_PLUGIN::FootprintDelete( const wxString& aLibraryPath, const wxString&
init( aProperties );
cacheLib( aLibraryPath );
validateCache( aLibraryPath );
if( !m_cache->IsWritable() )
{
@ -1137,7 +1126,7 @@ long long GPCB_PLUGIN::GetLibraryTimestamp() const
if( !m_cache )
return wxDateTime::Now().GetValue().GetValue();
return m_cache->GetLibModificationTime().GetValue().GetValue();
return m_cache->GetTimestamp();
}
@ -1147,7 +1136,7 @@ bool GPCB_PLUGIN::IsFootprintLibWritable( const wxString& aLibraryPath )
init( NULL );
cacheLib( aLibraryPath );
validateCache( aLibraryPath );
return m_cache->IsWritable();
}

View File

@ -65,6 +65,9 @@ public:
void FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aLibraryPath,
const PROPERTIES* aProperties = NULL) override;
MODULE* LoadEnumeratedFootprint( const wxString& aLibraryPath, const wxString& aFootprintName,
const PROPERTIES* aProperties = NULL ) override;
MODULE* FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName,
const PROPERTIES* aProperties = NULL ) override;
@ -96,8 +99,10 @@ protected:
wxString m_filename; ///< for saves only, name is in m_reader for loads
private:
/// we only cache one footprint library for now, this determines which one.
void cacheLib( const wxString& aLibraryPath, const wxString& aFootprintName = wxEmptyString );
void validateCache( const wxString& aLibraryPath, bool checkModified = true );
MODULE* doLoadFootprint( const wxString& aLibraryPath, const wxString& aFootprintName,
const PROPERTIES* aProperties, bool checkModified );
void init( const PROPERTIES* aProperties );
};