dbio.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  $RCSfile$
00003  -------------------
00004  cvs         : $Id: dbio.c 1393 2007-11-22 18:26:05Z martin $
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   }
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   /* if locking requested */
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   /* open file */
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   /* create io layer for this file */
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   /* write to file */
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   /* flush and close io layer */
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   /* remove lock, if any */
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   /* create io layer for this file */
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   /* write to buffer */
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   /* flush and close io layer */
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   /* if locking requested */
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   /* open file */
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   /* create io layer for this file */
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   /* read from file */
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   /* flush and close io layer */
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   /* remove lock, if any */
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 

Generated on Fri Apr 11 01:53:46 2008 for gwenhywfar by  doxygen 1.5.5