~ubuntu-branches/ubuntu/oneiric/strigi/oneiric

« back to all changes in this revision

Viewing changes to src/streamanalyzer/indexpluginloader.cpp

  • Committer: Package Import Robot
  • Author(s): Felix Geyer
  • Date: 2011-09-24 17:12:15 UTC
  • mfrom: (1.2.6 upstream)
  • mto: This revision was merged to the branch mainline in revision 44.
  • Revision ID: package-import@ubuntu.com-20110924171215-zmbi1f77jntvz65h
Tags: upstream-0.7.6
ImportĀ upstreamĀ versionĀ 0.7.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* This file is part of Strigi Desktop Search
2
 
 *
3
 
 * Copyright (C) 2007 Jos van den Oever <jos@vandenoever.info>
4
 
 *
5
 
 * This library is free software; you can redistribute it and/or
6
 
 * modify it under the terms of the GNU Library General Public
7
 
 * License as published by the Free Software Foundation; either
8
 
 * version 2 of the License, or (at your option) any later version.
9
 
 *
10
 
 * This library is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 
 * Library General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU Library General Public License
16
 
 * along with this library; see the file COPYING.LIB.  If not, write to
17
 
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18
 
 * Boston, MA 02110-1301, USA.
19
 
 */
20
 
#include "indexpluginloader.h"
21
 
#include "indexmanager.h"
22
 
#include <iostream>
23
 
#include <stdio.h>
24
 
#include <stdlib.h>
25
 
#include <string.h>
26
 
#include <stgdirent.h>
27
 
#include <sys/stat.h>
28
 
using namespace std;
29
 
using namespace Strigi;
30
 
 
31
 
#ifndef _WIN32
32
 
#include <dlfcn.h>
33
 
#define DLSYM dlsym
34
 
#define DLCLOSE dlclose
35
 
#else
36
 
#define DLSYM GetProcAddress
37
 
#define DLCLOSE FreeLibrary
38
 
#endif
39
 
 
40
 
#ifndef _WIN32
41
 
typedef void* StgModuleType;
42
 
#else
43
 
#include <windows.h>
44
 
typedef HMODULE StgModuleType;
45
 
#endif
46
 
 
47
 
vector<string> getdirs(const string& direnv) {
48
 
    vector<string> dirs;
49
 
    string::size_type lastp = 0;
50
 
    string::size_type p = direnv.find(PATH_SEPARATOR);
51
 
    while (p != string::npos) {
52
 
        dirs.push_back(direnv.substr(lastp, p-lastp));
53
 
        lastp = p+1;
54
 
        p = direnv.find(PATH_SEPARATOR, lastp);
55
 
    }
56
 
    dirs.push_back(direnv.substr(lastp));
57
 
    return dirs;
58
 
}
59
 
 
60
 
// anonymous namespace for static variables
61
 
namespace {
62
 
    class Module {
63
 
    private:
64
 
        const StgModuleType mod;
65
 
        Module(const Module&);
66
 
        void operator=(const Module&);
67
 
    public:
68
 
        Strigi::IndexManager* (*create)(const char*);
69
 
        void (*destroy)(Strigi::IndexManager*);
70
 
        Module(StgModuleType m)
71
 
            :mod(m) {}
72
 
        ~Module() {
73
 
// TODO: figure out why we get segfaults when cleaning up nicely
74
 
            DLCLOSE(mod);
75
 
        }
76
 
    };
77
 
    class ModuleList {
78
 
    private:
79
 
        map<std::string, Module*> modules;
80
 
    public:
81
 
        map<std::string, Module*>& mods() {
82
 
            if (!initialized) initialize();
83
 
            return modules;
84
 
        };
85
 
        map<void*, Module*> indexmanagers;
86
 
        bool initialized;
87
 
 
88
 
        ModuleList() {
89
 
            initialized = false;
90
 
        }
91
 
        void initialize() {
92
 
            initialized = true;
93
 
            // load the plugins from the environment setting
94
 
            string strigipluginpath;
95
 
            if (getenv("STRIGI_PLUGIN_PATH")) {
96
 
                strigipluginpath = getenv("STRIGI_PLUGIN_PATH");
97
 
            }
98
 
            vector<string> strigipluginpaths = getdirs(strigipluginpath);
99
 
            if (strigipluginpath.size()) {
100
 
                for (uint i=0; i<strigipluginpaths.size(); ++i) {
101
 
                    IndexPluginLoader::loadPlugins(strigipluginpaths[i].c_str());
102
 
                }
103
 
            } else {
104
 
                IndexPluginLoader::loadPlugins( LIBINSTALLDIR "/strigi");
105
 
            }
106
 
        }
107
 
        ~ModuleList() {
108
 
            // delete all leftover indexmanagers
109
 
            // if code deletes the indexmanager on it's own, the error will
110
 
            // appear here
111
 
            map<void*, Module*>::iterator j;
112
 
            for (j = indexmanagers.begin(); j != indexmanagers.end(); ++j) {
113
 
                j->second->destroy(static_cast<IndexManager*>(j->first));
114
 
            }
115
 
            // unload all the modules
116
 
            map<string, Module*>::iterator i;
117
 
            for (i = modules.begin(); i != modules.end(); ++i) {
118
 
                delete i->second;
119
 
            }
120
 
        }
121
 
        void loadModule(const string& name, const string& dir);
122
 
    };
123
 
    void
124
 
    ModuleList::loadModule(const string& name, const string& lib) {
125
 
        // check if this module was already loaded
126
 
        map<string, Module*>::iterator i = modules.find(name);
127
 
        if (i != modules.end()) {
128
 
            return;
129
 
        }
130
 
        StgModuleType handle;
131
 
#ifdef HAVE_DLFCN_H
132
 
        // do not use RTLD_GLOBAL here
133
 
        // note: If neither RTLD_GLOBAL nor RTLD_LOCAL are specified,
134
 
        // the default is RTLD_LOCAL.
135
 
        handle = dlopen(lib.c_str(), RTLD_LOCAL | RTLD_NOW);
136
 
#else
137
 
        handle = LoadLibrary(lib.c_str());
138
 
#endif
139
 
        if (!handle) {
140
 
#ifdef HAVE_DLFCN_H
141
 
            cerr << "Could not load '" << lib << "':" << dlerror() << endl;
142
 
#else
143
 
            cerr << "Could not load '" << lib << "': GetLastError(): "
144
 
                << GetLastError() << endl;
145
 
#endif
146
 
            return;
147
 
        }
148
 
        IndexManager*(*create)(const char*) = (IndexManager*(*)(const char*))
149
 
            DLSYM(handle, "createIndexManager");
150
 
        if (!create) {
151
 
#ifndef WIN32
152
 
            fprintf(stderr, "%s\n", dlerror());
153
 
#else
154
 
            fprintf(stderr, "GetLastError: %d\n", GetLastError());
155
 
#endif
156
 
            DLCLOSE(handle);
157
 
            return;
158
 
        }
159
 
        void(*destroy)(IndexManager*) = (void(*)(IndexManager*))
160
 
            DLSYM(handle, "deleteIndexManager");
161
 
        if (!destroy) {
162
 
#ifndef WIN32
163
 
            fprintf(stderr, "%s\n", dlerror());
164
 
#else
165
 
            fprintf(stderr, "GetLastError: %d\n", GetLastError());
166
 
#endif
167
 
            DLCLOSE(handle);
168
 
            return;
169
 
        }
170
 
        Module* module = new Module(handle);
171
 
        module->create = create;
172
 
        module->destroy = destroy;
173
 
        modules[name] = module;
174
 
    }
175
 
    static ModuleList modules;
176
 
}
177
 
void
178
 
IndexPluginLoader::loadPlugins(const char* d) {
179
 
    DIR *dir = opendir(d);
180
 
    if (dir == 0) {
181
 
        return;
182
 
    }
183
 
    struct dirent* ent = readdir(dir);
184
 
    string prefix("strigiindex_");
185
 
#ifdef WIN32
186
 
    string suffix(".dll");
187
 
#else
188
 
    string suffix(".so");
189
 
#endif
190
 
    while(ent) {
191
 
        size_t len = strlen(ent->d_name);
192
 
        const char* prepos = strstr(ent->d_name, prefix.c_str());
193
 
        const char* sufpos = strstr(ent->d_name, suffix.c_str());
194
 
        if (prepos && sufpos + suffix.length() == ent->d_name + len) {
195
 
            len -= (prepos - ent->d_name) + prefix.length() + suffix.length();
196
 
            string name(prepos + prefix.length(), len);
197
 
            string pluginpath = d;
198
 
            if (pluginpath[pluginpath.length()-1] != '/') {
199
 
                pluginpath.append("/");
200
 
            }
201
 
            pluginpath.append(ent->d_name);
202
 
            // check that the file is a regular file
203
 
            struct stat s;
204
 
            if (stat(pluginpath.c_str(), &s) == 0 && (S_IFREG & s.st_mode)) {
205
 
                modules.loadModule(name, pluginpath);
206
 
            }
207
 
        }
208
 
        ent = readdir(dir);
209
 
    }
210
 
    closedir(dir);
211
 
}
212
 
vector<string>
213
 
IndexPluginLoader::indexNames() {
214
 
    vector<string> names;
215
 
    map<string, Module*>::const_iterator i = modules.mods().begin();
216
 
    for (; i != modules.mods().end(); ++i) {
217
 
        names.push_back(i->first);
218
 
    }
219
 
    return names;
220
 
}
221
 
IndexManager*
222
 
IndexPluginLoader::createIndexManager(const char* name, const char* dir) {
223
 
    // find the right plugin
224
 
    map<string, Module*>::iterator i = modules.mods().find(name);
225
 
    if (i == modules.mods().end()) {
226
 
        return 0;
227
 
    }
228
 
    // create the indexmanager
229
 
    IndexManager* im = i->second->create(dir);
230
 
    if (im) {
231
 
        // map the indexmanager to the module that created it, so we can delete
232
 
        // it later
233
 
        modules.indexmanagers[im] = i->second;
234
 
    }
235
 
    return im;
236
 
}
237
 
void
238
 
IndexPluginLoader::deleteIndexManager(IndexManager* im) {
239
 
    // find the right module
240
 
    map<void*, Module*>::iterator i = modules.indexmanagers.find(im);
241
 
    if (i == modules.indexmanagers.end()) {
242
 
        return;
243
 
    }
244
 
    // let the module delete the indexmanager
245
 
    i->second->destroy(im);
246
 
    // remove the mapping from the map
247
 
    modules.indexmanagers.erase(i);
248
 
}