#At file:///C:/Work/bzr/Merge/mysql-6.0-falcon-team/ based on revid:kevin.lewis@stripped
3115 Kevin Lewis 2009-04-09
Bug#44161 & Bug#43145 - These two bugs are two different things that can happen when a data buffer suddenly disapears after being chilled to the serial log while another thread is following that pointer. To prevent this, data.record pointers within Record objects are now sent to purgatory for the CycleManager to release instead of being freed immediately.
Two new purgatory lists are added to the CycleManager since the data buffer can come in two forms; an array of Value objects and a char string. Each object in purgatory is now called a zombie. Record::deleteData is expanded to delete immediately when called from the Record destructor, or queueForDelete when called from anywhere else, such as SRLUpdateRecords::chill or a failed Table::update.
modified:
storage/falcon/CycleManager.cpp
storage/falcon/CycleManager.h
storage/falcon/Database.cpp
storage/falcon/Record.cpp
storage/falcon/Record.h
storage/falcon/Table.cpp
storage/falcon/Table.h
=== modified file 'storage/falcon/CycleManager.cpp'
--- a/storage/falcon/CycleManager.cpp 2009-03-27 04:29:33 +0000
+++ b/storage/falcon/CycleManager.cpp 2009-04-09 15:40:11 +0000
@@ -5,6 +5,7 @@
#include "Thread.h"
#include "Threads.h"
#include "RecordVersion.h"
+#include "Value.h"
#include "Interlock.h"
static const int CYCLE_SLEEP = 1000;
@@ -18,8 +19,11 @@ CycleManager::CycleManager(Database *db)
{
database = db;
thread = NULL;
- records = NULL;
- recordVersions = NULL;
+ recordPurgatory = NULL;
+ recordVersionPurgatory = NULL;
+ valuePurgatory = NULL;
+ bufferPurgatory = NULL;
+
currentCycle = &cycle1;
cycle1.setName("CycleManager::cycle1");
cycle2.setName("CycleManager::cycle2");
@@ -54,30 +58,54 @@ void CycleManager::cycleManager(void)
thread->sleep(CYCLE_SLEEP);
RecordVersion *doomedRecordVersions;
RecordList *doomedRecords;
+ ValueList *doomedValues;
+ BufferList *doomedBuffers;
// Pick up detrius registered for delete during cycle
- if (recordVersions)
+ if (recordVersionPurgatory)
for (;;)
{
- doomedRecordVersions = recordVersions;
+ doomedRecordVersions = recordVersionPurgatory;
- if (COMPARE_EXCHANGE_POINTER(&recordVersions, doomedRecordVersions, NULL))
+ if (COMPARE_EXCHANGE_POINTER(&recordVersionPurgatory, doomedRecordVersions, NULL))
break;
}
else
doomedRecordVersions = NULL;
- if (records)
+ if (recordPurgatory)
for (;;)
{
- doomedRecords = records;
+ doomedRecords = recordPurgatory;
- if (COMPARE_EXCHANGE_POINTER(&records, doomedRecords, NULL))
+ if (COMPARE_EXCHANGE_POINTER(&recordPurgatory, doomedRecords, NULL))
break;
}
else
doomedRecords = NULL;
+
+ if (valuePurgatory)
+ for (;;)
+ {
+ doomedValues = valuePurgatory;
+
+ if (COMPARE_EXCHANGE_POINTER(&valuePurgatory, doomedValues, NULL))
+ break;
+ }
+ else
+ doomedValues = NULL;
+
+ if (bufferPurgatory)
+ for (;;)
+ {
+ doomedBuffers = bufferPurgatory;
+
+ if (COMPARE_EXCHANGE_POINTER(&bufferPurgatory, doomedBuffers, NULL))
+ break;
+ }
+ else
+ doomedBuffers = NULL;
// Swap cycle clocks to start next cycle
@@ -95,41 +123,83 @@ void CycleManager::cycleManager(void)
doomedRecordVersions = recordVersion->nextInTrans;
recordVersion->release();
}
-
+
for (RecordList *recordList; (recordList = doomedRecords);)
{
doomedRecords = recordList->next;
- recordList->record->release();
+ recordList->zombie->release();
delete recordList;
}
+
+ for (ValueList *valueList; (valueList = doomedValues);)
+ {
+ doomedValues = valueList->next;
+ delete [] (Value*) valueList->zombie;
+ delete valueList;
+ }
+
+ for (BufferList *bufferList; (bufferList = doomedBuffers);)
+ {
+ doomedBuffers = bufferList->next;
+ DELETE_RECORD (bufferList->zombie);
+ delete bufferList;
+ }
+
}
}
-void CycleManager::queueForDelete(Record* record)
+void CycleManager::queueForDelete(Record* zombie)
{
- if (record->isVersion())
+ if (zombie->isVersion())
{
- RecordVersion *recordVersion = (RecordVersion*) record;
+ RecordVersion *recordVersion = (RecordVersion*) zombie;
for (;;)
{
- recordVersion->nextInTrans = recordVersions;
+ recordVersion->nextInTrans = recordVersionPurgatory;
- if (COMPARE_EXCHANGE_POINTER(&recordVersions, recordVersion->nextInTrans, recordVersion))
+ if (COMPARE_EXCHANGE_POINTER(&recordVersionPurgatory, recordVersion->nextInTrans, recordVersion))
break;
}
}
else
{
RecordList *recordList = new RecordList;
- recordList->record = record;
+ recordList->zombie = zombie;
for (;;)
{
- recordList->next = records;
+ recordList->next = recordPurgatory;
- if (COMPARE_EXCHANGE_POINTER(&records, recordList->next, recordList))
+ if (COMPARE_EXCHANGE_POINTER(&recordPurgatory, recordList->next, recordList))
break;
}
}
}
+void CycleManager::queueForDelete(Value** zombie)
+{
+ ValueList *valueList = new ValueList;
+ valueList->zombie = zombie;
+
+ for (;;)
+ {
+ valueList->next = valuePurgatory;
+
+ if (COMPARE_EXCHANGE_POINTER(&valuePurgatory, valueList->next, valueList))
+ break;
+ }
+}
+
+void CycleManager::queueForDelete(char* zombie)
+{
+ BufferList *bufferlist = new BufferList;
+ bufferlist->zombie = zombie;
+
+ for (;;)
+ {
+ bufferlist->next = bufferPurgatory;
+
+ if (COMPARE_EXCHANGE_POINTER(&bufferPurgatory, bufferlist->next, bufferlist))
+ break;
+ }
+}
=== modified file 'storage/falcon/CycleManager.h'
--- a/storage/falcon/CycleManager.h 2009-03-26 15:07:58 +0000
+++ b/storage/falcon/CycleManager.h 2009-04-09 15:40:11 +0000
@@ -7,14 +7,27 @@ class Thread;
class Database;
class Record;
class RecordVersion;
+class Value;
class CycleManager
{
struct RecordList
{
- Record *record;
+ Record *zombie;
RecordList *next;
};
+
+ struct ValueList
+ {
+ Value **zombie;
+ ValueList *next;
+ };
+
+ struct BufferList
+ {
+ char *zombie;
+ BufferList *next;
+ };
public:
CycleManager(Database *database);
@@ -23,15 +36,19 @@ public:
void start(void);
void shutdown(void);
void cycleManager(void);
- void queueForDelete(Record* record);
+ void queueForDelete(Record* zombie);
+ void queueForDelete(Value** zombie);
+ void queueForDelete(char* zombie);
static void cycleManager(void *arg);
SyncObject cycle1;
SyncObject cycle2;
SyncObject *currentCycle;
- RecordVersion *recordVersions;
- RecordList *records;
+ RecordVersion *recordVersionPurgatory;
+ RecordList *recordPurgatory;
+ ValueList *valuePurgatory;
+ BufferList *bufferPurgatory;
Thread *thread;
Database *database;
};
=== modified file 'storage/falcon/Database.cpp'
--- a/storage/falcon/Database.cpp 2009-04-02 22:36:19 +0000
+++ b/storage/falcon/Database.cpp 2009-04-09 15:40:11 +0000
@@ -1926,7 +1926,6 @@ void Database::pruneRecords(RecordScaven
Sync syncTbl(&syncTables, "Database::pruneRecords(tables)");
syncTbl.lock(Shared);
- CycleLock cyleLock(this);
for (Table *table = tableList; table; table = table->next)
{
=== modified file 'storage/falcon/Record.cpp'
--- a/storage/falcon/Record.cpp 2009-04-08 15:36:49 +0000
+++ b/storage/falcon/Record.cpp 2009-04-09 15:40:11 +0000
@@ -176,8 +176,8 @@ Record::~Record()
#ifdef CHECK_RECORD_ACTIVITY
ASSERT(!active);
#endif
-
- deleteData();
+
+ deleteData(true);
}
void Record::setValue(TransactionState * transaction, int id, Value * value, bool cloneFlag, bool copyFlag)
@@ -896,19 +896,32 @@ int Record::setRecordData(const UCHAR *
void Record::deleteData(void)
{
+ deleteData(false);
+}
+
+void Record::deleteData(bool now)
+{
if (data.record)
{
+ data.record = NULL;
+
switch (encoding)
{
case valueVector:
- delete [] (Value*) data.record;
+ if (now)
+ delete [] (Value*) data.record;
+ else
+ format->table->queueForDelete((Value**) data.record);
break;
default:
- DELETE_RECORD (data.record);
+ if (now)
+ {
+ DELETE_RECORD (data.record);
+ }
+ else
+ format->table->queueForDelete((char *) data.record);
}
-
- data.record = NULL;
}
}
=== modified file 'storage/falcon/Record.h'
--- a/storage/falcon/Record.h 2009-04-08 15:36:49 +0000
+++ b/storage/falcon/Record.h 2009-04-09 15:40:11 +0000
@@ -145,6 +145,7 @@ public:
bool getRecord (Stream *stream);
int getEncodedSize();
void deleteData(void);
+ void deleteData(bool now);
void printRecord(const char* header);
void validateData(void);
char* allocRecordData(int length);
=== modified file 'storage/falcon/Table.cpp'
--- a/storage/falcon/Table.cpp 2009-04-09 14:45:17 +0000
+++ b/storage/falcon/Table.cpp 2009-04-09 15:40:11 +0000
@@ -3900,3 +3900,13 @@ void Table::queueForDelete(Record* recor
{
database->cycleManager->queueForDelete(record);
}
+
+void Table::queueForDelete(Value** zombie)
+{
+ database->cycleManager->queueForDelete(zombie);
+}
+
+void Table::queueForDelete(char * zombie)
+{
+ database->cycleManager->queueForDelete(zombie);
+}
=== modified file 'storage/falcon/Table.h'
--- a/storage/falcon/Table.h 2009-04-08 15:36:49 +0000
+++ b/storage/falcon/Table.h 2009-04-09 15:40:11 +0000
@@ -215,6 +215,8 @@ public:
void unlockRecord(int recordNumber, int verbMark);
void unlockRecord(RecordVersion* record, int verbMark);
void queueForDelete(Record* record);
+ void queueForDelete(Value** record);
+ void queueForDelete(char* record);
void insert (Transaction *transaction, int count, Field **fields, Value **values);
uint insert (Transaction *transaction, Stream *stream);
Attachment: [text/bzr-bundle] bzr/kevin.lewis@sun.com-20090409154011-uxe4cmphl5uyedwl.bundle