From e2c430b237da5c0229fd8e0832eedc3b85045ec0 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Tue, 12 Sep 2006 17:30:23 +0000 Subject: Added cache functionality, which is really nice, things go much faster now. --- src/build.cpp | 64 ++++++++++++++++++++- src/build.h | 8 +++ src/cache.cpp | 149 +++++++++++++++++++++++++++++++++++++++++++++++++ src/cache.h | 33 +++++++++++ src/main.cpp | 25 +++++---- src/performcommand.cpp | 8 ++- src/targetfile.cpp | 32 +++++------ 7 files changed, 288 insertions(+), 31 deletions(-) create mode 100644 src/cache.cpp create mode 100644 src/cache.h diff --git a/src/build.cpp b/src/build.cpp index 5c0b721..13a2aee 100644 --- a/src/build.cpp +++ b/src/build.cpp @@ -1,18 +1,47 @@ #include "build.h" #include "function.h" #include "viewerfactory.h" +#include "serializerbinary.h" subExceptionDef( BuildException ); Build::Build() : pStrProc( NULL ), - pView( NULL ) + pView( NULL ), + bCacheUpdated( false ) { pView = ViewerFactory::getInstance().instantiate("plain"); } Build::~Build() { + if( sCacheName.size() > 0 && bCacheUpdated ) + { + try + { + SerializerBinary ar( sCacheName.c_str(), Serializer::save ); + + ar << cRequires; + } + catch( ExceptionBase &e ) + { + } + } +} + +void Build::setCache( const std::string &sFileName ) +{ + sCacheName = sFileName; + + try + { + SerializerBinary ar( sCacheName.c_str(), Serializer::load ); + + ar >> cRequires; + } + catch( ExceptionBase &e ) + { + } } void Build::setStringProc( StringProc *pStrProc ) @@ -271,3 +300,36 @@ StringList &Build::getRequires( std::string sName ) return mRequires[sName]; } +bool Build::getCached( const std::string &sID, int nTime, StringList &lOut ) +{ + Cache::Entry *pEnt = cRequires.get( sID ); + if( pEnt == NULL ) + return false; + if( pEnt->tCreated < nTime ) + return false; + + lOut.insert( lOut.end(), pEnt->lData.begin(), pEnt->lData.end() ); + + return true; +} + +void Build::updateCache( const std::string &sID, FunctionList &lFunc, StringList &lOut ) +{ + Cache::Entry *pEnt = new Cache::Entry; + getView()->beginRequiresCheck( false, sID ); + for( FunctionList::iterator f = lFunc.begin(); f != lFunc.end(); f++ ) + { + StringList lTmpIn; + lTmpIn.push_back( sID ); + (*f)->execute( this, lTmpIn, pEnt->lData ); + } + getView()->endRequiresCheck(); + + lOut.insert( lOut.end(), pEnt->lData.begin(), pEnt->lData.end() ); + cRequires.put( sID, pEnt ); + + pEnt->tCreated = time( NULL ); + + bCacheUpdated = true; +} + diff --git a/src/build.h b/src/build.h index a35b8e2..1477938 100644 --- a/src/build.h +++ b/src/build.h @@ -11,6 +11,7 @@ #include "target.h" #include "action.h" #include "stringproc.h" +#include "cache.h" subExceptionDecl( BuildException ); typedef std::map VarMap; @@ -66,6 +67,10 @@ public: return mTarget; } + void setCache( const std::string &sFileName ); + bool getCached( const std::string &sID, int nTime, StringList &lOut ); + void updateCache( const std::string &sID, FunctionList &lFunc, StringList &lOut ); + private: TargetMap mTarget; ReqMap mRequires; @@ -75,6 +80,9 @@ private: ActionMap mAction; StringProc *pStrProc; Viewer *pView; + Cache cRequires; + bool bCacheUpdated; + std::string sCacheName; //std::map mRule; //Action *pActDefault; diff --git a/src/cache.cpp b/src/cache.cpp new file mode 100644 index 0000000..10971b1 --- /dev/null +++ b/src/cache.cpp @@ -0,0 +1,149 @@ +#include "cache.h" +#include "serializer.h" +#include "staticstring.h" + +Cache::Cache() +{ +} + +Cache::~Cache() +{ + for( std::map::iterator i = mCache.begin(); + i != mCache.end(); i++ ) + { + delete (*i).second; + } +} + +void Cache::serialize( class Serializer &ar ) +{ + if( ar.isLoading() ) + { + int sCache, sData, sIndex; + + ar >> sIndex; + StaticString *Index = new StaticString[sIndex]; + for( int i = 0; i < sIndex; i++ ) + { + ar >> Index[i]; + } + + ar >> sCache; + int nTmp; + for( int i = 0; i < sCache; i++ ) + { + Entry *e = new Entry; + ar >> e->tCreated; + ar >> sData; + std::list &lData = e->lData; + for( int j = 0; j < sData; j++ ) + { + ar >> nTmp; + lData.push_back( Index[nTmp].getString() ); + } + ar >> nTmp; + mCache[Index[nTmp].getString()] = e; + } + /* + int sCache, sData; + ar >> sCache; + std::string sTmp; + + for( int i = 0; i < sCache; i++ ) + { + Entry *e = new Entry; + ar >> e->tCreated; + ar >> sData; + std::list &lData = e->lData; + for( int j = 0; j < sData; j++ ) + { + ar >> sTmp; + lData.push_back( sTmp ); + } + ar >> sTmp; + mCache[sTmp] = e; + } + */ + } + else + { + std::map mIndex; + for( std::map::iterator i = mCache.begin(); + i != mCache.end(); i++ ) + { + mIndex[(*i).first] = 0; + std::list &lData = (*i).second->lData; + for( std::list::iterator j = lData.begin(); + j != lData.end(); j++ ) + { + mIndex[(*j)] = 0; + } + } + + ar << mIndex.size(); + int cnt = 0; + for( std::map::iterator i = mIndex.begin(); + i != mIndex.end(); i++ ) + { + (*i).second = cnt; + cnt++; + std::string s = ((*i).first); + ar << s; + } + + ar << mCache.size(); + for( std::map::iterator i = mCache.begin(); + i != mCache.end(); i++ ) + { + ar << (*i).second->tCreated; + std::list &lData = (*i).second->lData; + ar << lData.size(); + for( std::list::iterator j = lData.begin(); + j != lData.end(); j++ ) + { + ar << mIndex[(*j)]; + } + + ar << mIndex[(*i).first]; + } + + + /* + ar << mCache.size(); + for( std::map::iterator i = mCache.begin(); + i != mCache.end(); i++ ) + { + ar << (*i).second->tCreated; + std::list &lData = (*i).second->lData; + ar << lData.size(); + for( std::list::iterator j = lData.begin(); + j != lData.end(); j++ ) + { + ar << (*j); + } + + std::string str = (*i).first; + ar << str; + } + */ + } +} + +Cache::Entry *Cache::get( const std::string &id ) +{ + std::map::iterator i = mCache.find( id ); + if( i != mCache.end() ) + return (*i).second; + + return NULL; +} + +void Cache::put( const std::string &id, Entry *data ) +{ + std::map::iterator i = mCache.find( id ); + if( i != mCache.end() ) + delete (*i).second; + + mCache[id] = data; +} + diff --git a/src/cache.h b/src/cache.h new file mode 100644 index 0000000..944aa24 --- /dev/null +++ b/src/cache.h @@ -0,0 +1,33 @@ +#ifndef CACHE_H +#define CACHE_H + +#include +#include +#include "serializable.h" +#include +#include +#include + +class Cache : public Serializable +{ +public: + Cache(); + virtual ~Cache(); + + virtual void serialize( class Serializer &ar ); + + class Entry + { + public: + int tCreated; + std::list lData; + }; + + Entry *get( const std::string &id ); + void put( const std::string &id, Entry *data ); + +private: + std::map mCache; +}; + +#endif diff --git a/src/main.cpp b/src/main.cpp index 9106a74..712213b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -72,19 +72,20 @@ int main( int argc, char *argv[] ) Param prm; prm.process( argc, argv ); - BuildParser bld;//*prm.pViewer ); + BuildParser bld; + Build *pBuild; - //bld.setCache( prm.sCache ); - //try - //{ - Build *pBuild = bld.load( prm.sFile.c_str() ); - //} - //catch( BuildException &e ) - //{ - // fputs( e.what(), stderr ); - // fputs( "\n", stderr ); - // return 1; - //} + try + { + pBuild = bld.load( prm.sFile.c_str() ); + pBuild->setCache( prm.sCache ); + } + catch( BuildException &e ) + { + fputs( e.what(), stderr ); + fputs( "\n", stderr ); + return 1; + } //if( prm.bDebug ) //{ diff --git a/src/performcommand.cpp b/src/performcommand.cpp index f6da4ac..5a9e746 100644 --- a/src/performcommand.cpp +++ b/src/performcommand.cpp @@ -1,5 +1,6 @@ #include "performcommand.h" #include "plugger.h" +#include "build.h" PluginInterface2(command, PerformCommand, Perform, "Mike Buland", 0, 1 ); @@ -20,6 +21,11 @@ Perform *PerformCommand::duplicate( Build &bld, const std::string &cont, VarMap void PerformCommand::execute( Build &bld ) { - system( lParam.front().c_str() ); + int n = system( lParam.front().c_str() ); + if( n != 0 ) + throw BuildException( + "Command exited with error code %d.", + WEXITSTATUS(n) + ); } diff --git a/src/targetfile.cpp b/src/targetfile.cpp index 0299f9d..dd0de9e 100644 --- a/src/targetfile.cpp +++ b/src/targetfile.cpp @@ -27,9 +27,8 @@ void TargetFile::check( Build &bld ) { time_t tTarget = getTime( bld, (*i)->getTarget() ); StringList &reqs = bld.getRequires( (*i)->getTarget() ); - FunctionList::iterator f = (*i)->getReqFuncs().begin(); - bool bBuilt = false; -aastrt: for( StringList::iterator j = reqs.begin(); j != reqs.end(); j++ ) + bool bExtras = false; + for( StringList::iterator j = reqs.begin(); j != reqs.end(); j++ ) { if( getTime( bld, *j ) > tTarget ) { @@ -37,22 +36,21 @@ aastrt: for( StringList::iterator j = reqs.begin(); j != reqs.end(); j++ ) (*i)->execute( bld ); bld.getView()->endPerform(); updateTime( (*i)->getTarget() ); - bBuilt = true; break; } - } - if( bBuilt == true ) - continue; - - if( f != (*i)->getReqFuncs().end() ) - { - StringList lTmpIn; - lTmpIn.push_back( (*i)->getTarget() ); - bld.getView()->beginRequiresCheck( false, (*i)->getTarget() ); - (*f)->execute( &bld, lTmpIn, reqs ); - bld.getView()->endRequiresCheck(); - f++; - goto aastrt; + if( bExtras == false ) + { + StringList::iterator jj = j; + jj++; + if( jj == reqs.end() ) + { + if( !bld.getCached( (*i)->getTarget(), tTarget, reqs ) ) + { + bld.updateCache( (*i)->getTarget(), (*i)->getReqFuncs(), reqs ); + } + bExtras = true; + } + } } } } -- cgit v1.2.3