dbio.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  $RCSfile$
00003  -------------------
00004  cvs         : $Id$
00005  begin       : Wed Mar 31 2004
00006  copyright   : (C) 2004 by Martin Preuss
00007  email       : martin@libchipcard.de
00008 
00009  ***************************************************************************
00010  *                                                                         *
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU Lesser General Public            *
00013  *   License as published by the Free Software Foundation; either          *
00014  *   version 2.1 of the License, or (at your option) any later version.    *
00015  *                                                                         *
00016  *   This library is distributed in the hope that it will be useful,       *
00017  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00018  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00019  *   Lesser General Public License for more details.                       *
00020  *                                                                         *
00021  *   You should have received a copy of the GNU Lesser General Public      *
00022  *   License along with this library; if not, write to the Free Software   *
00023  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
00024  *   MA  02111-1307  USA                                                   *
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 /* TODO: #include <gwenhywfar/plugin.h> */
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   /* create plugin paths */
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   /* if locking requested */
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   /* open file */
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   /* create io layer for this file */
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   /* write to file */
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   /* flush and close io layer */
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   /* remove lock, if any */
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   /* create io layer for this file */
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   /* write to buffer */
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   /* flush and close io layer */
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   /* if locking requested */
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   /* open file */
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   /* create io layer for this file */
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   /* read from file */
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   /* flush and close io layer */
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   /* remove lock, if any */
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 

Generated on Sat Jan 2 09:32:35 2010 for gwenhywfar by  doxygen 1.6.1