head 1.15; access; symbols Version_2_1:1.14 C_Demo_1:1.10; locks; strict; comment @ * @; 1.15 date 91.11.11.19.31.43; author mer; state Exp; branches; next 1.14; 1.14 date 90.09.26.18.00.16; author goh; state Exp; branches; next 1.13; 1.13 date 90.09.25.16.52.08; author kemnitz; state Exp; branches; next 1.12; 1.12 date 90.04.02.11.38.26; author hong; state Exp; branches; next 1.11; 1.11 date 90.02.12.19.51.00; author cimarron; state Exp; branches; next 1.10; 1.10 date 89.09.05.17.27.54; author mao; state C_Demo_1; branches; next 1.9; 1.9 date 89.07.14.21.18.16; author dillon; state Exp; branches; next 1.8; 1.8 date 89.07.14.18.12.32; author dillon; state Exp; branches; next 1.7; 1.7 date 89.07.14.18.09.47; author dillon; state Exp; branches; next 1.6; 1.6 date 89.07.14.17.48.11; author dillon; state Exp; branches; next 1.5; 1.5 date 89.06.17.01.53.27; author hirohama; state Exp; branches; next 1.4; 1.4 date 89.05.22.21.51.19; author dillon; state Exp; branches; next 1.3; 1.3 date 89.05.08.19.24.41; author dillon; state Exp; branches; next 1.2; 1.2 date 89.05.08.18.26.01; author hirohama; state Exp; branches; next 1.1; 1.1 date 89.05.05.16.13.52; author dillon; state Exp; branches; next ; desc @@ 1.15 log @prototyping changes @ text @ /* * TRACE.C * * System tracing routines */ #include /* XXX use own I/O routines */ #include /* XXX use own I/O routines */ #include "tmp/c.h" RcsId("$Header: /users/mer/postgres/src/utils/error/RCS/trace.c,v 1.14 1990/09/26 18:00:16 goh Exp $"); #include "tmp/simplelists.h" #include "utils/module.h" #include "utils/log.h" #include "utils/mcxt.h" #ifdef sprite #include "sprite_file.h" #include "sprite_file2.h" #else #include "storage/fd.h" #endif /* sprite */ typedef struct { char *Child; char *Parent1; char *Parent2; } TraceHier; /* * This array defines the parent heirarchy. Individual modules can * declare local trace variables with 'parents' such that turning the * trace on for the parent will turn the trace on for all its children. * * CHILD PARENT#1 PARENT#2 */ static TraceHier TraceTree[] = { "Root", NULL, NULL, "Memory", "Root", NULL, "Parser", "Root", NULL, "Planner", "Root", NULL, "Tcop", "Root", NULL, "Rules", "Root", NULL, "Storage", "Root", NULL, "Executor", "Root", NULL }; extern String getenv(); /* XXX style: use include */ static GlobalMemory TraceCxt; /* used for memory allocation */ static int TSDepth; /* how deep are we? */ static SLList TBList; /* list of known module trace blocks */ static SLList TSList; /* subroutine stack trace */ static FileNumber TraceFile; /* current trace file (fdcache) */ static char *DefaultTraceFile = "/dev/null"; extern char **environ; /* * TraceInitialize -- */ void TraceInitialize ARGS((TraceBlock *)); void WriteSpaces ARGS((File, int, int)); char *TailName ARGS((char *)); Pointer TraceAlloc ARGS((int)); void TraceFree ARGS((Pointer, int)); /* * Resource control */ static int NumEnabled; /* have we been initialized? .. count # of times */ void EnableTrace(enable) { static int fail; Assert(fail == 0); if (!enable && --NumEnabled) return; if (enable && NumEnabled++) return; ++fail; if (enable) { EnableFDCache(true); EnableMemoryContext(true); SLNewList(&TBList, offsetof(TraceBlock,Node)); SLNewList(&TSList, offsetof(TraceStack,Node)); TraceCxt = CreateGlobalMemory("Trace"); InitializeTheGlobalArray(); if (getenv("TRACEFILE")) DefaultTraceFile = getenv("TRACEFILE"); TraceFile = FileNameOpenFile(DefaultTraceFile,O_WRONLY|O_APPEND|O_CREAT,0666); Assert(TraceFile >= 0); { register char *ptr; register short i, j; char tracename[128]; for (i = 0; ptr = environ[i]; ++i) { uint32 traceLevel; if (strncmp(ptr, "TRACE_", 6) != 0) continue; strcpy(tracename, ptr + 6); for (j = 0; tracename[j] && tracename[j] != '='; ++j); tracename[j] = 0; traceLevel = atoi(tracename + j + 1); if (traceLevel == 0) traceLevel = 1; SetTraceLevel(tracename, traceLevel); } } } else { { register TraceBlock *tb; while (tb = (TraceBlock *)SLRemHead(&TBList)) { tb->Flags = 0; tb->Level = 0; } } DefaultTraceFile = "/dev/tty"; GlobalMemoryDestroy(TraceCxt); EnableFDCache(false); EnableMemoryContext(false); } --fail; } _TraceMsg(tb, level, nargs, arg0) TraceBlock *tb; int level, nargs; Pointer arg0; { Assert(NumEnabled); if ((tb->Flags & TBF_INITIALIZED) == 0) TraceInitialize(tb); if (level <= tb->Level) { Pointer *args = &arg0; char buf[1024]; int len; sprintf(buf, args[0], args[1], args[2], args[3], args[4], args[5]); len = strlen(buf); Assert(len < sizeof(buf)); buf[len++] = '\n'; switch(tb->Stream) { case DefaultStream: case LogStream: case InstallationStream: case DBStream: case ConsoleStream: case FrontendStream: case PostmasterStream: case AuxStream: FileWrite(TraceFile, buf, len); break; default: elog(WARN, "Unknown trace stream %s %d", tb->Name, tb->Stream); break; } } } /* * If not already initialized, initialize a trace block. */ void TraceInitialize(tb) TraceBlock *tb; { if (tb->Flags & TBF_INITIALIZED) return; Assert(NumEnabled); /* * Remove header and tailer spaces from Parent1 and Parent2 that might * have been stuck in by cpp. */ RemoveHeadTailSpaces(&tb->Parent1); RemoveHeadTailSpaces(&tb->Parent2); /* * Initial trace level determined by max of any parent's trace level. */ { uint32 l1 = TraceLevelByName(tb->Parent1); uint32 l2 = TraceLevelByName(tb->Parent2); tb->Level = Max(l1,l2); } /* * Trace level overriden by specific level already set for this name * (level for all matched names are the same) */ { register TraceBlock *t, *tnext; for (t = (TraceBlock *)SLGetHead(&TBList); t; t = tnext) { tnext = (TraceBlock *)SLGetSucc(&t->Node); if (strcmp(tb->Name, t->Name) == 0) { tb->Level = t->Level; break; } } } /* * Add trace block to TB list. */ SLNewNode(&tb->Node); SLAddTail(&TBList, &tb->Node); tb->Flags |= TBF_INITIALIZED; } RemoveHeadTailSpaces(str) char **str; { register char *ptr = *str; if (ptr) { while (*ptr == ' ' || *ptr == '\t') ++ptr; *str = ptr; while (*ptr && *ptr != ' ' && *ptr != '\t') ++ptr; *ptr = 0; } } InitializeTheGlobalArray() { register short i; for (i = 0; i < lengthof(TraceTree); ++i) { register TraceBlock *tb = (TraceBlock *)TraceAlloc(sizeof(TraceBlock)); bzero(tb, sizeof(TraceBlock)); tb->Name = TraceTree[i].Child; tb->Parent1 = TraceTree[i].Parent1; tb->Parent2 = TraceTree[i].Parent2; tb->Flags = TBF_INITIALIZED; SLNewNode(&tb->Node); SLAddTail(&TBList, &tb->Node); } } /* * TraceLevelByName() * * Return the trace level associated with the given trace variable * name. (0 if not found) */ static int TraceLevelByName(name) char *name; { register TraceBlock *tb; Assert(NumEnabled); if (name == NULL) return(0); for (tb = (TraceBlock *)SLGetHead(&TBList); tb; tb = (TraceBlock *)SLGetSucc(&tb->Node)) { if (strcmp(tb->Name, name) == 0) return(tb->Level); } return(0); } /* * SetChildrenOf() * * Subroutine used by SetTraceLevel() to search out the children of * a name and modify their level recursively. */ static void SetChildrenOf(Name, level) char *Name; { register TraceBlock *tb; Assert(NumEnabled); for (tb = (TraceBlock *)SLGetHead(&TBList); tb; tb = (TraceBlock *)SLGetSucc(&tb->Node)) { if (tb->Parent1 && strcmp(tb->Parent1, Name) == 0) { if (tb->Flags & TBF_FAULT) /* circular tree! */ Assert(0); tb->Level = level; tb->Flags |= TBF_FAULT; SetChildrenOf(tb->Name, level); tb->Flags &= ~TBF_FAULT; } if (tb->Parent2 && strcmp(tb->Parent2, Name) == 0) { if (tb->Flags & TBF_FAULT) /* circular tree! */ Assert(0); tb->Level = level; tb->Flags |= TBF_FAULT; SetChildrenOf(tb->Name, level); tb->Flags &= ~TBF_FAULT; } } } /* * SetTraceLevel() * * Modify the current trace level for the given trace variable. 0 turns * off the trace. The level for all children is recursively set to * this value too. * * Note that more than one traceblock with the same name may exist. */ void SetTraceLevel(traceName, level) char *traceName; int level; { short found = 0; Assert(NumEnabled); /* * Step (1), search list and update any matches. */ { register TraceBlock *tb; for (tb = (TraceBlock *)SLGetHead(&TBList); tb; tb = (TraceBlock *)SLGetSucc(&tb->Node)) { if (strcmp(traceName, tb->Name) == 0) { tb->Level = level; found = 1; } } } /* * Step (2), update children of this trace name, if any (recur) */ SetChildrenOf(traceName, level); /* * Step (3), if name was not in block list, add to block list. */ if (found == 0) { register TraceBlock *tb = (TraceBlock *)TraceAlloc(sizeof(*tb)); char *ptr = TraceAlloc(strlen(traceName)+1); SLNewNode(&tb->Node); strcpy(ptr, traceName); tb->Name = ptr; tb->Flags = TBF_INITIALIZED; tb->Level = level; SLAddHead(&TBList, &tb->Node); } } /* * Change the TraceFile messages are sent to. On failure, the old trace * file continues to be used. */ bool TraceFileName(fileName) char *fileName; { FileNumber newfile; char buf[256]; newfile = FileNameOpenFile(fileName,O_WRONLY|O_APPEND|O_CREAT,0666); if (newfile < 0) { sprintf(buf, "Unable to open new trace file %s\n", fileName); FileWrite(TraceFile, buf, strlen(buf)); return(false); } FileClose(TraceFile); TraceFile = newfile; return(true); } /* * Subroutine Call/Return tracing */ void _TracePush(tb, lineno, str) TraceBlock *tb; int lineno; char *str; { register TraceStack *ts; Assert(NumEnabled); if ((tb->Flags & TBF_INITIALIZED) == 0) TraceInitialize(tb); ts = (TraceStack *)TraceAlloc(sizeof(*ts)); ts->Tb = tb; ts->LineNo = lineno; ts->Text = str; SLNewNode(&ts->Node); SLAddTail(&TSList, &ts->Node); ++TSDepth; if (tb->Level) { char buf[256]; WriteSpaces(TraceFile, TSDepth, '#'); sprintf(buf, "BEGIN %s.%d %s\n", TailName(tb->Module), lineno, str); FileWrite(TraceFile, buf, strlen(buf)); } } void _TracePop(tb, lineno, str) TraceBlock *tb; int lineno; char *str; { register TraceStack *ts = (TraceStack *)SLGetTail(&TSList); Assert(PointerIsValid(ts)); Assert(ts->Tb == tb); SLRemove(&ts->Node); TraceFree((Pointer)ts, sizeof(*ts)); if (str[0] == '\0') str = ts->Text; if (tb->Level) { char buf[256]; WriteSpaces(TraceFile, TSDepth, '#'); sprintf(buf, "END %s.%d %s\n", TailName(tb->Module), lineno, str); FileWrite(TraceFile, buf, strlen(buf)); } --TSDepth; } void _TraceReset(tb, lineno, str) TraceBlock *tb; int lineno; char *str; { } /* * Called by exception handler */ void _TraceDump() { TraceStack *ts; char buf[256]; static int ReEntered = 0; if (NumEnabled <= 0) return; if (ReEntered) exitpg(1234); ++ReEntered; sprintf(buf, "\nTRACE STACK DUMP\n"); FileWrite(TraceFile, buf, strlen(buf)); for (ts = (TraceStack *)SLGetHead(&TSList); PointerIsValid(ts); ts = (TraceStack *)SLGetSucc(&ts->Node)) { sprintf(buf, "%15s.%-4d\t%s\n", ts->Tb->Module, ts->LineNo, ts->Text); FileWrite(TraceFile, buf, strlen(buf)); } sprintf(buf, "\nTRACE STACK END\n"); FileWrite(TraceFile, buf, strlen(buf)); --ReEntered; } static void WriteSpaces(file, n, firstchar) FileNumber file; int n; int firstchar; { char buf[256]; int i; ++n; for (i = 0; i < n && i < sizeof(buf); ++i) buf[i] = ' '; buf[0] = '#'; while (n > sizeof(buf)) { FileWrite(file, buf, n); buf[0] = ' '; n -= sizeof(buf); } FileWrite(file, buf, n); } char * TailName(str) char *str; { char *ptr = str + strlen(str); while (ptr >= str && *ptr != '/') --ptr; return(ptr + 1); } /* * ALLOCATION AND FREEING OF MEMORY * * Allocations smaller than 32 longwords are tabled for fast access. * (that is, TraceFree() calls table the pointer instead of freeing it) */ static char **AllocArray[32]; Pointer TraceAlloc(bytes) { int longwords; char **res; if (bytes < sizeof(char *)) bytes = sizeof(char *); longwords = (bytes + 3) >> 2; /* # of longwords to allocate */ if (longwords >= lengthof(AllocArray) || AllocArray[longwords] == NULL) { return(MemoryContextAlloc((MemoryContext)TraceCxt, longwords << 2)); } res = AllocArray[longwords]; AllocArray[longwords] = (char **)res[0]; return((Pointer)res); } void TraceFree(ptr, bytes) Pointer ptr; int bytes; { int longwords; if (bytes < sizeof(char *)) bytes = sizeof(char *); longwords = (bytes + 3) >> 2; /* # of longwords to free */ if (longwords >= lengthof(AllocArray)) { MemoryContextFree((MemoryContext)TraceCxt, ptr); return; } *(char **)ptr = (char *)AllocArray[longwords]; AllocArray[longwords] = (char **)ptr; } @ 1.14 log @changed the condition we are checking against. I am not convinced this is the right fix, but since no documentation exists as to the purpose of this code, I think this may fix the problem of tracedump ignoring the trace-enabled flag @ text @d13 1 a13 1 RcsId("$Header: RCS/trace.c,v 1.15 90/08/22 15:30:35 choi Exp $"); a112 1 void SetTraceLevel(); @ 1.13 log @Updating from revision 1.12 to revision 1.15 @ text @d489 1 a489 1 if (NumEnabled == 0) @ 1.12 log @minor changes for striping relations, but should not affect others. @ text @a7 5 #include "c.h" #include "log.h" RcsId("$Header: RCS/trace.c,v 1.11 90/02/12 19:51:00 cimarron Exp Locker: hong $"); d11 1 a11 3 #include "simplelists.h" #include "fd.h" #include "mcxt.h" d13 13 a25 1 #include "trace.h" @ 1.11 log @added buffer manager statistics and exitpg() stuff -cim @ text @d11 1 a11 1 RcsId("$Header: RCS/trace.c,v 1.10 89/09/05 17:27:54 mao C_Demo_1 $"); d55 1 a55 1 static File TraceFile; /* current trace file (fdcache) */ d393 1 a393 1 File newfile; d507 1 a507 1 File file; @ 1.10 log @Working version of C-only demo @ text @d11 1 a11 1 RcsId("$Header: /usr6/postgres/mao/postgres/src/utils/error/RCS/trace.c,v 1.9 89/07/14 21:18:16 dillon Exp $"); d487 1 a487 1 _exit(1234); @ 1.9 log @compile warning fixed, return near line 400 @ text @d11 1 a11 1 RcsId("$Header: /usr6/postgres/dillon/tree/src/utils/error/RCS/trace.c,v 1.8 89/07/14 18:12:32 dillon Exp $"); @ 1.8 log @CloseFile -> FileClose @ text @d11 1 a11 1 RcsId("$Header: /usr6/postgres/dillon/tree/src/utils/error/RCS/trace.c,v 1.7 89/07/14 18:09:47 dillon Exp $"); d400 1 a400 1 return(0); d404 1 a404 1 return(1); @ 1.7 log @*** empty log message *** @ text @d11 1 a11 1 RcsId("$Header: /usr6/postgres/dillon/tree/src/utils/error/RCS/trace.c,v 1.6 89/07/14 17:48:11 dillon Exp $"); d402 1 a402 1 CloseFile(TraceFile); @ 1.6 log @added subroutine tracing and display capability @ text @d11 1 a11 1 RcsId("$Header: trace.c,v 1.5 89/06/17 01:53:27 dillon Locked $"); d56 1 a56 1 static char *DefaultTraceFile = "/dev/tty"; d393 12 a404 1 ; @ 1.5 log @*** empty log message *** @ text @d11 1 a11 1 RcsId("$Header: /usr6/postgres/hirohama/postgres/src/utils/error/RCS/trace.c,v 1.4 89/05/22 21:51:19 dillon Exp $"); a46 4 #define TraceAlloc(bytes) \ MemoryContextAlloc((MemoryContext)TraceCxt,bytes) #define TraceFree(ptr) \ MemoryContextFree((MemoryContext)TraceCxt,(Pointer)ptr) d52 1 d54 1 a62 5 extern void TraceInitialize ARGS(( TraceBlock *tb; )); d64 6 d74 2 a78 1 static int numEnabled; d83 1 a83 1 if (!enable && --numEnabled) d85 1 a85 1 if (enable && numEnabled++) d94 1 d143 1 d184 2 d275 1 d300 2 d342 2 d395 174 @ 1.4 log @First working version @ text @d11 1 a11 1 RcsId("$Header: trace.c,v 1.3 89/05/08 19:24:41 dillon Locked $"); a15 1 #include "context.h" @ 1.3 log @*** empty log message *** @ text @d1 1 d5 1 a5 1 * d9 1 d11 1 a11 1 RcsId("$Header: /usr6/postgres/dillon/tree/src/utils/error/RCS/trace.c,v 1.2 89/05/08 18:26:01 hirohama Exp $"); d19 1 a22 2 extern String getenv(); /* XXX style: use include */ d24 4 a27 4 SLNode Node; char *Name; long Flags; } NN; d29 7 a35 1 typedef NN NameNode; d37 10 d48 11 a58 4 static SLList NameList; static SLList TBList; static struct context *TraceCxt = NULL; static File TraceFile; d76 2 a77 1 EnableTrace(initialInit) d79 2 a80 15 if (initialInit == 0) { register TraceBlock *tb, *tbn; for (tb = (TraceBlock *)SLGetHead(&TBList); tb; tb = tbn) { tbn = (TraceBlock *)SLGetSucc(tb); SLRemove(&tb->Node); tb->Flags = 0; } } if (initialInit == 0) { register NN *nn, *nnext; for (nn = (NN *)SLGetHead(&NameList); nn; nn = nnext) { nnext = (NN *)SLGetSucc(nn); SLRemove(&nn->Node); } } d82 1 a82 3 /* * Initialize trace lists */ d84 4 a87 2 SLNewList(&NameList, offsetof(NN,Node)); SLNewList(&TBList, offsetof(TraceBlock,Node)); d89 4 a92 9 /* * Initialize memory context */ { struct context *oldCxt; oldCxt = newnamedcontext("Trace"); TraceCxt = Curcxt; switchcontext(oldCxt); } d94 3 a96 4 /* * Initialize Trace File */ { d102 4 a105 1 } d107 17 a123 3 /* * Enable/Disable trace variables according to enviroment */ d125 9 a133 13 { register char *ptr; register short i, j; char tracename[128]; for (i = 0; ptr = environ[i]; ++i) { if (strncmp(ptr, "TRACE_", 6) == 0) { strcpy(tracename, ptr + 6); for (j = 6; tracename[j] && tracename[j] != '='; ++j); tracename[j] = 0; SetTraceOn(tracename + 6, atoi(tracename + j + 1)); } } d135 1 a137 1 d145 1 a145 1 if ((tb->Flags & TBF_ENABLED) && level <= tb->Level) { d154 16 a169 2 FileWrite(TraceFile, buf, len); } d172 4 d180 15 d196 18 a213 6 register NameNode *nn, *nnext; for (nn = (NN *)SetGetHead(&NameList); nn; nn = nnext) { nnext = (NN *)SetGetSucc(nn); if (strcmp(tb->Name, nn->Name) == 0) { SetRemove(&nn->Node); /* XXX is this right? nn is referenced below */ tb->Flags = (tb->OrigFlags & ~TBF_ENABLED) | nn->Flags; d217 7 a223 2 SetInitNode(&tb->Node); SetAddTail(&TBList, &tb->Node); d227 31 d259 4 a262 4 * Turn on and off tracing. If the trace name exists more than once, * all copies are enabled. If the trace name does not exist, the name * is placed on a special list so when it comes into existance it will * be turned on or off appropriately. d265 4 a268 4 void TraceNameOn(traceName, level) char *traceName; int level; d270 11 d283 45 d329 1 a329 1 TraceNameOff(traceName) d331 1 d333 41 d385 1 a385 1 @ 1.2 log @fixes to make it compile--I haven't tested this. Be careful! @ text @d9 1 a9 1 RcsId("$Header: trace.c,v 1.1 89/05/05 16:13:52 hirohama Locked $"); a29 1 RcsId("$Header: trace.c,v 1.1 89/05/05 16:13:52 dillon Locked $"); @ 1.1 log @Initial revision @ text @a0 1 d7 4 d12 4 a15 3 #include "c.h" #include "trace.h" #include "mmgr.h" d18 4 d23 1 a23 1 SetNode Node; d28 1 a28 1 RcsId("$Header: /usr6/postgres/dillon/stree/src/utils/error/RCS/ctrace.c,v 1.3 89/05/05 16:13:18 dillon Exp $"); d30 2 d41 9 d53 1 a53 1 EnableTrace(initialiInit) d75 2 a76 2 SLNewList(&NameList, offsetof(NameNode,Node)); SLNewList(&TBList, offsetob(TraceBlock,Node)); d149 1 a149 1 SetRemove(&namenode->Node); @