/* * Reconcile and resolve conflicts for incoming versioning events. * * This function handles both events generated locally and remotely by other * backends. * * When a new versioning event is received at the Local MDVSN, * look up if the same object has a conflicting version locally. * * If a conflict is detected, resolve by generating a new version for * the "combined" object. We don't generate a new VE for the conflict. * This means the combined object version is only visible to the * current backend. * * event: The new event to be considered * local_entry: The conflicting entry in the Local MDVSN cache */ static void mdver_localhandler_reconcile(mdver_event *event, mdver_entry *local_entry) { #ifdef MD_VERSIONING_INSTRUMENTATION char *mdev_str = mdver_event_str(event); elog(gp_mdversioning_loglevel, "Local VE Handler: Reconcile: Local entry = %d: (%d, %d). Incoming event %s", local_entry->key, (int) local_entry->ddl_version, (int) local_entry->dml_version, mdev_str); pfree(mdev_str); #endif uint64 new_ddl_version = event->new_ddl_version; uint64 new_dml_version = event->new_dml_version; bool conflict = false; if (local_entry->ddl_version != event->old_ddl_version) { new_ddl_version = mdver_next_global_version(); conflict = true; } if (local_entry->dml_version != event->old_dml_version) { new_dml_version = mdver_next_global_version(); conflict = true; } #if MD_VERSIONING_INSTRUMENTATION if (conflict) { elog(gp_mdversioning_loglevel, "Local VE Handler: Conflict resolved. New" "version generated, updated local entry to %d : (%d,%d) -> (%d, %d)", local_entry->key, (int) local_entry->ddl_version, (int) local_entry->dml_version, (int) new_ddl_version, (int) new_dml_version); } else { elog(gp_mdversioning_loglevel, "Local VE Handler: No conflict. Update local entry to %d : (%d,%d) -> (%d, %d)", local_entry->key, (int) event->old_ddl_version, (int) event->old_dml_version, (int) event->new_ddl_version, (int) event->new_dml_version); } #endif /* Update local entry with the resolved versions */ local_entry->ddl_version = new_ddl_version; local_entry->dml_version = new_dml_version; }
/* * When a backend is requesting the more recent version of an object, * if the Local MDVSN cache doesn't have the version, and if a NUKE event * has been encountered in the current transaction, a new version is * generated and returned for the object. A new versioning event is also * produced. * * key: The key of the looked-up object * ddl_version: used to return the ddl version for the object * dml_version: used to return the dml version for the object * */ static void mdver_request_after_nuke(Oid key, uint64 *ddl_version, uint64 *dml_version) { Assert(NULL != ddl_version); Assert(NULL != dml_version); /* Generate new version */ *ddl_version = mdver_next_global_version(); *dml_version = mdver_next_global_version(); mdver_event *new_event = (mdver_event *) palloc0(sizeof(mdver_event)); new_event->key = key; new_event->new_ddl_version = *ddl_version; new_event->new_dml_version = *dml_version; new_event->old_ddl_version = INVALID_MD_VERSION; new_event->old_dml_version = INVALID_MD_VERSION; #ifdef MD_VERSIONING_INSTRUMENTATION /* Add my current process id as the originating backend pid */ new_event->backend_pid = MyProcPid; #endif /* Annotate Versioning Event with the current version from Global MDVSN if exists */ mdver_entry *crt_entry = mdver_glob_mdvsn_find(key); if (NULL != crt_entry) { new_event->old_ddl_version = crt_entry->ddl_version; new_event->old_dml_version = crt_entry->dml_version; } CacheAddVersioningEvent(new_event); #ifdef MD_VERSIONING_INSTRUMENTATION char *mdev_str = mdver_event_str(new_event); ereport(gp_mdversioning_loglevel, (errmsg("mdver_consume_after_nuke: generated new VE %s", mdev_str), errprintstack(false))); pfree(mdev_str); #endif /* A copy of the event is added to the queue above. We can pfree our local copy */ pfree(new_event); }
/* * Entry point for the Local Versioning Event Handler. This gets called * for every message that is executed locally at a backend. */ extern void mdver_localhandler_new_event(SharedInvalidationMessage *msg) { Assert(NULL != msg); Assert(SHAREDVERSIONINGMSG_ID == msg->id); #ifdef MD_VERSIONING_INSTRUMENTATION char *mdev_str = mdver_event_str(&msg->ve.verEvent); ereport(gp_mdversioning_loglevel, (errmsg("LocalExecuteVE: got %s event %s", msg->ve.local ? "LOCAL" : "REMOTE", mdev_str), errprintstack(false))); pfree(mdev_str); #endif /* * There are some cases where we don't have a transInvalInfo structure, * and thus we don't have a Local MDVSN. For example: * - an auxiliary process (fts prober comes to mind) that queries * catalog tables directly using heap functions (no transaction) * - updating persistent tables during transaction commit * (transInvalInfo has already been reset). * - bootstrap * * In other cases, we simply don't have a Local MDVSN since we don't * cache versions: * - a QE process running on the master or segments will have a * syscache, but not a Metadata Version cache * * In those cases we don't care about versioning, so skip adding * to local MDVSN. */ mdver_local_mdvsn *local_mdvsn = GetCurrentLocalMDVSN(); if (NULL != local_mdvsn) { mdver_event *event = &msg->ve.verEvent; if (mdver_is_nuke_event(event)) { elog(gp_mdversioning_loglevel, "Local VE Handler: Received NUKE event"); mdver_local_mdvsn_nuke(local_mdvsn); return; } if (msg->ve.local) { /* * Locally generated event, we must add or update the version * in the Local MDVSN. */ mdver_entry entry; entry.key = event->key; /* FIXME gcaragea 7/4/2014: Can we assert anything here? */ entry.ddl_version = event->new_ddl_version; entry.dml_version = event->new_dml_version; mdver_local_mdvsn_add(local_mdvsn, &entry, msg->ve.local); } else { /* * An event coming from the global queue (GVQ) * If we are interested in this object, add / update * version in Local MDVSN. * */ mdver_entry *local_entry = mdver_local_mdvsn_find(local_mdvsn, event->key); if (NULL != local_entry) { /* * A VE came from SVQ for a key that we already have locally. * Need to reconcile and record. */ mdver_localhandler_reconcile(event, local_entry); } else { elog(gp_mdversioning_loglevel, "Local VE Handler: Ignoring remote event for object not of interest key=%d", event->key); } /* TODO gcaragea 5/27/2014: For subtransactions, keep all messages (MPP-22935) */ } } }