⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 saf.cpp

📁 ISO 8583 with c++ for financial transaction standard
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// IT24 Sistemas S.A.
// SAF Library Manager
//
//   Libreria de Manejo de SAF (StoreAndForward), que es una cola en disco de
// acumulacion de transacciones entrantes que no pueden rutearse momentaneamente,
// y son grabadas para su posterior reintento de envio.
//   Posee por seguridad un limite logico de cantidad de registros maximos.
//   Las funciones de I/O son estandard de bajo nivel ANSI C y ANSI UNIX.
//
// Tarea        Fecha           Autor   Observaciones
// (Inicial)    1997.09.10      mdc     Base
// (Inicial)    1997.09.11      mdc     _WIN32: WORD cambiados a UINT
// (Inicial)    1997.09.23      mdc     lcCurrPos (Cursor de I/O)
// (Inicial)    1997.10.17      mdc     Primer Registro STORED
// (Alfa)       1997.10.21      mdc     Precondiciones extendidas
// (Alfa)       1998.12.02      mdc     iMode para _sopen         
// (Alfa)       2002.07.25      mdc     Adaptacion a mensajes ISO8583 por LNET+ATM
// (Alfa)       2002.08.20      mdc     Remove() agregado. UseRandomNumber() tambien.
// (Beta)       2003.07.04      mdc     Cambio de libreria estandar IO.H por STDIO.H
//

// Header propio/local
#include <qusrinc/saf.h>
#include <qusrinc/typedefs.h>

// Headers globales
#include <memory.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <limits.h>

#ifdef _WIN32
#include <io.h>
#endif // _WIN32

#define RET_INVAL (-1) 
#ifndef _POSIX_        
#define _fsopen fopen  
#endif /* POSIX */     

// Constructor
EXPORT StoreAndForward::StoreAndForward(LPSTR szXFileName, BOOL bUseRandomNumber) 
    { 
	/////////////////////////////////////////////////////////////////
	tSAFInit      = time(NULL); // TimeStamp del inicio de SAF
	tLastSAFCheck = 0L;         // TimeStamp del ultimo chequeo SAF    
	/////////////////////////////////////////////////////////////////
	// Nro. pseudo-aleatorio por instancia de clase.
	// El nro 971 es primo de forma de obtener una distribucion buena,
	// en un rango desde 0 a 999.
	// Iniciar criba de numeros pseudo-aleatorios
	srand( time( NULL ) );
	iRandomNum  = rand() % 971 ;
	bUseRandom  = bUseRandomNumber; // Usar nombre random ?
	/////////////////////////////////////////////////////////////////
	// Asegurar handle de flujo de I/O en NULL    
    hfFile = NULL;
    // Bytes de I/O
    cbReadWrite = 0;
    // Limite logico de registros por default
    dwLimit = SAF_RECORDS_LIMIT;
    // Cuenta de Registros
    dwStdRecords = dwFwdRecords = 0L;
	// Cursores de Primero y Ultimo STORED
	dwFirstStdRecord = dwLastStdRecord = 0L;
	// Tamano de archivo inicialmente
	lFileSize = 0L;
    // Apertura con nombre fijo , y Estadisticas  
	InitStatistics( szXFileName );
	}

// Constructor
EXPORT StoreAndForward::StoreAndForward(LPSTR szXFileName) 
    { 
	/////////////////////////////////////////////////////////////////
	tSAFInit      = time(NULL); // TimeStamp del inicio de SAF
	tLastSAFCheck = 0L;         // TimeStamp del ultimo chequeo SAF    
	/////////////////////////////////////////////////////////////////
	// Nro. pseudo-aleatorio por instancia de clase.
	// El nro 971 es primo de forma de obtener una distribucion buena,
	// en un rango desde 0 a 999.
	// Iniciar criba de numeros pseudo-aleatorios
	srand( time( NULL ) );
	iRandomNum  = rand() % 971 ;
	bUseRandom  = TRUE; // Usar nombre random ?
	/////////////////////////////////////////////////////////////////
	// Asegurar handle de flujo de I/O en NULL    
    hfFile = NULL;
    // Bytes de I/O
    cbReadWrite = 0;
    // Limite logico de registros por default
    dwLimit = SAF_RECORDS_LIMIT;
    // Cuenta de Registros
    dwStdRecords = dwFwdRecords = 0L;
	// Cursores de Primero y Ultimo STORED
	dwFirstStdRecord = dwLastStdRecord = 0L;
	// Tamano de archivo inicialmente
	lFileSize = 0L;
    // Apertura y Estadisticas
    if(szXFileName != NULL) 
		Open(szXFileName);
    }
// Destructor
EXPORT StoreAndForward::~StoreAndForward(void) 
    { 	
	int  iRetval = 0;
	// Precondicion : recuperar tamano de archivo
	if(NULL != hfFile)
    {
		fseek( hfFile, 0L, SEEK_END );
        lFileSize = ftell( hfFile );
        fseek( hfFile, 0L, SEEK_SET );
    }
    // Cierre de archivo
    Close();
	// Si no tenia ningun registro, borrar el archivo
	if( 0L == dwStdRecords && 0 <= dwFwdRecords && 0L <= lFileSize )
		iRetval = remove( szFileName );
    // Estadisticas a cero
    dwLimit = dwStdRecords = dwFwdRecords = 0L;
	dwFirstStdRecord = dwLastStdRecord = 0L;
	iRandomNum  = 0 ;
	bUseRandom  = FALSE; // Usar nombre random ?
    }

// Apertura y Estadisticas
BOOL EXPORT StoreAndForward::Open(LPSTR szXFileName)
    {    
	BOOL bRetVal = FALSE;
    // Precondicion: Cerrado
    Close();          
	// Cambiar nombre segun fecha de hoy
	SetTodayFileName ( szXFileName, szFileName );
    // Error al abrir en modo BINARIO compartido?    
    if((hfFile = _fsopen((LPSTR)szFileName, "br+" )) == NULL)
        {
		// Intentar crearlo para saber si no existe ya
        if (!Create(szFileName)) 
			return FALSE;
		// Una vez creado, cerrarlo y reabrirlo
        Close();
        bRetVal = ((hfFile = _fsopen((LPSTR)szFileName, "br+" )) == NULL) 
                 ? FALSE 
				 : InitStatistics(szFileName) ;
		// Postcondicion : recuperar tamano de archivo
		if(NULL != hfFile)
        {
		    fseek( hfFile, 0L, SEEK_END );
            lFileSize = ftell( hfFile );
            fseek( hfFile, 0L, SEEK_SET );
        }
		// Postcondicion : TRUE/FALSE segun se haya podido abrir
		return bRetVal;
        }
    else 
        {
		// Postcondicion : recuperar tamano de archivo
		if(NULL != hfFile)
        {
		    fseek( hfFile, 0L, SEEK_END );
            lFileSize = ftell( hfFile );
            fseek( hfFile, 0L, SEEK_SET );
        }
		// Iniciar estadisticas
        return InitStatistics(szFileName);
        }
    }

// Establecer FORWARDED ultimo registro STORED leido
BOOL EXPORT StoreAndForward::SetForwarded(void)
    {
	// Posicion del Cursor de I/O sobre el archivo SAF
	long lcCurrPos = 0L;

    // Precondicion: handle valido
    if(NULL == hfFile) 
        return FALSE;
    
	/////////////////////////////////////////////
	// Grabar fecha-hora de este chequeo
	tLastSAFCheck = time( NULL );
	/////////////////////////////////////////////

	// Cursor磗 Current Position
	lcCurrPos = ftell(hfFile);

	// Se asume que el ultimo registro leido es el que se
	// quiere marcar como FORWARDED.
	// Asegurar posicion multiplo de registro
	if( (lcCurrPos % sizeof(safRecord)) != 0)
		return FALSE;

	// Es STORED?
    if(safRecord.wState == SAF_RECSTATE_STORED)
        {    	
		// Retroceder 1 registro (hasta el inicio del actual)
		// antes de regrabar		
		if( fseek(hfFile, lcCurrPos - sizeof(safRecord), SEEK_SET) 
			== RET_INVAL ) 			
			return FALSE;			

        // Forwarded
        safRecord.wState = SAF_RECSTATE_FORWARDED;
        // Hora (TIME_T Standard ANSI Unix)
        safRecord.tFwdTime = time(NULL);
        
		// Escritura en si misma, en la posicion del registro actual
        cbReadWrite = (SHORT)fwrite( (LPBYTE)&safRecord, 1, 
			                        sizeof(safRecord), hfFile);
	
		// Asegurar que se baje el buffer del Sistema Operativo a disco
		fflush(hfFile);
	
		// Error?
        if((cbReadWrite == RET_INVAL) || (cbReadWrite == 0))		
            return FALSE;			

		// Un Forwarded mas...
        if(dwFwdRecords < ULONG_MAX) dwFwdRecords++;
        else return FALSE;
        
		// Un Stored menos...
        if(dwStdRecords > 0L) dwStdRecords--;            

	    // Era primer registro STORED? Avanzar a siguiente registro...
		// ...que aunque no sea STORED, ya reasigna el cursor inicial a los mismos.
		if(dwFirstStdRecord == (DWORD)safRecord.dwRecord)
			dwFirstStdRecord++;

		// Reposicionar el Cursor de I/O como el original
		if( fseek(hfFile, lcCurrPos, SEEK_SET) == RET_INVAL ) 		
			return FALSE;		

		return TRUE;

        }
    else		
        return FALSE;		
    }
           
// Establecer CANCELLED ultimo registro STORED leido
BOOL EXPORT StoreAndForward::SetCancelled(void)
    {
    // Precondicion: handle valido
    if(NULL == hfFile) 
		return FALSE;

	// Posicion del Cursor de I/O sobre el archivo SAF:
	// Se asume que el ultimo registro leido es el que se
	// quiere marcar como CANCELLED.
	// Cursor磗 Current Position
	long lcCurrPos = ftell(hfFile);

	// Asegurar posicion multiplo de registro
	if( (lcCurrPos % sizeof(safRecord)) != 0)
		return FALSE;

    if(safRecord.wState == SAF_RECSTATE_STORED)
        {    
		// Retroceder 1 registro (hasta el inicio del actual)
		// antes de regrabar		
		if( fseek(hfFile, lcCurrPos - sizeof(safRecord), SEEK_SET) 
			== RET_INVAL ) 
			return FALSE;			

        // Cancelled
        safRecord.wState = SAF_RECSTATE_CANCELLED; // Estado CANCELLED    

        // Escritura en si misma, en la posicion actual
        cbReadWrite = (SHORT)fwrite((LPBYTE)&safRecord, 1,
			                        sizeof(safRecord), hfFile );
		
		// Asegurar que se baje el buffer del Sistema Operativo a disco
		fflush(hfFile);
		
		// Error?
        if((cbReadWrite == RET_INVAL) || (cbReadWrite == 0))
            return FALSE;
        
		// Un Stored menos...
        if(dwStdRecords > 0L) dwStdRecords--;        
		
		// Reposicionar el Cursor de I/O como el original
		if( fseek(hfFile, lcCurrPos, SEEK_SET) == RET_INVAL ) 		
			return FALSE;		

		return TRUE;

        }   
    else 
        return FALSE;
    }    

// Lectura de siguiente registro STORED
BOOL EXPORT StoreAndForward::ReadStored(LPBYTE lpbBuffer, 
                                        size_t cbLen, 
										size_t *pcbCopy,
										PDWORD pdwTraceNum,
										PDWORD pdwRefNum)
    {
    // Precondicion
    if(NULL == hfFile)
		return FALSE;    

    // Lectura en si misma de 1 registro STORED
    cbReadWrite = (SHORT)fread((LPBYTE)&safRecord, 1,
		                       sizeof(safRecord), hfFile );
	// Ciclo de lectura
    while ((cbReadWrite != 0) && (cbReadWrite != RET_INVAL))
        {         
        // Si es STORED...
        if(safRecord.wState == SAF_RECSTATE_STORED) 
		  {
            // Copiar Buffer de Datos generico. Asegurar longitud de copia.
            if((safRecord.cbBufferLen <= (short)cbLen) &&
			   (safRecord.cbBufferLen <= (short)sizeof(safRecord.bBuffer) ))
                {
                memcpy(lpbBuffer, (LPBYTE)safRecord.bBuffer, 
					   safRecord.cbBufferLen);
				if(pcbCopy)
					(*pcbCopy)     = safRecord.cbBufferLen ;
				if(pdwTraceNum)
					(*pdwTraceNum) = safRecord.dwTraceNum ;
				if(pdwTraceNum)
					(*pdwTraceNum) = safRecord.dwRefNum ;
				return ((cbReadWrite != 0) && (cbReadWrite != RET_INVAL)) 
					? TRUE 
					: FALSE;
                }            
            else if((short)cbLen < safRecord.cbBufferLen)
                {
                memcpy(lpbBuffer, (LPBYTE)safRecord.bBuffer, cbLen);
				if(pcbCopy)
					(*pcbCopy)     = safRecord.cbBufferLen ;
				if(pdwTraceNum)
					(*pdwTraceNum) = safRecord.dwTraceNum ;
				if(pdwTraceNum)
					(*pdwTraceNum) = safRecord.dwRefNum ;
				return ((cbReadWrite != 0) && (cbReadWrite != RET_INVAL)) 
					? TRUE 
					: FALSE;
                }
			else
				return FALSE;
          };
        // Siguiente registro
        cbReadWrite = (SHORT)fread((LPBYTE)&safRecord, 1,
		                           sizeof(safRecord), hfFile);
        }    
    return FALSE;
    }       
     
// Escritura de registro STORED
BOOL EXPORT StoreAndForward::WriteStored(LPBYTE lpbBuffer, 
										 SHORT cbLen,
										 DWORD dwTraceNum, 
										 DWORD dwRefNum)
    {    
    // Precondiciones
    if(NULL == hfFile) 
		return FALSE;    
    if(dwStdRecords > dwLimit) 
		return FALSE;
    
    // Armado de Registro SAF                                              
	safRecord.chEyeCatcher = '>';                // Marca visual, nada mas
    safRecord.dwRecord     = dwStdRecords + 1L;   // Registro Ordinal Autonumerado    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -