1 /*-------------------------------------------------------------------------
4 * POSTGRES C Backend Interface
6 * Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.61 1998/01/13 04:04:36 scrappy Exp $
13 * this is the "main" module of the postgres backend and
14 * hence the main module of the "traffic cop".
16 *-------------------------------------------------------------------------
26 #include <sys/types.h>
28 #include <sys/param.h> /* for MAXHOSTNAMELEN on most */
29 #ifndef MAXHOSTNAMELEN
30 #include <netdb.h> /* for MAXHOSTNAMELEN on some */
32 #ifndef MAXHOSTNAMELEN /* for MAXHOSTNAMELEN under sco3.2v5.0.2 */
33 #include <sys/socket.h>
37 #include <sys/select.h>
42 #include "miscadmin.h"
45 #include "access/xact.h"
46 #include "catalog/catname.h"
47 #include "commands/async.h"
48 #include "executor/execdebug.h"
49 #include "executor/executor.h"
50 #include "lib/dllist.h"
51 #include "libpq/libpq.h"
52 #include "libpq/pqsignal.h"
53 #include "nodes/pg_list.h"
54 #include "nodes/print.h"
55 #include "optimizer/cost.h"
56 #include "optimizer/planner.h"
57 #include "optimizer/prep.h"
58 #include "parser/parser.h"
59 #include "rewrite/rewriteHandler.h" /* for QueryRewrite() */
60 #include "storage/bufmgr.h"
61 #include "tcop/dest.h"
62 #include "tcop/fastpath.h"
63 #include "tcop/pquery.h"
64 #include "tcop/tcopdebug.h"
65 #include "tcop/tcopprot.h" /* where declarations for this file go */
66 #include "tcop/utility.h"
67 #include "utils/mcxt.h"
68 #include "utils/rel.h"
71 #include "nodes/relation.h"
75 #include "optimizer/xfunc.h"
79 #include "nodes/plannodes.h"
83 #include "nodes/memnodes.h"
86 static void quickdie(SIGNAL_ARGS);
92 static bool DebugPrintQuery = false;
93 static bool DebugPrintPlan = false;
94 static bool DebugPrintParse = false;
95 static bool DebugPrintRewrittenParsetree = false;
97 /*static bool EnableRewrite = true; , never changes why have it*/
98 CommandDest whereToSendOutput;
100 #ifdef LOCK_MGR_DEBUG
101 extern int lockDebug;
104 extern int lockingOff;
108 static int ShowStats;
109 static bool IsEmptyQuery = false;
111 char relname[80]; /* current relation name */
113 #if defined(nextstep)
114 jmp_buf Warn_restart;
116 #define sigsetjmp(x,y) setjmp(x)
117 #define siglongjmp longjmp
119 sigjmp_buf Warn_restart;
121 #endif /* defined(nextstep) */
126 static int EchoQuery = 0; /* default don't echo */
128 char pg_pathname[256];
129 static int ShowParserStats;
130 static int ShowPlannerStats;
131 int ShowExecutorStats;
134 typedef struct frontend
138 FILE *fn_Pfin; /* the input fd */
139 FILE *fn_Pfout; /* the output fd */
140 bool fn_done; /* set after the frontend closes its
144 static Dllist *frontendList;
147 * people who want to use EOF should #define DONTUSENEWLINE in
151 #ifndef TCOP_DONTUSENEWLINE
152 int UseNewLine = 1; /* Use newlines query delimiters (the
156 int UseNewLine = 0; /* Use EOF as query delimiters */
158 #endif /* TCOP_DONTUSENEWLINE */
161 * bushy tree plan flag: if true planner will generate bushy-tree
165 int BushyPlanFlag = 0; /* default to false -- consider only
169 ** Flags for expensive function optimization -- JMH 3/9/92
175 * Note: _exec_repeat_ defaults to 1 but may be changed
176 * by a DEBUG command. If you set this to a large
177 * number N, run a single query, and then set it
178 * back to 1 and run N queries, you can get an idea
179 * of how much time is being spent in the parser and
180 * planner b/c in the first case this overhead only
181 * happens once. -cim 6/9/91
184 int _exec_repeat_ = 1;
186 /* ----------------------------------------------------------------
187 * decls for routines only used in this file
188 * ----------------------------------------------------------------
190 static char InteractiveBackend(char *inBuf);
191 static char SocketBackend(char *inBuf, bool multiplexedBackend);
192 static char ReadCommand(char *inBuf, bool multiplexedBackend);
195 /* ----------------------------------------------------------------
196 * routines to obtain user input
197 * ----------------------------------------------------------------
201 * InteractiveBackend() is called for user interactive connections
202 * the string entered by the user is placed in its parameter inBuf.
207 InteractiveBackend(char *inBuf)
209 char *stuff = inBuf; /* current place in input buffer */
210 int c; /* character read from getc() */
211 bool end = false; /* end-of-input flag */
212 bool backslashSeen = false; /* have we seen a \ ? */
215 * display a prompt and obtain input from the user
225 * if we are using \n as a delimiter, then read
226 * characters until the \n.
229 while ((c = getc(stdin)) != EOF)
240 /* keep the newline character */
247 backslashSeen = true;
249 backslashSeen = false;
260 * otherwise read characters until EOF.
263 while ((c = getc(stdin)) != EOF)
279 * otherwise we have a user query so process it.
286 * if the query echo flag was given, print the query..
290 printf("query is: %s\n", inBuf);
296 * SocketBackend() Is called for frontend-backend connections
298 * If the input is a query (case 'Q') then the string entered by
299 * the user is placed in its parameter inBuf.
301 * If the input is a fastpath function call (case 'F') then
302 * the function call is processed in HandleFunctionRequest().
303 * (now called from PostgresMain())
308 SocketBackend(char *inBuf, bool multiplexedBackend)
314 * get input from the frontend
318 if (pq_getnchar(qtype, 0, 1) == EOF)
321 * when front-end applications quits/dies
324 if (multiplexedBackend)
335 * 'Q': user entered a query
339 pq_getstr(inBuf, MAX_PARSE_BUFFER);
344 * 'F': calling user/system functions
348 pq_getstr(inBuf, MAX_PARSE_BUFFER); /* ignore the rest of the
354 * 'X': frontend is exiting
362 * otherwise we got garbage from the frontend.
364 * XXX are we certain that we want to do an elog(FATAL) here?
369 elog(FATAL, "Socket command type %c unknown\n", *qtype);
376 * ReadCommand reads a command from either the frontend or
377 * standard input, places it in inBuf, and returns a char
378 * representing whether the string is a 'Q'uery or a 'F'astpath
383 ReadCommand(char *inBuf, bool multiplexedBackend)
385 if (IsUnderPostmaster || multiplexedBackend)
386 return SocketBackend(inBuf, multiplexedBackend);
388 return InteractiveBackend(inBuf);
392 pg_parse_and_plan(char *query_string, /* string to execute */
393 Oid *typev, /* argument types */
394 int nargs, /* number of arguments */
395 QueryTreeList **queryListP, /* pointer to the parse trees */
396 CommandDest dest) /* where results should go */
398 QueryTreeList *querytree_list;
400 List *plan_list = NIL;
403 QueryTreeList *new_list;
404 List *rewritten = NIL;
408 * (1) parse the request string into a list of parse trees
414 querytree_list = parser(query_string, typev, nargs);
418 fprintf(stderr, "! Parser Stats:\n");
422 /* new_list holds the rewritten queries */
423 new_list = (QueryTreeList *) malloc(sizeof(QueryTreeList));
424 new_list->len = querytree_list->len;
425 new_list->qtrees = (Query **) malloc(new_list->len * sizeof(Query *));
428 * (2) rewrite the queries, as necessary
431 j = 0; /* counter for the new_list, new_list can
432 * be longer than old list as a result of
434 for (i = 0; i < querytree_list->len; i++)
436 List *union_result, *union_list, *rewritten_list;
438 querytree = querytree_list->qtrees[i];
441 /* don't rewrite utilites */
442 if (querytree->commandType == CMD_UTILITY)
444 new_list->qtrees[j++] = querytree;
448 if (DebugPrintQuery == true)
450 printf("\n---- \tquery is:\n%s\n", query_string);
455 if (DebugPrintParse == true)
457 printf("\n---- \tparser outputs :\n");
458 nodeDisplay(querytree);
462 /* rewrite queries (retrieve, append, delete, replace) */
463 rewritten = QueryRewrite(querytree);
466 * Rewrite the UNIONS.
468 foreach(rewritten_list, rewritten)
470 Query *qry = (Query *)lfirst(rewritten_list);
472 foreach(union_list, qry->unionClause)
473 union_result = nconc(union_result, QueryRewrite((Query *)lfirst(union_list)));
474 qry->unionClause = union_result;
477 if (rewritten != NULL)
482 len = length(rewritten);
484 new_list->qtrees[j++] = (Query *) lfirst(rewritten);
487 /* rewritten queries are longer than original query */
488 /* grow the new_list to accommodate */
489 new_list->len += len - 1; /* - 1 because originally
490 * we allocated one space
492 new_list->qtrees = realloc(new_list->qtrees,
493 new_list->len * sizeof(Query *));
494 for (k = 0; k < len; k++)
495 new_list->qtrees[j++] = (Query *) nth(k, rewritten);
500 /* we're done with the original lists, free it */
501 free(querytree_list->qtrees);
502 free(querytree_list);
504 querytree_list = new_list;
506 if (DebugPrintRewrittenParsetree == true)
508 printf("\n---- \tafter rewriting:\n");
510 for (i = 0; i < querytree_list->len; i++)
512 print(querytree_list->qtrees[i]);
517 for (i = 0; i < querytree_list->len; i++)
519 querytree = querytree_list->qtrees[i];
522 * For each query that isn't a utility invocation, generate a
526 if (querytree->commandType != CMD_UTILITY)
529 if (IsAbortedTransactionBlockState())
532 * the EndCommand() stuff is to tell the frontend
533 * that the command ended. -cim 6/1/90
536 char *tag = "*ABORT STATE*";
538 EndCommand(tag, dest);
540 elog(NOTICE, "(transaction aborted): %s",
541 "queries ignored until END");
543 *queryListP = (QueryTreeList *) NULL;
544 return (List *) NULL;
547 if (ShowPlannerStats)
550 /* call that optimizer */
551 plan = planner(querytree);
553 if (ShowPlannerStats)
555 fprintf(stderr, "! Planner Stats:\n");
558 plan_list = lappend(plan_list, plan);
559 #ifdef INDEXSCAN_PATCH
561 * Print plan if debugging.
562 * This has been moved here to get debugging output
563 * also for queries in functions. DZ - 27-8-1996
566 if (DebugPrintPlan == true)
568 printf("\n---- \tplan is :\n");
574 #ifdef FUNC_UTIL_PATCH
577 * If the command is an utility append a null plan. This is needed
578 * to keep the plan_list aligned with the querytree_list or the
579 * function executor will crash. DZ - 30-8-1996
583 plan_list = lappend(plan_list, NULL);
589 *queryListP = querytree_list;
594 /* ----------------------------------------------------------------
597 * Takes a querystring, runs the parser/utilities or
598 * parser/planner/executor over it as necessary
599 * Begin Transaction Should have been called before this
600 * and CommitTransaction After this is called
601 * This is strictly because we do not allow for nested xactions.
603 * NON-OBVIOUS-RESTRICTIONS
604 * this function _MUST_ allocate a new "parsetree" each time,
605 * since it may be stored in a named portal and should not
608 * ----------------------------------------------------------------
612 pg_exec_query(char *query_string, char **argv, Oid *typev, int nargs)
614 pg_exec_query_dest(query_string, argv, typev, nargs, whereToSendOutput);
618 pg_exec_query_dest(char *query_string,/* string to execute */
619 char **argv, /* arguments */
620 Oid *typev, /* argument types */
621 int nargs, /* number of arguments */
622 CommandDest dest) /* where results should go */
629 QueryTreeList *querytree_list;
631 /* plan the queries */
632 plan_list = pg_parse_and_plan(query_string, typev, nargs, &querytree_list, dest);
634 /* pg_parse_and_plan could have failed */
635 if (querytree_list == NULL)
638 for (i = 0; i < querytree_list->len; i++)
640 querytree = querytree_list->qtrees[i];
642 #ifdef FUNC_UTIL_PATCH
645 * Advance on the plan_list in every case. Now the plan_list has
646 * the same length of the querytree_list. DZ - 30-8-1996
648 plan = (Plan *) lfirst(plan_list);
649 plan_list = lnext(plan_list);
651 if (querytree->commandType == CMD_UTILITY)
654 * process utility functions (create, destroy, etc..)
656 * Note: we do not check for the transaction aborted state
657 * because that is done in ProcessUtility.
663 printf("\tProcessUtility() at %s\n", ctime(&tim));
666 ProcessUtility(querytree->utilityStmt, dest);
671 #ifndef FUNC_UTIL_PATCH
674 * Moved before the if. DZ - 30-8-1996
676 plan = (Plan *) lfirst(plan_list);
677 plan_list = lnext(plan_list);
680 #ifdef INDEXSCAN_PATCH
683 * Print moved in pg_parse_and_plan. DZ - 27-8-1996
687 * print plan if debugging
690 if (DebugPrintPlan == true)
692 printf("\n---- plan is :\n");
702 if (ShowExecutorStats)
705 for (j = 0; j < _exec_repeat_; j++)
710 printf("\tProcessQuery() at %s\n", ctime(&tim));
712 ProcessQuery(querytree, plan, argv, typev, nargs, dest);
715 if (ShowExecutorStats)
717 fprintf(stderr, "! Executor Stats:\n");
723 * In a query block, we want to increment the command counter
724 * between queries so that the effects of early queries are
725 * visible to subsequent ones.
729 CommandCounterIncrement();
732 free(querytree_list->qtrees);
733 free(querytree_list);
736 /* --------------------------------
737 * signal handler routines used in PostgresMain()
739 * handle_warn() is used to catch kill(getpid(),1) which
740 * occurs when elog(ERROR) is called.
742 * quickdie() occurs when signalled by the postmaster.
743 * Some backend has bought the farm,
744 * so we need to stop what we're doing and exit.
746 * die() preforms an orderly cleanup via ExitPostgres()
747 * --------------------------------
751 handle_warn(SIGNAL_ARGS)
753 siglongjmp(Warn_restart, 1);
757 quickdie(SIGNAL_ARGS)
759 elog(NOTICE, "Message from PostgreSQL backend:"
760 "\n\tThe Postmaster has informed me that some other backend"
761 " died abnormally and possibly corrupted shared memory."
762 "\n\tI have rolled back the current transaction and am"
763 " going to terminate your database system connection and exit."
764 "\n\tPlease reconnect to the database system and repeat your query.");
768 * DO NOT ExitPostgres(0) -- we're here because shared memory may be
769 * corrupted, so we don't want to flush any shared state to stable
770 * storage. Just nail the windows shut and get out of town.
782 /* signal handler for floating point exception */
784 FloatExceptionHandler(SIGNAL_ARGS)
786 elog(ERROR, "floating point exception!"
787 " The last floating point operation either exceeded legal ranges"
788 " or was a divide by zero");
793 usage(char *progname)
796 "Usage: %s [-B nbufs] [-d lvl] ] [-f plantype] \t[-m portno] [\t -o filename]\n",
798 fprintf(stderr, "\t[-P portno] [-t tracetype] [-x opttype] [-bCEiLFNopQSs] [dbname]\n");
799 fprintf(stderr, " b: consider bushy plan trees during optimization\n");
800 fprintf(stderr, " B: set number of buffers in buffer pool\n");
801 fprintf(stderr, " C: supress version info\n");
802 fprintf(stderr, " d: set debug level\n");
803 fprintf(stderr, " E: echo query before execution\n");
804 fprintf(stderr, " e turn on European date format\n");
805 fprintf(stderr, " F: turn off fsync\n");
806 fprintf(stderr, " f: forbid plantype generation\n");
807 fprintf(stderr, " i: don't execute the query, just show the plan tree\n");
808 #ifdef LOCK_MGR_DEBUG
809 fprintf(stderr, " K: set locking debug level [0|1|2]\n");
811 fprintf(stderr, " L: turn off locking\n");
812 fprintf(stderr, " m: set up a listening backend at portno to support multiple front-ends\n");
813 fprintf(stderr, " M: start as postmaster\n");
814 fprintf(stderr, " N: don't use newline as query delimiter\n");
815 fprintf(stderr, " o: send stdout and stderr to given filename \n");
816 fprintf(stderr, " p: backend started by postmaster\n");
817 fprintf(stderr, " P: set port file descriptor\n");
818 fprintf(stderr, " Q: suppress informational messages\n");
819 fprintf(stderr, " S: set amount of sort memory available\n");
820 fprintf(stderr, " s: show stats after each query\n");
821 fprintf(stderr, " t: trace component execution times\n");
822 fprintf(stderr, " T: execute all possible plans for each query\n");
823 fprintf(stderr, " x: control expensive function optimization\n");
826 /* ----------------------------------------------------------------
829 * all backends, interactive or otherwise start here
830 * ----------------------------------------------------------------
833 PostgresMain(int argc, char *argv[])
845 char parser_input[MAX_PARSE_BUFFER];
848 bool multiplexedBackend;
849 char *hostName; /* the host name of the backend server */
851 int serverPortnum = 0;
852 int nSelected; /* number of descriptors ready from
854 int maxFd = 0; /* max file descriptor + 1 */
859 int numFE = 0; /* keep track of number of active
869 extern short DebugLvl;
872 * register signal handlers.
875 pqsignal(SIGINT, die);
877 pqsignal(SIGHUP, die);
878 pqsignal(SIGTERM, die);
879 pqsignal(SIGPIPE, die);
880 pqsignal(SIGUSR1, quickdie);
881 pqsignal(SIGUSR2, Async_NotifyHandler);
882 pqsignal(SIGFPE, FloatExceptionHandler);
884 /* --------------------
886 * -------------------
889 MasterPid = getpid();
892 * parse command line arguments
897 * Set default values.
899 flagC = flagQ = flagE = flagEu = ShowStats = 0;
900 ShowParserStats = ShowPlannerStats = ShowExecutorStats = 0;
901 #ifdef LOCK_MGR_DEBUG
906 * get hostname is either the environment variable PGHOST or NULL
907 * NULL means Unix-socket only
909 hostName = getenv("PGHOST");
910 DataDir = getenv("PGDATA");
912 * Try to get initial values for date styles and formats.
913 * Does not do a complete job, but should be good enough for backend.
914 * Cannot call parse_date() since palloc/pfree memory is not set up yet.
916 DBDate = getenv("PGDATESTYLE");
919 if (strcasecmp(DBDate, "ISO") == 0)
920 DateStyle = USE_ISO_DATES;
921 else if (strcasecmp(DBDate, "SQL") == 0)
922 DateStyle = USE_SQL_DATES;
923 else if (strcasecmp(DBDate, "POSTGRES") == 0)
924 DateStyle = USE_POSTGRES_DATES;
925 else if (strcasecmp(DBDate, "GERMAN") == 0)
927 DateStyle = USE_GERMAN_DATES;
931 if (strcasecmp(DBDate, "NONEURO") == 0)
933 else if (strcasecmp(DBDate, "EURO") == 0)
936 multiplexedBackend = false;
938 while ((flag = getopt(argc, argv, "B:bCD:d:Eef:iK:Lm:MNo:P:pQS:st:x:F"))
945 * set BushyPlanFlag to true.
952 * specify the size of buffer pool
955 NBuffers = atoi(optarg);
960 * don't print version string (don't know why this is 'C' --mao)
966 case 'D': /* PGDATA directory */
969 case 'd': /* debug level */
971 DebugLvl = (short) atoi(optarg);
973 DebugPrintQuery = true;
976 DebugPrintParse = true;
977 DebugPrintPlan = true;
978 DebugPrintRewrittenParsetree = true;
984 * E - echo the query the user entered
991 /* --------------------------
992 * Use european date formats.
993 * --------------------------
999 /* --------------------
1001 * --------------------
1007 /* -----------------
1008 * f - forbid generation of certain plans
1013 case 's': /* seqscan */
1014 _enable_seqscan_ = false;
1016 case 'i': /* indexscan */
1017 _enable_indexscan_ = false;
1019 case 'n': /* nestloop */
1020 _enable_nestloop_ = false;
1022 case 'm': /* mergejoin */
1023 _enable_mergesort_ = false;
1025 case 'h': /* hashjoin */
1026 _enable_hashjoin_ = false;
1038 #ifdef LOCK_MGR_DEBUG
1039 lockDebug = atoi(optarg);
1041 fprintf(stderr, "Lock debug not compiled in\n");
1046 /* --------------------
1048 * --------------------
1056 * start up a listening backend that can respond to
1057 * multiple front-ends. (Note: all the front-end
1058 * connections are still connected to a single-threaded
1059 * backend. Requests are FCFS. Everything is in one
1062 multiplexedBackend = true;
1063 serverPortnum = atoi(optarg);
1066 exit(PostmasterMain(argc, argv));
1070 * N - Don't use newline as a query delimiter
1078 * o - send output (stdout and stderr) to the given file
1081 StrNCpy(OutputFileName, optarg, MAXPGPATH);
1084 case 'p': /* started by postmaster */
1086 * p - special flag passed if backend was forked
1090 IsUnderPostmaster = true;
1095 * P - Use the passed file descriptor number as the port
1096 * on which to communicate with the user. This is ONLY
1097 * useful for debugging when fired up by the postmaster.
1100 Portfd = atoi(optarg);
1105 * Q - set Quiet mode (reduce debugging output)
1113 * S - amount of sort memory to use in 1k bytes
1120 if ( S >= 4*BLCKSZ/1024 )
1127 * s - report usage statistics (timings) after each query
1136 * tell postgres to report usage statistics (timings) for
1139 * -tpa[rser] = print stats for parser time of each query
1140 * -tpl[anner] = print stats for planner time of each query
1141 * -te[xecutor] = print stats for executor time of each query
1142 * caution: -s can not be used together with -t.
1149 if (optarg[1] == 'a')
1150 ShowParserStats = 1;
1151 else if (optarg[1] == 'l')
1152 ShowPlannerStats = 1;
1157 ShowExecutorStats = 1;
1166 #if 0 /* planner/xfunc.h */
1169 * control joey hellerstein's expensive function
1174 fprintf(stderr, "only one -x flag is allowed\n");
1178 if (strcmp(optarg, "off") == 0)
1179 XfuncMode = XFUNC_OFF;
1180 else if (strcmp(optarg, "nor") == 0)
1181 XfuncMode = XFUNC_NOR;
1182 else if (strcmp(optarg, "nopull") == 0)
1183 XfuncMode = XFUNC_NOPULL;
1184 else if (strcmp(optarg, "nopm") == 0)
1185 XfuncMode = XFUNC_NOPM;
1186 else if (strcmp(optarg, "pullall") == 0)
1187 XfuncMode = XFUNC_PULLALL;
1188 else if (strcmp(optarg, "wait") == 0)
1189 XfuncMode = XFUNC_WAIT;
1192 fprintf(stderr, "use -x {off,nor,nopull,nopm,pullall,wait}\n");
1200 * default: bad command line option
1207 * get user name and pathname and check command line validity
1211 userName = GetPgUserName();
1213 if (FindBackend(pg_pathname, argv[0]) < 0)
1214 elog(FATAL, "%s: could not locate executable, bailing out...",
1217 if (errs || argc - optind > 1)
1222 else if (argc - optind == 1)
1224 DBName = argv[optind];
1226 else if ((DBName = userName) == NULL)
1228 fprintf(stderr, "%s: USER undefined and no database specified\n",
1234 (ShowParserStats || ShowPlannerStats || ShowExecutorStats))
1236 fprintf(stderr, "-s can not be used together with -t.\n");
1242 fprintf(stderr, "%s does not know where to find the database system "
1243 "data. You must specify the directory that contains the "
1244 "database system either by specifying the -D invocation "
1245 "option or by setting the PGDATA environment variable.\n\n",
1261 puts("\t---debug info---");
1262 printf("\tQuiet = %c\n", Quiet ? 't' : 'f');
1263 printf("\tNoversion = %c\n", Noversion ? 't' : 'f');
1264 printf("\ttimings = %c\n", ShowStats ? 't' : 'f');
1265 printf("\tdates = %s\n", EuroDates ? "European" : "Normal");
1266 printf("\tbufsize = %d\n", NBuffers);
1267 printf("\tsortmem = %d\n", SortMem);
1269 printf("\tquery echo = %c\n", EchoQuery ? 't' : 'f');
1270 printf("\tmultiplexed backend? = %c\n", multiplexedBackend ? 't' : 'f');
1271 printf("\tDatabaseName = [%s]\n", DBName);
1272 puts("\t----------------\n");
1276 * initialize portal file descriptors
1279 if (IsUnderPostmaster == true)
1284 "Postmaster flag set: no port number specified, use /dev/null\n");
1285 Portfd = open(NULL_DEV, O_RDWR, 0666);
1290 if (multiplexedBackend)
1292 if (serverPortnum == 0 ||
1293 StreamServerPort(hostName, serverPortnum, &serverSock) != STATUS_OK)
1295 fprintf(stderr, "Postgres: cannot create stream port %d\n", serverPortnum);
1301 sprintf(buf, "stream port %d created, socket = %d\n", serverPortnum, serverSock);
1307 FD_SET(serverSock, &basemask);
1309 frontendList = DLNewList();
1310 /* add the original FrontEnd to the list */
1311 if (IsUnderPostmaster == true)
1313 FrontEnd *fe = malloc(sizeof(FrontEnd));
1315 FD_SET(Portfd, &basemask);
1316 maxFd = Max(serverSock, Portfd) + 1;
1318 fe->fn_connected = true;
1320 fe->fn_Pfout = Pfout;
1321 fe->fn_done = false;
1322 (fe->fn_port).sock = Portfd;
1323 DLAddHead(frontendList, DLNewElem(fe));
1329 maxFd = serverSock + 1;
1333 if (IsUnderPostmaster || multiplexedBackend)
1334 whereToSendOutput = Remote;
1336 whereToSendOutput = Debug;
1338 SetProcessingMode(InitProcessing);
1343 puts("\tInitPostgres()..");
1346 InitPostgres(DBName);
1349 * if an exception is encountered, processing resumes here
1350 * so we abort the current transaction and start a new one.
1351 * This must be done after we initialize the slave backends
1352 * so that the slaves signal the master to abort the transaction
1353 * rather than calling AbortCurrentTransaction() themselves.
1355 * Note: elog(ERROR) causes a kill(getpid(),1) to occur sending
1360 pqsignal(SIGHUP, handle_warn);
1362 if (sigsetjmp(Warn_restart, 1) != 0)
1369 printf("\tAbortCurrentTransaction() at %s\n", ctime(&tim));
1371 MemSet(parser_input, 0, MAX_PARSE_BUFFER);
1373 AbortCurrentTransaction();
1378 * POSTGRES main processing loop begins here
1381 if (IsUnderPostmaster == false)
1383 puts("\nPOSTGRES backend interactive interface");
1384 puts("$Revision: 1.61 $ $Date: 1998/01/13 04:04:36 $");
1388 * if stable main memory is assumed (-S(old) flag is set), it is necessary
1389 * to flush all dirty shared buffers before exit
1393 if (!TransactionFlushEnabled())
1394 on_exitpg(FlushBufferPool, (caddr_t) 0);
1399 if (multiplexedBackend)
1404 memmove((char *) &rmask, (char *) &basemask, sizeof(fd_set));
1405 nSelected = select(maxFd, &rmask, 0, 0, 0);
1412 fprintf(stderr, "postgres: multiplexed backend select failed\n");
1415 if (FD_ISSET(serverSock, &rmask))
1417 /* new connection pending on our well-known port's socket */
1418 newFE = (FrontEnd *) malloc(sizeof(FrontEnd));
1419 MemSet(newFE, 0, sizeof(FrontEnd));
1420 newFE->fn_connected = false;
1421 newFE->fn_done = false;
1422 newPort = &(newFE->fn_port);
1423 if (StreamConnection(serverSock, newPort) != STATUS_OK)
1425 StreamClose(newPort->sock);
1430 DLAddHead(frontendList, DLNewElem(newFE));
1432 newFd = newPort->sock;
1435 FD_SET(newFd, &rmask);
1436 FD_SET(newFd, &basemask);
1438 FD_CLR(serverSock, &rmask);
1441 } /* if FD_ISSET(serverSock) */
1444 * if we get here, it means that the serverSocket was not the
1445 * one selected. Instead, one of the front ends was selected.
1448 curr = DLGetHead(frontendList);
1451 FrontEnd *fe = (FrontEnd *) DLE_VAL(curr);
1452 Port *port = &(fe->fn_port);
1454 /* this is lifted from postmaster.c */
1455 if (FD_ISSET(port->sock, &rmask))
1457 if (fe->fn_connected == false)
1459 /* we have a message from a new frontEnd */
1460 status = PacketReceive(port, &port->buf, NON_BLOCKING);
1461 if (status == STATUS_OK)
1463 fe->fn_connected = true;
1464 pq_init(port->sock);
1466 fe->fn_Pfout = Pfout;
1469 fprintf(stderr, "Multiplexed backend: error in reading packets from %d\n", port->sock);
1472 /* we have a query from an existing, active FrontEnd */
1475 Pfout = fe->fn_Pfout;
1482 curr = DLGetSucc(curr);
1488 curr = DLGetSucc(curr);
1492 * (1) read a command.
1495 MemSet(parser_input, 0, MAX_PARSE_BUFFER);
1497 firstchar = ReadCommand(parser_input, multiplexedBackend);
1498 /* process the command */
1502 * 'F' indicates a fastpath call.
1503 * XXX HandleFunctionRequest
1507 IsEmptyQuery = false;
1509 /* start an xact for this function invocation */
1513 printf("\tStartTransactionCommand() at %s\n", ctime(&tim));
1516 StartTransactionCommand();
1517 HandleFunctionRequest();
1521 * 'Q' indicates a user query
1527 if (strspn(parser_input, " \t\n") == strlen(parser_input))
1530 * if there is nothing in the input buffer, don't bother
1531 * trying to parse and execute anything..
1534 IsEmptyQuery = true;
1539 * otherwise, process the input string.
1542 IsEmptyQuery = false;
1546 /* start an xact for this query */
1550 printf("\tStartTransactionCommand() at %s\n", ctime(&tim));
1552 StartTransactionCommand();
1554 pg_exec_query(parser_input, (char **) NULL, (Oid *) NULL, 0);
1562 * 'X' means that the frontend is closing down the socket
1566 IsEmptyQuery = true;
1567 if (multiplexedBackend)
1569 FD_CLR(currentFE->fn_port.sock, &basemask);
1570 currentFE->fn_done = true;
1577 elog(ERROR, "unknown frontend message was recieved");
1581 * (3) commit the current transaction
1583 * Note: if we had an empty input buffer, then we didn't
1584 * call pg_exec_query, so we don't bother to commit this transaction.
1592 printf("\tCommitTransactionCommand() at %s\n", ctime(&tim));
1594 CommitTransactionCommand();
1599 if (IsUnderPostmaster || multiplexedBackend)
1600 NullCommand(Remote);
1603 } /* infinite for-loop */
1608 #ifndef HAVE_GETRUSAGE
1609 #include "rusagestub.h"
1610 #else /* HAVE_GETRUSAGE */
1611 #include <sys/resource.h>
1612 #endif /* HAVE_GETRUSAGE */
1614 struct rusage Save_r;
1615 struct timeval Save_t;
1622 getrusage(RUSAGE_SELF, &Save_r);
1623 gettimeofday(&Save_t, &tz);
1625 /* ResetTupleCount(); */
1631 struct timeval user,
1633 struct timeval elapse_t;
1637 getrusage(RUSAGE_SELF, &r);
1638 gettimeofday(&elapse_t, &tz);
1639 memmove((char *) &user, (char *) &r.ru_utime, sizeof(user));
1640 memmove((char *) &sys, (char *) &r.ru_stime, sizeof(sys));
1641 if (elapse_t.tv_usec < Save_t.tv_usec)
1644 elapse_t.tv_usec += 1000000;
1646 if (r.ru_utime.tv_usec < Save_r.ru_utime.tv_usec)
1648 r.ru_utime.tv_sec--;
1649 r.ru_utime.tv_usec += 1000000;
1651 if (r.ru_stime.tv_usec < Save_r.ru_stime.tv_usec)
1653 r.ru_stime.tv_sec--;
1654 r.ru_stime.tv_usec += 1000000;
1658 * the only stats we don't show here are for memory usage -- i can't
1659 * figure out how to interpret the relevant fields in the rusage
1660 * struct, and they change names across o/s platforms, anyway. if you
1661 * can figure out what the entries mean, you can somehow extract
1662 * resident set size, shared text size, and unshared data and stack
1666 fprintf(StatFp, "! system usage stats:\n");
1668 "!\t%ld.%06ld elapsed %ld.%06ld user %ld.%06ld system sec\n",
1669 (long int) elapse_t.tv_sec - Save_t.tv_sec,
1670 (long int) elapse_t.tv_usec - Save_t.tv_usec,
1671 (long int) r.ru_utime.tv_sec - Save_r.ru_utime.tv_sec,
1672 (long int) r.ru_utime.tv_usec - Save_r.ru_utime.tv_usec,
1673 (long int) r.ru_stime.tv_sec - Save_r.ru_stime.tv_sec,
1674 (long int) r.ru_stime.tv_usec - Save_r.ru_stime.tv_usec);
1676 "!\t[%ld.%06ld user %ld.%06ld sys total]\n",
1677 (long int) user.tv_sec,
1678 (long int) user.tv_usec,
1679 (long int) sys.tv_sec,
1680 (long int) sys.tv_usec);
1681 #ifdef HAVE_GETRUSAGE
1683 "!\t%ld/%ld [%ld/%ld] filesystem blocks in/out\n",
1684 r.ru_inblock - Save_r.ru_inblock,
1685 /* they only drink coffee at dec */
1686 r.ru_oublock - Save_r.ru_oublock,
1687 r.ru_inblock, r.ru_oublock);
1689 "!\t%ld/%ld [%ld/%ld] page faults/reclaims, %ld [%ld] swaps\n",
1690 r.ru_majflt - Save_r.ru_majflt,
1691 r.ru_minflt - Save_r.ru_minflt,
1692 r.ru_majflt, r.ru_minflt,
1693 r.ru_nswap - Save_r.ru_nswap,
1696 "!\t%ld [%ld] signals rcvd, %ld/%ld [%ld/%ld] messages rcvd/sent\n",
1697 r.ru_nsignals - Save_r.ru_nsignals,
1699 r.ru_msgrcv - Save_r.ru_msgrcv,
1700 r.ru_msgsnd - Save_r.ru_msgsnd,
1701 r.ru_msgrcv, r.ru_msgsnd);
1703 "!\t%ld/%ld [%ld/%ld] voluntary/involuntary context switches\n",
1704 r.ru_nvcsw - Save_r.ru_nvcsw,
1705 r.ru_nivcsw - Save_r.ru_nivcsw,
1706 r.ru_nvcsw, r.ru_nivcsw);
1707 #endif /* HAVE_GETRUSAGE */
1708 fprintf(StatFp, "! postgres usage stats:\n");
1709 PrintBufferUsage(StatFp);
1710 /* DisplayTupleCount(StatFp); */