Changeset: b0cbfd75f3d2 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/b0cbfd75f3d2
Modified Files:
gdk/gdk_logger.c
sql/server/rel_exp.c
sql/storage/sql_storage.h
sql/storage/store.c
sql/storage/store_sequence.c
sql/storage/store_sequence.h
Branch: Jan2022
Log Message:
handle sequence numbers differently, ie log them only within the real
sql_trans_commit code.
ie store_sequnce structs are added to a list (seqchanges), which are logged in
the first committing trans.
diffs (truncated from 591 to 300 lines):
diff --git a/gdk/gdk_logger.c b/gdk/gdk_logger.c
--- a/gdk/gdk_logger.c
+++ b/gdk/gdk_logger.c
@@ -286,6 +286,8 @@ log_read_seq(logger *lg, logformat *l)
TRC_CRITICAL(GDK, "read failed\n");
return LOG_EOF;
}
+ if (lg->flushing)
+ return LOG_OK;
if ((p = log_find(lg->seqs_id, lg->dseqs, seq)) != BUN_NONE &&
p >= lg->seqs_id->batInserted) {
@@ -2766,7 +2768,7 @@ log_tdone(logger *lg, ulng commit_ts)
}
static gdk_return
-log_sequence_(logger *lg, int seq, lng val, int flush)
+log_sequence_(logger *lg, int seq, lng val)
{
logformat l;
@@ -2779,9 +2781,7 @@ log_sequence_(logger *lg, int seq, lng v
fprintf(stderr, "#log_sequence_ (%d," LLFMT ")\n", seq, val);
if (log_write_format(lg, &l) != GDK_SUCCEED ||
- !mnstr_writeLng(lg->output_log, val) ||
- (flush && mnstr_flush(lg->output_log, MNSTR_FLUSH_DATA)) ||
- (flush && !(GDKdebug & NOSYNCMASK) && mnstr_fsync(lg->output_log)))
{
+ !mnstr_writeLng(lg->output_log, val)) {
TRC_CRITICAL(GDK, "write failed\n");
return GDK_FAIL;
}
@@ -2819,7 +2819,7 @@ log_sequence(logger *lg, int seq, lng va
return GDK_FAIL;
}
}
- gdk_return r = log_sequence_(lg, seq, val, 1);
+ gdk_return r = log_sequence_(lg, seq, val);
logger_unlock(lg);
return r;
}
diff --git a/sql/server/rel_exp.c b/sql/server/rel_exp.c
--- a/sql/server/rel_exp.c
+++ b/sql/server/rel_exp.c
@@ -1270,6 +1270,9 @@ exp_match_list( list *l, list *r)
return l == r;
if (list_length(l) != list_length(r) || list_length(l) == 0 ||
list_length(r) == 0)
return 0;
+ if (list_length(l) > 10 || list_length(r) > 10)
+ return 0;/* to expensive */
+
lu = ZNEW_ARRAY(char, list_length(l));
ru = ZNEW_ARRAY(char, list_length(r));
if (!lu || !ru) {
diff --git a/sql/storage/sql_storage.h b/sql/storage/sql_storage.h
--- a/sql/storage/sql_storage.h
+++ b/sql/storage/sql_storage.h
@@ -490,6 +490,8 @@ typedef struct sqlstore {
list *changes; /* pending changes to cleanup */
sql_hash *dependencies; /* pending dependencies created to cleanup */
sql_hash *depchanges; /* pending dependencies changes to cleanup */
+ list *seqchanges; /* pending sequence number changes to
be add to the first commiting transaction */
+ sql_hash *sequences; /* loaded store sequence numbers */
sql_allocator *sa; /* for now a store allocator, needs a
special version with free operations (with reuse) */
sqlid obj_id, prev_oid;
diff --git a/sql/storage/store.c b/sql/storage/store.c
--- a/sql/storage/store.c
+++ b/sql/storage/store.c
@@ -1802,10 +1802,6 @@ store_load(sqlstore *store, sql_allocato
/* we store some spare oids */
store->obj_id = FUNC_OIDS;
- if (!sequences_init()) {
- TRC_CRITICAL(SQL_STORE, "Allocation failure while initializing
store\n");
- return NULL;
- }
tr = sql_trans_create(store, NULL, NULL);
if (!tr) {
TRC_CRITICAL(SQL_STORE, "Failed to start a transaction while
loading the storage\n");
@@ -1818,6 +1814,8 @@ store_load(sqlstore *store, sql_allocato
store->active = list_create(NULL);
store->dependencies = hash_new(NULL, 32, (fkeyvalue)&dep_hash);
store->depchanges = hash_new(NULL, 32, (fkeyvalue)&dep_hash);
+ store->sequences = hash_new(NULL, 32, (fkeyvalue)&seq_hash);
+ store->seqchanges = list_create(NULL);
s = bootstrap_create_schema(tr, "sys", 2000, ROLE_SYSADMIN,
USER_MONETDB);
if (!store->first)
@@ -2206,13 +2204,14 @@ store_exit(sqlstore *store)
os_destroy(store->cat->objects, store);
os_destroy(store->cat->schemas, store);
_DELETE(store->cat);
- sequences_exit();
}
store->logger_api.destroy(store);
list_destroy(store->active);
dep_hash_destroy(store->dependencies);
dep_hash_destroy(store->depchanges);
+ list_destroy(store->seqchanges);
+ seq_hash_destroy(store->sequences);
TRC_DEBUG(SQL_STORE, "Store unlocked\n");
MT_lock_unset(&store->flush);
@@ -3936,6 +3935,17 @@ sql_trans_commit(sql_trans *tr)
if (c->log && ok == LOG_OK)
ok = c->log(tr, c);
}
+ if (ok == LOG_OK) {
+ if (!list_empty(store->seqchanges)) {
+ sequences_lock(store);
+ for(node *n = store->seqchanges->h; n;
n = n->next) {
+ log_store_sequence(store,
n->data);
+ }
+ list_destroy(store->seqchanges);
+ store->seqchanges = list_create(NULL);
+ sequences_unlock(store);
+ }
+ }
if (ok == LOG_OK && store->prev_oid != store->obj_id)
ok = store->logger_api.log_sequence(store,
OBJ_SID, store->obj_id);
store->prev_oid = store->obj_id;
diff --git a/sql/storage/store_sequence.c b/sql/storage/store_sequence.c
--- a/sql/storage/store_sequence.c
+++ b/sql/storage/store_sequence.c
@@ -10,14 +10,42 @@
#include "store_sequence.h"
#include "sql_storage.h"
+void
+sequences_lock(sql_store Store)
+{
+ sqlstore *store = Store;
+ MT_lock_set(&store->column_locks[NR_COLUMN_LOCKS-1]);
+}
+
+void
+sequences_unlock(sql_store Store)
+{
+ sqlstore *store = Store;
+ MT_lock_unset(&store->column_locks[NR_COLUMN_LOCKS-1]);
+}
+
typedef struct store_sequence {
sqlid seqid;
- bit called;
lng cur;
- lng cached;
+ bool called;
+ bool intrans;
} store_sequence;
-static list *sql_seqs = NULL;
+void
+log_store_sequence(sql_store Store, void *s)
+{
+ sqlstore *store = Store;
+ store_sequence *seq = s;
+ store->logger_api.log_sequence(store, seq->seqid,
(seq->called)?seq->cur:lng_nil);
+ seq->intrans = false;
+}
+
+int
+seq_hash(void *s)
+{
+ store_sequence *seq = s;
+ return seq->seqid;
+}
static void
sequence_destroy( void *dummy, store_sequence *s )
@@ -26,34 +54,55 @@ sequence_destroy( void *dummy, store_seq
_DELETE(s);
}
-void*
-sequences_init(void)
+void
+seq_hash_destroy( sql_hash *h )
{
- sql_seqs = list_create( (fdestroy)sequence_destroy );
- return (void*) sql_seqs;
+ if (h == NULL || h->sa)
+ return ;
+ for (int i = 0; i < h->size; i++) {
+ sql_hash_e *e = h->buckets[i];
+
+ while (e) {
+ sql_hash_e *next = e->chain;
+
+ sequence_destroy(NULL, e->value);
+ _DELETE(e);
+ e = next;
+ }
+ }
+ _DELETE(h->buckets);
+ _DELETE(h);
}
-void
-sequences_exit(void)
+static store_sequence *
+sequence_lookup( sql_hash *h, sqlid id)
{
- if(sql_seqs) {
- list_destroy(sql_seqs);
- sql_seqs = NULL;
+ sql_hash_e *e = h->buckets[id & (h->size-1)];
+ while(e) {
+ sql_hash_e *next = e->chain;
+ store_sequence *s = e->value;
+
+ if (s->seqid == id)
+ return s;
+ e = next;
}
+ return NULL;
}
/* lock is held */
static void
-sql_update_sequence_cache(sqlstore *store, sql_sequence *seq, lng cached)
+update_sequence(sqlstore *store, store_sequence *s)
{
- store->logger_api.log_sequence(store, seq->base.id, cached);
+ if (!s->intrans)
+ list_append(store->seqchanges, s);
+ s->intrans = true;
}
/* lock is held */
static store_sequence *
-sql_create_sequence(sqlstore *store, sql_sequence *seq )
+sequence_create(sqlstore *store, sql_sequence *seq )
{
- lng id = 0;
+ lng val = 0;
store_sequence *s = NULL;
s = MNEW(store_sequence);
if(!s)
@@ -62,109 +111,77 @@ sql_create_sequence(sqlstore *store, sql
*s = (store_sequence) {
.seqid = seq->base.id,
.cur = seq->start,
- .cached = seq->start,
};
- if (!isNew(seq) && store->logger_api.get_sequence(store, seq->base.id,
&id )) {
- s->cached = id;
+ if (!isNew(seq) && store->logger_api.get_sequence(store, seq->base.id,
&val )) {
+ s->cur = val;
+ if (val != lng_nil)
+ s->called = 1; /* val is last used value */
}
- s -> cur = s->cached;
+ hash_add(store->sequences, seq_hash(s), s);
return s;
}
-static inline lng
-calculate_new_cached_value(lng cv /*current value*/, lng inc /*sequence
increment*/, lng ci /*cache increment*/, lng min, lng max)
+int
+seq_restart(sql_store Store, sql_sequence *seq, lng start)
{
- lng ncv; // new cached value;
- lng cl; // cache line
-
-
- if (inc > 0) {
- cl = inc * ci;
- /* New cached value is the start of the first cacheline that is
bigger then the current value
- * or
- * it is set to the minimum value of the sequence in case of a
GDK or max value overflow.
- * This computation also requires overflow checks hence its
complexity.*/
- if (GDK_lng_max - cl < ((cv / cl)*cl) || (ncv = ((cv / cl)*cl)
+ cl) > max )
- ncv = min;
- }
- else {
- cl = -inc * ci;
- /* New cached value is first cacheline that is smaller then the
current value
- * or
- * it is set to the maximum value of the sequence in case of a
GDK or min value underflow.
- * This computation also requires underflow checks hence its
complexity.*/
- if (-GDK_lng_max + cl > ((cv / cl)*cl) || (ncv = ((cv / cl)*cl)
- cl) < min )
- ncv = max;
- }
- return ncv;
-}
-
-int
-seq_restart(sql_store store, sql_sequence *seq, lng start)
-{
- node *n = NULL;
store_sequence *s;
+ sqlstore *store = Store;
assert(!is_lng_nil(start));
- store_lock(store);
- for ( n = sql_seqs->h; n; n = n ->next ) {
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list