View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0003158 | OpenFOAM | Bug | public | 2019-02-01 18:26 | 2019-02-04 09:43 |
Reporter | fede | Assigned To | will | ||
Priority | normal | Severity | minor | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Platform | Linux | OS | Debian | OS Version | Stretch |
Product Version | dev | ||||
Fixed in Version | dev | ||||
Summary | 0003158: codeOptions entry no longer supported by #codeStream | ||||
Description | Dear Henry, after the recent updates to the implementation of dynamicCode, the codeOptions entry is no longer read in the codeStream functions. This feature was supported in the previous versions of the code (OpenFOAM-6 for instance). This causes that some coded functions working with previous (but still recent) versions of OpenFOAM. The reason is that in the newest implementation of codeStream (available only in OpenFOAM-dev) some lines are missing. Everything works in OpenFOAM-6. Please find attached the files with the patch to revert the missing functionality. Wish this helps. Have a nice week end, /Federico | ||||
Steps To Reproduce | Try to include a "codeOption" entry in a codedFunction and a file "fileInSystemFolder.H" in the path specified in the codeOptions. The code will not work (of course "ileInSystemFolder.H" must be located in a folder which is not included in the PATH, for instance $FOAM_CASE/system). Example: <fileEntry> ( #codeStream { .... //! Optional: codeOptions #{ -I${FOAM_CASE}/system #}; code #{ #include "fileInSystemFolder.H" #} ... ); | ||||
Additional Information | Testing was done in OpenFOAM-dev, commit 5afec3aae0a06adc5e1af0a23f7afad94e5d4b60. | ||||
Tags | No tags attached. | ||||
|
codeStream.C (12,277 bytes)
/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org \\ / A nd | Copyright (C) 2011-2019 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License This file is part of OpenFOAM. OpenFOAM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenFOAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. \*---------------------------------------------------------------------------*/ #include "codeStream.H" #include "addToMemberFunctionSelectionTable.H" #include "IStringStream.H" #include "OStringStream.H" #include "dynamicCode.H" #include "dynamicCodeContext.H" #include "Time.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // namespace Foam { namespace functionEntries { defineTypeNameAndDebug(codeStream, 0); addToMemberFunctionSelectionTable ( functionEntry, codeStream, execute, dictionaryIstream ); addToMemberFunctionSelectionTable ( functionEntry, codeStream, execute, primitiveEntryIstream ); } } const Foam::word Foam::functionEntries::codeStream::codeTemplateC = "codeStreamTemplate.C"; // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // Foam::dlLibraryTable& Foam::functionEntries::codeStream::libs ( const dictionary& dict ) { const baseIOdictionary& d = static_cast<const baseIOdictionary&> ( dict.topDict() ); return const_cast<Time&>(d.time()).libs(); } bool Foam::functionEntries::codeStream::doingMasterOnlyReading ( const dictionary& dict ) { const dictionary& topDict = dict.topDict(); if (isA<baseIOdictionary>(topDict)) { const baseIOdictionary& d = static_cast<const baseIOdictionary&> ( topDict ); if (debug) { Pout<< "codeStream : baseIOdictionary:" << dict.name() << " master-only-reading:" << d.globalObject() << endl; } return d.globalObject(); } else { if (debug) { Pout<< "codeStream : not a baseIOdictionary:" << dict.name() << " master-only-reading:" << regIOobject::masterOnlyReading << endl; } // Fall back to regIOobject::masterOnlyReading return regIOobject::masterOnlyReading; } } Foam::functionEntries::codeStream::streamingFunctionType Foam::functionEntries::codeStream::getFunction ( const dictionary& parentDict, const dictionary& codeDict ) { // get code, codeInclude, ... dynamicCodeContext context(codeDict, {"code", "codeInclude", "codeOptions", "localCode"}); // codeName: codeStream + _<sha1> // codeDir : _<sha1> std::string sha1Str(context.sha1().str(true)); dynamicCode dynCode("codeStream" + sha1Str, sha1Str); // Load library if not already loaded // Version information is encoded in the libPath (encoded with the SHA1) const fileName libPath = dynCode.libPath(); // see if library is loaded void* lib = nullptr; const dictionary& topDict = parentDict.topDict(); if (isA<baseIOdictionary>(topDict)) { lib = libs(parentDict).findLibrary(libPath); } if (!lib) { Info<< "Using #codeStream with " << libPath << endl; } // nothing loaded // avoid compilation if possible by loading an existing library if (!lib) { if (isA<baseIOdictionary>(topDict)) { // Cached access to dl libs. Guarantees clean up upon destruction // of Time. dlLibraryTable& dlLibs = libs(parentDict); if (dlLibs.open(libPath, false)) { lib = dlLibs.findLibrary(libPath); } } else { // Uncached opening of libPath. Do not complain if cannot be loaded lib = dlOpen(libPath, false); } } // create library if required if (!lib) { bool create = Pstream::master() || (regIOobject::fileModificationSkew <= 0); // not NFS if (create) { if (!dynCode.upToDate(context)) { // filter with this context dynCode.reset(context); // compile filtered C template dynCode.addCompileFile(codeTemplateC); // define Make/options dynCode.setMakeOptions ( "EXE_INC = -g \\\n" + context.options() + "\n\nLIB_LIBS = \\\n" + " -lOpenFOAM \\\n" + context.libs() ); if (!dynCode.copyOrCreateFiles(true)) { FatalIOErrorInFunction ( parentDict ) << "Failed writing files for" << nl << dynCode.libRelPath() << nl << exit(FatalIOError); } } if (!dynCode.wmakeLibso()) { FatalIOErrorInFunction ( parentDict ) << "Failed wmake " << dynCode.libRelPath() << nl << exit(FatalIOError); } } //- Only block if we're not doing master-only reading. (flag set by // regIOobject::read, baseIOdictionary constructor) if ( !doingMasterOnlyReading(topDict) && regIOobject::fileModificationSkew > 0 ) { //- Since the library has only been compiled on the master the // other nodes need to pick this library up through NFS // We do this by just polling a few times using the // fileModificationSkew. off_t mySize = Foam::fileSize(libPath); off_t masterSize = mySize; Pstream::scatter(masterSize); if (debug) { Pout<< endl<< "on processor " << Pstream::myProcNo() << " have masterSize:" << masterSize << " and localSize:" << mySize << endl; } if (mySize < masterSize) { if (debug) { Pout<< "Local file " << libPath << " not of same size (" << mySize << ") as master (" << masterSize << "). Waiting for " << regIOobject::fileModificationSkew << " seconds." << endl; } Foam::sleep(regIOobject::fileModificationSkew); // Recheck local size mySize = Foam::fileSize(libPath); if (mySize < masterSize) { FatalIOErrorInFunction ( parentDict ) << "Cannot read (NFS mounted) library " << nl << libPath << nl << "on processor " << Pstream::myProcNo() << " detected size " << mySize << " whereas master size is " << masterSize << " bytes." << nl << "If your case is not NFS mounted" << " (so distributed) set fileModificationSkew" << " to 0" << exit(FatalIOError); } } if (debug) { Pout<< endl<< "on processor " << Pstream::myProcNo() << " after waiting: have masterSize:" << masterSize << " and localSize:" << mySize << endl; } } if (isA<baseIOdictionary>(topDict)) { // Cached access to dl libs. Guarantees clean up upon destruction // of Time. dlLibraryTable& dlLibs = libs(parentDict); if (debug) { Pout<< "Opening cached dictionary:" << libPath << endl; } if (!dlLibs.open(libPath, false)) { FatalIOErrorInFunction ( parentDict ) << "Failed loading library " << libPath << nl << "Did you add all libraries to the 'libs' entry" << " in system/controlDict?" << exit(FatalIOError); } lib = dlLibs.findLibrary(libPath); } else { // Uncached opening of libPath if (debug) { Pout<< "Opening uncached dictionary:" << libPath << endl; } lib = dlOpen(libPath, true); } } bool haveLib = lib; if (!doingMasterOnlyReading(topDict)) { reduce(haveLib, andOp<bool>()); } if (!haveLib) { FatalIOErrorInFunction ( parentDict ) << "Failed loading library " << libPath << " on some processors." << exit(FatalIOError); } // Find the function handle in the library streamingFunctionType function = reinterpret_cast<streamingFunctionType> ( dlSym(lib, dynCode.codeName()) ); if (!function) { FatalIOErrorInFunction ( parentDict ) << "Failed looking up symbol " << dynCode.codeName() << " in library " << lib << exit(FatalIOError); } return function; } // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // bool Foam::functionEntries::codeStream::execute ( const dictionary& parentDict, primitiveEntry& entry, Istream& is ) { Info<< "Using #codeStream at line " << is.lineNumber() << " in file " << parentDict.name() << endl; dynamicCode::checkSecurity ( "functionEntries::codeStream::execute(..)", parentDict ); // get code dictionary // must reference parent for stringOps::expand to work nicely dictionary codeDict("#codeStream", parentDict, is); streamingFunctionType function = getFunction(parentDict, codeDict); // use function to write stream OStringStream os(is.format()); (*function)(os, parentDict); // get the entry from this stream IStringStream resultStream(os.str()); entry.read(parentDict, resultStream); return true; } bool Foam::functionEntries::codeStream::execute ( dictionary& parentDict, Istream& is ) { Info<< "Using #codeStream at line " << is.lineNumber() << " in file " << parentDict.name() << endl; dynamicCode::checkSecurity ( "functionEntries::codeStream::execute(..)", parentDict ); // get code dictionary // must reference parent for stringOps::expand to work nicely dictionary codeDict("#codeStream", parentDict, is); streamingFunctionType function = getFunction(parentDict, codeDict); // use function to write stream OStringStream os(is.format()); (*function)(os, parentDict); // get the entry from this stream IStringStream resultStream(os.str()); parentDict.read(resultStream); return true; } // ************************************************************************* // dynamicCodeContext.C (3,390 bytes)
/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org \\ / A nd | Copyright (C) 2011-2019 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License This file is part of OpenFOAM. OpenFOAM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenFOAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. \*---------------------------------------------------------------------------*/ #include "dynamicCodeContext.H" #include "stringOps.H" #include "OSHA1stream.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // void Foam::dynamicCodeContext::addLineDirective ( string& code, const label lineNum, const fileName& name ) { code = "#line " + Foam::name(lineNum + 1) + " \"" + name + "\"\n" + code; } // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::dynamicCodeContext::dynamicCodeContext ( const dictionary& dict, const wordList& codeKeys ) : dict_(dict), code_(), options_(), libs_() { // Expand all dictionary entries. Note that this removes any leading or // trailing whitespace, which is necessary for compilation options, and // doesn't hurt for everything else List<const entry*> codePtrs(codeKeys.size(), nullptr); forAll(codeKeys, i) { const word& key = codeKeys[i]; codePtrs[i] = dict.lookupEntryPtr(key, false, false); if (codePtrs[i]) { code_.insert ( key, stringOps::expand ( stringOps::trim(codePtrs[i]->stream()), dict ) ); } else { code_.insert(key, ""); } } // Calculate SHA1 digest from all entries OSHA1stream os; forAllConstIter(HashTable<string>, code_, iter) { os << iter(); } sha1_ = os.digest(); // Add line directive after calculating SHA1 since this includes // "processor..." in the path which differs between cores forAll(codeKeys, i) { if (codePtrs[i]) { const word& key = codeKeys[i]; if (key != "codeOptions") { addLineDirective ( code_[key], codePtrs[i]->startLineNumber(), dict.name() ); } else { options_ = code_[key]; } } } } // ************************************************************************* // |
|
Apologies with my English. "This causes that some coded functions working with previous (but still recent) versions of OpenFOAM." means "This causes that some coded functions working with previous (but still recent) versions of OpenFOAM do not work with the latest commits of OpenFOAM-dev." |
|
Thanks you for the report. I haven't applied your changes. They do not resolve the problem in the way that the design intends. "codeOptions" was not intended to be part of the list of code keys, as it is not actually C++ code and therefore has to be handled a little differently. Similarly, "codeLibs" was also missing, but should not be one of the code keys for the same reason. What I forgot to add in my changes last week was just the reading and setting of the options and libs data in the dynamicCodeContext constructor. I have now done this as part of commit 528dccc0 in dev. It should now work as it did before. You did not provide a test case, so I cannot be 100% sure that this fixes your problem. I actually did my testing with codedFunctionObject. If your problem persists, please open another report and attach an example which reproduces the failure. |
Date Modified | Username | Field | Change |
---|---|---|---|
2019-02-01 18:26 | fede | New Issue | |
2019-02-01 18:26 | fede | File Added: codeStream.C | |
2019-02-01 18:26 | fede | File Added: dynamicCodeContext.C | |
2019-02-01 18:28 | fede | Note Added: 0010277 | |
2019-02-04 09:31 | will | View Status | private => public |
2019-02-04 09:32 | will | Note View State: 0010277: public | |
2019-02-04 09:43 | will | Assigned To | => will |
2019-02-04 09:43 | will | Status | new => resolved |
2019-02-04 09:43 | will | Resolution | open => fixed |
2019-02-04 09:43 | will | Fixed in Version | => dev |
2019-02-04 09:43 | will | Note Added: 0010278 |