📄 miscinit.c
字号:
} } /* * No, the creating process did not exist. However, it could be that * the postmaster crashed (or more likely was kill -9'd by a clueless * admin) but has left orphan backends behind. Check for this by * looking to see if there is an associated shmem segment that is * still in use. */ if (isDDLock) { char *ptr; unsigned long id1, id2; ptr = strchr(buffer, '\n'); if (ptr != NULL && (ptr = strchr(ptr + 1, '\n')) != NULL) { ptr++; if (sscanf(ptr, "%lu %lu", &id1, &id2) == 2) { if (PGSharedMemoryIsInUse(id1, id2)) ereport(FATAL, (errcode(ERRCODE_LOCK_FILE_EXISTS), errmsg("pre-existing shared memory block " "(key %lu, ID %lu) is still in use", id1, id2), errhint("If you're sure there are no old " "server processes still running, remove " "the shared memory block with " "the command \"ipcclean\", \"ipcrm\", " "or just delete the file \"%s\".", filename))); } } } /* * Looks like nobody's home. Unlink the file and try again to create * it. Need a loop because of possible race condition against other * would-be creators. */ if (unlink(filename) < 0) ereport(FATAL, (errcode_for_file_access(), errmsg("could not remove old lock file \"%s\": %m", filename), errhint("The file seems accidentally left over, but " "it could not be removed. Please remove the file " "by hand and try again."))); } /* * Successfully created the file, now fill it. */ snprintf(buffer, sizeof(buffer), "%d\n%s\n", amPostmaster ? (int) my_pid : -((int) my_pid), DataDir); errno = 0; if (write(fd, buffer, strlen(buffer)) != strlen(buffer)) { int save_errno = errno; close(fd); unlink(filename); /* if write didn't set errno, assume problem is no disk space */ errno = save_errno ? save_errno : ENOSPC; ereport(FATAL, (errcode_for_file_access(), errmsg("could not write lock file \"%s\": %m", filename))); } if (close(fd)) { int save_errno = errno; unlink(filename); errno = save_errno; ereport(FATAL, (errcode_for_file_access(), errmsg("could not write lock file \"%s\": %m", filename))); } /* * Arrange for automatic removal of lockfile at proc_exit. */ on_proc_exit(UnlinkLockFile, PointerGetDatum(strdup(filename)));}/* * Create the data directory lockfile. * * When this is called, we must have already switched the working * directory to DataDir, so we can just use a relative path. This * helps ensure that we are locking the directory we should be. */voidCreateDataDirLockFile(bool amPostmaster){ CreateLockFile(DIRECTORY_LOCK_FILE, amPostmaster, true, DataDir);}/* * Create a lockfile for the specified Unix socket file. */voidCreateSocketLockFile(const char *socketfile, bool amPostmaster){ char lockfile[MAXPGPATH]; snprintf(lockfile, sizeof(lockfile), "%s.lock", socketfile); CreateLockFile(lockfile, amPostmaster, false, socketfile); /* Save name of lockfile for TouchSocketLockFile */ strcpy(socketLockFile, lockfile);}/* * TouchSocketLockFile -- mark socket lock file as recently accessed * * This routine should be called every so often to ensure that the lock file * has a recent mod or access date. That saves it * from being removed by overenthusiastic /tmp-directory-cleaner daemons. * (Another reason we should never have put the socket file in /tmp...) */voidTouchSocketLockFile(void){ /* Do nothing if we did not create a socket... */ if (socketLockFile[0] != '\0') { /* * utime() is POSIX standard, utimes() is a common alternative; if we * have neither, fall back to actually reading the file (which only * sets the access time not mod time, but that should be enough in * most cases). In all paths, we ignore errors. */#ifdef HAVE_UTIME utime(socketLockFile, NULL);#else /* !HAVE_UTIME */#ifdef HAVE_UTIMES utimes(socketLockFile, NULL);#else /* !HAVE_UTIMES */ int fd; char buffer[1]; fd = open(socketLockFile, O_RDONLY | PG_BINARY, 0); if (fd >= 0) { read(fd, buffer, sizeof(buffer)); close(fd); }#endif /* HAVE_UTIMES */#endif /* HAVE_UTIME */ }}/* * Append information about a shared memory segment to the data directory * lock file. * * This may be called multiple times in the life of a postmaster, if we * delete and recreate shmem due to backend crash. Therefore, be prepared * to overwrite existing information. (As of 7.1, a postmaster only creates * one shm seg at a time; but for the purposes here, if we did have more than * one then any one of them would do anyway.) */voidRecordSharedMemoryInLockFile(unsigned long id1, unsigned long id2){ int fd; int len; char *ptr; char buffer[BLCKSZ]; fd = open(DIRECTORY_LOCK_FILE, O_RDWR | PG_BINARY, 0); if (fd < 0) { ereport(LOG, (errcode_for_file_access(), errmsg("could not open file \"%s\": %m", DIRECTORY_LOCK_FILE))); return; } len = read(fd, buffer, sizeof(buffer) - 100); if (len < 0) { ereport(LOG, (errcode_for_file_access(), errmsg("could not read from file \"%s\": %m", DIRECTORY_LOCK_FILE))); close(fd); return; } buffer[len] = '\0'; /* * Skip over first two lines (PID and path). */ ptr = strchr(buffer, '\n'); if (ptr == NULL || (ptr = strchr(ptr + 1, '\n')) == NULL) { elog(LOG, "bogus data in \"%s\"", DIRECTORY_LOCK_FILE); close(fd); return; } ptr++; /* * Append key information. Format to try to keep it the same length * always (trailing junk won't hurt, but might confuse humans). */ sprintf(ptr, "%9lu %9lu\n", id1, id2); /* * And rewrite the data. Since we write in a single kernel call, this * update should appear atomic to onlookers. */ len = strlen(buffer); errno = 0; if (lseek(fd, (off_t) 0, SEEK_SET) != 0 || (int) write(fd, buffer, len) != len) { /* if write didn't set errno, assume problem is no disk space */ if (errno == 0) errno = ENOSPC; ereport(LOG, (errcode_for_file_access(), errmsg("could not write to file \"%s\": %m", DIRECTORY_LOCK_FILE))); close(fd); return; } if (close(fd)) { ereport(LOG, (errcode_for_file_access(), errmsg("could not write to file \"%s\": %m", DIRECTORY_LOCK_FILE))); }}/*------------------------------------------------------------------------- * Version checking support *------------------------------------------------------------------------- *//* * Determine whether the PG_VERSION file in directory `path' indicates * a data version compatible with the version of this program. * * If compatible, return. Otherwise, ereport(FATAL). */voidValidatePgVersion(const char *path){ char full_path[MAXPGPATH]; FILE *file; int ret; long file_major, file_minor; long my_major = 0, my_minor = 0; char *endptr; const char *version_string = PG_VERSION; my_major = strtol(version_string, &endptr, 10); if (*endptr == '.') my_minor = strtol(endptr + 1, NULL, 10); snprintf(full_path, sizeof(full_path), "%s/PG_VERSION", path); file = AllocateFile(full_path, "r"); if (!file) { if (errno == ENOENT) ereport(FATAL, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("\"%s\" is not a valid data directory", path), errdetail("File \"%s\" is missing.", full_path))); else ereport(FATAL, (errcode_for_file_access(), errmsg("could not open file \"%s\": %m", full_path))); } ret = fscanf(file, "%ld.%ld", &file_major, &file_minor); if (ret != 2) ereport(FATAL, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("\"%s\" is not a valid data directory", path), errdetail("File \"%s\" does not contain valid data.", full_path), errhint("You may need to initdb."))); FreeFile(file); if (my_major != file_major || my_minor != file_minor) ereport(FATAL, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("database files are incompatible with server"), errdetail("The data directory was initialized by PostgreSQL version %ld.%ld, " "which is not compatible with this version %s.", file_major, file_minor, version_string)));}/*------------------------------------------------------------------------- * Library preload support *------------------------------------------------------------------------- */typedef void (*func_ptr) ();/* * process any libraries that should be preloaded and * optionally pre-initialized */voidprocess_preload_libraries(char *preload_libraries_string){ char *rawstring; List *elemlist; ListCell *l; if (preload_libraries_string == NULL) return; /* Need a modifiable copy of string */ rawstring = pstrdup(preload_libraries_string); /* Parse string into list of identifiers */ if (!SplitIdentifierString(rawstring, ',', &elemlist)) { /* syntax error in list */ pfree(rawstring); list_free(elemlist); ereport(LOG, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("invalid list syntax for parameter \"preload_libraries\""))); return; } foreach(l, elemlist) { char *tok = (char *) lfirst(l); char *sep = strstr(tok, ":"); char *filename = NULL; char *funcname = NULL; func_ptr initfunc; if (sep) { /* * a colon separator implies there is an initialization function * that we need to run in addition to loading the library */ size_t filename_len = sep - tok; size_t funcname_len = strlen(tok) - filename_len - 1; filename = (char *) palloc(filename_len + 1); memcpy(filename, tok, filename_len); filename[filename_len] = '\0'; funcname = (char *) palloc(funcname_len + 1); strcpy(funcname, sep + 1); } else { /* * no separator -- just load the library */ filename = pstrdup(tok); funcname = NULL; } canonicalize_path(filename); initfunc = (func_ptr) load_external_function(filename, funcname, true, NULL); if (initfunc) (*initfunc) (); if (funcname) ereport(LOG, (errmsg("preloaded library \"%s\" with initialization function \"%s\"", filename, funcname))); else ereport(LOG, (errmsg("preloaded library \"%s\"", filename))); pfree(filename); if (funcname) pfree(funcname); } pfree(rawstring); list_free(elemlist);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -