DatabasePluginManager.C 18.8 KB
Newer Older
hrchilds's avatar
hrchilds committed
1
2
/*****************************************************************************
*
brugger's avatar
   
brugger committed
3
* Copyright (c) 2000 - 2008, Lawrence Livermore National Security, LLC
hrchilds's avatar
hrchilds committed
4
* Produced at the Lawrence Livermore National Laboratory
brugger's avatar
   
brugger committed
5
* LLNL-CODE-400142
hrchilds's avatar
hrchilds committed
6
7
* All rights reserved.
*
brugger's avatar
   
brugger committed
8
* This file is  part of VisIt. For  details, see https://visit.llnl.gov/.  The
hrchilds's avatar
hrchilds committed
9
10
11
12
13
14
15
16
17
18
* full copyright notice is contained in the file COPYRIGHT located at the root
* of the VisIt distribution or at http://www.llnl.gov/visit/copyright.html.
*
* Redistribution  and  use  in  source  and  binary  forms,  with  or  without
* modification, are permitted provided that the following conditions are met:
*
*  - Redistributions of  source code must  retain the above  copyright notice,
*    this list of conditions and the disclaimer below.
*  - Redistributions in binary form must reproduce the above copyright notice,
*    this  list of  conditions  and  the  disclaimer (as noted below)  in  the
brugger's avatar
   
brugger committed
19
20
21
*    documentation and/or other materials provided with the distribution.
*  - Neither the name of  the LLNS/LLNL nor the names of  its contributors may
*    be used to endorse or promote products derived from this software without
hrchilds's avatar
hrchilds committed
22
23
24
25
26
*    specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT  HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR  IMPLIED WARRANTIES, INCLUDING,  BUT NOT  LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS FOR A PARTICULAR  PURPOSE
brugger's avatar
   
brugger committed
27
28
29
* ARE  DISCLAIMED. IN  NO EVENT  SHALL LAWRENCE  LIVERMORE NATIONAL  SECURITY,
* LLC, THE  U.S.  DEPARTMENT OF  ENERGY  OR  CONTRIBUTORS BE  LIABLE  FOR  ANY
* DIRECT,  INDIRECT,   INCIDENTAL,   SPECIAL,   EXEMPLARY,  OR   CONSEQUENTIAL
hrchilds's avatar
hrchilds committed
30
31
32
33
34
35
36
37
38
* DAMAGES (INCLUDING, BUT NOT  LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS OR
* SERVICES; LOSS OF  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER
* CAUSED  AND  ON  ANY  THEORY  OF  LIABILITY,  WHETHER  IN  CONTRACT,  STRICT
* LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY  WAY
* OUT OF THE  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
*****************************************************************************/

hrchilds's avatar
hrchilds committed
39
40
41
42
43
44
45
46
// ************************************************************************* //
//                          DatabasePluginManager.C                          //
// ************************************************************************* //

#include <DatabasePluginManager.h>
#include <DatabasePluginInfo.h>
#include <DebugStream.h>
#include <InvalidPluginException.h>
hrchilds's avatar
hrchilds committed
47
#include <visitstream.h>
48
#include <visit-config.h>
hrchilds's avatar
hrchilds committed
49
50
51
#include <string>
#include <vector>

52
53
#include <cstring>

hrchilds's avatar
hrchilds committed
54
55
56
57
58
59
60
61
62
63
using std::string;
using std::vector;

// ****************************************************************************
//  Method: DatabasePluginManager constructor
//
//  Programmer: Jeremy Meredith
//  Creation:   August 22, 2002
//
//  Modifications:
hrchilds's avatar
hrchilds committed
64
65
66
//    Brad Whitlock, Wed Nov 22 16:31:59 PST 2006
//    I made it call SetPluginDir since it's no longer done in the base
//    class's constructor.
hrchilds's avatar
hrchilds committed
67
//
68
69
70
71
//    Sean Ahern, Thu Jan 17 16:06:20 EST 2008
//    Moved the call to SetPluginDir to Initialize to make it conform
//    with the rest of the plugin managers.
//
hrchilds's avatar
hrchilds committed
72
73
74
75
76
77
78
79
80
81
82
83
84
// ****************************************************************************

DatabasePluginManager::DatabasePluginManager() : PluginManager("database")
{
}

// ****************************************************************************
//  Method: DatabasePluginManager destructor
//
//  Programmer: Jeremy Meredith
//  Creation:   August 22, 2002
//
//  Modifications:
85
86
//    Brad Whitlock, Wed Jun 25 10:27:17 PDT 2008
//    Call UnloadPlugins here since it calls virtual methods for this class.
hrchilds's avatar
hrchilds committed
87
88
89
90
91
//
// ****************************************************************************

DatabasePluginManager::~DatabasePluginManager()
{
92
    UnloadPlugins();
hrchilds's avatar
hrchilds committed
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
}

// ****************************************************************************
//  Method:  DatabasePluginManager::Initialize
//
//  Purpose:
//    Initialize the manager and read the plugins.
//
//  Arguments:
//    pluginCategory:   either GUI, Viewer, or Engine
//    parallel      :   true if need parallel libraries
//
//  Programmer:  Jeremy Meredith
//  Creation:    August 22, 2002
//
//  Modifications:
109
110
111
112
113
114
//    Sean Ahern, Thu Jan 17 16:10:00 EST 2008
//    Added SetPluginDir so that we can find plugins correctly.  Arguably,
//    this is better here than the constructor.
//
//    Brad Whitlock, Tue Jun 24 11:13:19 PDT 2008
//    Removed plugin characteristics.
hrchilds's avatar
hrchilds committed
115
116
117
118
119
//
// ****************************************************************************

void
DatabasePluginManager::Initialize(const PluginCategory pluginCategory,
120
                                  bool                 par,
121
                                  const char *         pluginDir)
hrchilds's avatar
hrchilds committed
122
{
123
124
125
126
    category = pluginCategory;
    parallel = par;
    SetPluginDir(pluginDir);
    ReadPluginInfo();
hrchilds's avatar
hrchilds committed
127
128
}

hrchilds's avatar
hrchilds committed
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// ****************************************************************************
//  Method: DatabasePluginManager::GetEnginePluginInfo
//
//  Purpose:
//    Return a pointer to the engine database plugin information for the
//    specified database type.
//
//  Arguments:
//    id        The id of the database type.
//
//  Returns:    The engine database plugin information for the database type.
//
//  Programmer: Jeremy Meredith
//  Creation:   February 22, 2005
//
//  Modifications:
145
146
147
148
//    Mark C. Miller, Mon Aug  6 13:36:16 PDT 2007
//    Fixed problem where calling this method in a situation where the given
//    plugin had not already been loaded would result in defining it in
//    loadedindexmap with an index of 0.
149
150
151
152
//
//    Brad Whitlock, Tue Jun 24 16:24:25 PDT 2008
//    Added a pointer to this in the info.
//
hrchilds's avatar
hrchilds committed
153
154
155
156
157
// ****************************************************************************

EngineDatabasePluginInfo *
DatabasePluginManager::GetEnginePluginInfo(const string &id)
{
158
159
    if (!PluginLoaded(id))
        return 0;
160
161
162
    EngineDatabasePluginInfo *info = enginePluginInfo[loadedindexmap[id]];
    info->SetPluginManager(this);
    return info;
hrchilds's avatar
hrchilds committed
163
164
}

hrchilds's avatar
hrchilds committed
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// ****************************************************************************
//  Method: DatabasePluginManager::GetCommonPluginInfo
//
//  Purpose:
//    Return a pointer to the common database plugin information for the
//    specified database type.
//
//  Arguments:
//    id        The id of the database type.
//
//  Returns:    The common database plugin information for the database type.
//
//  Programmer: Jeremy Meredith
//  Creation:   August 22, 2002
//
//  Modifications:
181
182
183
184
//    Mark C. Miller, Mon Aug  6 13:36:16 PDT 2007
//    Fixed problem where calling this method in a situation where the given
//    plugin had not already been loaded would result in defining it in
//    loadedindexmap with an index of 0.
185
186
187
188
//
//    Brad Whitlock, Tue Jun 24 16:24:25 PDT 2008
//    Added a pointer to this in the info.
//
hrchilds's avatar
hrchilds committed
189
190
191
192
193
// ****************************************************************************

CommonDatabasePluginInfo *
DatabasePluginManager::GetCommonPluginInfo(const string &id)
{
194
195
    if (!PluginLoaded(id))
        return 0;
196
197
198
    CommonDatabasePluginInfo *info = commonPluginInfo[loadedindexmap[id]];
    info->SetPluginManager(this);
    return info;
hrchilds's avatar
hrchilds committed
199
200
201
202
203
204
205
206
207
208
209
210
}

// ****************************************************************************
// Method: DatabasePluginManager::LoadGeneralPluginInfo
//
// Purpose: 
//   Loads general plugin info from the open plugin.
//
// Programmer: Jeremy Meredith
// Creation:   August 22, 2002
//
// Modifications:
hrchilds's avatar
hrchilds committed
211
212
//    Jeremy Meredith, Wed Nov  5 13:28:03 PST 2003
//    Use the default value for enabled status instead of always true.
hrchilds's avatar
hrchilds committed
213
//
hrchilds's avatar
hrchilds committed
214
215
216
//    Jeremy Meredith, Tue Feb 22 15:22:29 PST 2005
//    Added a way to determine directly if a plugin has a writer.
//
hrchilds's avatar
hrchilds committed
217
218
219
//    Hank Childs, Tue Mar 22 16:06:15 PST 2005
//    Fix memory leak.
//
220
221
//    Mark C. Miller, Mon Aug  6 13:36:16 PDT 2007
//    Added code to update extensions and filenames.
hrchilds's avatar
hrchilds committed
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
// ****************************************************************************

bool
DatabasePluginManager::LoadGeneralPluginInfo()
{
    // Get the GeneralPluginInfo creator
    GeneralDatabasePluginInfo *(*getInfo)(void)    =
        (GeneralDatabasePluginInfo*(*)(void))PluginSymbol("GetGeneralInfo");
    if (!getInfo)
    {
        EXCEPTION3(InvalidPluginException, "Error retrieving info creator",
                   openPlugin.c_str(), PluginError());
    }

    // Get the general plugin info
    GeneralDatabasePluginInfo *info = (*getInfo)();
    if (!info)
    {
        EXCEPTION2(InvalidPluginException, "Error creating general info",
                   openPlugin.c_str());
    }

    // We can't have two plugins with the same id.
    if (PluginExists(info->GetID()))
hrchilds's avatar
hrchilds committed
246
247
    {
        delete info;
hrchilds's avatar
hrchilds committed
248
        return false;
hrchilds's avatar
hrchilds committed
249
    }
hrchilds's avatar
hrchilds committed
250
251
252

    // Success!  Add it to the list.
    allindexmap[info->GetID()] = ids.size();
253
254
255
256
257
258
259
    ids       .push_back(info->GetID());
    names     .push_back(info->GetName());
    versions  .push_back(info->GetVersion());
    enabled   .push_back(info->EnabledByDefault());
    haswriter .push_back(info->HasWriter());
    extensions.push_back(info->GetDfltExtsFromGen());
    filenames .push_back(info->GetFilenamesFromGen());
hrchilds's avatar
hrchilds committed
260
    delete info;
hrchilds's avatar
hrchilds committed
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
    return true;
}

// ****************************************************************************
// Method: DatabasePluginManager::LoadEnginePluginInfo
//
// Purpose: 
//   Loads engine plugin info from the open plugin.
//
// Programmer: Jeremy Meredith
// Creation:   August 22, 2002
//
// Modifications:
//   
// ****************************************************************************

void
DatabasePluginManager::LoadEnginePluginInfo()
{
    EngineDatabasePluginInfo  *(*getEngineInfo)(void) =
        (EngineDatabasePluginInfo* (*)(void))PluginSymbol("GetEngineInfo");

    if (!getEngineInfo)
    {
        EXCEPTION2(InvalidPluginException,
                   "Error retrieving Engine info",
                   openPlugin.c_str());
    }

    enginePluginInfo.push_back((*getEngineInfo)());
    commonPluginInfo.push_back((*getEngineInfo)());
}

// ****************************************************************************
// Method: DatabasePluginManager::LoadMDServerPluginInfo
//
// Purpose: 
//   Loads mdserver plugin info from the open plugin.
//
// Programmer: Jeremy Meredith
// Creation:   August 22, 2002
//
// Modifications:
//   
// ****************************************************************************

void
DatabasePluginManager::LoadMDServerPluginInfo()
{
    MDServerDatabasePluginInfo  *(*getMDServerInfo)(void) =
        (MDServerDatabasePluginInfo* (*)(void))PluginSymbol("GetMDServerInfo");

    if (!getMDServerInfo)
    {
        EXCEPTION2(InvalidPluginException,
                   "Error retrieving MDServer info",
                   openPlugin.c_str());
    }

    mdserverPluginInfo.push_back((*getMDServerInfo)());
    commonPluginInfo.push_back((*getMDServerInfo)());
}

// ****************************************************************************
// Method: DatabasePluginManager::FreeCommonPluginInfo
//
// Purpose: 
//   Frees common plugin info.
//
// Programmer: Jeremy Meredith
// Creation:   August 22, 2002
//
// Modifications:
//
// ****************************************************************************

void
DatabasePluginManager::FreeCommonPluginInfo()
{
340
    for (size_t i=0; i<commonPluginInfo.size(); i++)
hrchilds's avatar
hrchilds committed
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
        delete commonPluginInfo[i];
    commonPluginInfo.clear();
}

// ****************************************************************************
//  Method: DatabasePluginManager::ReloadPlugins
//
//  Purpose:
//    Free the loaded database plugins.
//
//  Programmer: Jeremy Meredith
//  Creation:   August 22, 2002
//
//  Modifications:
//    Jeremy Meredith, Fri Feb 28 12:25:37 PST 2003
//    Made it use LoadPluginsNow or LoadPluginsOnDemand as appropriate.
//
// ****************************************************************************

void
DatabasePluginManager::ReloadPlugins()
{
    vector<void*>                        new_handles;
    vector<CommonDatabasePluginInfo*>    new_commonPluginInfo;

    loadedindexmap.clear();
367
    for (size_t i=0; i<loadedhandles.size(); i++)
hrchilds's avatar
hrchilds committed
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
    {
        if (enabled[allindexmap[commonPluginInfo[i]->GetID()]])
        {
            loadedindexmap[commonPluginInfo[i]->GetID()] = new_handles.size();
            new_commonPluginInfo.push_back(commonPluginInfo[i]);

            new_handles.push_back(loadedhandles[i]);
        }
        else
        {
            delete commonPluginInfo[i];

            handle = loadedhandles[i];
            PluginClose();
        }
    }
    commonPluginInfo    = new_commonPluginInfo;
    loadedhandles       = new_handles;

    if (loadOnDemand)
        LoadPluginsOnDemand();
    else
        LoadPluginsNow();
}

hrchilds's avatar
hrchilds committed
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
// ****************************************************************************
//  Method:  DatabasePluginManager::PluginHasWriter
//
//  Purpose:
//    Returns true if a database plugin has a writer method.
//
//  Arguments:
//    id         the plugin id
//
//  Programmer:  Jeremy Meredith
//  Creation:    February 22, 2005
//
// ****************************************************************************
bool
DatabasePluginManager::PluginHasWriter(const string &id)
{
    bool retval = false;
    if(allindexmap.find(id) != allindexmap.end())
    {
        int index = allindexmap[id];
        if(index < names.size())
            retval = haswriter[index];
    }

    return retval;
}
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482

// ****************************************************************************
//  Method:  DatabasePluginManager::PluginDefaultExtensions
//
//  Purpose: Returns file extensions for a plugin 
//
//  Arguments:
//    id         the plugin id
//
//  Programmer:  Mark C. Miller
//  Creation:    August 3, 2007 
//
// ****************************************************************************
vector<string>
DatabasePluginManager::PluginFileExtensions(const string &id)
{
    vector<string> retval;
    if(allindexmap.find(id) != allindexmap.end())
    {
        int index = allindexmap[id];
        if(index < names.size())
            retval = extensions[index];
    }

    return retval;
}

// ****************************************************************************
//  Method:  DatabasePluginManager::PluginDefaultFilenames
//
//  Purpose: Returns filenames for a plugin 
//
//  Arguments:
//    id         the plugin id
//
//  Programmer:  Mark C. Miller
//  Creation:    August 3, 2007 
//
// ****************************************************************************
vector<string>
DatabasePluginManager::PluginFilenames(const string &id)
{
    vector<string> retval;
    if(allindexmap.find(id) != allindexmap.end())
    {
        int index = allindexmap[id];
        if(index < names.size())
            retval = filenames[index];
    }

    return retval;
}

// ****************************************************************************
//  Method:  DatabasePluginManager::GetMatchingPluginId
//
//  Purpose: Returns database plugin id matching extensions with given filename
//
//  Arguments:
//    id         the filename to match with 
//
//  Programmer:  Mark C. Miller 
//  Creation:    July 31, 2007 
//
483
484
485
//  Modifications:
//    Mark C. Miller, Thu Aug  9 09:16:01 PDT 2007
//    Made it return a vector of strings
bonnell's avatar
bonnell committed
486
487
488
489
//
//    Kathleen Bonnell, Tue Sep 11 08:56:42 PDT 2007 
//    Replace 'and' with '&&' for compilation on windows. 
// 
490
// ****************************************************************************
491
492
vector<string>
DatabasePluginManager::GetMatchingPluginIds(const char *filename, bool searchAll)
493
494
{
    int i;
495
    vector<string> rv;
496
497
498
499
500
501
502
503
504
505

    //
    // Parse out the path and get just the filename.
    //
    string file_and_path = filename; 
    const char *fap = file_and_path.c_str();
    int len = strlen(fap);
    int lastSlash = -1;
    for (i = len-1 ; i >= 0 ; i--)
    {
506
        if (fap[i] == VISIT_SLASH_CHAR)
507
508
509
510
511
512
513
514
515
516
517
518
        {
            lastSlash = i;
            break;
        }
    }
    int start = lastSlash+1;
    string file(fap + start);

    //
    // Try each database type looking for a match to the given extensions
    //
    int iMax = searchAll ? GetNAllPlugins() : GetNEnabledPlugins();
519
    for (i=0; i<iMax; i++)
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
    {
        string id = searchAll ? GetAllID(i) : GetEnabledID(i);
        CommonDatabasePluginInfo *info = GetCommonPluginInfo(id);
        bool foundMatch = false;

        //
        // Check to see if there is an extension that matches.
	// Look first using GeneralPluginInfo via PluginFileExtensions
	// call (the newer way). If that yields nothing, then try the
	// CommonPluginInfo via the GetDefaultExtensions (the old way).
        //
	int j;
        vector<string> extensions = PluginFileExtensions(id);
        int nextensions = extensions.size();
	bool shouldIssueObsoletePluginWarning = false;
	if (nextensions == 0)
	{
	    if (info)
                extensions = info->GetDefaultExtensions();
            nextensions = extensions.size();
	    shouldIssueObsoletePluginWarning = nextensions > 0;
	}
        for (j=0; j<nextensions && !foundMatch; j++)
        {
            string ext = extensions[j];
            if (ext[0] != '.')
            {
                ext = string(".") + extensions[j];
            }
#if defined(_WIN32)
            if (file.length() >= ext.length())
            {
                string fileExt(file.substr(file.length() - ext.length()));
                foundMatch = (_stricmp(fileExt.c_str(), ext.c_str()) == 0);
            }
#else
            if (file.length() >= ext.length() &&
                file.substr(file.length() - ext.length()) == ext)
            {
                foundMatch = true;
            }
#endif
        }

        //
        // Check to see if there is an exact name that matches.
        // Again, get filenames first from GeneralPluginInfo and,
	// failing that, then the older way (from CommonPluginInfo).
	//
        vector<string> filenames = PluginFilenames(id);
        int nfiles = filenames.size();
	if (nfiles == 0)
	{
	    if (info)
                filenames = info->GetFilenames();
            nfiles = filenames.size();
	    shouldIssueObsoletePluginWarning |= nfiles > 0;
        }
        for (j=0; j<nfiles && !foundMatch; j++)
        {
            if (filenames[j] == file)
            {
                foundMatch = true;
            }
        }

        if (foundMatch)
587
            rv.push_back(id);
588

bonnell's avatar
bonnell committed
589
        if (foundMatch && shouldIssueObsoletePluginWarning)
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
	{
	    static bool issuedWarning = false;
	    if (!issuedWarning)
            {
                cerr << "Warning: For plugin id = \"" << id
                     << "\", default file extensions/names found in" << endl;
                cerr << "CommonPluginInfo indicating obsolete plugin code." << endl;
                cerr << "Please re-generate the plugin info files using xml2info." << endl;
                cerr << "This message will continue to appear, once per session," << endl;
                cerr << "until the problem has been addressed." << endl;
                issuedWarning = true;
            }
        }
    }

    return rv;
}