Changeset: 707217a26951 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=707217a26951
Modified Files:
        .hgignore
        clients/R/MonetDB.R/R/dplyr.R
        clients/Tests/exports.stable.out
        gdk/gdk.h
        gdk/gdk_logger.c
        gdk/gdk_logger.h
        gdk/gdk_private.h
        gdk/gdk_storage.c
        gdk/gdk_utils.c
        gdk/gdk_utils.h
        monetdb5/mal/mal_session.c
        monetdb5/modules/kernel/logger.c
        sql/backends/monet5/sql_scenario.c
        sql/jdbc/tests/Tests/Test_Dobjects.stable.out
        sql/scripts/99_system.sql
        sql/server/sql_mvc.c
        sql/storage/bat/bat_logger.c
        sql/storage/bat/bat_logger.h
        sql/storage/restrict/restrict_logger.c
        sql/storage/sql_storage.h
        sql/storage/store.c
        sql/test/Tests/systemfunctions.stable.out
        sql/test/leaks/Tests/check0.stable.out
        sql/test/leaks/Tests/check0.stable.out.int128
        sql/test/leaks/Tests/check1.stable.out
        sql/test/leaks/Tests/check1.stable.out.int128
        sql/test/leaks/Tests/check2.stable.out
        sql/test/leaks/Tests/check2.stable.out.int128
        sql/test/leaks/Tests/check3.stable.out
        sql/test/leaks/Tests/check3.stable.out.int128
        sql/test/leaks/Tests/check4.stable.out
        sql/test/leaks/Tests/check4.stable.out.int128
        sql/test/leaks/Tests/check5.stable.out
        sql/test/leaks/Tests/check5.stable.out.int128
        sql/test/leaks/Tests/drop3.stable.out
        sql/test/leaks/Tests/drop3.stable.out.int128
        sql/test/leaks/Tests/select1.stable.out
        sql/test/leaks/Tests/select1.stable.out.int128
        sql/test/leaks/Tests/select2.stable.out
        sql/test/leaks/Tests/select2.stable.out.int128
        sql/test/leaks/Tests/temp1.stable.out
        sql/test/leaks/Tests/temp1.stable.out.int128
        sql/test/leaks/Tests/temp2.stable.out
        sql/test/leaks/Tests/temp2.stable.out.int128
        sql/test/leaks/Tests/temp3.stable.out
        sql/test/leaks/Tests/temp3.stable.out.int128
        tools/merovingian/daemon/argvcmds.c
        tools/merovingian/daemon/argvcmds.h
        tools/merovingian/daemon/discoveryrunner.c
        tools/merovingian/daemon/discoveryrunner.h
        tools/merovingian/daemon/forkmserver.c
        tools/merovingian/daemon/merovingian.c
        tools/merovingian/utils/properties.c
        tools/merovingian/utils/properties.h
        tools/merovingian/utils/utils.c
        tools/merovingian/utils/utils.h
Branch: default
Log Message:

Merge transaction-replication into default


diffs (truncated from 2391 to 300 lines):

diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -91,3 +91,8 @@ NT/sql
 NT/testing
 NT/tools
 NT/unistd.h
+
+syntax: regexp
+^java/build$
+syntax: regexp
+^java/target$
diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out
--- a/clients/Tests/exports.stable.out
+++ b/clients/Tests/exports.stable.out
@@ -248,8 +248,10 @@ int GDKdebug;
 void GDKerror(_In_z_ _Printf_format_string_ const char *format, ...) 
__attribute__((__format__(__printf__, 1, 2)));
 void GDKexit(int status) __attribute__((__noreturn__));
 int GDKexiting(void);
+int GDKextractParentAndLastDirFromPath(const char *path, char 
*last_dir_parent, char *last_dir);
 void GDKfatal(_In_z_ _Printf_format_string_ const char *format, ...) 
__attribute__((__format__(__printf__, 1, 2))) __attribute__((__noreturn__));
 char *GDKfilepath(int farmid, const char *dir, const char *nme, const char 
*ext);
+char *GDKfilepath_long(int farmid, const char *dir, const char *ext);
 void GDKfree(void *blk);
 char *GDKgetenv(const char *name);
 int GDKgetenv_int(const char *name, int def);
@@ -417,12 +419,15 @@ int log_tend(logger *lg);
 int log_tstart(logger *lg);
 log_bid logger_add_bat(logger *lg, BAT *b, const char *name);
 lng logger_changes(logger *lg);
-int logger_cleanup(logger *lg);
-logger *logger_create(int debug, const char *fn, const char *logdir, int 
version, preversionfix_fptr prefuncp, postversionfix_fptr postfuncp);
+int logger_cleanup(logger *lg, int keep_persisted_log_files);
+logger *logger_create(int debug, const char *fn, const char *logdir, int 
version, preversionfix_fptr prefuncp, postversionfix_fptr postfuncp, int 
keep_persisted_log_files);
+logger *logger_create_shared(int debug, const char *fn, const char *logdir, 
const char *slave_logdir, int version, preversionfix_fptr prefuncp, 
postversionfix_fptr postfuncp);
 void logger_del_bat(logger *lg, log_bid bid);
 void logger_destroy(logger *lg);
 int logger_exit(logger *lg);
 log_bid logger_find_bat(logger *lg, const char *name);
+lng logger_read_last_transaction_id(logger *lg, char *dir, char *logger_file, 
int role);
+int logger_reload(logger *lg);
 int logger_restart(logger *lg);
 int logger_sequence(logger *lg, int seq, lng *id);
 void *mdlopen(const char *library, int mode);
diff --git a/gdk/gdk.h b/gdk/gdk.h
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -1487,6 +1487,8 @@ gdk_export int BATgetaccess(BAT *b);
 
 #define PERSISTENT             0
 #define TRANSIENT              1
+#define LOG_DIR                        2
+#define SHARED_LOG_DIR 3
 
 #define BAT_WRITE              0       /* all kinds of access allowed */
 #define BAT_READ               1       /* only read-access allowed */
@@ -1568,6 +1570,7 @@ gdk_export size_t BATmemsize(BAT *b, int
 #define NOFARM (-1) /* indicate to GDKfilepath to create relative path */
 
 gdk_export char *GDKfilepath(int farmid, const char *dir, const char *nme, 
const char *ext);
+gdk_export char *GDKfilepath_long(int farmid, const char *dir, const char 
*ext);
 gdk_export gdk_return GDKcreatedir(const char *nme);
 
 /*
diff --git a/gdk/gdk_logger.c b/gdk/gdk_logger.c
--- a/gdk/gdk_logger.c
+++ b/gdk/gdk_logger.c
@@ -96,8 +96,6 @@ typedef struct logformat_t {
        lng nr;
 } logformat;
 
-#define LOGFILE "log"
-
 static int bm_commit(logger *lg);
 static int tr_grow(trans *tr);
 
@@ -851,12 +849,60 @@ tr_abort(logger *lg, trans *tr)
 
 static int log_sequence_nrs(logger *lg);
 
+/* Update the last transaction id written in the catalog file.
+ * Only used by the shared logger. */
+static int
+logger_update_catalog_file(logger *lg, const char *dir, const char *filename, 
int role)
+{
+       FILE *fp;
+       int bak_exists;
+       int farmid = BBPselectfarm(role, 0, offheap);
+
+       bak_exists = 0;
+       /* check if an older file exists and move bak it up */
+#if defined(_MSC_VER)
+       if (_access(filename, 0) != -1) {
+#else
+       if (access(filename, 0) != -1) {
+#endif
+               bak_exists = 1;
+               if (GDKmove(farmid, dir, filename, NULL, dir, filename, "bak") 
== GDK_FAIL) {
+                       fprintf(stderr, "!ERROR: logger_update_catalog_file: 
rename %s to %s.bak in %s failed\n", filename, filename, dir);
+                       return LOG_ERR;
+               }
+       }
+
+       if ((fp = GDKfileopen(farmid, dir, filename, NULL, "w")) != NULL) {
+               if (fprintf(fp, "%06d\n\n", lg->version) < 0) {
+                       fprintf(stderr, "!ERROR: logger_update_catalog_file: 
write to %s failed\n", filename);
+                       return LOG_ERR;
+               }
+
+               if (fprintf(fp, LLFMT "\n", lg->id) < 0 || fclose(fp) < 0) {
+                       fprintf(stderr, "!ERROR: logger_update_catalog_file: 
write/flush to %s failed\n", filename);
+                       return LOG_ERR;
+               }
+
+               /* cleanup the bak file, if it exists*/
+               if (bak_exists) {
+                       GDKunlink(farmid, dir, filename, "bak");
+               }
+       } else {
+               fprintf(stderr, "!ERROR: logger_update_catalog_file: could not 
create %s\n", filename);
+               GDKerror("logger_update_catalog_file: could not open %s\n", 
filename);
+               return LOG_ERR;
+       }
+       return LOG_OK;
+}
+
 static int
 logger_open(logger *lg)
 {
-       char filename[BUFSIZ];
+       char id[BUFSIZ];
+       char *filename;
 
-       snprintf(filename, sizeof(filename), "%s%s." LLFMT, lg->dir, LOGFILE, 
lg->id);
+       snprintf(id, sizeof(id), LLFMT, lg->id);
+       filename = GDKfilepath(BBPselectfarm(lg->dbfarm_role, 0, offheap), 
lg->dir, LOGFILE, id);
 
        lg->log = open_wstream(filename);
        lg->end = 0;
@@ -888,21 +934,28 @@ logger_readlog(logger *lg, char *filenam
        time_t t0, t1;
        struct stat sb;
        lng fpos;
+       char* path = GDKfilepath_long(BBPselectfarm(lg->dbfarm_role, 0, 
offheap), filename, NULL);
 
-       lg->log = open_rstream(filename);
+       if (lg->debug & 1) {
+               fprintf(stderr, "#logger_readlog opening %s\n", filename);
+       }
+
+       lg->log = open_rstream(path);
 
        /* if the file doesn't exist, there is nothing to be read back */
        if (!lg->log || mnstr_errnr(lg->log)) {
                if (lg->log)
                        mnstr_destroy(lg->log);
                lg->log = NULL;
-               return 0;
+               return LOG_ERR;
        }
        if (fstat(fileno(getFile(lg->log)), &sb) < 0) {
                fprintf(stderr, "!ERROR: logger_readlog: fstat on opened file 
%s failed\n", filename);
                mnstr_destroy(lg->log);
                lg->log = NULL;
-               return 0;
+               /* If we can't read the files, it might simply be empty.
+                * In that case we can't return LOG_ERR, since it's actually 
fine */
+               return 1;
        }
        t0 = time(NULL);
        printf("# Start reading the write-ahead log '%s'\n", filename);
@@ -1008,31 +1061,35 @@ logger_readlog(logger *lg, char *filenam
        t0 = time(NULL);
        printf("# Finished reading the write-ahead log '%s'\n", filename);
        fflush(stdout);
-       return 0;
+       return LOG_OK;
 }
 
 /*
- * The log files are incrementally numbered. They are processed in the
+ * The log files are incrementally numbered, starting from 2. They are 
processed in the
  * same sequence.
  */
 static int
 logger_readlogs(logger *lg, FILE *fp, char *filename)
 {
-       int res = 0;
+       int res = LOG_OK;
        char id[BUFSIZ];
 
-       if (lg->debug & 1)
-               fprintf(stderr, "#logger_readlogs %s\n", filename);
+       if (lg->debug & 1) {
+               fprintf(stderr, "#logger_readlogs logger id is " LLFMT "\n", 
lg->id);
+       }
 
        while (fgets(id, sizeof(id), fp) != NULL) {
-               char buf[BUFSIZ];
+               char log_filename[BUFSIZ];
                lng lid = strtoll(id, NULL, 10);
 
-               if (lid >= lg->id) {
+               if (lg->debug & 1) {
+                       fprintf(stderr, "#logger_readlogs last logger id 
written in %s is " LLFMT "\n", filename, lid);
+               }
+
+               if (!lg->shared && lid >= lg->id) {
                        lg->id = lid;
-                       snprintf(buf, sizeof(buf), "%s." LLFMT, filename, 
lg->id);
-
-                       if ((res = logger_readlog(lg, buf)) != 0) {
+                       snprintf(log_filename, sizeof(log_filename), "%s." 
LLFMT, filename, lg->id);
+                       if ((res = logger_readlog(lg, log_filename)) != 0) {
                                /* we cannot distinguish errors from
                                 * incomplete transactions (even if we
                                 * would log aborts in the logs). So
@@ -1040,6 +1097,27 @@ logger_readlogs(logger *lg, FILE *fp, ch
                                 * next log file */
                                (void) res;
                        }
+               } else {
+                       while (lid >= lg->id && res != LOG_ERR) {
+                               snprintf(log_filename, sizeof(log_filename), 
"%s." LLFMT, filename, lg->id);
+                               if ((logger_readlog(lg, log_filename)) == 
LOG_ERR && lg->shared && lg->id > 1) {
+                                       /* The only special case is if the 
files is missing altogether
+                                        * and the logger is a shared one,
+                                        * then we have missing transactions 
and we should abort.
+                                        * Yeah, and we also ignore the 1st 
files it most likely never exists. */
+                                       res = LOG_ERR;
+                                       fprintf(stderr, "#logger_readlogs 
missing shared logger file %s. Aborting\n", log_filename);
+                               }
+                               /* Increment the id only at the end, since we 
want to re-read the last file.
+                                * That is because last time we read it, it was 
empty, since the logger creates empty files
+                                * and fills them in later. */
+                lg->id++;
+                       }
+            if (lid < lg->id) {
+                lg->id = lid;
+            }
+                       /* if this is a shared logger, write the id in the 
shared file */
+                       logger_update_catalog_file(lg, lg->local_dir, 
LOGFILE_SHARED, lg->local_dbfarm_role);
                }
        }
        return res;
@@ -1214,77 +1292,70 @@ logger_fatal(const char *format, const c
        GDKexit(1);
 }
 
-static logger *
-logger_new(int debug, const char *fn, const char *logdir, int version, 
preversionfix_fptr prefuncp, postversionfix_fptr postfuncp)
+/* Set the logdir path, add a dbfarm if needed.
+ * Returns the role of the dbfarm containing the logdir.
+ */
+static int
+logger_set_logdir_path(char *filename, const char *fn, const char *logdir, int 
shared) {
+       int role = PERSISTENT; /* default role is persistent, i.e. the default 
dbfarm */
+
+       if (MT_path_absolute(logdir)) {
+               char logdir_parent_path[BUFSIZ] = "";
+               char logdir_name[BUFSIZ] = "";
+               /* split the logdir string into absolute parent dir path and 
(relative) log dir name */
+               if (GDKextractParentAndLastDirFromPath(logdir, 
logdir_parent_path, logdir_name)) {
+                       /* set the new relative logdir locaiton including the 
logger function name subdir */
+                       snprintf(filename, BUFSIZ, "%s%c%s%c", logdir_name, 
DIR_SEP, fn, DIR_SEP);
+
+                       /* add a new dbfarm for the logger directory using the 
parent dir path,
+                        * assuming it is set, s.t. the logs are stored in a 
location other than the default dbfarm,
+                        * or at least it appears so to (multi)dbfarm aware 
functions */
+                       if (!shared) {
+                               role = LOG_DIR;
+                       } else {
+                               role = SHARED_LOG_DIR;
+                       }
+                       BBPaddfarm(logdir_parent_path, 1 << role);
+               } else {
+                       logger_fatal("logger_set_logdir_path: logdir path is 
not correct (%s)."
+                                       "Make sure you specify a valid absolute 
or relative path.\n", logdir, 0, 0);
+               }
+       } else {
+               /* just concat the logdir and fn with appropriate separators */
+               snprintf(filename, BUFSIZ, "%s%c%s%c", logdir, DIR_SEP, fn, 
DIR_SEP);
+       }
+
+       return role;
+}
+
+/* Load data from the logger logdir
+ * Initialize new directories and catalog files if none are present, unless 
running in read-only mode
+ * Load data and persist it in the BATs
+ * Convert 32bit data to 64bit, unless running in read-only mode */
+static int
+logger_load(int debug, const char* fn, char filename[BUFSIZ], logger* lg)
 {
        int id = LOG_SID;
-       logger *lg;
        FILE *fp;
-       char filename[BUFSIZ];
        char bak[BUFSIZ];
-       log_bid snapshots_bid = 0;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to