[GME-commit] GMESRC/GME/Mga MgaLibOps.h,1.2,1.3 MgaLibOps.cpp,1.12,1.13

gme-commit at list.isis.vanderbilt.edu gme-commit at list.isis.vanderbilt.edu
Tue Jan 16 18:13:35 CST 2007


Update of /project/gme-repository/GMESRC/GME/Mga
In directory escher:/tmp/cvs-serv5469

Modified Files:
	MgaLibOps.h MgaLibOps.cpp 
Log Message:
Feature added: optimized library attach/refresh.
Interface not changed yet.


CVS User: Zoltan Molnar, ISIS (zolmol)

Index: MgaLibOps.cpp
===================================================================
RCS file: /project/gme-repository/GMESRC/GME/Mga/MgaLibOps.cpp,v
retrieving revision 1.12
retrieving revision 1.13
diff -C2 -d -r1.12 -r1.13
*** MgaLibOps.cpp	3 Oct 2006 16:22:55 -0000	1.12
--- MgaLibOps.cpp	16 Jan 2007 18:13:33 -0000	1.13
***************
*** 9,12 ****
--- 9,15 ----
  #include "../interfaces/Parser.h"
  
+ /*static*/ const wchar_t* Ozer::StorageMgr::INCLUDES_STR        = L"_includes";
+ /*static*/ const wchar_t* Ozer::StorageMgr::INCLUDED_BY_STR     = L"_includedBy";
+ 
  HRESULT FCO::get_LibraryName(BSTR *libname) {
  	COMTRY {
***************
*** 121,125 ****
  /* *************************** Attach ********************************************* */
  
! void ObjTreeCopyFromExt(CMgaProject *mgaproject, const CoreObj &orig, CoreObj &nobj, PointerFixup &fixup) {
  	metaid_type s;
  	COMTHROW(mgaproject->dataproject->CreateObject(s = orig.GetMetaID(), &nobj.ComPtr()));
--- 124,128 ----
  /* *************************** Attach ********************************************* */
  
! void ObjTreeCopyFromExt(CMgaProject *mgaproject, const CoreObj &orig, CoreObj &nobj, PointerFixup &fixup, std::vector< std::pair< CoreObj, CoreObj > >& p_libPairs/*, bool refresh*/, std::vector< CoreObj >& p_superfluousLibs) {
  	metaid_type s;
  	COMTHROW(mgaproject->dataproject->CreateObject(s = orig.GetMetaID(), &nobj.ComPtr()));
***************
*** 128,134 ****
--- 131,169 ----
  		fixup.identify(orig, nobj);
  
+ 	bool skip_this = false;
  	if(s >= DTID_MODEL && s <= DTID_FOLDER) {
  		setcheck(mgaproject, nobj, CHK_NEW);
  		CoreObjMark(nobj, OBJEVENT_CREATED);
+ 
+ 		long pm = orig[ATTRID_PERMISSIONS];
+ 		if( pm & LIBROOT_FLAG)
+ 		{
+ 			BinGuid libn = Identifier::getPersistentIdOf( orig);
+ 			for( std::vector< std::pair< CoreObj, CoreObj > >::iterator it = p_libPairs.begin()
+ 				; it != p_libPairs.end()
+ 				; ++it)
+ 			{
+ 				//
+ 				BinGuid lib1 = Identifier::getPersistentIdOf( it->first);
+ 				if( libn == lib1)
+ 				{
+ 					skip_this = true;
+ 					//ASSERT( libn == lib1 == lib2);
+ 					ASSERT( libn == Identifier::getPersistentIdOf( it->second));
+ 					p_superfluousLibs.push_back( nobj);
+ 				}
+ 				/*BinGuid lib2 = Identifier::getPersistentIdOf( it->second);
+ 				if( libn == lib1 && lib1 == lib2) // 
+ 				{
+ 					// what about skipping to load this duplicate library
+ 					int k( 0);
+ 					++k;
+ 					//return;
+ 					skip_this = true;
+ 					p_superfluousLibs.push_back( nobj);
+ 				}*/
+ 			}
+ 		}
+ 
  	}
  
***************
*** 147,151 ****
  						//WAS: nobj[ai] = orig[ai] & INSTANCE_FLAG | LIBRARY_FLAG;
  						//this way we preserve nested libraries:
! 						nobj[ai] = orig[ai] & (INSTANCE_FLAG|LIBROOT_FLAG) | LIBRARY_FLAG;
  					}
  					else nobj[ai] = static_cast<CComVariant>(orig[ai]);
--- 182,192 ----
  						//WAS: nobj[ai] = orig[ai] & INSTANCE_FLAG | LIBRARY_FLAG;
  						//this way we preserve nested libraries:
! 						
! 						// we will delete this object later, that's why 
! 						// we don't apply a readonly flag to it now
! 						if( skip_this) 
! 							nobj[ai] = orig[ai]; 
! 						else
! 							nobj[ai] = orig[ai] & (INSTANCE_FLAG|LIBROOT_FLAG) | LIBRARY_FLAG;
  					}
  					else nobj[ai] = static_cast<CComVariant>(orig[ai]);
***************
*** 161,165 ****
  					ITERATE_THROUGH(collmembers) {
  						CoreObj nchild;
! 						ObjTreeCopyFromExt(mgaproject, ITER, nchild, fixup);
  						nchild[ai] = nobj;
  					}
--- 202,206 ----
  					ITERATE_THROUGH(collmembers) {
  						CoreObj nchild;
! 						ObjTreeCopyFromExt(mgaproject, ITER, nchild, fixup, p_libPairs/*, refresh*/, p_superfluousLibs);
  						nchild[ai] = nobj;
  					}
***************
*** 170,174 ****
  }
  
! void CreateLibraryImage(CMgaProject *mgaproject, CComBSTR &connstr, CoreObj &libimgroot, bool p_tolerateOldMga, bool *p_ptrIsOldMga) {
  	CComPtr<IMgaProject> p;
  	PointerFixup fixup;
--- 211,216 ----
  }
  
! void CreateLibraryImage(CMgaProject *mgaproject, LibWorker& lw, CoreObj &libimgroot, bool p_tolerateOldMga, bool *p_ptrIsOldMga, LibWorker::LIB_MAP& p_results, CComBSTR& p_includedIdList) {
! 	CComBSTR connstr = lw.getConnectionStr();
  	CComPtr<IMgaProject> p;
  	PointerFixup fixup;
***************
*** 184,187 ****
--- 226,230 ----
  		bool upgraded = false; CComBSTR connstr_upgraded( "MGA=");
  		long mga_ver( 0);
+ 		// checking project version, checking if the same paradigm or subparadigm, and convert thru XML in such cases
  		{
  			CComBSTR par_nm;
***************
*** 189,192 ****
--- 232,236 ----
  			CComVariant par_gd;  // not used now
  			VARIANT_BOOL ro_mode;// not used now 
+ 
  			COMTHROW(p->QueryProjectInfo( connstr, &mga_ver, &par_nm, &par_vs, &par_gd, &ro_mode));
  			if( par_nm != paradigmname)
***************
*** 267,281 ****
  		COMTHROW(p->OpenEx( upgraded?connstr_upgraded:connstr, paradigmname, paradigmGUID));
  
  		COMTHROW(p->BeginTransaction(NULL, TRANSACTION_READ_ONLY));
  		{
  			CComPtr<IMgaFolder> libroot;
  			COMTHROW(p->get_RootFolder(&libroot));
! 	
! 			ObjTreeCopyFromExt(mgaproject, CoreObj(libroot), libimgroot, fixup);
  		}
  		fixup.fixPointers();
  
! 		libimgroot[ATTRID_NAME] = connstr;
  		libimgroot[ATTRID_PERMISSIONS] = LIBROOT_FLAG;
  
  		COMTHROW(p->AbortTransaction());
--- 311,441 ----
  		COMTHROW(p->OpenEx( upgraded?connstr_upgraded:connstr, paradigmname, paradigmGUID));
  
+ 		std::vector< CoreObj > superfluousLibs;
+ 		std::vector< std::pair< CoreObj, CoreObj > > lib_pairs;
+ 
  		COMTHROW(p->BeginTransaction(NULL, TRANSACTION_READ_ONLY));
  		{
  			CComPtr<IMgaFolder> libroot;
  			COMTHROW(p->get_RootFolder(&libroot));
! 			if( 1)
! 			{
! 				CComPtr<IMgaFolder> prroot;
! 				COMTHROW(mgaproject->get_RootFolder(&prroot));
! 				CoreObj corerf = CoreObj( prroot);
! 
! 				//***********************************************************
! 				// Loading info about the libraries in the (attachable) file
! 				//-----------------------------------------------------------
! 
! 				LibWorker::LIB_MAP lib_results;
! 				CoreObj crlibroot( libroot);
! 				//LibWorker lw( mgaproject, upgraded?connstr_upgraded:connstr);
! 				LibWorker::recordLibs( true, crlibroot, lib_results);
! 				// the rootfolder of library is not yet a LIBROOT
! 				// so consider it a libroot now by pushing to the end of vector explicitly:
! 				//BinGuid libn = Identifier::getPersistentIdOf( crlibroot);
! 				//lib_results[ libn ].push_back( crlibroot);
! 
! 				// compare results with p_results
! 				for( LibWorker::LIB_MAP_ITER it = lib_results.begin()
! 					; it != lib_results.end()
! 					; ++it)
! 				{
! 					CComBSTR nm, pm;
! 					BinGuid bg = it->first;
! 					ASSERT( !it->second.empty());
! 					LibWorker::LIB_MAP_ITER jt = p_results.find( bg);
! 					if( jt != p_results.end()) // found
! 					{
! 						/*if( jt->second.size() >= 2) // more than one copy exists already
! 						{
! 						}*/
! 
! 						// duplicate lib
! 						if( jt->second.empty())
! 							ASSERT(0); 
! 						else // make a pair from to-be-lib libroot and project-hosted libroot
! 						{
! 							/*nm = it->second.front()[ATTRID_NAME];
! 							nm.Append( ":");
! 							pm = jt->second.front()[ATTRID_NAME];
! 							pm.Append( ":");*/
! 							CoreObj frntLibToBe = it->second.front();
! 							CoreObj frntHosted  = jt->second.front();
! 							lib_pairs.push_back( std::make_pair( frntLibToBe, frntHosted));
! 						}
! 					}
! 				}
! 				lib_results.clear();
! 			}
! 			if( lw.isOptimized()) 
! 			{
! 				fixup.setLibPairs( lib_pairs);
! 				ObjTreeCopyFromExt(mgaproject, CoreObj(libroot), libimgroot, fixup, lib_pairs, superfluousLibs);
! 			}
! 			else
! 			{
! 				std::vector< std::pair< CoreObj, CoreObj > > e_lib_pairs; // empty lib_pairs
! 				ObjTreeCopyFromExt(mgaproject, CoreObj(libroot), libimgroot, fixup, e_lib_pairs, superfluousLibs);
! 			}
  		}
  		fixup.fixPointers();
+ 		
+ 		
+ 		//*************************************************
+ 		// deleting the superfl. libs
+ 		//*************************************************
+ 		for( std::vector< CoreObj >::iterator it = superfluousLibs.begin()
+ 			; it != superfluousLibs.end()
+ 			; ++it)
+ 		{
+ 			ASSERT( lw.isOptimized());
+ 			//delete it->first
+ 			ObjForCore(*it)->inDeleteObject();
+ 			//CoreObj lib2root = it->first;
+ 			//long p1 = lib2root[ATTRID_PERMISSIONS];
+ 			//lib2root[ATTRID_PERMISSIONS] = p1 & ~LIBRARY_FLAG;
+ 		}
  
! 		libimgroot[ATTRID_NAME] = lw.getLongName();//connstr;
  		libimgroot[ATTRID_PERMISSIONS] = LIBROOT_FLAG;
+ 		
+ 		//*************************************************
+ 		// saving dependency information: IncludedBy
+ 		//*************************************************
+ 		CComBSTR id_of_toplib;
+ 		ObjForCore(libimgroot)->get_ID( &id_of_toplib);
+ 		CComBSTR incls_value_list;
+ 
+ 		for( std::vector< std::pair< CoreObj, CoreObj > >::iterator iiit = lib_pairs.begin()
+ 			; iiit != lib_pairs.end()
+ 			; ++iiit)
+ 		{
+ 			CoreObj frsst = iiit->first;
+ 			CoreObj seccc = iiit->second;
+ 
+ 			if( lw.isOptimized())
+ 			{
+ 				Ozer::addIncludedBy( seccc, id_of_toplib);
+ 
+ 				//
+ 				// put the 'includes' information into the toplib also
+ 				CComBSTR id_of_innerlib;
+ 				ObjForCore( seccc)->get_ID( &id_of_innerlib);
+ 
+ 				// 
+ 				// currently store it in a string only
+ 				// (registry of libimgroot is not available yet because its parent is not set)
+ 				if( p_includedIdList && p_includedIdList.Length() > 0) 
+ 					p_includedIdList.Append( L"\n");
+ 				p_includedIdList.AppendBSTR( id_of_innerlib);
+ 			}
+ 			else // not optimized
+ 			{ // needed?
+ 			}
+ 		}
+ 
+ 		superfluousLibs.clear();
+ 		lib_pairs.clear();
  
  		COMTHROW(p->AbortTransaction());
***************
*** 297,307 ****
  		CHECK_OUTPTRPARVALIDNULL(f);
  			
  		CoreObj libimgroot;
  		bool accept_old_lib( false); // don't tolerate old format MGA files (attachment of such a library fails)
  		bool is_old_lib( false);
! 		CreateLibraryImage(mgaproject, CComBSTR(libname), libimgroot, accept_old_lib, &is_old_lib);
  
  		assignnewchild(libimgroot);
  
  		docheck(mgaproject);
  
--- 457,481 ----
  		CHECK_OUTPTRPARVALIDNULL(f);
  			
+ 		// 'self' here is the rootfolder of the project
+ 		LibWorker::LIB_MAP top_libs;
+ 		LibWorker lw( mgaproject, libname);
+ 		LibWorker::recordLibs( false, self, top_libs); // consider existing toplibs only
+ 
  		CoreObj libimgroot;
  		bool accept_old_lib( false); // don't tolerate old format MGA files (attachment of such a library fails)
  		bool is_old_lib( false);
! 		CComBSTR idlist; // can't save includes information until libimgroot became child of self
! 		CreateLibraryImage(mgaproject, lw, libimgroot, accept_old_lib, &is_old_lib, top_libs, idlist);
  
  		assignnewchild(libimgroot);
  
+ 		if( idlist && idlist.Length() > 0)
+ 		{
+ 			Ozer::addIncludes( libimgroot, idlist);
+ 		}
+ 
+ 
+ 		lw.flatten( self, libimgroot);
+ 
  		docheck(mgaproject);
  
***************
*** 456,459 ****
--- 630,693 ----
  			}
  
+ 			LibWorker lw( mgaproject, libname);
+ 
+ 			if( mgaproject) Reporter::showIt( mgaproject, CComBSTR( "Examining the whole project"), false);
+ 
+ 			CComPtr<IMgaFolder> prroot;
+ 			COMTHROW(mgaproject->get_RootFolder(&prroot));
+ 			CoreObj corerf = CoreObj( prroot);
+ 			//CoreObj crlibroot( self);
+ 			// 'self' here is the refreshable library
+ 			CComBSTR id_of_this_library;
+ 			ObjForCore( self)->get_ID( &id_of_this_library);
+ 
+ 			// in the project consider existing toplibs only, [and avoid the library we are going to refresh]
+ 			LibWorker::LIB_MAP lib_results;
+ 			LibWorker::recordLibs( false, corerf, lib_results, id_of_this_library);
+ 
+ 			// in the refreshable lib examine the whole lib
+ 			LibWorker::LIB_MAP my_inner_lib_results;
+ 			if( mgaproject) Reporter::showIt( mgaproject, CComBSTR( "Examining the refreshable library"), false);
+ 			LibWorker::recordLibs( true, self, my_inner_lib_results);
+ 
+ #ifdef _DEBUG
+ 			for( LibWorker::LIB_MAP_ITER it = my_inner_lib_results.begin()
+ 				; it != my_inner_lib_results.end()
+ 				; ++it)
+ 			{
+ 				for( LibWorker::CORE_VEC_ITER jt = it->second.begin()
+ 					; jt != it->second.end()
+ 					; ++jt)
+ 				{
+ 					CComBSTR id;
+ 					ObjForCore( *jt)->get_ID( &id);
+ 					LibWorker::LIB_MAP_ITER kt = lib_results.find( it->first);
+ 					if( kt != lib_results.end()) // 
+ 					{
+ 						ASSERT( kt->first == it->first);
+ 						// look for 'id' in vector kt->second
+ 						for( std::vector< CoreObj >::iterator lt = kt->second.begin()
+ 							; lt != kt->second.end()
+ 							; ++lt)
+ 						{
+ 							CComBSTR id2;
+ 							ObjForCore( *lt)->get_ID( &id2);
+ 							if( id == id2) // found
+ 							{
+ 								ASSERT( 0 );
+ 								// recordlibs should have ignored the copies which are refershed
+ 								kt->second.erase( lt);
+ 								/*CComBSTR nsg;
+ 								nsg.Append( id);
+ 								nsg.Append( L" has been deleted from common map.");
+ 								Reporter( mgaproject).show( nsg, false);*/
+ 								break;
+ 							}
+ 						}
+ 					}
+ 				}
+ 			}
+ #endif
+ 
  			CComBSTR ln(libname);
  			if(!ln) COMTHROW(get_LibraryName(&ln));
***************
*** 461,469 ****
  			bool accept_old_lib( true); // refreshment of an old format MGA file is allowed
  			bool is_old_lib_copy( false);
! 			CreateLibraryImage(mgaproject, ln, libimgroot, accept_old_lib, &is_old_lib_copy);
  	 
  			libimgroot[ATTRID_PARENT] = self[ATTRID_PARENT];
  			libimgroot[ATTRID_RELID] = self[ATTRID_RELID];
  
  			if( is_old_lib_copy) // do a plain old refresh
  			{
--- 695,713 ----
  			bool accept_old_lib( true); // refreshment of an old format MGA file is allowed
  			bool is_old_lib_copy( false);
! 			CComBSTR idlist;
! 			CreateLibraryImage(mgaproject, lw, libimgroot, accept_old_lib, &is_old_lib_copy, lib_results, idlist);
  	 
  			libimgroot[ATTRID_PARENT] = self[ATTRID_PARENT];
  			libimgroot[ATTRID_RELID] = self[ATTRID_RELID];
  
+ 			if( idlist && idlist.Length() > 0)
+ 			{
+ 				Ozer::addIncludes( libimgroot, idlist);
+ 
+ 				// need to replace the id of self to the id of libimgroot
+ 				// in included libraries' 'IncludedBy' regnode
+ 				// actually self's id needs to be removed only
+ 			}
+ 
  			if( is_old_lib_copy) // do a plain old refresh
  			{
***************
*** 491,496 ****
--- 735,746 ----
  				rm.clearDepStorage();
  
+ 				// remove from all included libraries the 'dependent on self' info
+ 				// it does something only in No-optimized refresh case !!!
+ 				Ozer::removeDepForAll( mgaproject, corerf, self);
+ 
  				inDeleteObject();
  
+ 				lw.flatten( corerf, libimgroot);
+ 
  				try {
  					docheck(mgaproject);
***************
*** 512,513 ****
--- 762,1268 ----
  }
  
+ PointerFixup::PointerFixup()
+ 	: m_isOptimizing( false)
+ {
+ }
+ 
+ CoreObj PointerFixup::findLibRoot( const CoreObj& p_elem)
+ {   // copied from Identifier::getLibRootOf
+ 	CoreObj cur = p_elem;
+ 
+ 	bool goon = true;
+ 	while( goon)
+ 	{
+ 		//CComBSTR nm;
+ 		//ObjForCore(cur)->get_Name( &nm);
+ 		//nm.Append(";");
+ 
+ 		long perm = cur[ATTRID_PERMISSIONS];
+ 		if( perm & LIBROOT_FLAG)
+ 			return cur;
+ 
+ 		// if no library element, nor libroot element, must be a regular project
+ 		// element, so we consider these having a BinGuid(0) as their realm uid
+ 		if( (perm & LIBRARY_FLAG) == 0)
+ 			return cur;
+ 
+ 		cur = cur[ATTRID_PARENT];
+ 		metaid_type mt = cur.GetMetaID();
+ 		ASSERT( mt != DTID_ROOT);
+ 		goon = cur != 0;
+ 	}
+ 
+ 	return CoreObj();
+ }
+ 
+ CoreObj PointerFixup::findCounterpart( const CoreObj& p_libElem)
+ {
+ 	CoreObj lib = findLibRoot( p_libElem); // the library the element is part of
+ 	ASSERT( lib);
+ 
+ 	CoreObj cntpart_lib; // the libroot's counterpart (equivalent peer)
+ 	if( lib) 
+ 		cntpart_lib = cntPartLib( lib);
+ 
+ 	if( cntpart_lib)
+ 	{
+ 		//UniqueId u = Identifier::getDetailsOf( p_libElem);
+ 		CComPtr<IMgaFCO> fco = SearchTool::findLibObj( cntpart_lib, Identifier::getDetailsOf( p_libElem));
+ 		if( fco)
+ 		{
+ 			//CComBSTR nm; fco->get_Name( &nm);
+ 			//nm.Append( ":");
+ 			return CoreObj( fco); // this is the counterpart elem
+ 		}
+ 	}
+ 
+ 	return CoreObj();
+ }
+ 
+ CoreObj PointerFixup::cntPartLib( const CoreObj& lib2)
+ {
+ 	BinGuid g0 = Identifier::getPersistentIdOf( lib2);
+ 	for( LIBPAIRVEC::iterator it = m_libPairs.begin()
+ 		; it != m_libPairs.end()
+ 		; ++it)
+ 	{
+ 		BinGuid g1 = Identifier::getPersistentIdOf( it->first);
+ 		if( g0 == g1)
+ 		{
+ 			ASSERT( g1 == Identifier::getPersistentIdOf( it->second));
+ 			return it->second;
+ 		}
+ 	}
+ 
+ 	return CoreObj();
+ }
+ 
+ void PointerFixup::setLibPairs( LIBPAIRVEC& p_libPairs)
+ {
+ 	m_libPairs = p_libPairs;
+ 	m_isOptimizing = !p_libPairs.empty();
+ }
+ 
+ LibWorker::LibWorker( CMgaProject* p_mgaProject
+                     , CComBSTR     p_libName)
+     : m_mgaProject( p_mgaProject)
+     , m_libName( p_libName)
+     , m_optimized( false)
+ {
+ 	std::string ln;
+ 	CopyTo( m_libName, ln);
+ 	std::string magic_str( " (optimized)");
+ 	std::string::size_type pos = ln.find( magic_str);
+ 	if( pos != std::string::npos && pos + magic_str.length() == ln.length())
+ 	{
+ 		m_optimized = true;
+ 		ln = ln.substr( 0, pos);
+ 		CopyTo( ln, &m_libName);
+ 	}
+ }
+ 
+ bool LibWorker::isOptimized() const
+ {
+ 	return m_optimized;
+ }
+ 
+ CComBSTR LibWorker::getConnectionStr() const
+ {
+ 	return m_libName;
+ }
+ 
+ CComBSTR LibWorker::getLongName() const
+ {
+ 	CComBSTR res;
+ 	res.AppendBSTR( m_libName);
+ 	if( m_optimized)
+ 	{
+ 		std::string magic_str( " (optimized)");
+ 		res.Append( magic_str.c_str());
+ 	}
+ 
+ 	return res;
+ }
+ 
+ 
+ // static
+ void LibWorker::discover( int                                             p_recDepth
+                         , CoreObj&                                        p_container
+                         , const CComBSTR&                                 p_avoidThisLib
+ 						, LIB_MAP&                                        p_results)
+ {
+ 	// recursive method
+ 	// unlimited depth allowed if p_recDepth == -1
+ 	// limited depth allowed if positive p_recDepth provided
+ 
+ 	if( p_avoidThisLib.Length() > 0) 
+ 	{
+ 		// the caller is trying the discover the whole project EXCEPT 
+ 		// the library (and its internals) specified by this id
+ 		CComBSTR cont_id;
+ 		ObjForCore( p_container)->get_ID( &cont_id);
+ 		if( p_avoidThisLib == cont_id)
+ 			return; // avoid going into this library
+ 	}
+ 
+ 	long pm = p_container[ATTRID_PERMISSIONS];
+ 	if( pm & LIBROOT_FLAG)
+ 	{
+ 		BinGuid libn = Identifier::getPersistentIdOf( p_container);
+ 		p_results[ libn ].push_back( p_container);
+ 	}
+ 
+ 	if( p_recDepth) // specifically: -1 or > 0
+ 	{
+ 		ITERATE_THROUGH( p_container[ ATTRID_FCOPARENT + ATTRID_COLLECTION]) 
+ 		{
+ 			metaid_type mtyp = ITER.GetMetaID(); 
+ 			// in case p_recDepth > 0 the method will be called with decreased value
+ 			if( mtyp == DTID_FOLDER) discover( p_recDepth > 0 ? p_recDepth - 1:-1, ITER, p_avoidThisLib, p_results);
+ 		}
+ 	}
+ }
+ 
+ // static
+ void LibWorker::recordLibs( bool                 p_recordAllLibs
+                           //, CMgaProject*       p_mgaproject
+                           , CoreObj&             p_container
+ 						  , LIB_MAP&             p_results
+                           , const CComBSTR&      p_avoidThisLibrary)
+ {
+ 	// if all libs must be recorded then allow unlimited depth: -1
+ 	// otherwise (only toplevel libs need to be recorded): depth 1 is sufficient
+ 
+ 	LibWorker::discover( p_recordAllLibs ? -1:1, p_container, p_avoidThisLibrary, p_results);
+ }
+ 
+ void LibWorker::showDetails( CoreObj&  p_container, std::map< BinGuid, std::vector< CoreObj > >&  p_results)
+ {
+ 	CComBSTR oid;
+ 	ObjForCore( p_container)->get_ID( &oid);
+ 	oid.Append( L" lib recorded");
+ 	if( m_mgaProject) Reporter::showIt( m_mgaProject, oid, false);
+ 
+ 	for( std::map< BinGuid, std::vector< CoreObj > >::iterator it = p_results.begin()
+ 		; it != p_results.end()
+ 		; ++it)
+ 	{
+ 		if( it->second.size() > 1) // duplicates found
+ 		{
+ 			BinGuid bf = it->first;
+ 			MyCComBSTR m;
+ 			m.appendGuid( bf);
+ 			m.Append( L" duplicate lib");
+ 			if( m_mgaProject) Reporter::showIt( m_mgaProject, m, false);
+ 		}
+ 	}
+ }
+ 
+ // static
+ void LibWorker::groupTheLibs( CoreObj&              p_container
+                             , LIB_MAP&              p_results)
+ {
+ 	for( std::map< BinGuid, std::vector< CoreObj > >::iterator it = p_results.begin()
+ 		; it != p_results.end()
+ 		; ++it)
+ 	{
+ 		for( std::vector< CoreObj >::iterator jt = it->second.begin()
+ 			; jt != it->second.end()
+ 			; ++jt)
+ 		{
+ 			CoreObj librf = *jt;
+ 			CoreObj librfparent = librf[ATTRID_PARENT];
+ 			CComBSTR id1, id2;
+ 			ObjForCore( p_container)->get_ID( &id1);
+ 			ObjForCore( librfparent)->get_ID( &id2);
+ 			if( id1 != id2)
+ 			{
+ 				// move out to the root level
+ 				librf[ATTRID_FCOPARENT] = p_container;
+ 
+ 				// save the dependency info
+ 				Ozer::addIncludedBy( librf, id2);
+ 
+ 				CComBSTR id3;
+ 				ObjForCore( librf)->get_ID( &id3);
+ 
+ 				// save the includes info
+ 				Ozer::addIncludes( librfparent, id3);
+ 			}
+ 		}
+ 	}
+ }
+ 
+ void LibWorker::flatten( CoreObj&     p_rootfolder
+                        , CoreObj&     p_libimgroot)
+ {
+ 	if( m_optimized)
+ 	{
+ 		LIB_MAP results;
+ 		recordLibs( true, p_libimgroot, results);
+ 		groupTheLibs( p_rootfolder, results);
+ 	}
+ }
+ 
+ void Ozer::removeDepForAll( CMgaProject* p_mgaproject
+                           , CoreObj&     p_rootfolder
+                           , CoreObj&     p_libimgroot)
+ {
+ 	CComBSTR includes_valb;
+ 	Ozer::StorageMgr::getIncludes( p_libimgroot, includes_valb);
+ 
+ 	// don't have to remove this regnode, because the this is the old
+ 	// top lib regnode which will be discarded
+ 
+ 	// we have to remove the dependency entry in each of these libraries
+ 	// listed in the regnode
+ 	std::string includes_vals;
+     CopyTo( includes_valb, includes_vals);
+ 	// skip parsing if empty
+ 	std::string::size_type pos = includes_vals.empty()? std::string::npos : 0;
+ 	while( pos != std::string::npos)
+ 	{
+ 		std::string::size_type last_pos = pos;
+ 		pos = includes_vals.find("\n");
+ 
+ 		std::string token;
+ 		if( pos == std::string::npos)
+ 			token = includes_vals.substr( last_pos);
+ 		else
+ 			token = includes_vals.substr( last_pos, pos - last_pos);
+ 
+ 		CComBSTR lib_id_to_remove;
+ 		ObjForCore( p_libimgroot)->get_ID( &lib_id_to_remove);
+ 		
+ 		Ozer::removeDep( p_mgaproject, token, lib_id_to_remove);
+ 	}
+ }
+ 
+ bool Ozer::removeDep( CMgaProject*       p_mgaProject
+                     , const std::string& p_idOfLib
+                     , const CComBSTR&    p_idToRemoveFromReg)
+ {
+ 	bool all_right = false;
+ 
+ 	CComPtr<IMgaObject> obj;
+ 	ASSERT( p_idOfLib.length() == 16); // id like: "id-006a-00000002"
+ 	if( p_idOfLib.length() == 16 && SUCCEEDED( p_mgaProject->GetObjectByID( CComBSTR( p_idOfLib.c_str()), &obj)))
+ 	{
+ 		CComQIPtr<IMgaFolder> fld( obj);
+ 		long stat = OBJECT_ZOMBIE;
+ 		obj->get_Status( &stat);
+ 		if( fld && stat == OBJECT_EXISTS)
+ 		{
+ 			CoreObj fld_core( fld);
+ 			bool lib_freed = false;
+ 			all_right = Ozer::loseIncludedBy( fld_core, p_idToRemoveFromReg, lib_freed);
+ 		}
+ 	}
+ 
+ 	ASSERT( all_right);
+ 	return all_right;
+ }
+ 
+ bool Ozer::loseIncludedBy( CoreObj&          p_fldCore
+                          , const CComBSTR&   p_idToRemoveFromReg
+                          , bool&             p_libraryBecameFree)
+ {
+ 	bool     all_right = false;
+ 	try 
+ 	{
+ 		long     prm       = p_fldCore[ATTRID_PERMISSIONS];
+ 
+ 		CComBSTR valb;
+ 
+ 		p_fldCore[ATTRID_PERMISSIONS] = prm & ~READONLY_FLAG;
+ 		Ozer::StorageMgr::getIncludedBy( p_fldCore, valb);
+ 		p_fldCore[ATTRID_PERMISSIONS] = prm;
+ 
+ 		if( valb && valb.Length() > 0)
+ 		{
+ 			std::string vals;
+ 			CopyTo( valb, vals);
+ 
+ 			std::string erasable_val;
+ 			CopyTo( p_idToRemoveFromReg, erasable_val);
+ 			
+ 			bool res = eraseIdFromIdList( erasable_val, vals);
+ 			ASSERT( res);
+ 			if( res)
+ 			{
+ 				// write new value back into BSTR
+ 				valb.Empty();
+ 				CopyTo( vals, &valb);
+ 
+ 				// save modified value back
+ 				p_fldCore[ATTRID_PERMISSIONS] = prm & ~READONLY_FLAG;
+ 				Ozer::StorageMgr::setIncludedBy( p_fldCore, valb);
+ 				p_fldCore[ATTRID_PERMISSIONS] = prm;
+ 
+ 				if( valb.Length() == 0) // library became free
+ 				{
+ 					// let's take off the read-only flag
+ 					p_fldCore[ATTRID_PERMISSIONS] = prm & ~READONLY_FLAG;
+ 					p_libraryBecameFree = true;
+ 				}
+ 
+ 				all_right = true;
+ 			}
+ 		}
+ 		else ASSERT( 0); // empty registry value
+ 
+ 		ASSERT( all_right);
+ 	}
+ 	catch(hresult_exception& e)
+ 	{
+ 		if( e.hr == E_NOTFOUND)
+ 		{
+ 			int l(0);
+ 			++l;
+ 		}
+ 		else
+ 		{
+ 			int l(0);
+ 			++l;
+ 		}
+ 		ASSERT(0);
+ 	}
+ 	catch(...)
+ 	{
+ 		// the object might be a zombie, may throw exceptions
+ 		ASSERT( 0);
+ 	}
+ 	return all_right;
+ }
+ 
+ bool Ozer::addIncludes( CoreObj&           p_fldCore
+                       , const CComBSTR&    p_idToAddToReg)
+ {
+ 	long prm        = p_fldCore[ATTRID_PERMISSIONS];
+ 
+ 	// take off the Library (ro) flag
+ 	p_fldCore[ATTRID_PERMISSIONS] = prm & ~LIBRARY_FLAG & ~READONLY_FLAG;
+ 
+ 	// registry asked about 'Includes' info
+ 	// might create the node if not existing
+ 	CComBSTR valu;
+ 	Ozer::StorageMgr::getIncludes( p_fldCore, valu);
+ 	
+ 	// registry altered to show which library is logically included by this one (this depends on that)
+ 	if( valu && valu.Length() > 0) valu.Append( L"\n");
+ 	valu.AppendBSTR( p_idToAddToReg); // p_idToAddToReg might be a list of ids !!!
+ 
+ 	// save value
+ 	Ozer::StorageMgr::setIncludes( p_fldCore, valu);
+ 
+ 	// set saved perm values back
+ 	p_fldCore[ATTRID_PERMISSIONS] = prm;
+ 
+ 	return true;
+ }
+ 
+ bool Ozer::addIncludedBy( CoreObj&            p_fldCore
+                         , const CComBSTR&     p_idToAddToReg)
+ {
+ 	long prm        = p_fldCore[ATTRID_PERMISSIONS];
+ 
+ 	// take off the Library (ro) flag
+ 	p_fldCore[ATTRID_PERMISSIONS] = prm & ~LIBRARY_FLAG & ~READONLY_FLAG;
+ 
+ 	// registry asked about 'IncludedBy' info
+ 	// might create the node if not existing
+ 	CComBSTR valu;
+ 	Ozer::StorageMgr::getIncludedBy( p_fldCore, valu);
+ 	
+ 	// alter value
+ 	if( valu && valu.Length() > 0) valu.Append( L"\n");
+ 	valu.AppendBSTR( p_idToAddToReg);
+ 
+ 	// registry altered to show which library includes this one (depends of me)
+ 	// save value
+ 	Ozer::StorageMgr::setIncludedBy( p_fldCore, valu);
+ 
+ 	// alter permission values finally: READONLY applied, LIBRARY_FLAG unset
+ 	// MODIF:
+ 	// don't apply any readonly flag for now this way we allow 
+ 	// refresh for such included libraries as well
+ 	// 
+ 	//p_fldCore[ATTRID_PERMISSIONS] = prm & ~LIBRARY_FLAG | READONLY_FLAG;
+ 
+ 	return true;
+ }
+ 
+ bool Ozer::eraseIdFromIdList( const std::string&  p_erasableVal
+                             , std::string&        p_valueList)
+ {
+ 	bool all_right = false;
+ 	
+ 	std::string::size_type pos = p_valueList.find( p_erasableVal);
+ 	if( pos != std::string::npos) // found
+ 	{
+ 		all_right = true;
+ 
+ 		// delete the id, the p_erasableVal
+ 		p_valueList.erase( p_valueList.begin() + pos, p_valueList.begin() + pos + p_erasableVal.length());
+ 
+ 		// deal with separator issues
+ 		pos = p_valueList.find( "\n\n"); // two newlines found
+ 		if( pos == std::string::npos && !p_valueList.empty()) // although \n\n was not found, special cases remain
+ 		{
+ 			if( p_valueList[0] == '\n' ) pos = 0;
+ 			else if( p_valueList[ p_valueList.length() - 1] == '\n') pos = p_valueList.length() - 1;
+ 		}
+ 		
+ 		if( pos != std::string::npos)
+ 			p_valueList.erase( p_valueList.begin() + pos, p_valueList.begin() + pos + 1); // delete one of them
+ 	}
+ 
+ 	ASSERT( all_right);
+ 	return all_right;
+ }
+ 
+ void Ozer::StorageMgr::writer( CoreObj&                p_fldCore
+                              , const CComBSTR&         p_node
+                              , const CComBSTR&         p_value)
+ {
+ 	ObjForCore( p_fldCore)->put_RegistryValue( p_node, p_value);
+ }
+ 
+ void Ozer::StorageMgr::reader( CoreObj&                p_fldCore
+                              , const CComBSTR&         p_node
+                              , CComBSTR&               p_value)
+ {
+ 	ObjForCore( p_fldCore)->get_RegistryValue( p_node, &p_value);
+ }
+ 
+ void Ozer::StorageMgr::getIncludes( CoreObj&             p_fldCore
+                                   , CComBSTR&            p_idList)
+ {
+ 	// get_RegistryValue complains if its first parameter
+ 	// is a literal, that's why we pass a variable: path
+ 	CComBSTR path( INCLUDES_STR);
+ 	reader( p_fldCore, path, p_idList);
+ }
+ 
+ void Ozer::StorageMgr::setIncludes( CoreObj&             p_fldCore
+                                   , const CComBSTR&      p_idList)
+ {
+ 	// put_RegistryValue complains if its first parameter
+ 	// is a literal, that's why we pass a variable: path
+ 	CComBSTR path( INCLUDES_STR);
+ 	writer( p_fldCore, path, p_idList);
+ }
+ 
+ void Ozer::StorageMgr::getIncludedBy( CoreObj&           p_fldCore
+                                     , CComBSTR&          p_idList)
+ {
+ 	CComBSTR path( INCLUDED_BY_STR);
+ 	reader( p_fldCore, path, p_idList);
+ }
+ 
+ void Ozer::StorageMgr::setIncludedBy( CoreObj&           p_fldCore
+                                     , const CComBSTR&    p_idList)
+ {
+ 	CComBSTR path( INCLUDED_BY_STR);
+ 	writer( p_fldCore, path, p_idList);
+ }

Index: MgaLibOps.h
===================================================================
RCS file: /project/gme-repository/GMESRC/GME/Mga/MgaLibOps.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** MgaLibOps.h	13 Oct 2004 15:17:55 -0000	1.2
--- MgaLibOps.h	16 Jan 2007 18:13:33 -0000	1.3
***************
*** 1,5 ****
--- 1,14 ----
+ #pragma once
+ 
+ #include <map>
+ #include <vector>
+ class BinGuid;
  
  class PointerFixup
  {
+ public: // typedefs
+ 	typedef std::vector< std::pair< CoreObj, CoreObj > > LIBPAIRVEC;
+ 
+ protected:
  	coreobjpairhash identity_map;
  
***************
*** 13,17 ****
--- 22,36 ----
  	std::vector<resolve_entry> resolve_entries;
  
+ 	bool                       m_isOptimizing;
+ 	LIBPAIRVEC                 m_libPairs;
+ 
  public:
+ 	PointerFixup();
+ 	void setLibPairs( LIBPAIRVEC& p_libPairs);
+ 
+ 	CoreObj findLibRoot( const CoreObj& p_elem);
+ 	CoreObj findCounterpart( const CoreObj& p_libElem);
+ 	CoreObj cntPartLib( const CoreObj& p_lib2);
+ 
  	inline void identify(const CoreObj &original, const CoreObj &created)
  	{
***************
*** 31,37 ****
  			return;
  
  		coreobjpairhash::iterator i = identity_map.find(target);
  		if( i != identity_map.end() )
! 			created[attrid] = i->second;	// already created
  		else								// resolve it later
  		{
--- 50,79 ----
  			return;
  
+ 		// if lib1 to be imported contains a lib2
+ 		// while the project contains already
+ 		// a copy of lib2 (as a standalone lib)
+ 		// there is a possibility for optimization
+ 		//
+ 		// if pointer is in lib1 and tgt in lib2, then
+ 		// pointer of lib1 might be redirected to lib2's 
+ 		// existing counterpart in project (lib2copy)
  		coreobjpairhash::iterator i = identity_map.find(target);
  		if( i != identity_map.end() )
! 		{
! 			CoreObj iseccnpart;
! 			
! 			if( m_isOptimizing)
! 			{
! 				// i->second might be replaced by its counterpart 
! 				// in lib2copy
! 				iseccnpart = findCounterpart( i->second);
! 				ASSERT( iseccnpart);//SHOULDN'T IT FAIL if counterpart not found?
! 			}
! 
! 			if( iseccnpart)
! 				created[attrid] = iseccnpart;
! 			else
! 				created[attrid] = i->second;// already created
! 		}
  		else								// resolve it later
  		{
***************
*** 48,51 ****
--- 90,94 ----
  		resolve_entries.clear();
  		identity_map.clear();
+ 		m_libPairs.clear();
  	}
  
***************
*** 58,62 ****
  			ASSERT( new_target != NULL );
  
! 			(i->created)[i->attrid] = new_target;
  
  			++i;
--- 101,116 ----
  			ASSERT( new_target != NULL );
  
! 			CoreObj iseccnpart;
! 			if( m_isOptimizing)
! 			{
! 				// look for the element's peer in the peer library
! 				iseccnpart = findCounterpart( new_target);
! 				ASSERT( iseccnpart); // SHOULDN'T IT FAIL IF COUNTERPART NOT FOUND?
! 			}
! 
! 			if( iseccnpart)
! 				(i->created)[i->attrid] = iseccnpart;
! 			else
! 				(i->created)[i->attrid] = new_target;
  
  			++i;
***************
*** 64,66 ****
  		clear();
  	}
! };
\ No newline at end of file
--- 118,214 ----
  		clear();
  	}
! };
! 
! class Ozer //Optimizer
! {
! 	class StorageMgr // responsible for Storing and Retrieving the information
! 	{
! 		static void writer( CoreObj&                p_fldCore
! 		                  , const CComBSTR&         p_node
! 		                  , const CComBSTR&         p_value);
! 		static void reader( CoreObj&                p_fldCore
! 		                  , const CComBSTR&         p_node
! 		                  , CComBSTR&               p_value);
! 	public:
! 		static const wchar_t* INCLUDED_BY_STR;
! 		static const wchar_t* INCLUDES_STR;
! 
! 		static void getIncludes( CoreObj&           p_fldCore
! 		                       , CComBSTR&          p_idList);
! 		static void setIncludes( CoreObj&           p_fldCore
! 		                       , const CComBSTR&    p_idList);
! 
! 		static void getIncludedBy( CoreObj&           p_fldCore
! 		                         , CComBSTR&          p_idList);
! 		static void setIncludedBy( CoreObj&           p_fldCore
! 		                         , const CComBSTR&    p_idList);
! 	};
! 
! 	static bool eraseIdFromIdList( const std::string&  p_erasableVal
!                                  , std::string&        p_valueList);
! 
! 	static bool removeDep( CMgaProject*       p_mgaProject
!                          , const std::string& p_idOfLib
!                          , const CComBSTR&    p_idToRemoveFromReg);
! 
! public:
! 
! 	static bool addIncludedBy( CoreObj&            p_fldCore
!                              , const CComBSTR&     p_idToAddToReg);
! 
! 	static bool addIncludes( CoreObj&              p_fldCore
!                            , const CComBSTR&       p_idToAddToReg);
! 
! 	static bool loseIncludedBy( CoreObj&          p_fldCore
!                               , const CComBSTR&   p_idToRemoveFromReg
!                               , bool&             p_libraryBecameFree);
! 
! 	static void removeDepForAll( CMgaProject* p_mgaproject
!                                , CoreObj&     p_rootfolder
!                                , CoreObj&     p_libimgroot);
! };
! 
! class LibWorker
! {
! public: // typedefs
! 
! 	typedef std::vector< CoreObj >                      CORE_VEC;
! 	typedef CORE_VEC::iterator                          CORE_VEC_ITER;
! 	typedef std::map< BinGuid, std::vector< CoreObj > > LIB_MAP;
! 	typedef LIB_MAP::iterator                           LIB_MAP_ITER;
! 
! protected: // members
! 
! 	CMgaProject* m_mgaProject;
! 	CComBSTR     m_libName;
! 	bool         m_optimized;
! 
! 	static void groupTheLibs( CoreObj&              p_container
!                             , LIB_MAP&              p_results);
! 
! 	static void discover( int                       p_recDepth
!                         , CoreObj&                  p_container
!                         , const CComBSTR&           p_avoidThisLib
!                         , LIB_MAP&                  p_results);
! 
! 	void showDetails( CoreObj& p_container, LIB_MAP& p_results);
! 
! public:
! 
! 	LibWorker( CMgaProject* p_mgaProject
! 	         , CComBSTR     p_libName);
! 
! 	bool          isOptimized() const;
! 	CComBSTR      getConnectionStr() const;
! 	CComBSTR      getLongName() const;
! 
! 	void flatten( CoreObj&     p_rootfolder
!                 , CoreObj&     p_libimgroot);
! 
! 
! 	static void recordLibs( bool               p_recordAllLibs
!                           , CoreObj&           p_container
!                           , LIB_MAP&           p_results
!                           , const CComBSTR&    p_avoidThisLibrary = "");
! 
! };



More information about the GME-commit mailing list