home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdarg.h>
-
- #include <StuTypes.h>
-
- #include "Utils.h"
- #include "EventLog.h"
-
- #define buffer_size 0x8000L
- #define buffer_limit (buffer_size - 0x100)
- #define TIMER_SEED (-100000000)
-
- local void primetimer(TMTask *task)
- {
- task->tmAddr = NULL;
- task->tmCount = 0;
- task->tmWakeUp = 0;
- task->tmReserved = 0;
- InsTime((QElemPtr)task);
- PrimeTime((QElemPtr)task, TIMER_SEED);
- }
-
- local long readtimer(TMTask *task)
- {
- long interval;
- RmvTime((QElemPtr)task);
- interval = task->tmCount - TIMER_SEED;
- if (interval == -TIMER_SEED) return(-1); else return(interval);
- }
-
- local Boolean WritingData(EventLog *e)
- {
- Boolean x;
- InterruptStatus statusregister = DisableInterrupts();
- x = (e->savingbuffer->pb.ioResult == 1);
- RestoreInterrupts(statusregister);
- return(x);
- }
-
- local pascal void WriteComplete(void);
- local void writelog(EventLog *e)
- {
- InterruptStatus statusregister = DisableInterrupts();
-
- // Note: Even though it may seem wierd to flush the file and volume BEFORE
- // we do the write, remember that after the write actually completes, the
- // WriteComplete routine calls writelog again to actually flush the data to disk.
- // Also have to take care here in case PBFlushFile or PBFlushVol cause the completion
- // of our last write, which will result in a reentrant call of writelog even though
- // interrupts are disabled.
- // Further note: This code to flush the file out was an attempt to provide
- // the best possible post-mortem crash diagnosis right up to the moment before
- // the crash, but it doesn't work (the disk driver seems to cache stuff anyway)
- // and it may even have been responsible for some of the crashes
- if (0 && e->fileflusher.ioResult == noErr)
- {
- e->fileflusher.ioResult = 1;
- PBFlushFile((ParmBlkPtr)&e->fileflusher, TRUE);
- }
- if (0 && e->volflusher.ioResult == noErr)
- {
- e->volflusher.ioResult = 1;
- PBFlushVol((ParmBlkPtr)&e->volflusher, TRUE);
- }
-
- if (e->fRefNum && e->savingbuffer->pb.ioResult == noErr &&
- e->ptr > e->loggingbuffer->buffer)
- {
- LogBuffer *b = e->loggingbuffer;
- if (e->overflow)
- {
- e->overflow = FALSE;
- if (e->ptr < e->loggingbuffer->buffer + buffer_size - 32)
- e->ptr += sprintf((char*)e->ptr, "*** Log Buffer Overflow ***\r");
- }
- e->loggingbuffer = e->savingbuffer;
- e->savingbuffer = b;
- //WriteCompleteUP.routineRecords[0].procDescriptor = WriteComplete;
- b->pb.ioCompletion = WriteComplete;
- b->pb.ioRefNum = e->fRefNum;
- b->pb.ioBuffer = (Ptr)b->buffer;
- b->pb.ioReqCount = e->ptr - b->buffer;
- b->pb.ioPosMode = fsAtMark | fsNoCache;
- b->pb.ioPosOffset = 0;
- e->ptr = e->loggingbuffer->buffer;
- b->pb.ioResult = 1;
- RestoreInterrupts(statusregister);
- PBWrite((ParmBlkPtr)&b->pb, TRUE);
- return;
- // Caution: Completion routine could be invoked immediately
- // within PBWrite call. Be careful about any assumptions made
- // by code added here after the PBWrite call
- }
- RestoreInterrupts(statusregister);
- }
-
- local pascal void WriteComplete(void)
- {
- long *savereg;
- register EventLog *e;
- asm { move.l GLOBREG, savereg
- move.l LogBuffer.log(a0), e
- move.l EventLog.GlobalsReg(e), GLOBREG
- move.l e, -(sp)
- bsr writelog
- lea 4(sp), sp
- move.l savereg, GLOBREG
- }
- }
-
- export void logevent(EventLog *e, char *format, ...)
- {
- InterruptStatus statusregister;
- char buffer[0x100];
- long length;
- va_list ptr;
- if (!e->fRefNum) return;
- va_start(ptr,format);
- length = vsprintf(buffer, format, ptr);
- buffer[length++] = '\r';
- if (length > 0xF0)
- debug("Oops! String at %lX is %ld bytes long. Time for Reboot!", buffer, length);
- va_end(ptr);
- statusregister = DisableInterrupts();
- if (e->ptr >= e->loggingbuffer->buffer + buffer_limit) e->overflow = TRUE;
- else
- {
- static u_char overtime[12] = "--,---,--- ";
- u_char timesting[12], *timptr = ×ting[11];
- long interval = readtimer(&e->timer);
- primetimer(&e->timer);
- if (interval == -1) timptr = overtime;
- else
- {
- int i;
- *--timptr = ' ';
- for (i=0; i<8; i++)
- {
- if (i == 3 || i == 6) *--timptr = interval ? ',' : ' ';
- if (interval == 0) *--timptr = ' ';
- else { *--timptr = '0' + interval % 10; interval /= 10; }
- }
- }
- BlockMoveData(timptr, e->ptr, 11); e->ptr += 11;
- BlockMoveData(buffer, e->ptr, length); e->ptr += length;
- }
- RestoreInterrupts(statusregister);
- writelog(e);
- }
-
- export void logsuppliment(EventLog *e, char *format, ...)
- {
- InterruptStatus statusregister;
- char buffer[0x100];
- Size length;
- va_list ptr;
- if (!e->fRefNum) return;
- va_start(ptr,format);
- length = sprintf(buffer, " ");
- length += vsprintf(buffer+length, format, ptr);
- buffer[length++] = '\r';
- if (length > 100)
- debug("Oops! String at %lX is %ld bytes long. Time for Reboot!", buffer, length);
- va_end(ptr);
- statusregister = DisableInterrupts();
- if (e->ptr >= e->loggingbuffer->buffer + buffer_limit) e->overflow = TRUE;
- else { BlockMoveData(buffer, e->ptr, length); e->ptr += length; }
- RestoreInterrupts(statusregister);
- writelog(e);
- }
-
- export void logdata(EventLog *e, char *desc, void *data, u_short length, u_short limit)
- {
- u_short offset = 0;
- u_char *packet = (u_char *)data;
- if (!e->fRefNum) return;
- logevent(e, "%s Packet length 0x%X", desc, length);
- if (length > limit) length = limit;
- while (offset < length)
- {
- int i;
- char buffer[256], *ptr = buffer;
- ptr += sprintf(ptr, " %04X ", offset);
- for (i=0; i<16; i++)
- {
- static const char hex[16] = "0123456789ABCDEF";
- if (offset+i >= length) { *ptr++ = ' '; *ptr++ = ' '; }
- else
- {
- *ptr++ = hex[packet[offset+i] >> 4];
- *ptr++ = hex[packet[offset+i] & 0xF];
- }
- *ptr++ = ' ';
- }
- for (i=0; i<16; i++)
- if (offset+i < length)
- {
- if (packet[offset+i] < 32 || packet[offset+i] > 126) *ptr++ = '.';
- else *ptr++ = packet[offset+i];
- }
- *ptr++ = 0;
- logsuppliment(e, "%s", buffer);
- offset += 0x10;
- }
- }
-
- export void EventLog_Open(register EventLog *e, u_char *fileName)
- {
- //e->fRefNum = 0; return;
- e->GlobalsReg = GetGlobalsRegister();
- e->buffer1.pb.ioResult = noErr;
- e->buffer1.buffer = (u_char*)NewPtrSys(buffer_size);
- e->buffer1.log = e;
- e->buffer2.pb.ioResult = noErr;
- e->buffer2.buffer = (u_char*)NewPtrSys(buffer_size);
- e->buffer2.log = e;
- if (e->buffer1.buffer && e->buffer2.buffer)
- {
- OSErr err;
- Str255 thename;
- SysEnvRec system;
- SysEnvirons(1, &system);
- BlockMove(fileName, thename, 1+fileName[0]);
- thename[fileName[0]+1] = '.';
- thename[fileName[0]+2] = 'A';
- e->overflow = FALSE;
- e->ptr = e->buffer1.buffer;
- e->loggingbuffer = &e->buffer1;
- e->savingbuffer = &e->buffer2;
- while ((err = Create(thename, system.sysVRefNum, 'R*ch', 'TEXT')) == dupFNErr)
- { thename[0] = fileName[0]+2; thename[fileName[0]+2]++; }
- if (!err) err = FSOpen(thename, system.sysVRefNum, &e->fRefNum);
-
- e->fileflusher.ioCompletion = NULL;
- e->fileflusher.ioRefNum = e->fRefNum;
- PBFlushFile((ParmBlkPtr)&e->fileflusher, FALSE);
- e->volflusher.ioCompletion = NULL;
- e->volflusher.ioNamePtr = NULL;
- e->volflusher.ioVRefNum = e->fRefNum;
- PBFlushVol((ParmBlkPtr)&e->fileflusher, FALSE);
- primetimer(&e->timer);
- }
- }
-
- export void EventLog_Close(EventLog *e)
- {
- if (e->fRefNum)
- {
- SysEnvRec system;
- SysEnvirons(1, &system);
- readtimer(&e->timer);
- while(WritingData(e));
- FSClose(e->fRefNum);
- FlushVol(NULL, system.sysVRefNum);
- e->fRefNum = 0;
- }
- if (e->buffer1.buffer) DisposePtr((Ptr)e->buffer1.buffer);
- if (e->buffer2.buffer) DisposePtr((Ptr)e->buffer2.buffer);
- }
-