/* close.c -- Copyright 1994, 1996 Liam R. E. Quin. * All Rights Reserved. * This code is NOT in the public domain. * See the file COPYRIGHT for full details. */ #ifndef LINT static char *RcsId = "@(#) $Id: close.c,v 1.3 1996/05/15 22:58:30 lee Exp $"; #endif /* Actions to be taken on closing a database */ #include "globals.h" /* defines and declarations for database filenames */ #include "error.h" #include /* stderr, also for fileinfo.h */ #include /* for fileinfo.h, which uses time_t */ #ifdef HAVE_FCNTL_H # ifdef HAVE_SYSV_FCNTL_H # include # endif # include #endif #include /* for SEEK_SET */ #include "fileinfo.h" /* for wordinfo.h */ #include "wordinfo.h" /* for t_WID */ #include "pblock.h" #include "blkheader.h" #include "emalloc.h" #include "liblqtext.h" #include "lqutil.h" #include "lqtrace.h" typedef struct s_CallBackItem { int (* Function)(); char *Description; t_LQTEXT_Database *db; unsigned int Flags; struct s_CallBackItem *Next; } t_CallbackItem; /** Unix system calls that need to be declared: **/ /** C library functions that need to be declared: **/ /** lqtext library functions that need to be declared: **/ /** Functions within this file that need to be declared: **/ /** **/ static t_CallbackItem *ActionsForClose = 0; /* * LQT_AddActionOnClose * Database/Database * *

The given Action function will be called whenever LQT_CloseDatabase * or LQT_SyncDatabase is called.

*

The string Description is used in trace and debugging messages, and * also in error messages; it should be a human-readable description of * the action that the function is performing, or it could be * an ASCII string containing the name of the function. The Description * string is not copied; a pointer to it is retained. Therefore, it is * an error to free it after calling LQT_AddActionOnClose.

*

The given Flags argument may be any combination of * LQT_ON_SYNC and LQT_ON_CLOSE using bitwise or. * If the LQT_ON_SYNC flag is given, the given Action is called by * LQT_SyncDatabase; if LQT_ON_CLOSE is given, the given Action is * called by LQT_CloseDatabase. * It is unusual to have an action for the Sync case and not for the * Close case, but it is not forbidden.

*

You can register any number of functions in this way. * The most recently registered function is called first, and so on.

*

LQT_OpenDatabase uses this function to register the following * functions, in order, so that LQT_FlushBlockCache is called last: *

  • LQT_FlushBlockCache (Write out cached low-level * data blocks);
  • *
  • LQT_WriteCurrentMaxWID (Write out largest allocated WID);
  • *
  • LQTpFlushWIDCache (Write out cached WID index blocks);
  • *
  • LQTp_FlushLastBlockCache (Write out cached lastblock data);
  • *
  • LQT_SyncAndCloseAllKeyValueDatabases (Flush and close all open * Dynamic Hashing (ndbm) key-value databases)
  • *

    You can see these called by running a client with the Debug * trace flag set (e.g. lqwordlist -t Debug).

    * *

    The list of functions registered may change between revisions of * lq-text, and is given here for illustrative purposes.

    * * LQT_OpenDatabase * LQT_CloseDatabase * LQT_OpenKeyValueDatabase *
    */ API void LQT_AddActionOnClose(db, Description, Action, Flags) t_LQTEXT_Database *db; char *Description; int (* Action)( #ifdef HAVE_PROTO t_LQTEXT_Database * # endif ); unsigned int Flags; { t_CallbackItem *newCallback; if (!Action) { Error(E_FATAL|E_BUG, "LQT_AddActionOnClose called with NULL action", Action ); } newCallback = (t_CallbackItem *) emalloc( "CloseAction", sizeof(t_CallbackItem) ); newCallback->Next = ActionsForClose; newCallback->Description = Description; newCallback->Function = Action; newCallback->db = db; newCallback->Flags = Flags; ActionsForClose = newCallback; return; } /* * LQT_CloseDatabase * Database/Database * * Closes the current lq-text database. * Any actions that have been registered with LQT_AddActionOnClose are * performed, including the ones that liblqtext has registered. * It is not necessary to call LQT_SyncDatabase before closing a * database, as LQT_CloseDatabase does this. * All pending data is flushed, and all file descriptors that have * been opened by liblqtext functions are closed. * Currently, not all allocated memory is freed, but any such memory * is not lost, because it will be reused on a subsequent call to * LQT_OpenDatabase. * * zero. * * LQT_AddActionOnClose * LQT_OpenDatabase * LQT_SyncDatabase * */ API int LQT_CloseDatabase(theDatabase) t_LQTEXT_Database *theDatabase; { t_CallbackItem *theAction; for (theAction = ActionsForClose; theAction; theAction = theAction->Next) { if (theAction->Flags & LQT_ON_CLOSE) { if (theAction->db) { LQT_Trace( LQTRACE_DEBUG, "Close: %s [db: 0x%x]\n", theAction->Description, theAction->db ); } else { LQT_Trace( LQTRACE_DEBUG, "Close: %s\n", theAction->Description ); } (* (theAction->Function))(theAction->db); } } return 0; } /* * LQT_SyncDatabase * Database/Database * *

    Syncs the current lq-text database; that is, writes any pending data * blocks to disk, and closes and deletes any temporary files. * You could think of this function as closing the database and then * opening it again, except that it doesn't actually do that.

    *

    Any actions that have been registered with LQT_AddActionOnClose * with the LQT_ON_SYNC flag are performed, including * the ones that liblqtext has registered internally.

    *

    It is not necessary to call LQT_SyncDatabase before closing a * database, as LQT_CloseDatabase does this. * * zero. * * LQT_AddActionOnClose * LQT_OpenDatabase * LQT_CloseDatabase * */ API int LQT_SyncDatabase(theDatabase) t_LQTEXT_Database *theDatabase; { t_CallbackItem *theAction; for (theAction = ActionsForClose; theAction; theAction = theAction->Next) { if (theAction->Flags & LQT_ON_SYNC) { if (theAction->db) { LQT_Trace( LQTRACE_DEBUG, "Sync: %s [db: 0x%x]", theAction->Description, theAction->db ); } else { LQT_Trace( LQTRACE_DEBUG, "Sync: %s", theAction->Description ); } (* (theAction->Function))(theAction->db); } } return 0; }