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