00001
00021 #ifdef HAVE_CONFIG_H
00022 #include "config.h"
00023 #endif
00024
00025 #include <dlfcn.h>
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029
00030 #include "lightmediascanner.h"
00031 #include "lightmediascanner_private.h"
00032 #include "lightmediascanner_plugin.h"
00033
00034 #define DEFAULT_SLAVE_TIMEOUT 1000
00035 #define DEFAULT_COMMIT_INTERVAL 100
00036
00037 static int
00038 _parser_load(struct parser *p, const char *so_path)
00039 {
00040 lms_plugin_t *(*plugin_open)(void);
00041 char *errmsg;
00042
00043 memset(p, 0, sizeof(*p));
00044
00045 p->dl_handle = dlopen(so_path, RTLD_NOW | RTLD_LOCAL);
00046 errmsg = dlerror();
00047 if (errmsg) {
00048 fprintf(stderr, "ERROR: could not dlopen() %s\n", errmsg);
00049 return -1;
00050 }
00051
00052 plugin_open = dlsym(p->dl_handle, "lms_plugin_open");
00053 errmsg = dlerror();
00054 if (errmsg) {
00055 fprintf(stderr, "ERROR: could not find plugin entry point %s\n",
00056 errmsg);
00057 return -2;
00058 }
00059
00060 p->so_path = strdup(so_path);
00061 if (!p->so_path) {
00062 perror("strdup");
00063 return -3;
00064 }
00065
00066 p->plugin = plugin_open();
00067 if (!p->plugin) {
00068 fprintf(stderr, "ERROR: plugin \"%s\" failed to init.\n", so_path);
00069 return -4;
00070 }
00071
00072 return 0;
00073 }
00074
00075 static int
00076 _parser_unload(struct parser *p)
00077 {
00078 int r;
00079
00080 r = 0;
00081 if (p->plugin) {
00082 if (p->plugin->close(p->plugin) != 0) {
00083 fprintf(stderr, "ERROR: plugin \"%s\" failed to deinit.\n",
00084 p->so_path);
00085 r -= 1;
00086 }
00087 }
00088
00089 if (p->dl_handle) {
00090 char *errmsg;
00091
00092 dlclose(p->dl_handle);
00093 errmsg = dlerror();
00094 if (errmsg) {
00095 fprintf(stderr, "ERROR: could not dlclose() plugin \"%s\": %s\n",
00096 errmsg, p->so_path);
00097 r -= 1;
00098 }
00099 }
00100
00101 if (p->so_path)
00102 free(p->so_path);
00103
00104 return r;
00105 }
00106
00107
00108
00109
00110
00118 lms_t *
00119 lms_new(const char *db_path)
00120 {
00121 lms_t *lms;
00122
00123 lms = calloc(1, sizeof(lms_t));
00124 if (!lms) {
00125 perror("calloc");
00126 return NULL;
00127 }
00128
00129 lms->cs_conv = lms_charset_conv_new();
00130 if (!lms->cs_conv) {
00131 free(lms);
00132 return NULL;
00133 }
00134
00135 lms->commit_interval = DEFAULT_COMMIT_INTERVAL;
00136 lms->slave_timeout = DEFAULT_SLAVE_TIMEOUT;
00137 lms->db_path = strdup(db_path);
00138 if (!lms->db_path) {
00139 perror("strdup");
00140 lms_charset_conv_free(lms->cs_conv);
00141 free(lms);
00142 return NULL;
00143 }
00144
00145 return lms;
00146 }
00147
00156 int
00157 lms_free(lms_t *lms)
00158 {
00159 int i;
00160
00161 if (!lms)
00162 return 0;
00163
00164 if (lms->is_processing)
00165 return -1;
00166
00167 if (lms->parsers) {
00168 for (i = 0; i < lms->n_parsers; i++)
00169 _parser_unload(lms->parsers + i);
00170
00171 free(lms->parsers);
00172 }
00173
00174 free(lms->db_path);
00175 lms_charset_conv_free(lms->cs_conv);
00176 free(lms);
00177 return 0;
00178 }
00179
00189 lms_plugin_t *
00190 lms_parser_add(lms_t *lms, const char *so_path)
00191 {
00192 struct parser *parser;
00193
00194 if (!lms)
00195 return NULL;
00196
00197 if (!so_path)
00198 return NULL;
00199
00200 if (lms->is_processing) {
00201 fprintf(stderr, "ERROR: do not add parsers while it's processing.\n");
00202 return NULL;
00203 }
00204
00205 lms->parsers = realloc(lms->parsers,
00206 (lms->n_parsers + 1) * sizeof(struct parser));
00207 if (!lms->parsers) {
00208 perror("realloc");
00209 return NULL;
00210 }
00211
00212 parser = lms->parsers + lms->n_parsers;
00213 if (_parser_load(parser, so_path) != 0) {
00214 _parser_unload(parser);
00215 return NULL;
00216 }
00217
00218 lms->n_parsers++;
00219 return parser->plugin;
00220 }
00221
00234 lms_plugin_t *
00235 lms_parser_find_and_add(lms_t *lms, const char *name)
00236 {
00237 char so_path[PATH_MAX];
00238
00239 if (!lms)
00240 return NULL;
00241 if (!name)
00242 return NULL;
00243
00244 snprintf(so_path, sizeof(so_path), "%s/%s.so", PLUGINSDIR, name);
00245 return lms_parser_add(lms, so_path);
00246 }
00247
00248 int
00249 lms_parser_del_int(lms_t *lms, int i)
00250 {
00251 struct parser *parser;
00252
00253 parser = lms->parsers + i;
00254 _parser_unload(parser);
00255 lms->n_parsers--;
00256
00257 if (lms->n_parsers == 0) {
00258 free(lms->parsers);
00259 lms->parsers = NULL;
00260 return 0;
00261 } else {
00262 int dif;
00263
00264 dif = lms->n_parsers - i;
00265 if (dif)
00266 lms->parsers = memmove(parser, parser + 1,
00267 dif * sizeof(struct parser));
00268
00269 lms->parsers = realloc(lms->parsers,
00270 lms->n_parsers * sizeof(struct parser));
00271 if (!lms->parsers) {
00272 lms->n_parsers = 0;
00273 return -1;
00274 }
00275
00276 return 0;
00277 }
00278 }
00279
00288 int
00289 lms_parser_del(lms_t *lms, lms_plugin_t *handle)
00290 {
00291 int i;
00292
00293 if (!lms)
00294 return -1;
00295 if (!handle)
00296 return -2;
00297 if (!lms->parsers)
00298 return -3;
00299 if (lms->is_processing) {
00300 fprintf(stderr, "ERROR: do not del parsers while it's processing.\n");
00301 return -4;
00302 }
00303
00304 for (i = 0; i < lms->n_parsers; i++)
00305 if (lms->parsers[i].plugin == handle)
00306 return lms_parser_del_int(lms, i);
00307
00308 return -3;
00309 }
00310
00320 int
00321 lms_is_processing(const lms_t *lms)
00322 {
00323 if (!lms) {
00324 fprintf(stderr, "ERROR: lms_is_processing(NULL)\n");
00325 return -1;
00326 }
00327
00328 return lms->is_processing;
00329 }
00330
00339 const char *
00340 lms_get_db_path(const lms_t *lms)
00341 {
00342 if (!lms) {
00343 fprintf(stderr, "ERROR: lms_get_db_path(NULL)\n");
00344 return NULL;
00345 }
00346
00347 return lms->db_path;
00348 }
00349
00361 int
00362 lms_get_slave_timeout(const lms_t *lms)
00363 {
00364 if (!lms) {
00365 fprintf(stderr, "ERROR: lms_get_slave_timeout(NULL)\n");
00366 return -1;
00367 }
00368
00369 return lms->slave_timeout;
00370 }
00371
00382 void lms_set_slave_timeout(lms_t *lms, int ms)
00383 {
00384 if (!lms) {
00385 fprintf(stderr, "ERROR: lms_set_slave_timeout(NULL, %d)\n", ms);
00386 return;
00387 }
00388
00389 lms->slave_timeout = ms;
00390 }
00391
00403 unsigned int
00404 lms_get_commit_interval(const lms_t *lms)
00405 {
00406 if (!lms) {
00407 fprintf(stderr, "ERROR: lms_get_commit_interval(NULL)\n");
00408 return (unsigned int)-1;
00409 }
00410
00411 return lms->commit_interval;
00412 }
00413
00426 void
00427 lms_set_commit_interval(lms_t *lms, unsigned int transactions)
00428 {
00429 if (!lms) {
00430 fprintf(stderr, "ERROR: lms_set_commit_interval(NULL, %u)\n",
00431 transactions);
00432 return;
00433 }
00434
00435 lms->commit_interval = transactions;
00436 }
00437
00450 int
00451 lms_charset_add(lms_t *lms, const char *charset)
00452 {
00453 if (!lms) {
00454 fprintf(stderr, "ERROR: lms_charset_add(NULL)\n");
00455 return -1;
00456 }
00457
00458 return lms_charset_conv_add(lms->cs_conv, charset);
00459 }
00460
00473 int
00474 lms_charset_del(lms_t *lms, const char *charset)
00475 {
00476 if (!lms) {
00477 fprintf(stderr, "ERROR: lms_charset_del(NULL)\n");
00478 return -1;
00479 }
00480
00481 return lms_charset_conv_del(lms->cs_conv, charset);
00482 }