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
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to