diff --git a/harbour/ChangeLog b/harbour/ChangeLog index b475e7cfae..eae320c7c6 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,28 @@ 2008-12-31 13:59 UTC+0100 Foo Bar (foo.bar foobar.org) */ +2009-01-18 21:39 UTC+0100 Francesco Saverio Giudice (info/at/fsgiudice.com) + + harbour/source/rdd/usrrdd/example/exlog.prg + + harbour/source/rdd/usrrdd/rdds/logrdd.prg + * harbour/source/rdd/usrrdd/rdds/Makefile + + Added new LOGRDD rdd file and related example + ; NOTE: A simple RDD which introduce logging to file. It inheriths from + any existent RDD but if you write / replace / delete something + on tables it writes changes in a log file. + It needs to inherit a standard RDD to which it adds logging + capabilities. + Related functions: + hb_LogRddInherit() -> + REQUESTED - It must returns the standard RDD name to be inherited. + This function HAVE to be defined from user in application. + hb_LogRddLogFileName( [] ) -> + OPTIONAL - Set/Get logging file name (default "changes.log"). + hb_LogRddTag( [] ) -> + OPTIONAL - Set/Get Tag string added in each log line. + (default COMPUTERNAME\UserName) + hb_LogRddActive( [] ) -> + OPTIONAL - Set/Get logging active status (default .F.). + 2009-01-14 17:51 UTC+0100 Viktor Szakats (harbour.01 syenar hu) * contrib/hbmzip/hbmzip.c + Added .prg level functions: diff --git a/harbour/source/rdd/usrrdd/example/exlog.prg b/harbour/source/rdd/usrrdd/example/exlog.prg new file mode 100644 index 0000000000..32f21a9b3f --- /dev/null +++ b/harbour/source/rdd/usrrdd/example/exlog.prg @@ -0,0 +1,44 @@ +/* + * $Id: exfcm.prg 9551 2008-10-05 18:13:15Z vszakats $ + */ + +#include "dbinfo.ch" + +// Request for LOGRDD rdd driver +REQUEST LOGRDD + +// Here put Request for RDD you want to inherit then add +// function hb_LogRddInherit() (see at bottom) +REQUEST DBFCDX + +PROCEDURE Main() + + // Set LOGRDD as default RDD otherwise I have to set explicitly use + // with DRIVER option + RDDSetDefault( "LOGRDD" ) + // Adding Memofile Info + rddInfo( RDDI_MEMOVERSION, DB_MEMOVER_CLIP, "LOGRDD" ) + + // Define Log File Name and position + hb_LogRddLogFileName( "logs\changes.log" ) + // Define Tag to add for each line logged + hb_LogRddTag( NETNAME() + "\" + hb_USERNAME() ) + // Activate Logging, it can be stopped/started at any moment + hb_LogRddActive( .T. ) + + // Start program logic + + // Open a table with logging (default RDD is LOGRDD) + USE test + field->name := "Francesco" + CLOSE + + // Open a table without logging + USE test DRIVER "DBFCDX" + APPEND BLANK + field->name := "Francesco" + +RETURN + +FUNCTION hb_LogRddInherit() +RETURN "DBFCDX" diff --git a/harbour/source/rdd/usrrdd/rdds/Makefile b/harbour/source/rdd/usrrdd/rdds/Makefile index 99aba73fda..2a2d984a7d 100644 --- a/harbour/source/rdd/usrrdd/rdds/Makefile +++ b/harbour/source/rdd/usrrdd/rdds/Makefile @@ -6,6 +6,7 @@ ROOT = ../../../../ PRG_SOURCES=\ arrayrdd.prg \ + logrdd.prg \ fcomma.prg \ hscdx.prg \ rlcdx.prg \ diff --git a/harbour/source/rdd/usrrdd/rdds/logrdd.prg b/harbour/source/rdd/usrrdd/rdds/logrdd.prg new file mode 100644 index 0000000000..13a5f5be97 --- /dev/null +++ b/harbour/source/rdd/usrrdd/rdds/logrdd.prg @@ -0,0 +1,417 @@ +/* + * $Id: rlcdx.prg 9754 2008-10-27 22:40:04Z vszakats $ + */ + +/* + * Harbour Project source code: + * LOGRDD + * + * Copyright 2009 Francesco Saverio Giudice + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + */ + +/* + * A simple RDD which introduce logging to file. It inheriths from + * any existent RDD but if you write / replace / delete something + * on tables it writes changes in a log file. + * An example is avalaible at bottom of this file. + */ + +#include "rddsys.ch" +#ifdef __XHARBOUR__ + #include "usrrdd.ch" + #xtranslate hb_valtoexp( => cStr( +#else + #include "hbusrrdd.ch" +#endif +#include "common.ch" +#include "fileio.ch" +#include "dbinfo.ch" + +#define ARRAY_FILENAME 1 +#define ARRAY_FHANDLE 2 +#define ARRAY_TAG 3 +#define ARRAY_ACTIVE 4 +#define ARRAY_RDDNAME 5 + +ANNOUNCE LOGRDD +REQUEST HB_LOGRDDINHERIT /* To be defined at user level */ + +STATIC FUNCTION LOGRDD_INIT( nRDD ) + LOCAL lActive, cFileName, cTag, cRDDName + + /* Defaults */ + cFileName := "changes.log" + lActive := .F. + #ifdef __XHARBOUR__ + cTag := NETNAME() + "\" + NETNAME( 1 ) + #else + cTag := NETNAME() + "\" + hb_USERNAME() + #endif + cRDDName := hb_LogRddInherit() + + /* Log File will be open later so user can change parameters */ + + /* Store data in RDD cargo */ + /* cFileName, nHandle, cTag, lActive, cRDDName */ + USRRDD_RDDDATA( nRDD, { cFileName, NIL, cTag, lActive, cRDDName } ) + +RETURN SUCCESS + +STATIC FUNCTION LOGRDD_EXIT( nRDD ) + LOCAL aRDDData := USRRDD_RDDDATA( nRDD ) + + /* Closing log file */ + IF aRDDData[ ARRAY_FHANDLE ] != NIL + FClose( aRDDData[ ARRAY_FHANDLE ] ) + aRDDData[ ARRAY_FHANDLE ] := NIL + ENDIF + +RETURN SUCCESS + +// Create database from current WA fields definition +STATIC FUNCTION LOGRDD_CREATE( nWA, aOpenInfo ) + LOCAL nResult := UR_SUPER_CREATE( nWA, aOpenInfo ) + IF nResult == SUCCESS + ToLog( "CREATE", nWA, aOpenInfo[ UR_OI_NAME ] ) + ENDIF + RETURN nResult + +// Creating fields for new DBF - dbCreate() in current workarea +STATIC FUNCTION LOGRDD_CREATEFIELDS( nWA, aStruct ) + LOCAL nResult := UR_SUPER_CREATEFIELDS( nWA, aStruct ) + IF nResult == SUCCESS + ToLog( "CREATEFIELDS", nWA, hb_ValToExp( aStruct ) ) + ENDIF + RETURN nResult + +// Open workarea +STATIC FUNCTION LOGRDD_OPEN( nWA, aOpenInfo ) + LOCAL nResult := UR_SUPER_OPEN( nWA, aOpenInfo ) + IF nResult == SUCCESS + ToLog( "OPEN", nWA, 'Table : "' + aOpenInfo[ UR_OI_NAME ] + '", Alias : "' + Alias() + '", WorkArea : ' + LTrim( Str( nWA ) ) ) + ENDIF + RETURN nResult + +// Close workarea +STATIC FUNCTION LOGRDD_CLOSE( nWA ) + LOCAL cDbf := dbInfo( DBI_FULLPATH ) + LOCAL cAlias := Alias() + LOCAL nResult := UR_SUPER_CLOSE( nWA ) + IF nResult == SUCCESS + ToLog( "CLOSE", nWA, 'Table : "' + cDbf + '", Alias : "' + cAlias + '", WorkArea : ' + LTrim( Str( nWA ) ) ) + ENDIF + RETURN nResult + +STATIC FUNCTION LOGRDD_APPEND( nWA, lUnlockAll ) + LOCAL nResult := UR_SUPER_APPEND( nWA, lUnlockAll ) + IF nResult == SUCCESS + ToLog( "APPEND", nWA, Alias() + "->RecNo() = " + LTrim( Str( RecNo() ) ) ) + ENDIF + RETURN nResult + +STATIC FUNCTION LOGRDD_DELETE( nWA ) + LOCAL nResult := UR_SUPER_DELETE( nWA ) + IF nResult == SUCCESS + ToLog( "DELETE", nWA, Alias() + "->RecNo() = " + LTrim( Str( RecNo() ) ) ) + ENDIF + RETURN nResult + +STATIC FUNCTION LOGRDD_RECALL( nWA ) + LOCAL nResult := UR_SUPER_RECALL( nWA ) + IF nResult == SUCCESS + ToLog( "RECALL", nWA, Alias() + "->RecNo() = " + LTrim( Str( RecNo() ) ) ) + ENDIF + RETURN nResult + +STATIC FUNCTION LOGRDD_PUTVALUE( nWA, nField, xValue ) + LOCAL xOldValue := FieldGet( nField ) + LOCAL nResult := UR_SUPER_PUTVALUE( nWA, nField, xValue ) + + //Log Only Changes + IF !( xOldValue == xValue ) + ToLog( "PUTVALUE", nWA, Alias() + "(" + LTrim( Str( RecNo() ) ) + ")->" + PadR( FieldName( nField ), 10 ) + " := " + ValToText( xValue ) ) + ENDIF + RETURN nResult + +STATIC FUNCTION LOGRDD_ZAP( nWA ) + LOCAL cDbf := dbInfo( DBI_FULLPATH ) + LOCAL cAlias := Alias() + LOCAL nResult := UR_SUPER_ZAP( nWA ) + IF nResult == SUCCESS + ToLog( "ZAP", nWA, 'Alias : "' + Alias() + ' Table : "' + cDbf + '"' ) + ENDIF + RETURN nResult + +/* Force linking DBFCDX from which our RDD inherits */ +REQUEST DBFCDX + +/* + * This function have to exist in all RDD and then name have to be in + * format: _GETFUNCTABLE + */ +FUNCTION LOGRDD_GETFUNCTABLE( pFuncCount, pFuncTable, pSuperTable, nRddID ) + LOCAL cSuperRDD := hb_LogRddInherit() /* We are inheriting from a User Defined RDD */ + LOCAL aMyFunc[ UR_METHODCOUNT ] + + aMyFunc[ UR_INIT ] := ( @LOGRDD_INIT() ) + aMyFunc[ UR_EXIT ] := ( @LOGRDD_EXIT() ) + aMyFunc[ UR_CREATE ] := ( @LOGRDD_CREATE() ) + aMyFunc[ UR_CREATEFIELDS ] := ( @LOGRDD_CREATEFIELDS() ) + aMyFunc[ UR_OPEN ] := ( @LOGRDD_OPEN() ) + aMyFunc[ UR_CLOSE ] := ( @LOGRDD_CLOSE() ) + aMyFunc[ UR_APPEND ] := ( @LOGRDD_APPEND() ) + aMyFunc[ UR_DELETE ] := ( @LOGRDD_DELETE() ) + aMyFunc[ UR_RECALL ] := ( @LOGRDD_RECALL() ) + aMyFunc[ UR_PUTVALUE ] := ( @LOGRDD_PUTVALUE() ) + aMyFunc[ UR_ZAP ] := ( @LOGRDD_ZAP() ) + +RETURN USRRDD_GETFUNCTABLE( pFuncCount, pFuncTable, pSuperTable, nRddID, ; + cSuperRDD, aMyFunc ) + +INIT PROCEDURE _LOGRDD_INIT() + rddRegister( "LOGRDD", RDT_FULL ) + RETURN + +/* -------------------------------------------------- */ +/* UTILITY FUNCTIONS */ +/* -------------------------------------------------- */ + +FUNCTION hb_LogRddLogFileName( cFileName ) + LOCAL nRDD, aRDDList + LOCAL aRDDData + LOCAL cOldFileName + + aRDDList := RDDLIST( RDT_FULL ) + nRDD := AScan( aRDDList, "LOGRDD" ) + + IF nRDD > 0 + + nRDD -- // HACK: Possibly an error of nRDD value in UR_INIT() ? - TODO + + aRDDData := USRRDD_RDDDATA( nRDD ) + + cOldFileName := aRDDData[ ARRAY_FILENAME ] + + IF HB_ISSTRING( cFileName ) + aRDDData[ ARRAY_FILENAME ] := cFileName + ENDIF + + ENDIF + RETURN cOldFileName + +FUNCTION hb_LogRddTag( cTag ) + LOCAL nRDD, aRDDList + LOCAL aRDDData + LOCAL cOldTag + + aRDDList := RDDLIST( RDT_FULL ) + nRDD := AScan( aRDDList, "LOGRDD" ) + + IF nRDD > 0 + + nRDD -- // HACK: Possibly an error of nRDD value in UR_INIT() ? - TODO + + aRDDData := USRRDD_RDDDATA( nRDD ) + + cOldTag := aRDDData[ ARRAY_TAG ] + + IF HB_ISSTRING( cTag ) + aRDDData[ ARRAY_TAG ] := cTag + ENDIF + + ENDIF + RETURN cOldTag + +FUNCTION hb_LogRddActive( lActive ) + LOCAL nRDD, aRDDList + LOCAL aRDDData + LOCAL lOldActive + + aRDDList := RDDLIST( RDT_FULL ) + nRDD := AScan( aRDDList, "LOGRDD" ) + + IF nRDD > 0 + + nRDD -- // HACK: Possibly an error of nRDD value in UR_INIT() ? - TODO + + aRDDData := USRRDD_RDDDATA( nRDD ) + + lOldActive := aRDDData[ ARRAY_ACTIVE ] + + IF HB_ISLOGICAL( lActive ) + aRDDData[ ARRAY_ACTIVE ] := lActive + ENDIF + + ENDIF + RETURN lOldActive + +STATIC PROCEDURE OpenLogFile( nWA ) + LOCAL aRDDData := USRRDD_RDDDATA( USRRDD_ID( nWA ) ) + LOCAL cFileName := aRDDData[ ARRAY_FILENAME ] + LOCAL nHandle := aRDDData[ ARRAY_FHANDLE ] + LOCAL lActive := aRDDData[ ARRAY_ACTIVE ] + + //TraceLog( "nHandle " + cStr( nHandle ) ) + + IF lActive .AND. nHandle == NIL + + /* Open Access Log File */ + IF File( cFileName ) + nHandle := FOpen( cFileName, FO_READWRITE + FO_SHARED ) + ELSE + nHandle := FCreate( cFileName ) + /* Close and reopen in shared mode */ + IF FError() == 0 .AND. nHandle > 0 + FClose( nHandle ) + nHandle := FOpen( cFileName, FO_READWRITE + FO_SHARED ) + ENDIF + ENDIF + IF FError() == 0 .AND. nHandle > 0 + /* Move to end of file */ + FSeek( nHandle, 0, FS_END ) + ELSE + nHandle := NIL + ENDIF + + aRDDData[ ARRAY_FHANDLE ] := nHandle + + ENDIF + RETURN + +STATIC PROCEDURE ToLog( cCmd, nWA, cMsg ) + LOCAL aRDDData := USRRDD_RDDDATA( USRRDD_ID( nWA ) ) + LOCAL nHandle := aRDDData[ ARRAY_FHANDLE ] + LOCAL cTag := aRDDData[ ARRAY_TAG ] + LOCAL lActive := aRDDData[ ARRAY_ACTIVE ] + LOCAL cRDDName := aRDDData[ ARRAY_RDDNAME ] + + //TraceLog( "nHandle " + cStr( nHandle ) + " cUser " + cUser ) + IF lActive + + IF nHandle == NIL + OpenLogFile( nWA ) + ENDIF + + IF nHandle != NIL + FWrite( nHandle, DToS( Date() ) + " " + Time() + " " + cTag + ": " + PadR( cRDDName + "_" + cCmd, 20 ) + " - " + cMsg + hb_OSNewLine() ) + ENDIF + + ENDIF + RETURN + +#ifdef __XHARBOUR__ +STATIC FUNCTION ValToText( uValue ) + + LOCAL cType := ValType( uValue ) + LOCAL cText := ValToPrg( uValue ) + + RETURN "[" + cType + "]>>>" + cText + "<<<" +#else +STATIC FUNCTION ValToText( uValue ) + + LOCAL cType := ValType( uValue ) + LOCAL cText + + DO CASE + CASE cType == "C" + cText := hb_StrToExp( uValue ) + + CASE cType == "N" + cText := hb_NToS( uValue ) + + CASE cType == "D" + cText := DToS( uValue ) + cText := "0d" + iif( Empty( cText ), "00000000", cText ) + + OTHERWISE + cText := hb_ValToStr( uValue ) + ENDCASE + + RETURN "[" + cType + "]>>>" + cText + "<<<" +#endif + +/***************************************************************** + EXAMPLE: + +#include "dbinfo.ch" + +// Request for LOGRDD rdd driver +REQUEST LOGRDD + +// Here put Request for RDD you want to inherit then add +// function hb_LogRddInherit() (see at bottom) +REQUEST DBFCDX + +PROCEDURE Main() + + // Set LOGRDD as default RDD otherwise I have to set explicitly use + // with DRIVER option + RDDSetDefault( "LOGRDD" ) + // Adding Memofile Info + rddInfo( RDDI_MEMOVERSION, DB_MEMOVER_CLIP, "LOGRDD" ) + + // Define Log File Name and position + hb_LogRddLogFileName( "logs\changes.log" ) + // Define Tag to add for each line logged + hb_LogRddTag( NETNAME() + "\" + hb_USERNAME() ) + // Activate Logging, it can be stopped/started at any moment + hb_LogRddActive( .T. ) + + // Start program logic + + // Open a table with logging (default RDD is LOGRDD) + USE test + field->name := "Francesco" + CLOSE + + // Open a table without logging + USE test DRIVER "DBFCDX" + .... + +RETURN + +FUNCTION hb_LogRddInherit() +RETURN "DBFCDX" + +*******************************************************************/