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