📄 postgres.c
字号:
/* ---------------- * T - tracing options * ---------------- */ parse_options(optarg, secure); break; case 't': /* ---------------- * tell postgres to report usage statistics (timings) for * each query * * -tpa[rser] = print stats for parser time of each query * -tpl[anner] = print stats for planner time of each query * -te[xecutor] = print stats for executor time of each query * caution: -s can not be used together with -t. * ---------------- */ StatFp = stderr; switch (optarg[0]) { case 'p': if (optarg[1] == 'a') ShowParserStats = 1; else if (optarg[1] == 'l') ShowPlannerStats = 1; else errs++; break; case 'e': ShowExecutorStats = 1; break; default: errs++; break; } break; case 'v': if (secure) FrontendProtocol = (ProtocolVersion) atoi(optarg); break; case 'W': /* ---------------- * wait N seconds to allow attach from a debugger * ---------------- */ sleep(atoi(optarg)); break; case 'x':#ifdef NOT_USED /* planner/xfunc.h */ /* * control joey hellerstein's expensive function * optimization */ if (XfuncMode != 0) { fprintf(stderr, "only one -x flag is allowed\n"); errs++; break; } if (strcmp(optarg, "off") == 0) XfuncMode = XFUNC_OFF; else if (strcmp(optarg, "nor") == 0) XfuncMode = XFUNC_NOR; else if (strcmp(optarg, "nopull") == 0) XfuncMode = XFUNC_NOPULL; else if (strcmp(optarg, "nopm") == 0) XfuncMode = XFUNC_NOPM; else if (strcmp(optarg, "pullall") == 0) XfuncMode = XFUNC_PULLALL; else if (strcmp(optarg, "wait") == 0) XfuncMode = XFUNC_WAIT; else { fprintf(stderr, "use -x {off,nor,nopull,nopm,pullall,wait}\n"); errs++; }#endif break; default: /* ---------------- * default: bad command line option * ---------------- */ errs++; break; } /* ---------------- * get user name (needed now in case it is the default database name) * and check command line validity * ---------------- */ SetPgUserName(); userName = GetPgUserName(); if (IsUnderPostmaster) { /* noninteractive case: nothing should be left after switches */ if (errs || argc != optind || DBName == NULL) { usage(argv[0]); proc_exit(1); } } else { /* interactive case: database name can be last arg on command line */ if (errs || argc - optind > 1) { usage(argv[0]); proc_exit(1); } else if (argc - optind == 1) DBName = argv[optind]; else if ((DBName = userName) == NULL) { fprintf(stderr, "%s: USER undefined and no database specified\n", argv[0]); proc_exit(1); } } if (ShowStats && (ShowParserStats || ShowPlannerStats || ShowExecutorStats)) { fprintf(stderr, "-s can not be used together with -t.\n"); proc_exit(1); } if (!DataDir) { fprintf(stderr, "%s does not know where to find the database system " "data. You must specify the directory that contains the " "database system either by specifying the -D invocation " "option or by setting the PGDATA environment variable.\n\n", argv[0]); proc_exit(1); } /* * Set up additional info. */#ifdef CYR_RECODE SetCharSet();#endif if (FindExec(pg_pathname, argv[0], "postgres") < 0) elog(FATAL, "%s: could not locate executable, bailing out...", argv[0]); /* * Find remote host name or address. */ if (IsUnderPostmaster) { switch (MyProcPort->raddr.sa.sa_family) { struct hostent *host_ent; case AF_INET: remote_info = remote_host = malloc(48); remote_port = ntohs(MyProcPort->raddr.in.sin_port); strcpy(remote_host, inet_ntoa(MyProcPort->raddr.in.sin_addr)); if (HostnameLookup) { host_ent = \ gethostbyaddr((char *) &MyProcPort->raddr.in.sin_addr, sizeof(MyProcPort->raddr.in.sin_addr), AF_INET); if (host_ent) { strncpy(remote_host, host_ent->h_name, 48); *(remote_host + 47) = '\0'; } } if (ShowPortNumber) { remote_info = malloc(strlen(remote_host) + 6); sprintf(remote_info, "%s:%d", remote_host, remote_port); } break; case AF_UNIX: remote_info = remote_host = "localhost"; break; default: remote_info = remote_host = "unknown"; break; } } /* ---------------- * set process params for ps * ---------------- */ if (IsUnderPostmaster) { PS_INIT_STATUS(real_argc, real_argv, argv[0], remote_info, userName, DBName); PS_SET_STATUS("startup"); } /* ---------------- * print flags * ---------------- */ if (Verbose) { if (Verbose == 1) { TPRINTF(TRACE_VERBOSE, "started: host=%s user=%s database=%s", remote_host, userName, DBName); } else { TPRINTF(TRACE_VERBOSE, "debug info:"); TPRINTF(TRACE_VERBOSE, "\tUser = %s", userName); TPRINTF(TRACE_VERBOSE, "\tRemoteHost = %s", remote_host); TPRINTF(TRACE_VERBOSE, "\tRemotePort = %d", remote_port); TPRINTF(TRACE_VERBOSE, "\tDatabaseName = %s", DBName); TPRINTF(TRACE_VERBOSE, "\tVerbose = %d", Verbose); TPRINTF(TRACE_VERBOSE, "\tNoversion = %c", Noversion ? 't' : 'f'); TPRINTF(TRACE_VERBOSE, "\ttimings = %c", ShowStats ? 't' : 'f'); TPRINTF(TRACE_VERBOSE, "\tdates = %s", EuroDates ? "European" : "Normal"); TPRINTF(TRACE_VERBOSE, "\tbufsize = %d", NBuffers); TPRINTF(TRACE_VERBOSE, "\tsortmem = %d", SortMem); TPRINTF(TRACE_VERBOSE, "\tquery echo = %c", EchoQuery ? 't' : 'f'); } } /* ---------------- * initialize I/O * ---------------- */ if (IsUnderPostmaster) { pq_init(); /* initialize libpq at backend startup */ whereToSendOutput = Remote; } else whereToSendOutput = Debug; /* ---------------- * general initialization * ---------------- */ SetProcessingMode(InitProcessing); if (Verbose) TPRINTF(TRACE_VERBOSE, "InitPostgres"); InitPostgres(DBName);#ifdef MULTIBYTE /* set default client encoding */ if (Verbose) puts("\treset_client_encoding().."); reset_client_encoding(); if (Verbose) puts("\treset_client_encoding() done.");#endif on_shmem_exit(remove_all_temp_relations, NULL); /* ---------------- * Set up handler for cancel-request signal, and * send this backend's cancellation info to the frontend. * This should not be done until we are sure startup is successful. * ---------------- */ pqsignal(SIGHUP, read_pg_options); /* update pg_options from file */ pqsignal(SIGINT, QueryCancelHandler); /* cancel current query */ pqsignal(SIGQUIT, handle_warn); /* handle error */ pqsignal(SIGTERM, die); pqsignal(SIGPIPE, SIG_IGN); /* ignore failure to write to frontend */ /* * Note: if frontend closes connection, we will notice it and exit * cleanly when control next returns to outer loop. This seems safer * than forcing exit in the midst of output during who-knows-what * operation... */ pqsignal(SIGUSR1, quickdie); pqsignal(SIGUSR2, Async_NotifyHandler); /* flush also sinval cache */ pqsignal(SIGCHLD, SIG_IGN); /* ignored, sent by LockOwners */ pqsignal(SIGFPE, FloatExceptionHandler); if (whereToSendOutput == Remote && PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2) { StringInfoData buf; pq_beginmessage(&buf); pq_sendbyte(&buf, 'K'); pq_sendint(&buf, (int32) MyProcPid, sizeof(int32)); pq_sendint(&buf, (int32) MyCancelKey, sizeof(int32)); pq_endmessage(&buf); /* Need not flush since ReadyForQuery will do it. */ } if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); puts("$Revision: 1.119 $ $Date: 1999/07/02 18:09:27 $\n"); } /* ---------------- * POSTGRES main processing loop begins here * * if an exception is encountered, processing resumes here * so we abort the current transaction and start a new one. * * Note: elog(ERROR) does a siglongjmp() to transfer control here. * ---------------- */ if (sigsetjmp(Warn_restart, 1) != 0) { InError = true; time(&tim); if (Verbose) TPRINTF(TRACE_VERBOSE, "AbortCurrentTransaction"); AbortCurrentTransaction(); } InError = false; /* * Non-error queries loop here. */ for (;;) { PS_SET_STATUS("idle"); /* ---------------- * (1) tell the frontend we're ready for a new query. * * Note: this includes fflush()'ing the last of the prior output. * ---------------- */ ReadyForQuery(whereToSendOutput); /* ---------------- * (2) deal with pending asynchronous NOTIFY from other backends, * and enable async.c's signal handler to execute NOTIFY directly. * ---------------- */ QueryCancel = false; /* forget any earlier CANCEL signal */ EnableNotifyInterrupt(); /* ---------------- * (3) read a command. * ---------------- */ MemSet(parser_input, 0, MAX_PARSE_BUFFER); firstchar = ReadCommand(parser_input); QueryCancel = false; /* forget any earlier CANCEL signal */ /* ---------------- * (4) disable async.c's signal handler. * ---------------- */ DisableNotifyInterrupt(); /* ---------------- * (5) process the command. * ---------------- */ switch (firstchar) { /* ---------------- * 'F' indicates a fastpath call. * XXX HandleFunctionRequest * ---------------- */ case 'F': IsEmptyQuery = false; /* start an xact for this function invocation */ if (Verbose) TPRINTF(TRACE_VERBOSE, "StartTransactionCommand"); StartTransactionCommand(); HandleFunctionRequest(); break; /* ---------------- * 'Q' indicates a user query * ---------------- */ case 'Q': if (strspn(parser_input, " \t\n") == strlen(parser_input)) { /* ---------------- * if there is nothing in the input buffer, don't bother * trying to parse and execute anything.. * ---------------- */ IsEmptyQuery = true; } else { /* ---------------- * otherwise, process the input string. * ---------------- */ IsEmptyQuery = false; if (ShowStats) ResetUsage(); /* start an xact for this query */ if (Verbose) TPRINTF(TRACE_VERBOSE, "StartTransactionCommand"); StartTransactionCommand(); pg_exec_query(parser_input); if (ShowStats) ShowUsage(); } break; /* ---------------- * 'X' means that the frontend is closing down the socket * ---------------- */ case 'X': pq_close(); proc_exit(0); break; default: elog(ERROR, "unknown frontend message was received"); } /* ---------------- * (6) commit the current transaction * * Note: if we had an empty input buffer, then we didn't * call pg_exec_query, so we don't bother to commit this transaction. * ---------------- */ if (!IsEmptyQuery) { if (Verbose) TPRINTF(TRACE_VERBOSE, "CommitTransactionCommand"); PS_SET_STATUS("commit"); CommitTransactionCommand(); } else { if (IsUnderPostmaster) NullCommand(Remote); } } /* infinite for-loop */ proc_exit(0); /* shouldn't get here... */ return 1;}#ifndef HAVE_GETRUSAGE#include "rusagestub.h"#else /* HAVE_GETRUSAGE */#include <sys/resource.h>#endif /* HAVE_GETRUSAGE */struct rusage Save_r;struct timeval Save_t;voidResetUsage(void){ struct timezone tz; getrusage(RUSAGE_SELF, &Save_r); gettimeofday(&Save_t, &tz); ResetBufferUsage();/* ResetTupleCount(); */}voidShowUsage(void){ struct timeval user, sys; struct timeval elapse_t; struct timezone tz; struct rusage r; getrusage(RUSAGE_SELF, &r); gettimeofday(&elapse_t, &tz); memmove((char *) &user, (char *) &r.ru_utime, sizeof(user)); memmove((char *) &sys, (char *) &r.ru_stime, sizeof(sys)); if (elapse_t.tv_usec < Save_t.tv_usec) { elapse_t.tv_sec--; elapse_t.tv_usec += 1000000; } if (r.ru_utime.tv_usec < Save_r.ru_utime.tv_usec) { r.ru_utime.tv_sec--; r.ru_utime.tv_usec += 1000000; } if (r.ru_stime.tv_usec < Save_r.ru_stime.tv_usec) { r.ru_stime.tv_sec--; r.ru_stime.tv_usec += 1000000; } /* * the only stats we don't show here are for memory usage -- i can't * figure out how to interpret the relevant fields in the rusage * struct, and they change names across o/s platforms, anyway. if you * can figure out what the entries mean, you can somehow extract * resident set size, shared text size, and unshared data and stack * sizes. */ fprintf(StatFp, "! system usage stats:\n"); fprintf(StatFp, "!\t%ld.%06ld elapsed %ld.%06ld user %ld.%06ld system sec\n", (long int) elapse_t.tv_sec - Save_t.tv_sec, (long int) elapse_t.tv_usec - Save_t.tv_usec, (long int) r.ru_utime.tv_sec - Save_r.ru_utime.tv_sec, (long int) r.ru_utime.tv_usec - Save_r.ru_utime.tv_usec, (long int) r.ru_stime.tv_sec - Save_r.ru_stime.tv_sec, (long int) r.ru_stime.tv_usec - Save_r.ru_stime.tv_usec); fprintf(StatFp, "!\t[%ld.%06ld user %ld.%06ld sys total]\n", (long int) user.tv_sec, (long int) user.tv_usec, (long int) sys.tv_sec, (long int) sys.tv_usec);#ifdef HAVE_GETRUSAGE fprintf(StatFp, "!\t%ld/%ld [%ld/%ld] filesystem blocks in/out\n", r.ru_inblock - Save_r.ru_inblock, /* they only drink coffee at dec */ r.ru_oublock - Save_r.ru_oublock, r.ru_inblock, r.ru_oublock); fprintf(StatFp, "!\t%ld/%ld [%ld/%ld] page faults/reclaims, %ld [%ld] swaps\n", r.ru_majflt - Save_r.ru_majflt, r.ru_minflt - Save_r.ru_minflt, r.ru_majflt, r.ru_minflt, r.ru_nswap - Save_r.ru_nswap, r.ru_nswap); fprintf(StatFp, "!\t%ld [%ld] signals rcvd, %ld/%ld [%ld/%ld] messages rcvd/sent\n", r.ru_nsignals - Save_r.ru_nsignals, r.ru_nsignals, r.ru_msgrcv - Save_r.ru_msgrcv, r.ru_msgsnd - Save_r.ru_msgsnd, r.ru_msgrcv, r.ru_msgsnd); fprintf(StatFp, "!\t%ld/%ld [%ld/%ld] voluntary/involuntary context switches\n", r.ru_nvcsw - Save_r.ru_nvcsw, r.ru_nivcsw - Save_r.ru_nivcsw, r.ru_nvcsw, r.ru_nivcsw);#endif /* HAVE_GETRUSAGE */ fprintf(StatFp, "! postgres usage stats:\n"); PrintBufferUsage(StatFp);/* DisplayTupleCount(StatFp); */}#ifdef USE_ASSERT_CHECKINGintassertEnable(int val){ assert_enabled = val; return val;}#ifdef ASSERT_CHECKING_TESTintassertTest(int val){ Assert(val == 0); if (assert_enabled) { /* val != 0 should be trapped by previous Assert */ elog(NOTICE, "Assert test successfull (val = %d)", val); } else elog(NOTICE, "Assert checking is disabled (val = %d)", val); return val;}#endif#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -