Changeset: 89a284108096 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=89a284108096
Modified Files:
gdk/gdk.h
gdk/gdk_bbp.c
gdk/gdk_logger.c
gdk/gdk_logger.h
gdk/gdk_private.h
monetdb5/modules/atoms/mtime.c
monetdb5/modules/atoms/mtime.h
Branch: mtime
Log Message:
Changed internal representation of the date type.
The internal representation now consists of a number of months since
an epoch and separately the day within that month.
diffs (truncated from 1274 to 300 lines):
diff --git a/gdk/gdk.h b/gdk/gdk.h
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -778,7 +778,8 @@ typedef struct {
#define GDKLIBRARY_TALIGN 061036U /* talign field in BBP.dir */
#define GDKLIBRARY_NIL_NAN 061037U /* flt/dbl NIL not represented by NaN */
#define GDKLIBRARY_BLOB_SORT 061040U /* blob compare changed */
-#define GDKLIBRARY 061041U
+#define GDKLIBRARY_OLDDATE 061041U
+#define GDKLIBRARY 061042U
typedef struct BAT {
/* static bat properties */
diff --git a/gdk/gdk_bbp.c b/gdk/gdk_bbp.c
--- a/gdk/gdk_bbp.c
+++ b/gdk/gdk_bbp.c
@@ -586,6 +586,267 @@ fixfloatbats(void)
}
#endif
+#ifdef GDKLIBRARY_OLDDATE
+#define leapyear(y) ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400
== 0))
+#define YEARDAYS(y) (leapyear(y) ? 366 : 365)
+static int CUMLEAPDAYS[13] = {
+ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366
+};
+static int CUMDAYS[13] = {
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
+};
+static int
+leapyears(int year)
+{
+ /* count the 4-fold years that passed since jan-1-0 */
+ int y4 = year / 4;
+
+ /* count the 100-fold years */
+ int y100 = year / 100;
+
+ /* count the 400-fold years */
+ int y400 = year / 400;
+
+ return y4 + y400 - y100 + (year >= 0); /* may be negative */
+}
+
+#define YEAR_OFFSET 4712
+#define DTDAY_WIDTH 5 /* 1..28/29/30/31, depending on month */
+#define DTDAY_SHIFT 0
+#define DTMONTH_WIDTH 21 /* enough for 174762 year */
+#define DTMONTH_SHIFT (DTDAY_WIDTH+DTDAY_SHIFT)
+#define mkdate(d, m, y) (((((y) + YEAR_OFFSET) * 12 + (m) - 1) <<
DTMONTH_SHIFT) \
+ | ((d) << DTDAY_SHIFT))
+int
+cvtdate(int n)
+{
+ int day, month, year;
+
+ year = n / 365;
+ day = (n - year * 365) - leapyears(year >= 0 ? year - 1 : year);
+ if (n < 0) {
+ year--;
+ while (day >= 0) {
+ year++;
+ day -= YEARDAYS(year);
+ }
+ day = YEARDAYS(year) + day;
+ } else {
+ while (day < 0) {
+ year--;
+ day += YEARDAYS(year);
+ }
+ }
+
+ day++;
+ if (leapyear(year)) {
+ for (month = day / 31 == 0 ? 1 : day / 31; month <= 12; month++)
+ if (day > CUMLEAPDAYS[month - 1] && day <=
CUMLEAPDAYS[month]) {
+ break;
+ }
+ day -= CUMLEAPDAYS[month - 1];
+ } else {
+ for (month = day / 31 == 0 ? 1 : day / 31; month <= 12; month++)
+ if (day > CUMDAYS[month - 1] && day <= CUMDAYS[month]) {
+ break;
+ }
+ day -= CUMDAYS[month - 1];
+ }
+ /* clamp date */
+ if (year < -YEAR_OFFSET) {
+ day = 1;
+ month = 1;
+ year = -YEAR_OFFSET;
+ } else if (year > ((1<<21)/12 - YEAR_OFFSET)) {
+ day = 31;
+ month = 12;
+ year = (1<<21)/12 - YEAR_OFFSET;
+ }
+ return mkdate(day, month, year);
+}
+
+static gdk_return
+fixdateheap(BAT *b, const char *anme)
+{
+ long_str filename;
+ Heap h1; /* old heap */
+ Heap h2; /* new heap */
+ const char *nme, *bnme;
+ char *srcdir;
+ BUN i;
+ bool nofix = true;
+
+ nme = BBP_physical(b->batCacheid);
+ srcdir = GDKfilepath(NOFARM, BATDIR, nme, NULL);
+ if (srcdir == NULL) {
+ return GDK_FAIL;
+ }
+ *strrchr(srcdir, DIR_SEP) = 0;
+
+ if ((bnme = strrchr(nme, DIR_SEP)) != NULL)
+ bnme++;
+ else
+ bnme = nme;
+ sprintf(filename, "BACKUP%c%s", DIR_SEP, bnme);
+
+ /* make backup of heap */
+ if (GDKmove(b->theap.farmid, srcdir, bnme, "tail", BAKDIR, bnme,
"tail") != GDK_SUCCEED) {
+ GDKfree(srcdir);
+ GDKerror("fixdateheap: cannot make backup of %s.tail\n", nme);
+ return GDK_FAIL;
+ }
+ /* load old heap */
+ h1 = b->theap;
+ stpconcat(h1.filename, filename, ".tail", NULL);
+ h1.base = NULL;
+ h1.dirty = false;
+ if (HEAPload(&h1, filename, "tail", false) != GDK_SUCCEED) {
+ GDKfree(srcdir);
+ GDKerror("fixdateheap: loading old tail heap "
+ "for BAT %d failed\n", b->batCacheid);
+ return GDK_FAIL;
+ }
+
+ /* create new heap */
+ h2 = b->theap;
+ stpconcat(h2.filename, nme, ".tail", NULL);
+ if (HEAPalloc(&h2, b->batCapacity, b->twidth) != GDK_SUCCEED) {
+ GDKfree(srcdir);
+ HEAPfree(&h1, false);
+ GDKerror("fixdateheap: allocating new tail heap "
+ "for BAT %d failed\n", b->batCacheid);
+ return GDK_FAIL;
+ }
+ h2.dirty = true;
+ h2.free = h1.free;
+
+ if (strcmp(anme, "date") == 0) {
+ const int *restrict o = (const int *) h1.base;
+ int *restrict n = (int *) h2.base;
+
+ for (i = 0; i < b->batCount; i++) {
+ if (is_int_nil(o[i])) {
+ b->tnil = true;
+ n[i] = int_nil;
+ } else {
+ n[i] = cvtdate(o[i]);
+ nofix = false;
+ }
+ }
+ } else {
+ union timestamp {
+ lng l;
+ struct {
+#ifndef WORDS_BIGENDIAN
+ int p_msecs;
+ int p_days;
+#else
+ int p_days;
+ int p_msecs;
+#endif
+ } t;
+ };
+ const union timestamp *restrict o = (const union timestamp *)
h1.base;
+ union timestamp *restrict n = (union timestamp *) h2.base;
+ for (i = 0; i < b->batCount; i++) {
+ if (is_lng_nil(o[i].l)) {
+ b->tnil = true;
+ n[i].l = lng_nil;
+ } else {
+ n[i].t.p_days = cvtdate(o[i].t.p_days);
+ n[i].t.p_msecs = o[i].t.p_msecs;
+ nofix = false;
+ }
+ }
+ }
+
+ /* cleanup */
+ HEAPfree(&h1, false);
+ if (nofix) {
+ /* didn't fix anything, move backup back */
+ HEAPfree(&h2, true);
+ if (GDKmove(b->theap.farmid, BAKDIR, bnme, "tail", srcdir,
bnme, "tail") != GDK_SUCCEED) {
+ GDKfree(srcdir);
+ GDKerror("fixdateheap: cannot restore backup of
%s.tail\n", nme);
+ return GDK_FAIL;
+ }
+ } else {
+ /* heap was fixed */
+ b->batDirtydesc = true;
+ if (HEAPsave(&h2, nme, "tail") != GDK_SUCCEED) {
+ HEAPfree(&h2, false);
+ GDKfree(srcdir);
+ GDKerror("fixdateheap: saving heap failed\n");
+ return GDK_FAIL;
+ }
+ HEAPfree(&h2, false);
+ b->theap = h2;
+ }
+ GDKfree(srcdir);
+ return GDK_SUCCEED;
+}
+
+static gdk_return
+fixdatebats(void)
+{
+ bat bid;
+ BAT *b;
+ char filename[FILENAME_MAX];
+ FILE *fp;
+ size_t len;
+ int written;
+
+ for (bid = 1; bid < (bat) ATOMIC_GET(&BBPsize); bid++) {
+ if ((b = BBP_desc(bid)) == NULL) {
+ /* not a valid BAT */
+ continue;
+ }
+ if (BBP_logical(bid) &&
+ (len = strlen(BBP_logical(bid))) > 12 &&
+ strcmp(BBP_logical(bid) + len - 12, "_catalog_nme") == 0) {
+ /* this is one of the files used by the
+ * logger. We need to communicate to the
+ * logger that it also needs to do a
+ * conversion. That is done by creating a
+ * file here based on the name of this BAT. */
+ written = snprintf(filename, sizeof(filename),
+ "%s/%.*s_date-convert",
+ BBPfarms[0].dirname,
+ (int) (len - 12), BBP_logical(bid));
+ if (written == -1 || written >= FILENAME_MAX) {
+ GDKerror("fixdatebats: cannot create file %s
has a very large pathname\n",
+ filename);
+ return GDK_FAIL;
+ }
+ fp = fopen(filename, "w");
+ if (fp == NULL) {
+ GDKsyserror("fixdatebats: cannot create file
%s\n",
+ filename);
+ return GDK_FAIL;
+ }
+ fclose(fp);
+ }
+ if (b->batCount == 0 || b->tnonil) {
+ /* no NILs to convert */
+ continue;
+ }
+ /* The date type is not known in GDK when reading the BBP */
+ if (b->ttype < 0) {
+ const char *anme;
+
+ /* as yet unknown tail column type */
+ anme = ATOMunknown_name(b->ttype);
+ /* known string types */
+ if ((strcmp(anme, "date") == 0 ||
+ strcmp(anme, "timestamp") == 0) &&
+ fixdateheap(b, anme) != GDK_SUCCEED)
+ return GDK_FAIL;
+ }
+ }
+ return GDK_SUCCEED;
+}
+#endif
+
static int
heapinit(BAT *b, const char *buf, int *hashash, unsigned bbpversion, bat bid,
const char *filename)
{
@@ -1250,6 +1511,11 @@ BBPinit(void)
if (fixfloatbats() != GDK_SUCCEED)
return GDK_FAIL;
#endif
+#ifdef GDKLIBRARY_OLDDATE
+ if (bbpversion <= GDKLIBRARY_OLDDATE)
+ if (fixdatebats() != GDK_SUCCEED)
+ return GDK_FAIL;
+#endif
if (bbpversion < GDKLIBRARY)
TMcommit();
return GDK_SUCCEED;
diff --git a/gdk/gdk_logger.c b/gdk/gdk_logger.c
--- a/gdk/gdk_logger.c
+++ b/gdk/gdk_logger.c
@@ -400,6 +400,47 @@ mbrRead(void *dst, stream *s, size_t cnt
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list