/* log4back.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved. */ /* Backs up server .LOG file */ /**************************************************************************** **:: Preprocessor Directives ****************************************************************************/ #include "d4all.h" #ifndef S4UTILS #error - Must compile with S4UTILS defined #endif #include "u4trans.h" #ifndef S4WINDOWS #ifndef S4UNIX #ifdef __TURBOC__ #pragma hdrstop #endif extern unsigned _stklen = 10000; #endif #endif #ifdef S4DLL_BUILD extern FILE *stdout, *stderr ; extern unsigned int messageType ; HWND hWndStatus ; /* status window handle */ #endif #define FILENAMELEN 12 #define UTIL4BACKLOG 0 #define UTIL4COMPRESS 1 #define UTIL4OVERWRITE 3 #ifndef S4UTIL_CONCURRENCY #define UTIL4LOG 2 #else #define UTIL4CONFIG 2 #endif /**************************************************************************** **:: Global scope types and variables ****************************************************************************/ static UTIL4FLAG u4flags[] = { { "Backlog", 0, 1, 1, 1, 1, 0, 0, 0, "{-backlog }\r\n" }, { "COMpress", 0, 3, 1, 1, 1, 0, 0, 0, "[-compress {OFF | ON}]\r\n" }, #ifndef S4UTIL_CONCURRENCY { "Log", 0, 1, 1, 1, 1, 0, 0, 0, "{-log }\r\n" }, #else { "CONfig", 0, 3, 1, -1, 0, 0, 0, 0, "[-config []]\r\n" }, #endif { "Overwrite", 0, 1, 1, 1, 1, 0, 0, 0, "[-overwrite {OFF | ON}]\r\n" }, }; static int u4flagsNum = 4; static FIELD4INFO openFields[] = { { "CLIENTID", 'N', 11, 0 }, { "CLIENTDTID", 'N', 11, 0 }, { "SERVERDTID", 'N', 11, 0 }, { "PHYSNAME", 'C', LEN4PATH, 0 }, { "RECWIDTH", 'N', 6, 0 }, { "NUMFIELDS", 'N', 6, 0 }, { "NUMRECORDS", 'N', 10, 0 }, { "DBFTIME", 'N', 11, 0 }, { "DBFDATE", 'C', 3, 0 }, { "TEMP", 'L', 1, 0 }, { "TIME", 'N', 11, 0 }, { 0,0,0,0 }, }; static TAG4INFO openTags[] = { { "CLID", "STR(CLIENTID,11,0)+STR(SERVERDTID,11,0)", ".NOT.DELETED()", r4unique, 0 }, { 0,0,0,0,0 }, }; static FIELD4INFO tranFields[] = { { "TRANID", 'N', 11, 0 }, { 0,0,0,0 }, }; static TAG4INFO tranTags[] = { { "TRANID", "STR(TRANID,11,0)", ".NOT.DELETED()", r4unique, 0 }, { 0,0,0,0,0 }, }; static FIELD4INFO initFields[] = { { "CLIENTID", 'N', 11, 0 }, { "NETNAME", 'C', 80, 0 }, { "CBNAME", 'C', 80, 0 }, { "TIME", 'N', 11, 0 }, { 0,0,0,0 }, }; static TAG4INFO initTags[] = { { "CLIENTID", "STR(CLIENTID,11,0)", ".NOT.DELETED()", r4unique, 0 }, { 0,0,0,0,0 }, }; #ifndef S4WINDOWS char *statusStringBlank = " "; char *statusStringMessg = "Processing log file: "; char *statusStringBckSp = "\r"; char *statusStringFormt = "%3d.%02d%%%%"; #ifdef S4UNIX char statusStringSpace[10] ; #else char *statusStringSpace = "100.00 "; #endif #else extern char *statusStringBlank ; extern char *statusStringMessg ; extern char *statusStringBckSp ; extern char *statusStringFormt ; extern char *statusStringSpace ; #endif /*::************************************************************************/ /**************************************************************************** **:: Function: getLogFileName ** ***************************************************************************** ** ** Function: getLogFileName() ** ****************************************************************************/ #ifdef S4UTIL_CONCURRENCY int S4FUNCTION getLogFileName(CODE4 *c4, UTIL4FLAG *u4flag, char **logFileName, char **serverName, char **protocol, char **processId) { int rc; DATA4 *configDbf=0; char *outMess[1]; if (u4flags[UTIL4CONFIG].ptr != 0) configDbf = d4open(c4, u4flags[UTIL4CONFIG].ptr[0]); else configDbf = d4open(c4, "S4SERVER"); if (configDbf == 0) return(-1); rc = d4top(configDbf); if (rc == 0) { *logFileName = u4allocFree(c4, f4len(d4field(configDbf, "LOGNAME"))+1); if (*logFileName == 0) rc = -1; } if (rc == 0) { *serverName = u4allocFree(c4, f4len(d4field(configDbf, "SERVERID"))+1); if (*serverName == 0) rc = -1; } if (rc == 0) { *protocol = u4allocFree(c4, f4len(d4field(configDbf, "PROTOCOL"))+1); if (*protocol == 0) rc = -1; } if (rc == 0) { *processId = u4allocFree(c4, f4len(d4field(configDbf, "PROCESSID"))+1); if (*processId == 0) rc = -1; } if (rc == 0) { strcpy(*logFileName, f4str(d4field(configDbf, "LOGNAME"))); c4trimN(*logFileName, f4len(d4field(configDbf, "LOGNAME"))+1); if (**logFileName == 0) { rc = -1; outMess[0] = "Config Dbf error! Logging is disabled.\r\n\r\n"; util4out(c4, stdout, outMess, 1); } #ifdef S4UNIX u4nameExt(*logFileName, f4len(d4field(configDbf, "LOGNAME"))+1, "log", 0); #else u4nameExt(*logFileName, f4len(d4field(configDbf, "LOGNAME"))+1, "LOG", 0); #endif strcpy(*serverName, f4str(d4field(configDbf, "SERVERID"))); c4trimN(*serverName, f4len(d4field(configDbf, "SERVERID"))+1); if (**serverName == 0) { u4free(*serverName); *serverName = 0; } strcpy(*protocol, f4str(d4field(configDbf, "PROTOCOL"))); c4trimN(*protocol, f4len(d4field(configDbf, "PROTOCOL"))+1); if (**protocol == 0) { u4free(*protocol); *protocol = 0; } else if (**protocol == 'S' || **protocol == 's') **protocol -= ('S'-'U'); else { rc = -1; outMess[0] = "Config Dbf error! Protocol name does not follow expected naming convention.\r\n\r\n"; util4out(c4, stdout, outMess, 1); } strcpy(*processId, f4str(d4field(configDbf, "PROCESSID"))); c4trimN(*processId, f4len(d4field(configDbf, "PROCESSID"))+1); if (**processId == 0) { u4free(*processId); *processId = 0; } } rc = rc || d4close(configDbf); return(rc); } #endif /**************************************************************************** **:: Function: findIncompleteTran ** ***************************************************************************** ** ** Function: findIncompleteTran() ** ****************************************************************************/ int S4FUNCTION findIncompleteTran(CODE4 *c4, DATA4 *openDbf, DATA4 *tranDbf, DATA4 *initDbf, unsigned long logFileEof) { int rc, netNameLen, cbNameLen; TRAN4 *t4; char client[23], *outMess[3], *data; TRAN4ENTRY_LEN len; short intPart, decPart; t4 = &c4->c4trans.trans; #ifndef S4WINDOWS outMess[0] = statusStringBlank; util4out(c4, stderr, outMess, 1); #endif #ifdef S4DATA_ALIGN long templong ; short tempshort ; #endif for (rc = tran4top(t4); rc == 0; rc = tran4skip(t4, TRAN4FORWARDS)) { intPart = (short)((unsigned long)c4->c4trans.trans.pos*50/logFileEof); decPart = (short)((unsigned long)c4->c4trans.trans.pos*5000/logFileEof%100); #ifndef S4WINDOWS sprintf(statusStringSpace, statusStringFormt, intPart, decPart); outMess[0] = statusStringBckSp; outMess[1] = statusStringMessg; outMess[2] = statusStringSpace; util4out(c4, stderr, outMess, 3); #else sendStatusMessage( hWndStatus, intPart ) ; #endif switch (tran4type(t4)) { case TRAN4BACKEDUP: case TRAN4WRITE: case TRAN4APPEND: case TRAN4PACK: case TRAN4ZAP: case TRAN4VOID: break; case TRAN4SHUTDOWN: rc = d4pack(openDbf); if (rc != 0) break; if (d4recCount(openDbf) > 0) { outMess[0] = "\r\n\r\nLog file corrupt! DBF('s) open at shutdown, continuing.\r\n\r\n"; #ifndef S4WINDOWS outMess[1] = statusStringBlank; util4out(c4, stdout, outMess, 2); #else util4out(c4, stdout, outMess, 1) ; #endif rc = d4zap(openDbf, 1L, d4recCount(openDbf)); if (rc != 0) break; } rc = d4pack(tranDbf); if (rc != 0) break; if (d4recCount(tranDbf) > 0) { outMess[0] = "\r\n\r\nLog file corrupt! Transaction(s) unfinished at shutdown, continuing.\r\n\r\n"; #ifndef S4WINDOWS outMess[1] = statusStringBlank; util4out(c4, stdout, outMess, 2); #else util4out(c4, stdout, outMess, 1) ; #endif rc = d4zap(tranDbf, 1L, d4recCount(tranDbf)); if (rc != 0) break; } rc = d4pack(initDbf); if (rc != 0) break; if (d4recCount(initDbf) > 0) { outMess[0] = "\r\n\r\nLog file corrupt! User(s) initialized at shutdown, continuing.\r\n\r\n"; #ifndef S4WINDOWS outMess[1] = statusStringBlank; util4out(c4, stdout, outMess, 2); #else util4out(c4, stdout, outMess, 1) ; #endif rc = d4zap(initDbf, 1L, d4recCount(initDbf)); if (rc != 0) break; } if (tran4serverDataId(&c4->c4trans.trans) > TRAN4VERSION_NUM) { outMess[0] = "\r\n\r\nLog file error! File is a newer version than this utility can handle!\r\n\r\n"; util4out(c4, stdout, outMess, 1); rc = -1; } break; case TRAN4INIT: data = (char *)tran4getData(t4, 0L); if (data == 0) { rc = -1; break; } rc = d4appendStart(initDbf, 0); if (rc != 0) break; d4blank(initDbf); f4assignLong(d4field(initDbf, "CLIENTID"), tran4clientId(t4)); f4assignLong(d4field(initDbf, "TIME"), t4->header.time); netNameLen = *(short *)data; f4assignN(d4field(initDbf, "NETNAME"), data+2, netNameLen); cbNameLen = *(short *)(data+2+netNameLen); f4assignN(d4field(initDbf, "CBNAME"), data+4+netNameLen, cbNameLen); rc = d4append(initDbf); if (rc == r4unique) { outMess[0] = "\r\n\r\nLog file error! User already initialized.\r\n\r\n"; util4out(c4, stdout, outMess, 1); } break; case TRAN4INIT_UNDO: util4rightJ(ltoa(tran4clientId(t4), client, 10), 12); rc = d4seek(initDbf, client); if (rc != 0) { if (rc == r4after || rc == r4eof) { outMess[0] = "\r\n\r\nLog file error! User uninitialized that is not initialized.\r\n\r\n"; util4out(c4, stdout, outMess, 1); rc = -1; } break; } d4delete(initDbf); rc = d4seek(openDbf, client); if (rc == 0) { outMess[0] = "\r\n\r\nLog file error! User uninitialized with DBF's still open.\r\n\r\n"; util4out(c4, stdout, outMess, 1); rc = -1; break; } if (rc == r4after || rc == r4eof) rc = 0; break; case TRAN4OPEN: case TRAN4OPEN_TEMP: data = (char *)tran4getData(t4, 0L); if (data == 0) { rc = -1; break; } rc = d4appendStart(openDbf, 0); if (rc != 0) break; d4blank(openDbf); f4assignLong(d4field(openDbf, "CLIENTID"), tran4clientId(t4)); f4assignLong(d4field(openDbf, "CLIENTDTID"), tran4clientDataId(t4)); f4assignLong(d4field(openDbf, "SERVERDTID"), tran4serverDataId(t4)); f4assignLong(d4field(openDbf, "TIME"), t4->header.time); f4assignN(d4field(openDbf, "PHYSNAME"), data+2, *(short *)data); #ifdef S4DATA_ALIGN memcpy(&templong, (data+2+*(short *)data), sizeof(long)) ; f4assignLong(d4field(openDbf, "RECWIDTH"), templong ); memcpy(&tempshort, (data+6+*(short *)data), sizeof(short)) ; f4assignInt(d4field(openDbf, "NUMFIELDS"), tempshort); memcpy(&templong, (data+8+*(short *)data), sizeof(long)) ; f4assignLong(d4field(openDbf, "NUMRECORDS"), templong); memcpy(&templong, (data+12+*(short *)data), sizeof(long)) ; f4assignLong(d4field(openDbf, "DBFTIME"), templong); #else f4assignLong(d4field(openDbf, "RECWIDTH"), *(long *)(data+2+(*(short *)data))); f4assignInt(d4field(openDbf, "NUMFIELDS"), *(short *)(data+6+(*(short *)data))); f4assignLong(d4field(openDbf, "NUMRECORDS"), *(long *)(data+8+(*(short *)data))); f4assignLong(d4field(openDbf, "DBFTIME"), *(long *)(data+12+(*(short *)data))); #endif f4assignN(d4field(openDbf, "DBFDATE"), data+16+(*(short *)data), 3); if (tran4type(t4) == TRAN4OPEN_TEMP) f4assignChar(d4field(openDbf, "TEMP"), 'Y'); rc = d4append(openDbf); if (rc == r4unique) { outMess[0] = "\r\n\r\nLog file error! DBF identifier already used.\r\n\r\n"; util4out(c4, stdout, outMess, 1); } break; case TRAN4CLOSE: util4rightJ(ltoa(tran4clientId(t4), client, 10), 12); util4rightJ(ltoa(tran4serverDataId(t4), client+11, 10), 12); rc = d4seek(openDbf, client); if (rc != 0) { if (rc == r4after || rc == r4eof) { outMess[0] = "\r\n\r\nLog file error! DBF closed that is not open.\r\n\r\n"; util4out(c4, stdout, outMess, 1); rc = -1; } break; } d4delete(openDbf); break; case TRAN4START: util4rightJ(ltoa(tran4clientId(t4), client, 10), 12); rc = d4seek(initDbf, client); if (rc != 0) { if (rc == r4after || rc == r4eof) { outMess[0] = "\r\n\r\nLog file error! Transaction started by user that is not initialized.\r\n\r\n"; util4out(c4, stdout, outMess, 1); rc = -1; } break; } rc = d4appendStart(tranDbf, 0); if (rc != 0) break; d4blank(tranDbf); f4assignLong(d4field(tranDbf, "TRANID"), tran4id(t4)); rc = d4append(tranDbf); if (rc == r4unique) { outMess[0] = "\r\n\r\nLog file error! Transaction ID already started.\r\n\r\n"; util4out(c4, stdout, outMess, 1); } break; case TRAN4COMPLETE: case TRAN4ROLLBACK: util4rightJ(ltoa(tran4id(t4), client, 10), 12); rc = d4seek(tranDbf, client); if (rc != 0) { if (rc == r4after || rc == r4eof) { if (tran4type(t4) == TRAN4COMPLETE) outMess[0] = "\r\n\r\nLog file error! Transaction completed that was not started.\r\n\r\n"; else outMess[0] = "\r\n\r\nLog file error! Transaction rolledback that was not started.\r\n\r\n"; util4out(c4, stdout, outMess, 1); rc = -1; } break; } d4delete(tranDbf); break; default: outMess[0] = "\r\n\r\nLog file error! Unknown log entry type.\r\n\r\n"; util4out(c4, stdout, outMess, 1); rc = -1; } if ( rc != 0 ) break; if ((unsigned long)t4->pos+sizeof(LOG4HEADER)+sizeof(TRAN4ENTRY_LEN) > logFileEof) { rc = r4eof; break; } rc = file4readAll(&c4->transFile.file, t4->pos+sizeof(LOG4HEADER), &len, sizeof(TRAN4ENTRY_LEN)); if (rc == 0 && (unsigned long)t4->pos+sizeof(LOG4HEADER)+len > logFileEof) { rc = r4eof; break; } if (rc != 0) break; } if (rc == r4eof) rc = 0; return(rc); } /**************************************************************************** **:: Function: compressTran ** ***************************************************************************** ** ** Function: compressTran() ** ****************************************************************************/ short S4FUNCTION compressTran(CODE4 *c4, DATA4 *openDbf, DATA4 *tranDbf, DATA4 *initDbf, unsigned long logFileEof, CODE4 *outTrans, CODE4 *tempTrans, int compress) { short rc, netLen, cbLen, physLen, numFields, intPart, decPart; int type=-1; TRAN4 *t4, *outT4, *tempT4; char client[23], cbName[81], netName[81], *physName, *outMess[3]; long tempLong; TRAN4ENTRY_LEN len; t4 = &c4->c4trans.trans; outT4 = &outTrans->c4trans.trans; if (compress) tempT4 = &tempTrans->c4trans.trans; rc = tran4set(outT4, r4off, -1, 0, TRAN4BACKEDUP, 0, 0L, 0L); if (rc < 0) return(rc); rc = tran4lowAppend(outT4, 0); if (rc < 0) return(rc); if (compress != 0) { rc = tran4set(tempT4, r4off, -1, 0, TRAN4SHUTDOWN, 0, 0L, TRAN4VERSION_NUM); if (rc < 0) return(rc); tempT4->header.time = 0L; rc = tran4lowAppend(tempT4, 0); if (rc < 0) return(rc); for (rc = d4top(initDbf); rc == 0; rc = d4skip(initDbf, 1L)) { strcpy(netName, f4str(d4field(initDbf, "NETNAME"))); c4trimN(netName, 81); netLen = strlen(netName); strcpy(cbName, f4str(d4field(initDbf, "CBNAME"))); c4trimN(cbName, 81); cbLen = strlen(cbName); rc = tran4set(tempT4, r4off, -1, f4long(d4field(initDbf, "CLIENTID")), TRAN4INIT, cbLen+netLen+sizeof(cbLen)+sizeof(netLen), 0L, 0L); if (rc < 0) break; tempT4->header.time = f4long(d4field(initDbf, "TIME")); rc = tran4putData(tempT4, (void *)&netLen, sizeof(netLen)); if (rc < 0) break; if (netLen != 0) { rc = tran4putData(tempT4, (void *)netName, netLen); if (rc < 0) break; } rc = tran4putData(tempT4, (void *)&cbLen, sizeof(cbLen)); if (rc < 0) break; if (cbLen != 0) { rc = tran4putData(tempT4, (void *)cbName, cbLen); if (rc < 0) break; } rc = tran4lowAppend(tempT4, 0); if (rc < 0) break; } if (rc != r4eof) return(rc); for (rc = d4top(openDbf); rc == 0; rc = d4skip(openDbf, 1L)) { physName = f4str(d4field(openDbf, "PHYSNAME")); c4trimN(physName, LEN4PATH+1); physLen = strlen(physName); if (f4true(d4field(openDbf, "TEMP"))) type = TRAN4OPEN_TEMP; else type = TRAN4OPEN; rc = tran4set(tempT4, r4off, -1, f4long(d4field(openDbf, "CLIENTID")), type, physLen+19, f4long(d4field(openDbf, "CLIENTDTID")), f4long(d4field(openDbf, "SERVERDTID"))); if (rc < 0) break; tempT4->header.time = f4long(d4field(openDbf, "TIME")); rc = tran4putData(tempT4, (void *)&physLen, sizeof(physLen)); if (rc < 0) break; rc = tran4putData(tempT4, (void *)physName, physLen); if (rc < 0) break; tempLong = f4long(d4field(openDbf, "RECWIDTH")); rc = tran4putData(tempT4, (void *)&tempLong, sizeof(tempLong)); if (rc < 0) break; numFields = (short)f4long(d4field(openDbf, "NUMFIELDS")); rc = tran4putData(tempT4, (void *)&numFields, sizeof(numFields)); if (rc < 0) break; tempLong = f4long(d4field(openDbf, "NUMRECORDS")); rc = tran4putData(tempT4, (void *)&tempLong, sizeof(tempLong)); if (rc < 0) break; tempLong = f4long(d4field(openDbf, "DBFTIME")); rc = tran4putData(tempT4, (void *)&tempLong, sizeof(tempLong)); if (rc < 0) break; rc = tran4putData(tempT4, f4ptr(d4field(openDbf, "DBFDATE")), 3); if (rc < 0) break; rc = tran4lowAppend(tempT4, 0); if (rc < 0) break; } if (rc != r4eof) return(rc); } for (rc = tran4top(t4); rc == 0; rc = tran4skip(t4, TRAN4FORWARDS)) { intPart = (short)((unsigned long)c4->c4trans.trans.pos*50/logFileEof+50); decPart = (short)((unsigned long)c4->c4trans.trans.pos*5000/logFileEof%100); #ifndef S4WINDOWS sprintf(statusStringSpace, statusStringFormt, intPart, decPart); outMess[0] = statusStringBckSp; outMess[1] = statusStringMessg; outMess[2] = statusStringSpace; util4out(c4, stderr, outMess, 3); #else sendStatusMessage( hWndStatus, intPart ) ; #endif type = tran4type(t4); switch (type) { case TRAN4SHUTDOWN: case TRAN4BACKEDUP: case TRAN4INIT: case TRAN4INIT_UNDO: case TRAN4OPEN: case TRAN4OPEN_TEMP: case TRAN4CLOSE: case TRAN4PACK: case TRAN4ZAP: case TRAN4VOID: rc = tran4fileAppend(&outTrans->transFile, &t4->header, t4->c4trans->c4->tranData); break; case TRAN4START: case TRAN4COMPLETE: case TRAN4ROLLBACK: case TRAN4WRITE: case TRAN4APPEND: util4rightJ(ltoa(tran4id(t4), client, 10), 12); rc = d4seek(tranDbf, client); if (rc == 0) { if (compress) rc = tran4fileAppend(&tempTrans->transFile, &t4->header, t4->c4trans->c4->tranData); } else if (rc == r4after || rc == r4eof) rc = tran4fileAppend(&outTrans->transFile, &t4->header, t4->c4trans->c4->tranData); break; default: outMess[0] = "\r\n\r\nLog file error! Unknown log entry type.\r\n\r\n"; util4out(c4, stdout, outMess, 1); rc = -1; } if (rc != 0) break; if ((unsigned long)t4->pos+sizeof(LOG4HEADER)+sizeof(TRAN4ENTRY_LEN) > logFileEof) { rc = r4eof; break; } rc = file4readAll(&c4->transFile.file, t4->pos+sizeof(LOG4HEADER), &len, sizeof(TRAN4ENTRY_LEN)); if (rc == 0 && (unsigned long)t4->pos+sizeof(LOG4HEADER)+len > logFileEof) { rc = r4eof; break; } if (rc != 0) break; } if (rc != r4eof) return(rc); #ifndef S4WINDOWS outMess[0] = statusStringBckSp; outMess[1] = statusStringMessg; sprintf(statusStringSpace, statusStringFormt, 100, 0); outMess[2] = statusStringSpace; util4out(c4, stderr, outMess, 3); outMess[0] = "\r\n"; util4out(c4, stderr, outMess, 1); util4out(c4, stdout, outMess, 1); #endif for (rc = d4top(openDbf); rc == 0; rc = d4skip(openDbf, 1L)) { rc = tran4set(outT4, r4off, -1, f4long(d4field(openDbf, "CLIENTID")), TRAN4CLOSE, 0, f4long(d4field(openDbf, "CLIENTDTID")), f4long(d4field(openDbf, "SERVERDTID"))); if (rc < 0) break; outT4->header.time = 0L; rc = tran4lowAppend(outT4, 0); if (rc < 0) break; } if (rc != r4eof) return(rc); for (rc = d4top(initDbf); rc == 0; rc = d4skip(initDbf, 1L)) { rc = tran4set(outT4, r4off, -1, f4long(d4field(initDbf, "CLIENTID")), TRAN4INIT_UNDO, 0, 0L, 0L); if (rc < 0) break; outT4->header.time = 0L; rc = tran4lowAppend(outT4, 0); if (rc < 0) break; } if (rc != r4eof) return(rc); rc = 0; if (type != TRAN4SHUTDOWN) { rc = tran4set(outT4, r4off, -1, 0, TRAN4SHUTDOWN, 0, 0L, TRAN4VERSION_NUM); if (rc < 0) return(rc); outT4->header.time = 0L; rc = tran4lowAppend(outT4, 0); } else { if (compress) { rc = tran4set(tempT4, r4off, -1, 0, TRAN4SHUTDOWN, 0, 0L, TRAN4VERSION_NUM); if (rc < 0) return(rc); tempT4->header.time = 0L; rc = tran4lowAppend(tempT4, 0); } } return(rc); } /**************************************************************************** **:: Function: backupLogFile ** ***************************************************************************** ** ** Function: backupLogFile() ** ****************************************************************************/ int S4FUNCTION backupLogFile(CODE4 *c4, CODE4 *outTrans, CODE4 *tempTrans, unsigned long logFileEof, int compress) { DATA4 *openDbf, *tranDbf, *initDbf; int rc=0; openDbf = d4createTemp(c4, openFields, openTags); tranDbf = d4createTemp(c4, tranFields, tranTags); initDbf = d4createTemp(c4, initFields, initTags); if ((openDbf == 0) || (tranDbf == 0) || (initDbf == 0)) rc = -1; if (rc == 0) { d4tagSelect(openDbf, d4tag(openDbf, "CLID")); d4tagSelect(tranDbf, d4tag(tranDbf, "TRANID")); d4tagSelect(initDbf, d4tag(initDbf, "CLIENTID")); rc = findIncompleteTran(c4, openDbf, tranDbf, initDbf, logFileEof); } if (rc == 0) rc = compressTran(c4, openDbf, tranDbf, initDbf, logFileEof, outTrans, tempTrans, compress); if (initDbf) rc = rc || d4close(initDbf); if (tranDbf) rc = rc || d4close(tranDbf); if (openDbf) rc = rc || d4close(openDbf); return(rc); } /**************************************************************************** **:: Function: copyResidualLogFile ** ***************************************************************************** ** ** Function: copyResidualLogFile() ** ****************************************************************************/ short S4FUNCTION copyResidualLogFile(CODE4 *c4, CODE4 *tempTrans, unsigned long logFileEof, unsigned long logFileEofFull) { unsigned long diff; unsigned short rc, bufSize; char *buffer; diff = logFileEofFull - logFileEof; if (diff <= 0) return((short)diff); file4refresh(&c4->transFile.file); file4refresh(&tempTrans->transFile.file); bufSize = (unsigned short)(diff > 65000 ? 65000 : diff); buffer = (char *)u4allocFree(c4, bufSize); if (buffer == 0) return(-1); for (; diff>0; diff -= rc, logFileEof+= rc ) { rc = file4read(&c4->transFile.file, logFileEof, buffer, bufSize); if (rc <= 0) { u4free(buffer); return(-1); } if (file4write(&tempTrans->transFile.file, file4len(&tempTrans->transFile.file), buffer, rc) < 0) { u4free(buffer); return(-1); } } u4free(buffer); return(0); } /**************************************************************************** **:: Function: main ** ***************************************************************************** ** ** Function: main() ** ****************************************************************************/ #ifdef S4DLL_BUILD int S4FUNCTION mainLog4Back(int argc, char *argv[], int hWnd ) #else int main( int argc, char *argv[] ) #endif { CODE4 c4, outTrans, tempTrans; char *logFileName=0, *tempFileName=0 ; unsigned long logFileEof, logFileEofFull; long len; int rc=0, serverUp=0, i, j=0, compress, overwrite; char *outMess[5], *outFileName; #ifdef S4UTIL_CONCURRENCY char *serverName=0, *protocol=0, *processId=0; #endif #ifdef S4WINDOWS hWndStatus = hWnd ; messageType = MB_ICONSTOP ; #endif #ifndef S4DLL_BUILD #ifdef _WINDOWS _wabout("LOG4BACK.EXE\r\n(c)Copyright Sequiter Software Inc., 1988-1996"); #endif #endif #ifdef S4UNIX strcpy(statusStringSpace, "100.00 "); #endif code4init(&c4); c4.lockAttempts = WAIT4EVER; c4.autoOpen = 0; #ifndef S4WINDOWS outMess[0] = "\r\n"; util4out(&c4, stderr, outMess, 1); #endif if (argc < 2) rc = -1; if (rc == 0) rc = util4parseCommandLine(&c4, u4flags, u4flagsNum, argv, argc); if (rc == 0 && u4flags[UTIL4BACKLOG].found == 0) { outMess[0] = "Command line error! Must specify -backlog switch.\r\n\r\n"; util4out(&c4, stdout, outMess, 1); rc = -1; } #ifndef S4UTIL_CONCURRENCY if (rc == 0 && u4flags[UTIL4LOG].found == 0) { outMess[0] = "Command line error! Must specify -log switch.\r\n\r\n"; util4out(&c4, stdout, outMess, 1); rc = -1; } #endif compress = util4checkOnOffCommandLine(&c4, u4flags, UTIL4COMPRESS, 0); if (compress == -1) rc = -1; overwrite = util4checkOnOffCommandLine(&c4, u4flags, UTIL4OVERWRITE, 0); if (overwrite == -1) rc = -1; if (rc != 0) { util4printCommandLine(&c4, u4flags, u4flagsNum, argv[0]); util4flagsFree(u4flags, u4flagsNum); code4initUndo(&c4); #ifdef S4WINDOWS sendCloseMessage( hWndStatus ) ; #endif return(rc); } outFileName = (char *)u4allocFree(&c4, strlen(u4flags[UTIL4BACKLOG].ptr[0])+5); if (outFileName == 0) rc = -1; else { strcpy(outFileName, u4flags[UTIL4BACKLOG].ptr[0]); #ifdef S4UNIX u4nameExt(outFileName, strlen(u4flags[UTIL4BACKLOG].ptr[0])+5, "log", 0); #else u4nameExt(outFileName, strlen(u4flags[UTIL4BACKLOG].ptr[0])+5, "LOG", 0); #endif } if (rc == 0) { rc = access(outFileName, 0); if (rc == 0) if (overwrite) { rc = remove(outFileName); if (rc != 0) { outMess[0] = "Access error! Can not overwrite -backlog file "; outMess[1] = outFileName; outMess[2] = "\r\n\r\n"; util4out(&c4, stdout, outMess, 3); } } else { #ifndef S4WINDOWS outMess[0] = "Command line error! -backlog file "; #else outMess[0] = "Access error! Backup log file "; #endif outMess[1] = outFileName; outMess[2] = " already exists.\r\n\r\n"; util4out(&c4, stdout, outMess, 3); rc = -1; } else rc = 0; } if (rc != 0) { outMess[0] = "Error! Utility did not successfully finish!\r\n"; util4out(&c4, stdout, outMess, 1); if (outFileName) u4free(outFileName); util4flagsFree(u4flags, u4flagsNum); code4initUndo(&c4); #ifdef S4WINDOWS sendCloseMessage( hWndStatus ) ; #endif return(rc); } #ifdef S4UTIL_CONCURRENCY rc = getLogFileName(&c4, u4flags, &logFileName, &serverName, &protocol, &processId); #else logFileName = u4flags[UTIL4LOG].ptr[0] ; #endif if (rc == 0) { rc = code4logOpen( &c4, logFileName, "" ) ; code4tranStatusSet(&c4, r4off); } if (rc == 0 && sizeof(LOG4HEADER)+sizeof(TRAN4ENTRY_LEN) > file4len(&c4.transFile.file)) { rc = file4lenSet(&c4.transFile.file, 0L); outMess[0] = "Log file error! Log file is empty.\r\n\r\n"; util4out(&c4, stdout, outMess, 1); rc = -1; } code4init(&outTrans); outTrans.errOpen = 0; outTrans.safety = 0; if (rc == 0) { rc = code4logOpen( &outTrans, outFileName, "" ) ; if( rc == r4no_open ) { rc = code4logCreate( &outTrans, outFileName, "" ) ; error4set( &outTrans, 0 ) ; } code4tranStatusSet(&outTrans, r4off); } if (rc == 0) { len = file4len(&outTrans.transFile.file); if (len < 0) rc = -1; if (rc == 0) rc = file4lenSet(&outTrans.transFile.file, 0L); } if (compress) { code4init(&tempTrans); tempTrans.errOpen = 0; tempTrans.safety = 0; if (rc == 0) { i = strlen(logFileName); while (--i>=0 && logFileName[i] != '.' && logFileName[i] != '\\'); if (i == -1 || logFileName[i] == '\\') i = strlen(logFileName); tempFileName = (char *)u4allocFree(&c4, i+5); if (tempFileName != 0) { strcpy(tempFileName, logFileName); do u4nameExt(tempFileName, i+5, ltoa(j++, " ", 10), 1); while (access(tempFileName, 0) == 0 && j < 1000); if (j == 1000) rc = -1; if (rc == 0) { rc = code4logCreate( &tempTrans, tempFileName, "" ) ; code4tranStatusSet(&tempTrans, r4off); } if (rc == 0) rc = file4lenSet(&tempTrans.transFile.file, 0L); } } } c4.lockAttempts = 1; if (rc == 0) { rc = code4tranLockTransactions(&c4.c4trans, TRAN4LOCK_FIX); if (rc == r4locked) { outMess[0] = "Concurrency error! Fix utility is running!\r\n\r\n"; util4out(&c4, stdout, outMess, 1); } } if (rc == 0) { rc = code4tranLockTransactions(&c4.c4trans, TRAN4LOCK_BACKUP); if (rc == r4locked) { outMess[0] = "Concurrency error! Another copy of this utility is running!\r\n\r\n"; util4out(&c4, stdout, outMess, 1); } } if (rc == 0) { rc = code4tranLockTransactions(&outTrans.c4trans, TRAN4LOCK_RESTORE); if (rc == r4locked) { outMess[0] = "Concurrency error! Restore utility is using -backlog file "; outMess[1] = outFileName; outMess[2] = "!\r\n\r\n"; util4out(&c4, stdout, outMess, 3); } } if (rc == 0) { rc = code4tranLockTransactions(&outTrans.c4trans, TRAN4LOCK_BACKUP); if (rc == r4locked) { outMess[0] = "Concurrency error! Another copy of this utility is using -backlog file "; outMess[1] = outFileName; outMess[2] = "!\r\n\r\n"; util4out(&c4, stdout, outMess, 3); } } if (rc == 0) { /* query server for eof */ rc = code4tranLockTransactions(&c4.c4trans, TRAN4LOCK_SERVER); if (rc == r4locked) { #ifdef S4UTIL_CONCURRENCY rc = code4connect(&c4, serverName, processId, 0, 0, protocol); if (rc == 0) rc = tran4serverEof(&c4.c4trans.trans, &logFileEof); else c4.errorCode = 0; if (rc == r4noServer) { outMess[0] = "Concurrency error! Unknown application has locked the server on log file.\r\n\r\n"; util4out(&c4, stdout, outMess, 1); } else if (rc == 0) serverUp = 1; #else outMess[0] = "Concurrency error! The server is running!\r\n\r\n"; util4out(&c4, stdout, outMess, 1); #endif } else if (rc == 0) logFileEof = file4len(&c4.transFile.file); } c4.lockAttempts = WAIT4EVER; if (rc == 0) { rc = tran4top(&c4.c4trans.trans); if (rc == 0 && (tran4type(&c4.c4trans.trans) != TRAN4SHUTDOWN || tran4serverDataId(&c4.c4trans.trans) > TRAN4VERSION_NUM)) { outMess[0] = "Log file error! File is either a backup file or a newer version than this utility can handle!\r\n\r\n"; util4out(&c4, stdout, outMess, 1); rc = -1; } } /* backup transaction file to eof */ if (rc == 0) rc = backupLogFile(&c4, &outTrans, &tempTrans, logFileEof, compress); /* query server for eof and halt server */ #ifdef S4UTIL_CONCURRENCY if (rc == 0 && serverUp && compress) { rc = tran4serverEofHalt(&c4.c4trans.trans, &logFileEofFull); if (rc == 0) { rc = code4tranLockTransactions(&c4.c4trans, TRAN4LOCK_SERVER); if (rc == r4locked) { outMess[0] = "Concurrency error! Unknown application has locked the server on log file.\r\n\r\n"; util4out(&c4, stdout, outMess, 1); } } } else #endif logFileEofFull = logFileEof; /* copy residual */ if (rc == 0 && compress) rc = copyResidualLogFile(&c4, &tempTrans, logFileEof, logFileEofFull); /* overwite old */ if (compress) code4transInitUndo(&tempTrans.c4trans); code4transInitUndo(&outTrans.c4trans); code4transInitUndo(&c4.c4trans); if (rc != 0) { remove(outFileName); if (compress) remove(tempFileName); } if (rc == 0 && compress) { rc = remove(logFileName); if (rc != 0) { outMess[0] = "!!!ERROR!!! Original log file not removed! To complete backup rename:\r\n\r\n"; outMess[1] = tempFileName; outMess[2] = "\r\nover top of:\r\n"; outMess[3] = logFileName; outMess[4] = "\r\n\r\n"; util4out(&c4, stdout, outMess, 5); } else { rename(tempFileName, logFileName); if (rc != 0) { outMess[0] = "!!!ERROR!!! New log file not renamed! To complete backup rename:\r\n"; outMess[1] = tempFileName; outMess[2] = "\r\nto:\r\n"; outMess[3] = logFileName; outMess[4] = "\r\n\r\n"; util4out(&c4, stdout, outMess, 5); } } } if (rc != 0) { outMess[0] = "Error! Utility did not successfully finish!\r\n"; util4out(&c4, stdout, outMess, 1); } else { #ifdef S4WINDOWS messageType = MB_ICONEXCLAMATION ; sendStatusMessage( hWndStatus, 100 ) ; #endif outMess[0] = "Utility successfully finished!\r\n"; util4out(&c4, stdout, outMess, 1); } if (compress) { if (tempFileName) u4free(tempFileName); code4initUndo(&tempTrans); } code4initUndo(&outTrans); if (outFileName) u4free(outFileName); #ifdef S4UTIL_CONCURRENCY if (processId) u4free(processId); if (protocol) u4free(protocol); if (serverName) u4free(serverName); if (logFileName) u4free(logFileName); #endif util4flagsFree(u4flags, u4flagsNum); code4initUndo(&c4); #ifdef S4WINDOWS sendCloseMessage( hWndStatus ) ; #endif return(rc); }