00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifdef HAVE_CONFIG_H
00027 # include <config.h>
00028 #endif
00029
00030 #define DISABLE_DEBUGLOG
00031
00032 #include "dbio_p.h"
00033 #include <gwenhywfar/gwenhywfar.h>
00034 #include <gwenhywfar/misc.h>
00035 #include <gwenhywfar/debug.h>
00036 #include <gwenhywfar/path.h>
00037 #include <gwenhywfar/text.h>
00038 #include <gwenhywfar/directory.h>
00039 #include <gwenhywfar/syncio.h>
00040 #include <gwenhywfar/syncio_file.h>
00041 #include <gwenhywfar/syncio_memory.h>
00042 #include <gwenhywfar/fslock.h>
00043 #include <gwenhywfar/pathmanager.h>
00044
00045
00046
00047
00048 #include <stdlib.h>
00049 #include <assert.h>
00050 #include <string.h>
00051 #include <errno.h>
00052 #include <ctype.h>
00053
00054 #include <sys/types.h>
00055 #ifdef HAVE_SYS_STAT_H
00056 # include <sys/stat.h>
00057 #endif
00058 #ifdef HAVE_FCNTL_H
00059 # include <fcntl.h>
00060 #endif
00061 #ifdef HAVE_UNISTD_H
00062 # include <unistd.h>
00063 #endif
00064
00065
00066 #ifdef OS_WIN32
00067 # define DIRSEP "\\"
00068 # include <windows.h>
00069 #else
00070 # define DIRSEP "/"
00071 #endif
00072
00073
00074
00075 GWEN_LIST_FUNCTIONS(GWEN_DBIO, GWEN_DBIO)
00076 GWEN_INHERIT_FUNCTIONS(GWEN_DBIO)
00077
00078 GWEN_INHERIT(GWEN_PLUGIN, GWEN_DBIO_PLUGIN)
00079
00080
00081 int GWEN_DBIO_ModuleInit(void){
00082 GWEN_PLUGIN_MANAGER *pm;
00083 int err;
00084 GWEN_STRINGLIST *sl;
00085
00086 pm=GWEN_PluginManager_new("dbio", GWEN_PM_LIBNAME);
00087 err=GWEN_PluginManager_Register(pm);
00088 if (err) {
00089 DBG_ERROR(GWEN_LOGDOMAIN, "Could not register DBIO plugin manager");
00090 return err;
00091 }
00092
00093
00094 sl=GWEN_PathManager_GetPaths(GWEN_PM_LIBNAME, GWEN_PM_PLUGINDIR);
00095 if (sl) {
00096 GWEN_STRINGLISTENTRY *se;
00097 GWEN_BUFFER *pbuf;
00098
00099 pbuf=GWEN_Buffer_new(0, 256, 0, 1);
00100
00101 se=GWEN_StringList_FirstEntry(sl);
00102 while(se) {
00103 GWEN_Buffer_AppendString(pbuf, GWEN_StringListEntry_Data(se));
00104 GWEN_Buffer_AppendString(pbuf, DIRSEP GWEN_DBIO_FOLDER);
00105 DBG_INFO(GWEN_LOGDOMAIN, "Adding plugin path [%s]",
00106 GWEN_Buffer_GetStart(pbuf));
00107 GWEN_PluginManager_AddPath(pm, GWEN_PM_LIBNAME,
00108 GWEN_Buffer_GetStart(pbuf));
00109 GWEN_Buffer_Reset(pbuf);
00110 se=GWEN_StringListEntry_Next(se);
00111 }
00112 GWEN_Buffer_free(pbuf);
00113 GWEN_StringList_free(sl);
00114 }
00115
00116 return 0;
00117 }
00118
00119
00120
00121 int GWEN_DBIO_ModuleFini(void){
00122 GWEN_PLUGIN_MANAGER *pm;
00123
00124 pm=GWEN_PluginManager_FindPluginManager("dbio");
00125 if (pm) {
00126 int rv;
00127
00128 rv=GWEN_PluginManager_Unregister(pm);
00129 if (rv) {
00130 DBG_ERROR(GWEN_LOGDOMAIN,
00131 "Could not unregister DBIO plugin manager (%d)", rv);
00132 return rv;
00133 }
00134 else
00135 GWEN_PluginManager_free(pm);
00136 }
00137
00138 return 0;
00139 }
00140
00141
00142
00143
00144
00145 GWEN_PLUGIN *GWEN_DBIO_Plugin_new(GWEN_PLUGIN_MANAGER *pm,
00146 const char *name,
00147 const char *fileName) {
00148 GWEN_PLUGIN *pl;
00149 GWEN_DBIO_PLUGIN *pldbio;
00150
00151 pl=GWEN_Plugin_new(pm, name, fileName);
00152 GWEN_NEW_OBJECT(GWEN_DBIO_PLUGIN, pldbio);
00153 GWEN_INHERIT_SETDATA(GWEN_PLUGIN, GWEN_DBIO_PLUGIN, pl, pldbio,
00154 GWEN_DBIO_Plugin_FreeData);
00155
00156 return pl;
00157 }
00158
00159
00160
00161 void GWENHYWFAR_CB GWEN_DBIO_Plugin_FreeData(GWEN_UNUSED void *bp, void *p) {
00162 GWEN_DBIO_PLUGIN *pldbio;
00163
00164 pldbio=(GWEN_DBIO_PLUGIN*)p;
00165 GWEN_FREE_OBJECT(pldbio);
00166 }
00167
00168
00169
00170 GWEN_DBIO *GWEN_DBIO_Plugin_Factory(GWEN_PLUGIN *pl) {
00171 GWEN_DBIO_PLUGIN *pldbio;
00172
00173 assert(pl);
00174 pldbio=GWEN_INHERIT_GETDATA(GWEN_PLUGIN, GWEN_DBIO_PLUGIN, pl);
00175 assert(pldbio);
00176
00177 assert(pldbio->factoryFn);
00178 return pldbio->factoryFn(pl);
00179 }
00180
00181
00182
00183 void GWEN_DBIO_Plugin_SetFactoryFn(GWEN_PLUGIN *pl,
00184 GWEN_DBIO_PLUGIN_FACTORYFN f) {
00185 GWEN_DBIO_PLUGIN *pldbio;
00186
00187 assert(pl);
00188 pldbio=GWEN_INHERIT_GETDATA(GWEN_PLUGIN, GWEN_DBIO_PLUGIN, pl);
00189 assert(pldbio);
00190
00191 pldbio->factoryFn=f;
00192 }
00193
00194
00195
00196
00197
00198
00199
00200
00201 GWEN_DBIO *GWEN_DBIO_new(const char *name, const char *descr){
00202 GWEN_DBIO *dbio;
00203
00204 assert(name);
00205 GWEN_NEW_OBJECT(GWEN_DBIO, dbio);
00206 GWEN_LIST_INIT(GWEN_DBIO, dbio);
00207 GWEN_INHERIT_INIT(GWEN_DBIO, dbio);
00208 dbio->name=strdup(name);
00209 if (descr)
00210 dbio->descr=strdup(descr);
00211
00212 dbio->usage=1;
00213 return dbio;
00214 }
00215
00216
00217
00218 void GWEN_DBIO_free(GWEN_DBIO *dbio){
00219 if (dbio) {
00220 assert(dbio->usage);
00221 if (--(dbio->usage)==0) {
00222 GWEN_INHERIT_FINI(GWEN_DBIO, dbio);
00223 GWEN_LIST_FINI(GWEN_DBIO, dbio);
00224
00225 free(dbio->name);
00226 free(dbio->descr);
00227
00228 GWEN_FREE_OBJECT(dbio);
00229 }
00230 }
00231 }
00232
00233
00234
00235 void GWEN_DBIO_Attach(GWEN_DBIO *dbio){
00236 assert(dbio);
00237 dbio->usage++;
00238 }
00239
00240
00241
00242 int GWEN_DBIO_Import(GWEN_DBIO *dbio,
00243 GWEN_SYNCIO *sio,
00244 GWEN_DB_NODE *db,
00245 GWEN_DB_NODE *params,
00246 uint32_t flags) {
00247 assert(dbio);
00248 assert(sio);
00249 assert(db);
00250
00251 if (GWEN_SyncIo_GetStatus(sio) != GWEN_SyncIo_Status_Connected) {
00252 DBG_ERROR(GWEN_LOGDOMAIN, "GWEN_SYNCIO %s not connected; did you forget to call GWEN_SyncIo_Connect()?", GWEN_SyncIo_GetTypeName(sio));
00253 return -1;
00254 }
00255
00256 if (dbio->importFn)
00257 return dbio->importFn(dbio, sio, db, params, flags);
00258 else {
00259 DBG_INFO(GWEN_LOGDOMAIN, "No import function set");
00260 return -1;
00261 }
00262 }
00263
00264
00265
00266 int GWEN_DBIO_Export(GWEN_DBIO *dbio,
00267 GWEN_SYNCIO *sio,
00268 GWEN_DB_NODE *db,
00269 GWEN_DB_NODE *params,
00270 uint32_t flags) {
00271 assert(dbio);
00272 assert(sio);
00273 assert(db);
00274
00275 if (dbio->exportFn)
00276 return dbio->exportFn(dbio, sio, db, params, flags);
00277 else {
00278 DBG_INFO(GWEN_LOGDOMAIN, "No export function set");
00279 return -1;
00280 }
00281 }
00282
00283
00284
00285 GWEN_DBIO_CHECKFILE_RESULT GWEN_DBIO_CheckFile(GWEN_DBIO *dbio,
00286 const char *fname) {
00287 assert(dbio);
00288 assert(fname);
00289
00290 if (dbio->checkFileFn)
00291 return dbio->checkFileFn(dbio, fname);
00292 else {
00293 DBG_INFO(GWEN_LOGDOMAIN, "No checkFile function set");
00294 return GWEN_DBIO_CheckFileResultUnknown;
00295 }
00296 }
00297
00298
00299
00300 const char *GWEN_DBIO_GetName(const GWEN_DBIO *dbio){
00301 assert(dbio);
00302 return dbio->name;
00303 }
00304
00305
00306
00307 const char *GWEN_DBIO_GetDescription(const GWEN_DBIO *dbio){
00308 assert(dbio);
00309 return dbio->descr;
00310 }
00311
00312
00313
00314 void GWEN_DBIO_SetImportFn(GWEN_DBIO *dbio, GWEN_DBIO_IMPORTFN f){
00315 assert(dbio);
00316 dbio->importFn=f;
00317 }
00318
00319
00320
00321 void GWEN_DBIO_SetExportFn(GWEN_DBIO *dbio, GWEN_DBIO_EXPORTFN f){
00322 assert(dbio);
00323 dbio->exportFn=f;
00324 }
00325
00326
00327 void GWEN_DBIO_SetCheckFileFn(GWEN_DBIO *dbio, GWEN_DBIO_CHECKFILEFN f){
00328 assert(dbio);
00329 dbio->checkFileFn=f;
00330 }
00331
00332
00333
00334 GWEN_DBIO *GWEN_DBIO_GetPlugin(const char *modname){
00335 GWEN_PLUGIN_MANAGER *pm;
00336 GWEN_PLUGIN *pl;
00337 GWEN_DBIO *dbio;
00338
00339 pm=GWEN_PluginManager_FindPluginManager("dbio");
00340 if (!pm) {
00341 DBG_ERROR(GWEN_LOGDOMAIN, "No plugin manager for \"dbio\" found");
00342 return 0;
00343 }
00344
00345 pl=GWEN_PluginManager_GetPlugin(pm, modname);
00346 if (!pl) {
00347 DBG_INFO(GWEN_LOGDOMAIN, "DBIO-Plugin \"%s\" not found", modname);
00348 return 0;
00349 }
00350
00351 dbio=GWEN_DBIO_Plugin_Factory(pl);
00352 if (!dbio) {
00353 DBG_INFO(GWEN_LOGDOMAIN,
00354 "Plugin did not create a GWEN_DBIO");
00355 }
00356 return dbio;
00357 }
00358
00359
00360
00361 int GWEN_DBIO_ExportToFile(GWEN_DBIO *dbio,
00362 const char *fname,
00363 GWEN_DB_NODE *db,
00364 GWEN_DB_NODE *params,
00365 uint32_t dbflags) {
00366 int rv;
00367 GWEN_FSLOCK *lck=0;
00368 GWEN_SYNCIO *sio;
00369
00370
00371 if (dbflags & GWEN_DB_FLAGS_LOCKFILE) {
00372 GWEN_FSLOCK_RESULT res;
00373
00374 lck=GWEN_FSLock_new(fname, GWEN_FSLock_TypeFile);
00375 assert(lck);
00376 res=GWEN_FSLock_Lock(lck, GWEN_DB_DEFAULT_LOCK_TIMEOUT, 0);
00377 if (res!=GWEN_FSLock_ResultOk) {
00378 DBG_ERROR(GWEN_LOGDOMAIN,
00379 "Could not apply lock to file \"%s\" (%d)",
00380 fname, res);
00381 GWEN_FSLock_free(lck);
00382 return -1;
00383 }
00384 }
00385
00386
00387 sio=GWEN_SyncIo_File_new(fname, GWEN_SyncIo_File_CreationMode_CreateAlways);
00388 if (dbflags & GWEN_DB_FLAGS_APPEND_FILE)
00389 GWEN_SyncIo_AddFlags(sio, GWEN_SYNCIO_FILE_FLAGS_APPEND);
00390 GWEN_SyncIo_AddFlags(sio,
00391 GWEN_SYNCIO_FILE_FLAGS_READ |
00392 GWEN_SYNCIO_FILE_FLAGS_WRITE |
00393 GWEN_SYNCIO_FILE_FLAGS_UREAD |
00394 GWEN_SYNCIO_FILE_FLAGS_UWRITE);
00395 rv=GWEN_SyncIo_Connect(sio);
00396 if (rv<0) {
00397 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00398 GWEN_SyncIo_free(sio);
00399 if (lck) {
00400 GWEN_FSLock_Unlock(lck);
00401 GWEN_FSLock_free(lck);
00402 }
00403 return rv;
00404 }
00405
00406 rv=GWEN_DBIO_Export(dbio, sio, db, params, dbflags);
00407 if (rv<0) {
00408 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00409 GWEN_SyncIo_Disconnect(sio);
00410 GWEN_SyncIo_free(sio);
00411 if (lck) {
00412 GWEN_FSLock_Unlock(lck);
00413 GWEN_FSLock_free(lck);
00414 }
00415 return rv;
00416 }
00417
00418 rv=GWEN_SyncIo_Disconnect(sio);
00419 if (rv<0) {
00420 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00421 GWEN_SyncIo_free(sio);
00422 if (lck) {
00423 GWEN_FSLock_Unlock(lck);
00424 GWEN_FSLock_free(lck);
00425 }
00426 return rv;
00427 }
00428 GWEN_SyncIo_free(sio);
00429
00430
00431 if (lck) {
00432 GWEN_FSLOCK_RESULT res;
00433
00434 res=GWEN_FSLock_Unlock(lck);
00435 if (res!=GWEN_FSLock_ResultOk) {
00436 DBG_WARN(GWEN_LOGDOMAIN,
00437 "Could not remove lock on file \"%s\" (%d)",
00438 fname, res);
00439 }
00440 GWEN_FSLock_free(lck);
00441 }
00442
00443 return 0;
00444 }
00445
00446
00447
00448 int GWEN_DBIO_ExportToBuffer(GWEN_DBIO *dbio,
00449 GWEN_BUFFER *buf,
00450 GWEN_DB_NODE *db,
00451 GWEN_DB_NODE *params,
00452 uint32_t flags) {
00453 GWEN_SYNCIO *sio;
00454 int rv;
00455
00456
00457 sio=GWEN_SyncIo_Memory_new(buf, 0);
00458 rv=GWEN_DBIO_Export(dbio, sio, db, params, flags);
00459 if (rv<0) {
00460 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00461 GWEN_SyncIo_free(sio);
00462 return rv;
00463 }
00464
00465 GWEN_SyncIo_free(sio);
00466 return 0;
00467 }
00468
00469
00470
00471 int GWEN_DBIO_ImportFromFile(GWEN_DBIO *dbio,
00472 const char *fname,
00473 GWEN_DB_NODE *db,
00474 GWEN_DB_NODE *params,
00475 uint32_t dbflags) {
00476 GWEN_SYNCIO *sio;
00477 int rv;
00478 GWEN_FSLOCK *lck=0;
00479
00480
00481 if (dbflags & GWEN_DB_FLAGS_LOCKFILE) {
00482 GWEN_FSLOCK_RESULT res;
00483
00484 lck=GWEN_FSLock_new(fname, GWEN_FSLock_TypeFile);
00485 assert(lck);
00486 res=GWEN_FSLock_Lock(lck, GWEN_DB_DEFAULT_LOCK_TIMEOUT, 0);
00487 if (res!=GWEN_FSLock_ResultOk) {
00488 DBG_ERROR(GWEN_LOGDOMAIN,
00489 "Could not apply lock to file \"%s\" (%d)",
00490 fname, res);
00491 GWEN_FSLock_free(lck);
00492 return GWEN_ERROR_IO;
00493 }
00494 }
00495
00496 sio=GWEN_SyncIo_File_new(fname, GWEN_SyncIo_File_CreationMode_OpenExisting);
00497 GWEN_SyncIo_AddFlags(sio, GWEN_SYNCIO_FILE_FLAGS_READ);
00498 rv=GWEN_SyncIo_Connect(sio);
00499 if (rv<0) {
00500 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00501 GWEN_SyncIo_free(sio);
00502 if (lck) {
00503 GWEN_FSLock_Unlock(lck);
00504 GWEN_FSLock_free(lck);
00505 }
00506 return rv;
00507 }
00508
00509
00510 rv=GWEN_DBIO_Import(dbio, sio, db, params, dbflags);
00511 if (rv<0) {
00512 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00513 GWEN_SyncIo_Disconnect(sio);
00514 GWEN_SyncIo_free(sio);
00515 if (lck) {
00516 GWEN_FSLock_Unlock(lck);
00517 GWEN_FSLock_free(lck);
00518 }
00519 return rv;
00520 }
00521
00522
00523 GWEN_SyncIo_Disconnect(sio);
00524 GWEN_SyncIo_free(sio);
00525
00526
00527 if (lck) {
00528 GWEN_FSLOCK_RESULT res;
00529
00530 res=GWEN_FSLock_Unlock(lck);
00531 if (res!=GWEN_FSLock_ResultOk) {
00532 DBG_WARN(GWEN_LOGDOMAIN,
00533 "Could not remove lock on file \"%s\" (%d)",
00534 fname, res);
00535 }
00536 GWEN_FSLock_free(lck);
00537 }
00538
00539 return 0;
00540 }
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554