int64 FileSeek(File file, int64 offset, int whence) { int returnCode; Assert(FileIsValid(file)); DO_DB(elog(LOG, "FileSeek: %d (%s) " INT64_FORMAT " " INT64_FORMAT " %d", file, VfdCache[file].fileName, VfdCache[file].seekPos, offset, whence)); if (FileIsNotOpen(file)) { switch (whence) { case SEEK_SET: Assert(offset >= INT64CONST(0)); VfdCache[file].seekPos = offset; break; case SEEK_CUR: VfdCache[file].seekPos += offset; break; case SEEK_END: returnCode = FileAccess(file); if (returnCode < 0) return returnCode; VfdCache[file].seekPos = pg_lseek64(VfdCache[file].fd, offset, whence); break; default: Assert(!"invalid whence"); break; } } else { switch (whence) { case SEEK_SET: Assert(offset >= INT64CONST(0)); if (VfdCache[file].seekPos != offset) VfdCache[file].seekPos = pg_lseek64(VfdCache[file].fd, offset, whence); break; case SEEK_CUR: if (offset != 0 || VfdCache[file].seekPos == FileUnknownPos) VfdCache[file].seekPos = pg_lseek64(VfdCache[file].fd, offset, whence); break; case SEEK_END: VfdCache[file].seekPos = pg_lseek64(VfdCache[file].fd, offset, whence); break; default: Assert(!"invalid whence"); break; } } return VfdCache[file].seekPos; }
Datum interval_reltime(PG_FUNCTION_ARGS) { Interval *interval = PG_GETARG_INTERVAL_P(0); RelativeTime time; int year, month, day; TimeOffset span; year = interval->month / MONTHS_PER_YEAR; month = interval->month % MONTHS_PER_YEAR; day = interval->day; #ifdef HAVE_INT64_TIMESTAMP span = ((INT64CONST(365250000) * year + INT64CONST(30000000) * month + INT64CONST(1000000) * day) * INT64CONST(86400)) + interval->time; span /= USECS_PER_SEC; #else span = (DAYS_PER_YEAR * year + (double) DAYS_PER_MONTH * month + day) * SECS_PER_DAY + interval->time; #endif if (span < INT_MIN || span > INT_MAX) time = INVALID_RELTIME; else time = span; PG_RETURN_RELATIVETIME(time); }
/* tm2timestamp() * Convert a tm structure to a timestamp data type. * Note that year is _not_ 1900-based, but is an explicit full value. * Also, month is one-based, _not_ zero-based. * * Returns -1 on failure (overflow). */ int tm2timestamp(struct tm * tm, fsec_t fsec, int *tzp, timestamp *result) { #ifdef HAVE_INT64_TIMESTAMP int dDate; int64 time; #else double dDate, time; #endif /* Julian day routines are not correct for negative Julian days */ if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday)) return -1; dDate = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1); time = time2t(tm->tm_hour, tm->tm_min, tm->tm_sec, fsec); #ifdef HAVE_INT64_TIMESTAMP *result = (dDate * INT64CONST(86400000000)) + time; /* check for major overflow */ if ((*result - time) / INT64CONST(86400000000) != dDate) return -1; /* check for just-barely overflow (okay except time-of-day wraps) */ if ((*result < 0) ? (dDate >= 0) : (dDate < 0)) return -1; #else *result = ((dDate * 86400) + time); #endif if (tzp != NULL) *result = dt2local(*result, -(*tzp)); return 0; } /* tm2timestamp() */
static void LruDelete(File file) { Vfd *vfdP; Assert(file != 0); DO_DB(elog(LOG, "LruDelete %d (%s)", file, VfdCache[file].fileName)); vfdP = &VfdCache[file]; /* delete the vfd record from the LRU ring */ Delete(file); /* save the seek position */ vfdP->seekPos = pg_lseek64(vfdP->fd, INT64CONST(0), SEEK_CUR); Assert(vfdP->seekPos != INT64CONST(-1)); /* close the file */ if (close(vfdP->fd)) elog(ERROR, "could not close file \"%s\": %m", vfdP->fileName); --nfile; vfdP->fd = VFD_CLOSED; }
/* returns 0 on success, -1 on re-open failure (with errno set) */ static int LruInsert(File file) { Vfd *vfdP; Assert(file != 0); DO_DB(elog(LOG, "LruInsert %d (%s)", file, VfdCache[file].fileName)); vfdP = &VfdCache[file]; if (FileIsNotOpen(file)) { while (nfile + numAllocatedDescs >= max_safe_fds) { if (!ReleaseLruFile()) break; } /* * The open could still fail for lack of file descriptors, eg due to * overall system file table being full. So, be prepared to release * another FD if necessary... */ vfdP->fd = BasicOpenFile(vfdP->fileName, vfdP->fileFlags, vfdP->fileMode); if (vfdP->fd < 0) { DO_DB(elog(LOG, "RE_OPEN FAILED: %d", errno)); return vfdP->fd; } else { DO_DB(elog(LOG, "RE_OPEN SUCCESS")); ++nfile; } /* seek to the right position */ if (vfdP->seekPos != INT64CONST(0)) { int64 returnValue; returnValue = pg_lseek64(vfdP->fd, vfdP->seekPos, SEEK_SET); Assert(returnValue != INT64CONST(-1)); } } /* * put it at the head of the Lru ring */ Insert(file); return 0; }
static void dt2time(timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec) { #ifdef HAVE_INT64_TIMESTAMP int64 time; #else double time; #endif time = jd; #ifdef HAVE_INT64_TIMESTAMP *hour = (time / INT64CONST(3600000000)); time -= ((*hour) * INT64CONST(3600000000)); *min = (time / INT64CONST(60000000)); time -= ((*min) * INT64CONST(60000000)); *sec = (time / INT64CONST(1000000)); *fsec = (time - (*sec * INT64CONST(1000000))); *sec = (time / INT64CONST(1000000)); *fsec = (time - (*sec * INT64CONST(1000000))); #else *hour = (time / 3600); time -= ((*hour) * 3600); *min = (time / 60); time -= ((*min) * 60); *sec = time; *fsec = JROUND(time - *sec); #endif return; } /* dt2time() */
static int tm2interval(struct tm *tm, fsec_t fsec, interval * span) { if ((double) tm->tm_year * MONTHS_PER_YEAR + tm->tm_mon > INT_MAX || (double) tm->tm_year * MONTHS_PER_YEAR + tm->tm_mon < INT_MIN) return -1; span->month = tm->tm_year * MONTHS_PER_YEAR + tm->tm_mon; span->time = (((((((tm->tm_mday * INT64CONST(24)) + tm->tm_hour) * INT64CONST(60)) + tm->tm_min) * INT64CONST(60)) + tm->tm_sec) * USECS_PER_SEC) + fsec; return 0; } /* tm2interval() */
Datum tstz_dist(PG_FUNCTION_ARGS) { TimestampTz a = PG_GETARG_TIMESTAMPTZ(0); TimestampTz b = PG_GETARG_TIMESTAMPTZ(1); Interval *r; if (TIMESTAMP_NOT_FINITE(a) || TIMESTAMP_NOT_FINITE(b)) { Interval *p = palloc(sizeof(Interval)); p->day = INT_MAX; p->month = INT_MAX; #ifdef HAVE_INT64_TIMESTAMP p->time = INT64CONST(0x7FFFFFFFFFFFFFFF); #else p->time = DBL_MAX; #endif PG_RETURN_INTERVAL_P(p); } r = DatumGetIntervalP(DirectFunctionCall2(timestamp_mi, PG_GETARG_DATUM(0), PG_GETARG_DATUM(1))); PG_RETURN_INTERVAL_P(abs_interval(r)); }
Datum gbt_timetz_compress(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); GISTENTRY *retval; if (entry->leafkey) { timeKEY *r = (timeKEY *) palloc(sizeof(timeKEY)); TimeTzADT *tz = DatumGetTimeTzADTP(entry->key); TimeADT tmp; retval = palloc(sizeof(GISTENTRY)); /* We are using the time + zone only to compress */ #ifdef HAVE_INT64_TIMESTAMP tmp = tz->time + (tz->zone * INT64CONST(1000000)); #else tmp = (tz->time + tz->zone); #endif r->lower = r->upper = tmp; gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page, entry->offset, sizeof(timeKEY), FALSE); } else retval = entry; PG_RETURN_POINTER(retval); }
Datum gbt_timetz_consistent(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); TimeTzADT *query = PG_GETARG_TIMETZADT_P(1); StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); /* Oid subtype = PG_GETARG_OID(3); */ bool *recheck = (bool *) PG_GETARG_POINTER(4); timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key); TimeADT qqq; GBT_NUMKEY_R key; /* All cases served by this function are inexact */ *recheck = true; #ifdef HAVE_INT64_TIMESTAMP qqq = query->time + (query->zone * INT64CONST(1000000)); #else qqq = (query->time + query->zone); #endif key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; PG_RETURN_BOOL( gbt_num_consistent(&key, (void *) &qqq, &strategy, GIST_LEAF(entry), &tinfo) ); }
/* ---------- * scanint8 --- try to parse a string into an int8. * * If errorOK is false, ereport a useful error message if the string is bad. If * errorOK is true, just return "false" for bad input. * ---------- */ int slon_scanint64(char *str, int64 * result) { char *ptr = str; int64 tmp = 0; int sign = 1; /* * Do our own scan, rather than relying on sscanf which might be broken * for long long. */ /* skip leading spaces */ while (*ptr && isspace((unsigned char)*ptr)) ptr++; /* handle sign */ if (*ptr == '-') { ptr++; sign = -1; /* * Do an explicit check for INT64_MIN. Ugly though this is, it's * cleaner than trying to get the loop below to handle it portably. */ #ifndef INT64_IS_BUSTED if (strcmp(ptr, "9223372036854775808") == 0) { *result = -INT64CONST(0x7fffffffffffffff) - 1; return (int) true; } #endif } else if (*ptr == '+') ptr++; /* require at least one digit */ if (!isdigit((unsigned char)*ptr)) return false; /* process digits */ while (*ptr && isdigit((unsigned char)*ptr)) { int64 newtmp = tmp * 10 + (*ptr++ - '0'); if ((newtmp / 10) != tmp) /* overflow? */ return false; tmp = newtmp; } /* trailing junk? */ if (*ptr) return false; *result = (sign < 0) ? -tmp : tmp; return true; }
static int tm2interval(struct tm * tm, fsec_t fsec, interval * span) { span->month = tm->tm_year * MONTHS_PER_YEAR + tm->tm_mon; #ifdef HAVE_INT64_TIMESTAMP span->time = (((((((tm->tm_mday * INT64CONST(24)) + tm->tm_hour) * INT64CONST(60)) + tm->tm_min) * INT64CONST(60)) + tm->tm_sec) * USECS_PER_SEC) + fsec; #else span->time = (((((tm->tm_mday * (double) HOURS_PER_DAY) + tm->tm_hour) * (double) MINS_PER_HOUR) + tm->tm_min) * (double) SECS_PER_MINUTE) + tm->tm_sec + fsec; #endif return 0; } /* tm2interval() */
static int tm2interval(struct tm * tm, fsec_t fsec, interval *span) { span->month = ((tm->tm_year * 12) + tm->tm_mon); #ifdef HAVE_INT64_TIMESTAMP span->time = ((((((((tm->tm_mday * INT64CONST(24)) + tm->tm_hour) * INT64CONST(60)) + tm->tm_min) * INT64CONST(60)) + tm->tm_sec) * INT64CONST(1000000)) + fsec); #else span->time = ((((((tm->tm_mday * 24.0) + tm->tm_hour) * 60.0) + tm->tm_min) * 60.0) + tm->tm_sec); span->time = JROUND(span->time + fsec); #endif return 0; } /* tm2interval() */
static timestamp dt2local(timestamp dt, int tz) { #ifdef HAVE_INT64_TIMESTAMP dt -= (tz * INT64CONST(1000000)); #else dt -= tz; dt = JROUND(dt); #endif return dt; } /* dt2local() */
AOHeaderCheckError AppendOnlyStorageFormat_GetLargeContentHeaderInfo( uint8 *headerPtr, int headerLen, bool usingChecksums, int32 *largeContentLen, int *executorBlockKind, bool *hasFirstRowNum, int64 *firstRowNum, int *largeRowCount) { AOLargeContentHeader *largeContentHeader; int32 offset; Assert(headerPtr != NULL); largeContentHeader = (AOLargeContentHeader*)headerPtr; *executorBlockKind = AOLargeContentHeaderGet_executorBlockKind(largeContentHeader); *hasFirstRowNum = AOLargeContentHeaderGet_hasFirstRowNum(largeContentHeader); *largeRowCount = AOLargeContentHeaderGet_largeRowCount(largeContentHeader); *largeContentLen = AOLargeContentHeaderGet_largeContentLength(largeContentHeader); if (*largeContentLen == 0) { sprintf(AoHeaderCheckErrorStr, "Append-only storage header is invalid -- large content length is zero " "(block_bytes_0_3 0x%08x, block_bytes_4_7 0x%08x)", largeContentHeader->largecontent_bytes_0_3, largeContentHeader->largecontent_bytes_4_7); return AOHeaderCheckLargeContentLenIsZero; } offset = AoHeader_RegularSize + (usingChecksums ? 2 * sizeof(pg_crc32) : 0); if (*hasFirstRowNum) { int64 *firstRowNumPtr; firstRowNumPtr = (int64*)&headerPtr[offset]; *firstRowNum = *firstRowNumPtr; offset += sizeof(int64); } else *firstRowNum = INT64CONST(-1); if (offset != headerLen) elog(ERROR, "Content offset %d doesn't equal header length parameter %d", offset, headerLen); return AOHeaderCheckOk; }
/* * Local version of TimestampDifferenceExceeds(), since we are not * linked with backend code. */ static bool localTimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec) { TimestampTz diff = stop_time - start_time; #ifdef HAVE_INT64_TIMESTAMP return (diff >= msec * INT64CONST(1000)); #else return (diff * 1000.0 >= msec); #endif }
/* * open a file in an arbitrary directory * * NB: if the passed pathname is relative (which it usually is), * it will be interpreted relative to the process' working directory * (which should always be $PGDATA when this code is running). */ File PathNameOpenFile(FileName fileName, int fileFlags, int fileMode) { char *fnamecopy; File file; Vfd *vfdP; DO_DB(elog(LOG, "PathNameOpenFile: %s %x %o", fileName, fileFlags, fileMode)); /* * We need a malloc'd copy of the file name; fail cleanly if no room. */ fnamecopy = strdup(fileName); if (fnamecopy == NULL) ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"))); file = AllocateVfd(); vfdP = &VfdCache[file]; while (nfile + numAllocatedDescs >= max_safe_fds) { if (!ReleaseLruFile()) break; } vfdP->fd = BasicOpenFile(fileName, fileFlags, fileMode); if (vfdP->fd < 0) { FreeVfd(file); free(fnamecopy); return -1; } ++nfile; DO_DB(elog(LOG, "PathNameOpenFile: success %d", vfdP->fd)); Insert(file); vfdP->fileName = fnamecopy; /* Saved flags are adjusted to be OK for re-opening file */ vfdP->fileFlags = fileFlags & ~(O_CREAT | O_TRUNC | O_EXCL); vfdP->fileMode = fileMode; vfdP->seekPos = INT64CONST(0); vfdP->fdstate = 0x0; return file; }
/** * @brief Parse int64 expression */ int64 ParseInt64(char *value, int64 minValue) { int64 i; if (pg_strcasecmp(value, "INFINITE") == 0) return INT64CONST(0x7FFFFFFFFFFFFFFF); i = DatumGetInt64(DirectFunctionCall1(int8in, CStringGetDatum(value))); if (i < minValue) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("value \"%s\" is out of range", value))); return i; }
/* Decode a timestamp type */ static int decode_timestamp(const char *buffer, unsigned int buff_size, unsigned int *out_size) { const char *new_buffer = (const char *) TYPEALIGN(sizeof(int64), (uintptr_t) buffer); unsigned int delta = (unsigned int) ((uintptr_t) new_buffer - (uintptr_t) buffer); int64 timestamp, timestamp_sec; int32 jd, year, month, day; if (buff_size < delta) return -1; buff_size -= delta; buffer = new_buffer; if (buff_size < sizeof(int64)) return -2; *out_size = sizeof(int64) + delta; timestamp = *(int64 *) buffer; jd = timestamp / USECS_PER_DAY; if (jd != 0) timestamp -= jd * USECS_PER_DAY; if (timestamp < INT64CONST(0)) { timestamp += USECS_PER_DAY; jd -= 1; } /* add offset to go from J2000 back to standard Julian date */ jd += POSTGRES_EPOCH_JDATE; j2date(jd, &year, &month, &day); timestamp_sec = timestamp / 1000000; CopyAppendFmt("%04d-%02d-%02d %02ld:%02ld:%02ld.%06ld%s", (year <= 0) ? -year + 1 : year, month, day, timestamp_sec / 60 / 60, (timestamp_sec / 60) % 60, timestamp_sec % 60, timestamp % 1000000, (year <= 0) ? " BC" : ""); return 0; }
/* * pg_lltoa: convert a signed 64-bit integer to its string representation * * Caller must ensure that 'a' points to enough memory to hold the result * (at least MAXINT8LEN+1 bytes, counting a leading sign and trailing NUL). */ void pg_lltoa(int64 value, char *a) { char *start = a; bool neg = false; /* * Avoid problems with the most negative integer not being representable * as a positive integer. */ if (value == (-INT64CONST(0x7FFFFFFFFFFFFFFF) - 1)) { memcpy(a, "-9223372036854775808", 21); return; } else if (value < 0) { value = -value; neg = true; } /* Compute the result string backwards. */ do { int64 remainder; int64 oldval = value; value /= 10; remainder = oldval - value * 10; *a++ = '0' + remainder; } while (value != 0); if (neg) *a++ = '-'; /* Add trailing NUL byte, and back up 'a' to the last character. */ *a-- = '\0'; /* Reverse string. */ while (start < a) { char swap = *start; *start++ = *a; *a-- = swap; } }
/* interval2tm() * Convert a interval data type to a tm structure. */ static int interval2tm(interval span, struct tm * tm, fsec_t *fsec) { #ifdef HAVE_INT64_TIMESTAMP int64 time; #else double time; #endif if (span.month != 0) { tm->tm_year = span.month / 12; tm->tm_mon = span.month % 12; } else { tm->tm_year = 0; tm->tm_mon = 0; } time = span.time; #ifdef HAVE_INT64_TIMESTAMP tm->tm_mday = (time / INT64CONST(86400000000)); time -= (tm->tm_mday * INT64CONST(86400000000)); tm->tm_hour = (time / INT64CONST(3600000000)); time -= (tm->tm_hour * INT64CONST(3600000000)); tm->tm_min = (time / INT64CONST(60000000)); time -= (tm->tm_min * INT64CONST(60000000)); tm->tm_sec = (time / INT64CONST(1000000)); *fsec = (time - (tm->tm_sec * INT64CONST(1000000))); #else TMODULO(time, tm->tm_mday, 86400e0); TMODULO(time, tm->tm_hour, 3600e0); TMODULO(time, tm->tm_min, 60e0); TMODULO(time, tm->tm_sec, 1e0); *fsec = time; #endif return 0; } /* interval2tm() */
/* * Close the current segment file. * * No error if the current is already closed. */ void AppendOnlyStorageRead_CloseFile( AppendOnlyStorageRead *storageRead) { if(!storageRead->isActive) return; if (storageRead->file == -1) return; FileClose(storageRead->file); storageRead->file = -1; storageRead->logicalEof = INT64CONST(0); if(storageRead->bufferedRead.file >= 0) BufferedReadCompleteFile(&storageRead->bufferedRead); }
date PGTYPESdate_from_timestamp(timestamp dt) { date dDate; dDate = 0; /* suppress compiler warning */ if (TIMESTAMP_NOT_FINITE(dt)) return #ifdef HAVE_INT64_TIMESTAMP /* Microseconds to days */ dDate = (dt / INT64CONST(86400000000)); #else /* Seconds to days */ dDate = (dt / 86400.0); #endif return dDate; }
static Timestamp * tstz_to_ts_gmt(Timestamp *gmt, TimestampTz *ts) { int val, tz; *gmt = *ts; DecodeSpecial(0, "gmt", &val); if (*ts < DT_NOEND && *ts > DT_NOBEGIN) { tz = val * 60; #ifdef HAVE_INT64_TIMESTAMP *gmt -= (tz * INT64CONST(1000000)); #else *gmt -= tz; #endif } return gmt; }
static Timestamp tstz_to_ts_gmt(TimestampTz ts) { Timestamp gmt; int val, tz; gmt = ts; DecodeSpecial(0, "gmt", &val); if (ts < DT_NOEND && ts > DT_NOBEGIN) { tz = val * 60; #ifdef HAVE_INT64_TIMESTAMP gmt -= (tz * INT64CONST(1000000)); #else gmt -= tz; #endif } return gmt; }
Datum gbt_timetz_consistent(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); TimeTzADT *query = PG_GETARG_TIMETZADT_P(1); StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key); TimeADT qqq; GBT_NUMKEY_R key; #ifdef HAVE_INT64_TIMESTAMP qqq = query->time + (query->zone * INT64CONST(1000000)); #else qqq = (query->time + query->zone); #endif key.lower = (GBT_NUMKEY *) & kkk->lower; key.upper = (GBT_NUMKEY *) & kkk->upper; PG_RETURN_BOOL( gbt_num_consistent(&key, (void *) &qqq, &strategy, GIST_LEAF(entry), &tinfo) ); }
/* * scanint8 --- try to parse a string into an int8. * * If errorOK is false, ereport a useful error message if the string is bad. * If errorOK is true, just return "false" for bad input. */ bool scanint8(const char *str, bool errorOK, int64 *result) { const char *ptr = str; int64 tmp = 0; int sign = 1; /* * Do our own scan, rather than relying on sscanf which might be broken * for long long. */ /* skip leading spaces */ while (*ptr && isspace((unsigned char) *ptr)) ptr++; /* handle sign */ if (*ptr == '-') { ptr++; /* * Do an explicit check for INT64_MIN. Ugly though this is, it's * cleaner than trying to get the loop below to handle it portably. */ if (strncmp(ptr, "9223372036854775808", 19) == 0) { tmp = -INT64CONST(0x7fffffffffffffff) - 1; ptr += 19; goto gotdigits; } sign = -1; } else if (*ptr == '+') ptr++; /* require at least one digit */ if (!isdigit((unsigned char) *ptr)) { if (errorOK) return false; else ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input syntax for integer: \"%s\"", str))); } /* process digits */ while (*ptr && isdigit((unsigned char) *ptr)) { int64 newtmp = tmp * 10 + (*ptr++ - '0'); if ((newtmp / 10) != tmp) /* overflow? */ { if (errorOK) return false; else ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("value \"%s\" is out of range for type bigint", str))); } tmp = newtmp; } gotdigits: /* allow trailing whitespace, but not other trailing chars */ while (*ptr != '\0' && isspace((unsigned char) *ptr)) ptr++; if (*ptr != '\0') { if (errorOK) return false; else ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input syntax for integer: \"%s\"", str))); } *result = (sign < 0) ? -tmp : tmp; return true; }
int smgrGetAppendOnlyMirrorResyncEofs(EndXactRecKind endXactRecKind, PersistentEndXactAppendOnlyMirrorResyncEofs **ptr) { int nestLevel = GetCurrentTransactionNestLevel(); int nentries; PersistentEndXactAppendOnlyMirrorResyncEofs *rptr; HASH_SEQ_STATUS iterateStatus; AppendOnlyMirrorResyncEofs *entry; int entryIndex; if (endXactRecKind == EndXactRecKind_Abort) { /* * No Append-Only Mirror Resync EOF information needed on abort. */ *ptr = NULL; return 0; } nentries = 0; if (AppendOnlyMirrorResyncEofsTable != NULL) { hash_seq_init(&iterateStatus, AppendOnlyMirrorResyncEofsTable); while ((entry = hash_seq_search(&iterateStatus)) != NULL) { if (entry->key.nestLevel >= nestLevel) nentries++; } } if (nentries == 0) { *ptr = NULL; return 0; } if (Debug_persistent_print || Debug_persistent_appendonly_commit_count_print) elog(Persistent_DebugPrintLevel(), "Storage Manager: Get Append-Only mirror resync eofs list entries (current transaction nest level %d, Append-Only commit work system count %d)", nestLevel, FileRepPrimary_GetAppendOnlyCommitWorkCount()); rptr = (PersistentEndXactAppendOnlyMirrorResyncEofs *) palloc(nentries * sizeof(PersistentEndXactAppendOnlyMirrorResyncEofs)); *ptr = rptr; entryIndex = 0; hash_seq_init(&iterateStatus, AppendOnlyMirrorResyncEofsTable); while ((entry = hash_seq_search(&iterateStatus)) != NULL) { MIRRORED_LOCK_DECLARE; bool returned; int resultSystemAppendOnlyCommitCount; returned = false; if (entry->key.nestLevel >= nestLevel) { MIRRORED_LOCK; MirroredAppendOnly_EndXactCatchup(entryIndex, &entry->key.relFileNode, entry->key.segmentFileNum, entry->key.nestLevel, entry->relationName, &entry->persistentTid, entry->persistentSerialNum, &mirroredLockLocalVars, entry->mirrorCatchupRequired, entry->mirrorDataLossTrackingState, entry->mirrorDataLossTrackingSessionNum, entry->mirrorNewEof); /* * See if the mirror situation for this Append-Only segment file * has changed since we flushed it to disk. */ rptr->relFileNode = entry->key.relFileNode; rptr->segmentFileNum = entry->key.segmentFileNum; rptr->persistentTid = entry->persistentTid; rptr->persistentSerialNum = entry->persistentSerialNum; if (entry->mirrorCatchupRequired) { rptr->mirrorLossEof = INT64CONST(-1); } else { rptr->mirrorLossEof = entry->mirrorNewEof; } rptr->mirrorNewEof = entry->mirrorNewEof; rptr++; returned = true; START_CRIT_SECTION(); LWLockAcquire(FileRepAppendOnlyCommitCountLock, LW_EXCLUSIVE); resultSystemAppendOnlyCommitCount = FileRepPrimary_IntentAppendOnlyCommitWork(); /* Set this inside the Critical Section. */ entry->didIncrementCommitCount = true; if (endXactRecKind == EndXactRecKind_Prepare) { char gid[TMGIDSIZE]; if (!getDistributedTransactionIdentifier(gid)) elog(ERROR, "Unable to obtain gid during prepare"); PrepareIntentAppendOnlyCommitWork(gid); entry->isDistributedTransaction = true; memcpy(entry->gid, gid, TMGIDSIZE); } pendingAppendOnlyMirrorResyncIntentCount++; } else { MIRRORED_LOCK; START_CRIT_SECTION(); LWLockAcquire(FileRepAppendOnlyCommitCountLock, LW_EXCLUSIVE); resultSystemAppendOnlyCommitCount = FileRepPrimary_GetAppendOnlyCommitWorkCount(); } if (Debug_persistent_print || Debug_persistent_appendonly_commit_count_print) { if (entry->relationName == NULL) elog(Persistent_DebugPrintLevel(), "Storage Manager: Get Append-Only mirror resync eofs list entry #%d: %u/%u/%u, segment file #%d " "(returned %s, result system Append-Only commit count %d, transaction nest level %d, persistent TID %s, persistent serial number " INT64_FORMAT ", mirror catchup required %s, mirror new EOF " INT64_FORMAT ")", entryIndex, entry->key.relFileNode.spcNode, entry->key.relFileNode.dbNode, entry->key.relFileNode.relNode, entry->key.segmentFileNum, (returned ? "true" : "false"), resultSystemAppendOnlyCommitCount, entry->key.nestLevel, ItemPointerToString(&entry->persistentTid), entry->persistentSerialNum, (entry->mirrorCatchupRequired ? "true" : "false"), entry->mirrorNewEof); else elog(Persistent_DebugPrintLevel(), "Storage Manager: Get Append-Only mirror resync eofs list entry #%d: %u/%u/%u, segment file #%d, relation name '%s' " "(returned %s, result system Append-Only commit count %d, transaction nest level %d, persistent TID %s, persistent serial number " INT64_FORMAT ", mirror catchup required %s, mirror new EOF " INT64_FORMAT ")", entryIndex, entry->key.relFileNode.spcNode, entry->key.relFileNode.dbNode, entry->key.relFileNode.relNode, entry->key.segmentFileNum, entry->relationName, (returned ? "true" : "false"), resultSystemAppendOnlyCommitCount, entry->key.nestLevel, ItemPointerToString(&entry->persistentTid), entry->persistentSerialNum, (entry->mirrorCatchupRequired ? "true" : "false"), entry->mirrorNewEof); } LWLockRelease(FileRepAppendOnlyCommitCountLock); END_CRIT_SECTION(); MIRRORED_UNLOCK; entryIndex++; } return nentries; }
/* timestamp2tm() * Convert timestamp data type to POSIX time structure. * Note that year is _not_ 1900-based, but is an explicit full value. * Also, month is one-based, _not_ zero-based. * Returns: * 0 on success * -1 on out of range * * For dates within the system-supported time_t range, convert to the * local time zone. If out of this range, leave as GMT. - tgl 97/05/27 */ static int timestamp2tm(timestamp dt, int *tzp, struct tm * tm, fsec_t *fsec, char **tzn) { #ifdef HAVE_INT64_TIMESTAMP int64 dDate, date0; int64 time; #else double dDate, date0; double time; #endif time_t utime; #if defined(HAVE_TM_ZONE) || defined(HAVE_INT_TIMEZONE) struct tm *tx; #endif date0 = date2j(2000, 1, 1); #ifdef HAVE_INT64_TIMESTAMP time = dt; TMODULO(time, dDate, USECS_PER_DAY); if (time < INT64CONST(0)) { time += USECS_PER_DAY; dDate -= 1; } /* add offset to go from J2000 back to standard Julian date */ dDate += date0; /* Julian day routine does not work for negative Julian days */ if (dDate < 0 || dDate > (timestamp) INT_MAX) return -1; j2date((int) dDate, &tm->tm_year, &tm->tm_mon, &tm->tm_mday); dt2time(time, &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec); #else time = dt; TMODULO(time, dDate, (double) SECS_PER_DAY); if (time < 0) { time += SECS_PER_DAY; dDate -= 1; } /* add offset to go from J2000 back to standard Julian date */ dDate += date0; recalc_d: /* Julian day routine does not work for negative Julian days */ if (dDate < 0 || dDate > (timestamp) INT_MAX) return -1; j2date((int) dDate, &tm->tm_year, &tm->tm_mon, &tm->tm_mday); recalc_t: dt2time(time, &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec); *fsec = TSROUND(*fsec); /* roundoff may need to propagate to higher-order fields */ if (*fsec >= 1.0) { time = ceil(time); if (time >= (double) SECS_PER_DAY) { time = 0; dDate += 1; goto recalc_d; } goto recalc_t; } #endif if (tzp != NULL) { /* * Does this fall within the capabilities of the localtime() * interface? Then use this to rotate to the local time zone. */ if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday)) { #ifdef HAVE_INT64_TIMESTAMP utime = dt / USECS_PER_SEC + ((date0 - date2j(1970, 1, 1)) * INT64CONST(86400)); #else utime = dt + (date0 - date2j(1970, 1, 1)) * SECS_PER_DAY; #endif #if defined(HAVE_TM_ZONE) || defined(HAVE_INT_TIMEZONE) tx = localtime(&utime); tm->tm_year = tx->tm_year + 1900; tm->tm_mon = tx->tm_mon + 1; tm->tm_mday = tx->tm_mday; tm->tm_hour = tx->tm_hour; tm->tm_min = tx->tm_min; tm->tm_isdst = tx->tm_isdst; #if defined(HAVE_TM_ZONE) tm->tm_gmtoff = tx->tm_gmtoff; tm->tm_zone = tx->tm_zone; *tzp = -tm->tm_gmtoff; /* tm_gmtoff is Sun/DEC-ism */ if (tzn != NULL) *tzn = (char *) tm->tm_zone; #elif defined(HAVE_INT_TIMEZONE) *tzp = (tm->tm_isdst > 0) ? TIMEZONE_GLOBAL - SECS_PER_HOUR : TIMEZONE_GLOBAL; if (tzn != NULL) *tzn = TZNAME_GLOBAL[(tm->tm_isdst > 0)]; #endif #else /* not (HAVE_TM_ZONE || HAVE_INT_TIMEZONE) */ *tzp = 0; /* Mark this as *no* time zone available */ tm->tm_isdst = -1; if (tzn != NULL) *tzn = NULL; #endif dt = dt2local(dt, *tzp); } else { *tzp = 0; /* Mark this as *no* time zone available */ tm->tm_isdst = -1; if (tzn != NULL) *tzn = NULL; } } else { tm->tm_isdst = -1; if (tzn != NULL) *tzn = NULL; } return 0; } /* timestamp2tm() */
int32 Timestamp_getTimeZone_id(int64 dt) { return Timestamp_getTimeZone( (dt / INT64CONST(1000000) + (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * 86400)); }