ndb - bug#19872 fix (sufficient for replication)

parent a94ad6a2
...@@ -1933,15 +1933,16 @@ static struct Ev_t { ...@@ -1933,15 +1933,16 @@ static struct Ev_t {
enum_DEL = NdbDictionary::Event::_TE_DELETE, enum_DEL = NdbDictionary::Event::_TE_DELETE,
enum_UPD = NdbDictionary::Event::_TE_UPDATE, enum_UPD = NdbDictionary::Event::_TE_UPDATE,
enum_NUL = NdbDictionary::Event::_TE_NUL, enum_NUL = NdbDictionary::Event::_TE_NUL,
enum_ERR = 255 enum_IDM = 254, // idempotent op possibly allowed on NF
enum_ERR = 255 // always impossible
}; };
int t1, t2, t3; int t1, t2, t3;
} ev_t[] = { } ev_t[] = {
{ Ev_t::enum_INS, Ev_t::enum_INS, Ev_t::enum_ERR }, { Ev_t::enum_INS, Ev_t::enum_INS, Ev_t::enum_IDM },
{ Ev_t::enum_INS, Ev_t::enum_DEL, Ev_t::enum_NUL }, //ok { Ev_t::enum_INS, Ev_t::enum_DEL, Ev_t::enum_NUL }, //ok
{ Ev_t::enum_INS, Ev_t::enum_UPD, Ev_t::enum_INS }, //ok { Ev_t::enum_INS, Ev_t::enum_UPD, Ev_t::enum_INS }, //ok
{ Ev_t::enum_DEL, Ev_t::enum_INS, Ev_t::enum_UPD }, //ok { Ev_t::enum_DEL, Ev_t::enum_INS, Ev_t::enum_UPD }, //ok
{ Ev_t::enum_DEL, Ev_t::enum_DEL, Ev_t::enum_ERR }, { Ev_t::enum_DEL, Ev_t::enum_DEL, Ev_t::enum_IDM },
{ Ev_t::enum_DEL, Ev_t::enum_UPD, Ev_t::enum_ERR }, { Ev_t::enum_DEL, Ev_t::enum_UPD, Ev_t::enum_ERR },
{ Ev_t::enum_UPD, Ev_t::enum_INS, Ev_t::enum_ERR }, { Ev_t::enum_UPD, Ev_t::enum_INS, Ev_t::enum_ERR },
{ Ev_t::enum_UPD, Ev_t::enum_DEL, Ev_t::enum_DEL }, //ok { Ev_t::enum_UPD, Ev_t::enum_DEL, Ev_t::enum_DEL }, //ok
...@@ -2010,6 +2011,34 @@ NdbEventBuffer::merge_data(const SubTableData * const sdata, ...@@ -2010,6 +2011,34 @@ NdbEventBuffer::merge_data(const SubTableData * const sdata,
} }
assert(tp != 0 && tp->t3 != Ev_t::enum_ERR); assert(tp != 0 && tp->t3 != Ev_t::enum_ERR);
if (tp->t3 == Ev_t::enum_IDM) {
LinearSectionPtr (&ptr1)[3] = data->ptr;
/*
* TODO
* - can get data in INS ptr2[2] which is supposed to be empty
* - can get extra data in DEL ptr2[2]
* - why does DBUG_PRINT not work in this file ???
*
* replication + bug#19872 can ignore this since merge is on
* only for tables with explicit PK and before data is not used
*/
const int maxsec = 1; // ignore section 2
int i;
for (i = 0; i <= maxsec; i++) {
if (ptr1[i].sz != ptr2[i].sz ||
memcmp(ptr1[i].p, ptr2[i].p, ptr1[i].sz << 2) != 0) {
DBUG_PRINT("info", ("idempotent op %d*%d data differs in sec %d",
tp->t1, tp->t2, i));
assert(false);
DBUG_RETURN_EVENT(-1);
}
}
DBUG_PRINT("info", ("idempotent op %d*%d data ok", tp->t1, tp->t2));
DBUG_RETURN_EVENT(0);
}
// save old data // save old data
EventBufData olddata = *data; EventBufData olddata = *data;
data->memory = 0; data->memory = 0;
......
...@@ -25,7 +25,8 @@ ...@@ -25,7 +25,8 @@
#define GETNDB(ps) ((NDBT_NdbApiStep*)ps)->getNdb() #define GETNDB(ps) ((NDBT_NdbApiStep*)ps)->getNdb()
static int createEvent(Ndb *pNdb, const NdbDictionary::Table &tab) static int createEvent(Ndb *pNdb, const NdbDictionary::Table &tab,
bool merge_events = false)
{ {
char eventName[1024]; char eventName[1024];
sprintf(eventName,"%s_EVENT",tab.getName()); sprintf(eventName,"%s_EVENT",tab.getName());
...@@ -45,6 +46,7 @@ static int createEvent(Ndb *pNdb, const NdbDictionary::Table &tab) ...@@ -45,6 +46,7 @@ static int createEvent(Ndb *pNdb, const NdbDictionary::Table &tab)
for(int a = 0; a < tab.getNoOfColumns(); a++){ for(int a = 0; a < tab.getNoOfColumns(); a++){
myEvent.addEventColumn(a); myEvent.addEventColumn(a);
} }
myEvent.mergeEvents(merge_events);
int res = myDict->createEvent(myEvent); // Add event to database int res = myDict->createEvent(myEvent); // Add event to database
...@@ -137,7 +139,8 @@ NdbEventOperation *createEventOperation(Ndb *ndb, ...@@ -137,7 +139,8 @@ NdbEventOperation *createEventOperation(Ndb *ndb,
static int runCreateEvent(NDBT_Context* ctx, NDBT_Step* step) static int runCreateEvent(NDBT_Context* ctx, NDBT_Step* step)
{ {
if (createEvent(GETNDB(step),* ctx->getTab()) != 0){ bool merge_events = ctx->getProperty("MergeEvents");
if (createEvent(GETNDB(step),* ctx->getTab(), merge_events) != 0){
return NDBT_FAILED; return NDBT_FAILED;
} }
return NDBT_OK; return NDBT_OK;
...@@ -584,6 +587,8 @@ int runEventApplier(NDBT_Context* ctx, NDBT_Step* step) ...@@ -584,6 +587,8 @@ int runEventApplier(NDBT_Context* ctx, NDBT_Step* step)
g_err << "Event operation creation failed on %s" << buf << endl; g_err << "Event operation creation failed on %s" << buf << endl;
DBUG_RETURN(NDBT_FAILED); DBUG_RETURN(NDBT_FAILED);
} }
bool merge_events = ctx->getProperty("MergeEvents");
pOp->mergeEvents(merge_events);
int i; int i;
int n_columns= table->getNoOfColumns(); int n_columns= table->getNoOfColumns();
...@@ -616,6 +621,11 @@ int runEventApplier(NDBT_Context* ctx, NDBT_Step* step) ...@@ -616,6 +621,11 @@ int runEventApplier(NDBT_Context* ctx, NDBT_Step* step)
while ((pOp= ndb->nextEvent()) != 0) while ((pOp= ndb->nextEvent()) != 0)
{ {
assert(pOp == pCreate); assert(pOp == pCreate);
if (pOp->getEventType() >=
NdbDictionary::Event::TE_FIRST_NON_DATA_EVENT)
continue;
int noRetries= 0; int noRetries= 0;
do do
{ {
...@@ -1607,6 +1617,33 @@ TESTCASE("EventOperationApplier_NR", ...@@ -1607,6 +1617,33 @@ TESTCASE("EventOperationApplier_NR",
FINALIZER(runVerify); FINALIZER(runVerify);
FINALIZER(runDropShadowTable); FINALIZER(runDropShadowTable);
} }
TESTCASE("MergeEventOperationApplier",
"Verify that if we apply the data we get from merged event "
"operation is the same as the original table"
"NOTE! No errors are allowed!" ){
TC_PROPERTY("MergeEvents", 1);
INITIALIZER(runCreateEvent);
INITIALIZER(runCreateShadowTable);
STEP(runEventApplier);
STEP(runEventMixedLoad);
FINALIZER(runDropEvent);
FINALIZER(runVerify);
FINALIZER(runDropShadowTable);
}
TESTCASE("MergeEventOperationApplier_NR",
"Verify that if we apply the data we get from merged event "
"operation is the same as the original table"
"NOTE! No errors are allowed!" ){
TC_PROPERTY("MergeEvents", 1);
INITIALIZER(runCreateEvent);
INITIALIZER(runCreateShadowTable);
STEP(runEventApplier);
STEP(runEventMixedLoad);
STEP(runRestarter);
FINALIZER(runDropEvent);
FINALIZER(runVerify);
FINALIZER(runDropShadowTable);
}
TESTCASE("Multi", TESTCASE("Multi",
"Verify that we can work with all tables in parallell" "Verify that we can work with all tables in parallell"
"NOTE! HugoOperations::startTransaction, pTrans != NULL errors, " "NOTE! HugoOperations::startTransaction, pTrans != NULL errors, "
......
...@@ -213,6 +213,11 @@ max-time: 2500 ...@@ -213,6 +213,11 @@ max-time: 2500
cmd: test_event cmd: test_event
args: -n EventOperationApplier_NR -l 2 args: -n EventOperationApplier_NR -l 2
#
max-time: 2500
cmd: test_event
args: -n MergeEventOperationApplier_NR -l 2
# #
max-time: 2500 max-time: 2500
cmd: test_event cmd: test_event
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment