Initial commit for version 2.0.x patch release
[OpenFOAM-2.0.x.git] / src / OpenFOAM / db / dictionary / functionEntries / codeStream / codeStream.C
blob8eefcb86d92675ace7715e9f9ec4c3cafd6bedc6
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 2011-2011 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
9     This file is part of OpenFOAM.
11     OpenFOAM is free software: you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by
13     the Free Software Foundation, either version 3 of the License, or
14     (at your option) any later version.
16     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19     for more details.
21     You should have received a copy of the GNU General Public License
22     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "codeStream.H"
27 #include "addToMemberFunctionSelectionTable.H"
28 #include "IStringStream.H"
29 #include "OStringStream.H"
30 #include "IOstreams.H"
31 #include "stringOps.H"
32 #include "dynamicCode.H"
33 #include "dynamicCodeContext.H"
34 #include "dlLibraryTable.H"
35 #include "OSspecific.H"
36 #include "Time.H"
37 #include "PstreamReduceOps.H"
39 #include "long.H"
41 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
43 namespace Foam
45 namespace functionEntries
47     defineTypeNameAndDebug(codeStream, 0);
49     addToMemberFunctionSelectionTable
50     (
51         functionEntry,
52         codeStream,
53         execute,
54         primitiveEntryIstream
55     );
61 const Foam::word Foam::functionEntries::codeStream::codeTemplateC
62     = "codeStreamTemplate.C";
65 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
67 const Foam::dictionary& Foam::functionEntries::codeStream::topDict
69     const dictionary& dict
72     const dictionary& p = dict.parent();
74     if (&p != &dict && !p.name().empty())
75     {
76         return topDict(p);
77     }
78     else
79     {
80         return dict;
81     }
85 Foam::dlLibraryTable& Foam::functionEntries::codeStream::libs
87     const dictionary& dict
90     const IOdictionary& d = static_cast<const IOdictionary&>(topDict(dict));
91     return const_cast<Time&>(d.time()).libs();
95 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
97 bool Foam::functionEntries::codeStream::execute
99     const dictionary& parentDict,
100     primitiveEntry& entry,
101     Istream& is
104     Info<< "Using #codeStream at line " << is.lineNumber()
105         << " in file " <<  parentDict.name() << endl;
107     dynamicCode::checkSecurity
108     (
109         "functionEntries::codeStream::execute(..)",
110         parentDict
111     );
113     // get code dictionary
114     // must reference parent for stringOps::expand to work nicely
115     dictionary codeDict("#codeStream", parentDict, is);
117     // get code, codeInclude, codeOptions
118     dynamicCodeContext context(codeDict);
120     // codeName: codeStream + _<sha1>
121     // codeDir : _<sha1>
122     dynamicCode dynCode
123     (
124         "codeStream" + context.sha1().str(true),
125         context.sha1().str(true)
126     );
128     // Load library if not already loaded
129     // Version information is encoded in the libPath (encoded with the SHA1)
130     const fileName libPath = dynCode.libPath();
132     // see if library is loaded
133     void* lib = NULL;
134     if (isA<IOdictionary>(topDict(parentDict)))
135     {
136         lib = libs(parentDict).findLibrary(libPath);
137     }
139     if (!lib)
140     {
141         Info<< "Using #codeStream with " << libPath << endl;
142     }
145     // nothing loaded
146     // avoid compilation if possible by loading an existing library
147     if (!lib)
148     {
149         if (isA<IOdictionary>(topDict(parentDict)))
150         {
151             // Cached access to dl libs. Guarantees clean up upon destruction
152             // of Time.
153             dlLibraryTable& dlLibs = libs(parentDict);
154             if (dlLibs.open(libPath, false))
155             {
156                 lib = dlLibs.findLibrary(libPath);
157             }
158         }
159         else
160         {
161             // Uncached opening of libPath
162             lib = dlOpen(libPath);
163         }
164     }
167     // create library if required
168     if (!lib)
169     {
170         bool create = Pstream::master();
172         if (create)
173         {
174             if (!dynCode.upToDate(context))
175             {
176                 // filter with this context
177                 dynCode.reset(context);
179                 // compile filtered C template
180                 dynCode.addCompileFile(codeTemplateC);
182                 // define Make/options
183                 dynCode.setMakeOptions
184                 (
185                     "EXE_INC = -g \\\n"
186                   + context.options()
187                   + "\n\nLIB_LIBS = \\\n"
188                   + "    -lOpenFOAM \\\n"
189                   + context.libs()
190                 );
192                 if (!dynCode.copyOrCreateFiles(true))
193                 {
194                     FatalIOErrorIn
195                     (
196                         "functionEntries::codeStream::execute(..)",
197                         parentDict
198                     )   << "Failed writing files for" << nl
199                         << dynCode.libRelPath() << nl
200                         << exit(FatalIOError);
201                 }
202             }
204             if (!dynCode.wmakeLibso())
205             {
206                 FatalIOErrorIn
207                 (
208                     "functionEntries::codeStream::execute(..)",
209                     parentDict
210                 )   << "Failed wmake " << dynCode.libRelPath() << nl
211                     << exit(FatalIOError);
212             }
213         }
215         // all processes must wait for compile to finish
216         reduce(create, orOp<bool>());
218         if (isA<IOdictionary>(topDict(parentDict)))
219         {
220             // Cached access to dl libs. Guarantees clean up upon destruction
221             // of Time.
222             dlLibraryTable& dlLibs = libs(parentDict);
223             if (!dlLibs.open(libPath, false))
224             {
225                 FatalIOErrorIn
226                 (
227                     "functionEntries::codeStream::execute(..)",
228                     parentDict
229                 )   << "Failed loading library " << libPath << nl
230                     << "Did you add all libraries to the 'libs' entry"
231                     << " in system/controlDict?"
232                     << exit(FatalIOError);
233             }
235             lib = dlLibs.findLibrary(libPath);
236         }
237         else
238         {
239             // Uncached opening of libPath
240             lib = dlOpen(libPath);
241         }
242     }
245     // Find the function handle in the library
246     streamingFunctionType function =
247         reinterpret_cast<streamingFunctionType>
248         (
249             dlSym(lib, dynCode.codeName())
250         );
253     if (!function)
254     {
255         FatalIOErrorIn
256         (
257             "functionEntries::codeStream::execute(..)",
258             parentDict
259         )   << "Failed looking up symbol " << dynCode.codeName()
260             << " in library " << lib << exit(FatalIOError);
261     }
263     // use function to write stream
264     OStringStream os(is.format());
265     (*function)(os, parentDict);
267     // get the entry from this stream
268     IStringStream resultStream(os.str());
269     entry.read(parentDict, resultStream);
271     return true;
275 // ************************************************************************* //