Below is the list of changes that have just been committed into a local
6.0 repository of hakan. When hakan does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-09-25 07:14:45+02:00, hakank@stripped +32 -0
Latest changes of Jim Starkey from 5.1-falcon tree.
sql/CMakeLists.txt@stripped, 2007-09-25 07:14:41+02:00, hakank@stripped +2 -3
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/CMakeLists.txt@stripped, 2007-09-25 07:14:41+02:00, hakank@stripped +4 -0
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/Database.cpp@stripped, 2007-09-25 07:14:41+02:00, hakank@stripped +33 -155
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/Database.h@stripped, 2007-09-25 07:14:41+02:00, hakank@stripped +5 -10
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/Format.cpp@stripped, 2007-09-25 07:14:41+02:00, hakank@stripped +4 -2
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/Format.h@stripped, 2007-09-25 07:14:41+02:00, hakank@stripped +2 -1
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/Makefile.am@stripped, 2007-09-25 07:14:41+02:00, hakank@stripped +7 -2
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/MemFreeBlock.cpp@stripped, 2007-09-25 07:14:42+02:00, hakank@stripped +483 -0
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/MemFreeBlock.cpp@stripped, 2007-09-25 07:14:42+02:00, hakank@stripped +0 -0
storage/falcon/MemFreeBlock.h@stripped, 2007-09-25 07:14:42+02:00, hakank@stripped +51 -0
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/MemFreeBlock.h@stripped, 2007-09-25 07:14:42+02:00, hakank@stripped +0 -0
storage/falcon/MemMgr.cpp@stripped, 2007-09-25 07:14:41+02:00, hakank@stripped +92 -47
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/MemMgr.h@stripped, 2007-09-25 07:14:41+02:00, hakank@stripped +11 -5
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/Record.cpp@stripped, 2007-09-25 07:14:41+02:00, hakank@stripped +42 -32
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/Record.h@stripped, 2007-09-25 07:14:41+02:00, hakank@stripped +15 -16
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/RecordGroup.cpp@stripped, 2007-09-25 07:14:41+02:00, hakank@stripped +7 -0
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/RecordGroup.h@stripped, 2007-09-25 07:14:41+02:00, hakank@stripped +8 -6
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/RecordLeaf.cpp@stripped, 2007-09-25 07:14:41+02:00, hakank@stripped +17 -15
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/RecordLeaf.h@stripped, 2007-09-25 07:14:41+02:00, hakank@stripped +1 -0
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/RecordScavenge.cpp@stripped, 2007-09-25 07:14:42+02:00, hakank@stripped +102 -0
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/RecordScavenge.cpp@stripped, 2007-09-25 07:14:42+02:00, hakank@stripped +0 -0
storage/falcon/RecordScavenge.h@stripped, 2007-09-25 07:14:42+02:00, hakank@stripped +50 -0
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/RecordScavenge.h@stripped, 2007-09-25 07:14:42+02:00, hakank@stripped +0 -0
storage/falcon/RecordSection.h@stripped, 2007-09-25 07:14:41+02:00, hakank@stripped +8 -6
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/RecordVersion.cpp@stripped, 2007-09-25 07:14:41+02:00, hakank@stripped +12 -5
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/RecordVersion.h@stripped, 2007-09-25 07:14:41+02:00, hakank@stripped +1 -1
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/SRLUpdateRecords.cpp@stripped, 2007-09-25 07:14:41+02:00, hakank@stripped +2 -1
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/SerialLog.cpp@stripped, 2007-09-25 07:14:41+02:00, hakank@stripped +7 -7
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/SerialLogControl.cpp@stripped, 2007-09-25 07:14:41+02:00, hakank@stripped +5 -5
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/SerialLogWindow.cpp@stripped, 2007-09-25 07:14:42+02:00, hakank@stripped +1 -1
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/Table.cpp@stripped, 2007-09-25 07:14:42+02:00, hakank@stripped +46 -8
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/Table.h@stripped, 2007-09-25 07:14:42+02:00, hakank@stripped +4 -2
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/Transaction.cpp@stripped, 2007-09-25 07:14:42+02:00, hakank@stripped +78 -10
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/Transaction.h@stripped, 2007-09-25 07:14:42+02:00, hakank@stripped +9 -7
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/TransactionManager.cpp@stripped, 2007-09-25 07:14:42+02:00, hakank@stripped +19 -0
Latest changes of Jim Starkey from 5.1-falcon tree.
storage/falcon/TransactionManager.h@stripped, 2007-09-25 07:14:42+02:00, hakank@stripped +2 -0
Latest changes of Jim Starkey from 5.1-falcon tree.
diff -Nrup a/sql/CMakeLists.txt b/sql/CMakeLists.txt
--- a/sql/CMakeLists.txt 2007-09-20 17:41:27 +02:00
+++ b/sql/CMakeLists.txt 2007-09-25 07:14:41 +02:00
@@ -98,9 +98,8 @@ SET_TARGET_PROPERTIES(mysqld PROPERTIES
# Work around for 2.4.6 bug, OUTPUT_NAME will not set the right .PDB
# file name. Note that COMPILE_FLAGS set some temporary pdb during build,
# LINK_FLAGS sets the real one.
-SET_TARGET_PROPERTIES(mysqld PROPERTIES
- COMPILE_FLAGS "/Fd${CMAKE_CFG_INTDIR}/mysqld${MYSQLD_EXE_SUFFIX}.pdb"
- LINK_FLAGS "/PDB:${CMAKE_CFG_INTDIR}/mysqld${MYSQLD_EXE_SUFFIX}.pdb")
+# COMPILE_FLAGS "/Fd${CMAKE_CFG_INTDIR}/mysqld${MYSQLD_EXE_SUFFIX}.pdb"
+# LINK_FLAGS "/PDB:${CMAKE_CFG_INTDIR}/mysqld${MYSQLD_EXE_SUFFIX}.pdb")
IF(EMBED_MANIFESTS)
MYSQL_EMBED_MANIFEST("mysqld" "asInvoker")
diff -Nrup a/storage/falcon/CMakeLists.txt b/storage/falcon/CMakeLists.txt
--- a/storage/falcon/CMakeLists.txt 2007-09-20 17:41:32 +02:00
+++ b/storage/falcon/CMakeLists.txt 2007-09-25 07:14:41 +02:00
@@ -118,6 +118,7 @@ ADD_LIBRARY(ha_falcon
LogStream.cpp
MemMgr.cpp
MemControl.cpp
+ MemFreeBlock.cpp
MemoryResultSetColumn.cpp
MemoryResultSet.cpp
MemoryResultSetMetaData.cpp
@@ -167,6 +168,7 @@ ADD_LIBRARY(ha_falcon
RecordLeaf.cpp
RecordLocatorPage.cpp
RecordSection.cpp
+ RecordScavenge.cpp
RecordVersion.cpp
RecoveryObjects.cpp
RecoveryPage.cpp
@@ -378,6 +380,7 @@ ADD_LIBRARY(ha_falcon
LogStream.h
MemMgr.h
MemControl.h
+ MemFreeBlock.h
MemoryManager.h
MemoryResultSetColumn.h
MemoryResultSet.h
@@ -430,6 +433,7 @@ ADD_LIBRARY(ha_falcon
RecordGroup.h
RecordLeaf.h
RecordLocatorPage.h
+ RecordScavenge.h
RecordSection.h
RecordVersion.h
RecoveryObjects.h
diff -Nrup a/storage/falcon/Database.cpp b/storage/falcon/Database.cpp
--- a/storage/falcon/Database.cpp 2007-09-20 17:41:36 +02:00
+++ b/storage/falcon/Database.cpp 2007-09-25 07:14:41 +02:00
@@ -69,7 +69,9 @@
#include "TableSpace.h"
#include "InfoTable.h"
#include "MemoryManager.h"
-#include "Record.h"
+#include "MemMgr.h"
+#include "RecordScavenge.h"
+#include "LogStream.h"
#ifndef STORAGE_ENGINE
#include "Applications.h"
@@ -398,9 +400,9 @@ Database::Database(const char *dbName, C
memset(tablesModId, 0, sizeof (tablesModId));
memset(unTables, 0, sizeof (unTables));
memset(schemas, 0, sizeof (schemas));
- currentAgeGroup = 1;
- overflowSize = 0;
- memset((void*) ageGroupSizes, 0, sizeof (ageGroupSizes));
+ currentGeneration = 1;
+ //overflowSize = 0;
+ //memset((void*) ageGroupSizes, 0, sizeof (ageGroupSizes));
tableList = NULL;
recordMemoryMax = configuration->recordMemoryMax;
recordScavengeFloor = configuration->recordScavengeFloor;
@@ -448,7 +450,6 @@ Database::Database(const char *dbName, C
zombieTables = NULL;
updateCardinality = NULL;
lastScavenge = 0;
- lastRetireRecords = 0;
scavengeCycle = 0;
longSync = false;
recordDataPool = MemMgrGetFixedPool(MemMgrPoolRecordData);
@@ -1184,60 +1185,6 @@ Transaction* Database::startTransaction(
return transactionManager->startTransaction(connection);
}
-/**
-int32 Database::insertStub(int32 recordSection, Transaction *transaction)
-{
- int32 recordNumber = dbb->insertStub (recordSection, TRANSACTION_ID(transaction));
- //Log::debug ("Created %d/%d\n", recordSection, recordNumber);
-
- return recordNumber;
-}
-***/
-
-/***
-void Database::logRecord(int32 section, int32 recordNumber, Stream * stream, Transaction *transaction)
-{
- dbb->logRecord (section, recordNumber, stream, transaction);
-}
-***/
-
-/***
-void Database::updateRecord(int32 section, int32 recordNumber, Stream *stream, Transaction *transaction)
-{
- dbb->updateRecord (section, recordNumber, stream, TRANSACTION_ID(transaction), false);
-}
-***/
-
-/***
-void Database::updateBlob(int32 section, int32 recordNumber, Stream *stream, Transaction *transaction)
-{
- dbb->updateBlob (section, recordNumber, stream, TRANSACTION_ID(transaction));
- transaction->pendingPageWrites = true;
-}
-***/
-
-/***
-void Database::expungeRecord(int32 section, int32 recordNumber)
-{
- dbb->expungeRecord (section, recordNumber);
-}
-***/
-
-/***
-int32 Database::findNextRecord(int32 sectionId, int32 recordNumber, Stream *stream)
-{
- int32 number = dbb->findNextRecord (sectionId, recordNumber, stream);
-
- return number;
-}
-***/
-
-/***
-bool Database::fetchRecord(int32 sectionId, int32 recordNumber, Stream * stream)
-{
- return dbb->fetchRecord (sectionId, recordNumber, stream);
-}
-***/
void Database::flush()
{
@@ -1251,27 +1198,6 @@ void Database::commitSystemTransaction()
systemConnection->commit();
}
-/***
-int32 Database::createIndex(Transaction *transaction)
-{
- return dbb->createIndex(TRANSACTION_ID(transaction));
-}
-***/
-
-/***
-bool Database::addIndexEntry(int32 indexId, int indexVersion, IndexKey *key, int32 recordNumber, Transaction *transaction)
-{
- return dbb->addIndexEntry (indexId, indexVersion, key, recordNumber, TRANSACTION_ID(transaction));
-}
-***/
-
-/***
-void Database::deleteIndex(int32 indexId, int indexVersion, Transaction *transaction)
-{
- dbb->deleteIndex (indexId, indexVersion, TRANSACTION_ID(transaction));
-}
-***/
-
void Database::setDebug()
{
dbb->setDebug();
@@ -1684,6 +1610,7 @@ void Database::scavenge()
void Database::retireRecords(bool forced)
{
+ //transactionManager->printBlockage();
int cycle = scavengeCycle;
Sync lock(&syncScavenge, "Database::retireRecords");
lock.lock(Exclusive);
@@ -1696,50 +1623,36 @@ void Database::retireRecords(bool forced
if (forced)
Log::log("Forced record scavenge cycle\n");
- if (systemConnection->transaction)
+ if (!forced && systemConnection->transaction)
commitSystemTransaction();
- int threshold = 0;
- int64 total = 0;
transactionManager->purgeTransactions();
TransId oldestActiveTransaction = transactionManager->findOldestActive();
- int n;
-
- // Compute record memory in use. Note point we pass lower limit
-
- for (n = 0; n < AGE_GROUPS; ++n)
- {
- int64 size = ageGroupSizes[n];
-
- if (size > 0)
- total += size;
-
- if (!threshold && total > (int64)recordScavengeFloor)
- threshold = currentAgeGroup - n;
- }
-
- total += overflowSize;
- RecordScavenge recordScavenge;
- memset(&recordScavenge, 0, sizeof(recordScavenge));
- recordScavenge.age = threshold;
- recordScavenge.transactionId = oldestActiveTransaction;
-
- if (forced)
- recordScavenge.age = MAX(threshold, currentAgeGroup - AGE_GROUPS / 2);
-
+ int threshold = 0;
+ uint64 total = recordDataPool->activeMemory;
+ RecordScavenge recordScavenge(this, oldestActiveTransaction);
+
// If we passed the upper limit, scavenge. If we didn't pick up
// a significant amount of memory since the last cycle, don't bother
// bumping the age group.
- if (forced || total > (int64)recordScavengeThreshold)
+ if (forced || total > recordScavengeThreshold)
{
- printRecordMemory (threshold, total);
- Sync sync (&syncTables, "Database::retireRecords");
- sync.lock (Shared);
+ LogStream stream;
+ recordDataPool->analyze(0, &stream, NULL, NULL);
+ Sync syncTbl (&syncTables, "Database::retireRecords");
+ syncTbl.lock (Shared);
+ Table *table;
+
+ for (table = tableList; table; table = table->next)
+ table->inventoryRecords(&recordScavenge);
+
+ threshold = recordScavenge.computeThreshold(recordScavengeFloor);
+ recordScavenge.printRecordMemory();
int count = 0;
int skipped = 0;
- for (Table *table = tableList; table; table = table->next)
+ for (table = tableList; table; table = table->next)
{
try
{
@@ -1752,68 +1665,33 @@ void Database::retireRecords(bool forced
}
catch (SQLException &exception)
{
- sync.unlock();
+ //syncTbl.unlock();
Log::debug ("Exception during scavenger of table %s.%s: %s\n",
table->schemaName, table->name, exception.getText());
}
}
- sync.unlock();
- int64 newTotal = overflowSize;
-
- for (int n = 0; n < AGE_GROUPS; ++n)
- newTotal += ageGroupSizes [n];
-
+ syncTbl.unlock();
Log::log(LogScavenge, " %d records, " I64FORMAT " bytes reclaimed\n",
recordScavenge.recordsReclaimed, recordScavenge.spaceReclaimed);
- total = newTotal;
+ total = recordScavenge.spaceRemaining;
}
- else if ((total - lastRecordMemory) < (int64) recordScavengeThreshold / 4)
+ else if ((total - lastRecordMemory) < recordScavengeThreshold / AGE_GROUPS)
{
- recordScavenge.age = -1;
+ recordScavenge.scavengeGeneration = -1;
cleanupRecords (&recordScavenge);
return;
}
else
{
- recordScavenge.age = -1;
+ recordScavenge.scavengeGeneration = -1;
cleanupRecords (&recordScavenge);
- printRecordMemory (threshold, total);
- }
-
- lastRecordMemory = total;
- INTERLOCKED_INCREMENT (currentAgeGroup);
- INTERLOCKED_ADD(&overflowSize, ageGroupSizes [AGE_GROUPS - 1]);
- //overflowSize += ageGroupSizes [AGE_GROUPS - 1];
-
- for (n = AGE_GROUPS - 1; n > 0; --n)
- {
- long size = ageGroupSizes [n - 1];
- INTERLOCKED_EXCHANGE(ageGroupSizes + n, (size >= 0) ? size : 0);
}
-
- //ageGroupSizes [0] = 0;
- INTERLOCKED_EXCHANGE(ageGroupSizes + 0, 0);
- lastRetireRecords = timestamp;
-}
-
-void Database::printRecordMemory(int64 threshold, int64 total)
-{
- Log::debug ("Record Memory usage for %s:\n", (const char*) name);
- int max;
-
- for (max = AGE_GROUPS - 1; max > 0; --max)
- if (ageGroupSizes [max])
- break;
-
- for (int n = 0; n <= max; ++n)
- if (ageGroupSizes [n])
- Log::debug (" %d. %d\n", currentAgeGroup - n, ageGroupSizes [n]);
- Log::log(LogScavenge, " total: " I64FORMAT ", threshold " I64FORMAT "%s\n", total, threshold,
- (total > (int64)recordScavengeThreshold) ? " -- scavenge" : "");
+ lastRecordMemory = recordDataPool->activeMemory;
+ INTERLOCKED_INCREMENT (currentGeneration);
}
void Database::ticker(void * database)
diff -Nrup a/storage/falcon/Database.h b/storage/falcon/Database.h
--- a/storage/falcon/Database.h 2007-09-20 17:41:36 +02:00
+++ b/storage/falcon/Database.h 2007-09-25 07:14:41 +02:00
@@ -35,7 +35,7 @@
#define ODS_MINOR_VERSION2 2 // Has SequencePages external to the section tree
#define ODS_MINOR_VERSION3 3 // Switch to variable length record numbers in index
#define ODS_MINOR_VERSION ODS_MINOR_VERSION3
-#define AGE_GROUPS 32
+//#define AGE_GROUPS 32
#define COMBINED_VERSION(major,minor) (major * 100 + minor)
#define VERSION_CURRENT COMBINED_VERSION(ODS_VERSION, ODS_MINOR_VERSION)
@@ -93,9 +93,9 @@ class IndexKey;
class InfoTable;
class TableSpace;
class MemMgr;
+class RecordScavenge;
struct JavaCallback;
-struct RecordScavenge;
class Database
{
@@ -106,7 +106,6 @@ public:
void shutdownNow();
void dropDatabase();
void rollback (Transaction *transaction);
- //void updateBlob(int32 section, int32 recordNumber, Stream *stream, Transaction *transaction);
void commit (Transaction *transaction);
void start();
void deleteRepositoryBlob(const char *schema, const char *repositoryName, int volume, int64 blobId, Transaction *transaction);
@@ -119,7 +118,6 @@ public:
void licenseCheck();
void cleanupRecords (RecordScavenge *recordScavenge);
void serverOperation (int op, Parameters *parameters);
- void printRecordMemory(int64 threshold, int64 tota);
void retireRecords(bool forced);
int getMemorySize (const char *string);
JString analyze(int mask);
@@ -186,7 +184,6 @@ public:
void addRef();
PreparedStatement* prepareStatement (const char *sqlStr);
void addSystemTables();
- //int32 createSection(Transaction *transaction);
Table* addTable (User *owner, const char *name, const char *schema, TableSpace *tableSpace);
Table* findTable (const char *schema, const char *name);
Statement* createStatement();
@@ -267,7 +264,6 @@ public:
PageWriter *pageWriter;
PreparedStatement *updateCardinality;
MemMgr *recordDataPool;
- //MemMgr *recordObjectPool;
volatile time_t timestamp;
volatile int numberQueries;
@@ -277,16 +273,15 @@ public:
int odsVersion;
int noSchedule;
- volatile INTERLOCK_TYPE currentAgeGroup;
- volatile long overflowSize;
- volatile long ageGroupSizes [AGE_GROUPS];
+ volatile INTERLOCK_TYPE currentGeneration;
+ //volatile long overflowSize;
+ //volatile long ageGroupSizes [AGE_GROUPS];
uint64 recordMemoryMax;
uint64 recordScavengeThreshold;
uint64 recordScavengeFloor;
int64 lastRecordMemory;
time_t creationTime;
volatile time_t lastScavenge;
- volatile time_t lastRetireRecords;
};
#endif // !defined(AFX_DATABASE_H__5EC961D1_A406_11D2_AB5B_0000C01D2301__INCLUDED_)
diff -Nrup a/storage/falcon/Format.cpp b/storage/falcon/Format.cpp
--- a/storage/falcon/Format.cpp 2007-09-20 17:41:42 +02:00
+++ b/storage/falcon/Format.cpp 2007-09-25 07:14:41 +02:00
@@ -38,8 +38,9 @@ static const char THIS_FILE[]=__FILE__;
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
-Format::Format(Table *table, int newVersion)
+Format::Format(Table *tbl, int newVersion)
{
+ table = tbl;
version = newVersion;
maxId = 0;
saved = false;
@@ -83,8 +84,9 @@ Format::Format(Table *table, int newVers
length = offset;
}
-Format::Format(ResultSet * resultSet)
+Format::Format(Table *tbl, ResultSet * resultSet)
{
+ table = tbl;
format = NULL;
saved = false;
diff -Nrup a/storage/falcon/Format.h b/storage/falcon/Format.h
--- a/storage/falcon/Format.h 2007-09-20 17:41:42 +02:00
+++ b/storage/falcon/Format.h 2007-09-25 07:14:41 +02:00
@@ -40,7 +40,7 @@ class Format
{
public:
void save (Table *table);
- Format (ResultSet *resultSet);
+ Format (Table *tbl, ResultSet *resultSet);
bool validate (Table *table);
Format(Table *table, int newVersion);
virtual ~Format();
@@ -50,6 +50,7 @@ public:
int32 length;
int count;
FieldFormat *format;
+ Table *table;
Format *hash;
bool saved;
};
diff -Nrup a/storage/falcon/Makefile.am b/storage/falcon/Makefile.am
--- a/storage/falcon/Makefile.am 2007-09-20 17:41:56 +02:00
+++ b/storage/falcon/Makefile.am 2007-09-25 07:14:41 +02:00
@@ -78,8 +78,9 @@ falcon_headers= Agent.h Alias.h Applicat
Log.h \
LogLock.h \
LogStream.h \
- MemControl.h \
MemMgr.h \
+ MemControl.h \
+ MemFreeBlock.h \
MemoryManager.h \
MemoryResultSetColumn.h \
MemoryResultSet.h MemoryResultSetMetaData.h \
@@ -98,7 +99,9 @@ falcon_headers= Agent.h Alias.h Applicat
Protocol.h PStatement.h Queue.h QueryString.h RecordGroup.h \
Record.h RecordLeaf.h \
RecordLocatorPage.h \
- RecordSection.h RecordVersion.h \
+ RecordSection.h \
+ RecordScavenge.h \
+ RecordVersion.h \
RecoveryObjects.h \
RecoveryPage.h \
Registry.h Repository.h RepositoryManager.h RepositoryVolume.h \
@@ -228,6 +231,7 @@ falcon_sources= Agent.cpp Alias.cpp \
LogLock.cpp \
LogStream.cpp \
MemControl.cpp \
+ MemFreeBlock.cpp \
MemMgr.cpp \
MemoryResultSetColumn.cpp \
MemoryResultSet.cpp MemoryResultSetMetaData.cpp \
@@ -248,6 +252,7 @@ falcon_sources= Agent.cpp Alias.cpp \
RecordGroup.cpp RecordLeaf.cpp \
RecordLocatorPage.cpp \
RecordSection.cpp \
+ RecordScavenge.cpp \
RecordVersion.cpp \
RecoveryObjects.cpp \
RecoveryPage.cpp \
diff -Nrup a/storage/falcon/MemFreeBlock.cpp b/storage/falcon/MemFreeBlock.cpp
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/storage/falcon/MemFreeBlock.cpp 2007-09-25 07:14:42 +02:00
@@ -0,0 +1,483 @@
+/* Copyright (C) 2007 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#include <stdio.h>
+#include "Engine.h"
+#include "MemMgr.h"
+#include "MemFreeBlock.h"
+
+static const int TWIN = 10;
+
+#define RESET_PARENT(newChild) \
+ if (parent->smaller == this) \
+ parent->smaller = newChild; \
+ else \
+ parent->larger = newChild;
+
+static int lastRemove;
+
+MemFreeBlock::MemFreeBlock(void)
+{
+ larger = NULL;
+ smaller = NULL;
+ balance = 0;
+ nextTwin = priorTwin = this;
+ memHeader.length = 0;
+}
+
+MemFreeBlock::~MemFreeBlock(void)
+{
+}
+
+void MemFreeBlock::rotateLeft(void)
+{
+ MemFreeBlock *root = larger;
+
+ if ( (larger = larger->smaller) )
+ larger->parent = this;
+
+ root->smaller = this;
+ balance -= (1 + MAX(root->balance, 0));
+ root->balance -= (1 - MIN(balance, 0));
+ RESET_PARENT(root);
+ root->parent = parent;
+ parent = root;
+}
+
+void MemFreeBlock::rotateRight(void)
+{
+ MemFreeBlock *root = smaller;
+
+ if ( (smaller = smaller->larger) )
+ smaller->parent = this;
+
+ root->larger = this;
+ balance += (1 - MIN(root->balance, 0));
+ root->balance += (1 + MAX(balance, 0));
+ RESET_PARENT(root);
+ root->parent = parent;
+ parent = root;
+}
+
+void MemFreeBlock::insert(MemFreeBlock *newNode)
+{
+ newNode->larger = NULL;
+ newNode->smaller = NULL;
+ newNode->balance = 0;
+ MemFreeBlock *node = this;
+
+ // Find insertion point and insert new node as leaf
+
+ while (node)
+ if (newNode->memHeader.length < node->memHeader.length)
+ {
+ if (node->smaller)
+ node = node->smaller;
+ else
+ {
+ node->smaller = newNode;
+ --node->balance;
+ break;
+ }
+ }
+ else if (newNode->memHeader.length > node->memHeader.length)
+ {
+ if (node->larger)
+ node = node->larger;
+ else
+ {
+ node->larger = newNode;
+ ++node->balance;
+ break;
+ }
+ }
+ else
+ {
+ newNode->balance = TWIN;
+ newNode->nextTwin = node->nextTwin;
+ newNode->nextTwin->priorTwin = newNode;
+ newNode->priorTwin = node;
+ node->nextTwin = newNode;
+ //node->nextLarger = NULL;
+
+ return;
+ }
+
+ // New node is inserted. Balance tree upwards
+
+ newNode->parent = node;
+ newNode->nextTwin = newNode->priorTwin = newNode;
+
+ for (MemFreeBlock *nodeParent; node->balance && (nodeParent = node->parent) && nodeParent->parent; node = nodeParent)
+ {
+ if (nodeParent->smaller == node)
+ {
+ if (--nodeParent->balance < -1)
+ {
+ nodeParent->rebalance();
+ break;
+ }
+ }
+ else
+ {
+ if (++nodeParent->balance > +1)
+ {
+ nodeParent->rebalance();
+ break;
+ }
+ }
+ }
+}
+
+MemFreeBlock* MemFreeBlock::findNextLargest(int size)
+{
+ ASSERT(size > 0);
+ MemFreeBlock *block = this;
+
+ // Travse down the tree looking for a block that fits
+
+ while (block)
+ if (size < block->memHeader.length)
+ {
+ if (block->smaller)
+ block = block->smaller;
+ else
+ break;
+ }
+ else if (size > block->memHeader.length)
+ {
+ if (block->larger)
+ block = block->larger;
+ else
+ break;
+ }
+ else
+ break;
+
+ for (; block; block = block->parent)
+ if (size <= block->memHeader.length)
+ {
+ if (block->nextTwin == block)
+ {
+ block->remove();
+
+ return block;
+ }
+
+ // We've got a twin of the same size. Take it out of the twin list.
+
+ MemFreeBlock *twin = block->nextTwin;
+ twin->nextTwin->priorTwin = twin->priorTwin;
+ twin->priorTwin->nextTwin = twin->nextTwin;
+
+ return twin;
+ }
+
+ return NULL;
+}
+
+void MemFreeBlock::remove()
+{
+ // If we a simple twin, zip out of the twin list and we're done
+
+ if (balance == TWIN)
+ {
+ nextTwin->priorTwin = priorTwin;
+ priorTwin->nextTwin = nextTwin;
+ lastRemove = 1;
+
+ return;
+ }
+
+ // If we have a twin, promote the first twin into the tree
+
+ if (nextTwin != this)
+ {
+ MemFreeBlock *twin = nextTwin;
+ priorTwin->nextTwin = twin;
+ twin->priorTwin = priorTwin;
+
+ twin->balance = balance;
+ twin->parent = parent;
+
+ if ( (twin->smaller = smaller) )
+ smaller->parent = twin;
+
+ if ( (twin->larger = larger) )
+ larger->parent = twin;
+
+ RESET_PARENT(twin);
+ parent->validate();
+ //validateFreeList();
+ lastRemove = 2;
+
+ return;
+ }
+
+ // There are three cases a) No children, b) One child, c) Two children
+
+ if (!smaller || !larger)
+ {
+ MemFreeBlock *next = (smaller) ? smaller : larger;
+
+ if (next)
+ next->parent = parent;
+
+ if (parent->smaller == this)
+ {
+ parent->smaller = next;
+ parent->rebalanceUpward(+1);
+ }
+ else
+ {
+ parent->larger = next;
+ parent->rebalanceUpward(-1);
+ }
+
+ lastRemove = 3;
+
+ return;
+ }
+
+ // We're an equality with two children. Bummer. Find successor node (next larger value)
+ // and swap it into our place
+
+ bool shallower;
+ MemFreeBlock *node = larger->getSuccessor(&larger, &shallower);
+
+ if ( (node->smaller = smaller) )
+ smaller->parent = node;
+
+ if ( (node->larger = larger) )
+ larger->parent = node;
+
+ node->balance = balance;
+ node->parent = parent;
+ RESET_PARENT(node);
+ lastRemove = 4;
+
+ // If we got shallower, adjust balance and rebalance if necessary
+
+ if (shallower)
+ {
+ lastRemove = 5;
+ node->rebalanceUpward(-1);
+ }
+}
+
+void MemFreeBlock::rebalance(void)
+{
+ if (balance > 1)
+ {
+ if (larger->balance < 0)
+ larger->rotateRight();
+
+ rotateLeft();
+ }
+ else if (balance < 1)
+ {
+ if (smaller->balance > 0)
+ smaller->rotateLeft();
+
+ rotateRight();
+ }
+}
+
+bool MemFreeBlock::rebalanceDelete()
+{
+ if (balance > 1)
+ {
+ if (larger->balance < 0)
+ {
+ larger->rotateRight();
+ rotateLeft();
+
+ return true;
+ }
+
+ rotateLeft();
+
+ return parent->balance == 0;
+ }
+
+ if (balance < 1)
+ {
+ if (smaller->balance > 0)
+ {
+ smaller->rotateLeft();
+ rotateRight();
+
+ return true;
+ }
+
+ rotateRight();
+
+ return parent->balance == 0;
+ }
+
+ return false;
+}
+
+MemFreeBlock* MemFreeBlock::getSuccessor(MemFreeBlock** parentPointer, bool* shallower)
+{
+ // If there's a smaller node, recurse down it rebalancing
+ // if the subtree gets shallower
+
+ if (smaller)
+ {
+ int was = balance;
+ MemFreeBlock *node = smaller->getSuccessor(&smaller, shallower);
+
+ // If we got shallower, adjust balance and rebalance if necessary
+
+ if (*shallower)
+ {
+ if (++balance > 1)
+ *shallower = rebalanceDelete();
+ else if (!was && (*parentPointer)->balance)
+ *shallower = false;
+ }
+
+ return node;
+ }
+
+ // We're the bottom. Remove us from our parent and we're done.
+
+ RESET_PARENT(larger);
+
+ if (larger)
+ larger->parent = parent;
+
+ *shallower = true;
+
+ return this;
+}
+
+void MemFreeBlock::rebalanceUpward(int delta)
+{
+ MemFreeBlock *node = this;
+
+ for (;;)
+ {
+ MemFreeBlock *nodeParent = node->parent;
+
+ if (!nodeParent)
+ {
+ node->balance += delta;
+
+ return;
+ }
+
+ int parentDelta = (nodeParent->smaller == node) ? 1 : -1;
+ node->balance += delta;
+
+ if (node->balance == delta)
+ break;
+
+ if (node->balance > 1 || node->balance < -1)
+ if (!node->rebalanceDelete())
+ break;
+
+ delta = parentDelta;
+ node = nodeParent;
+ }
+}
+
+MemFreeBlock* MemFreeBlock::getFirst(void)
+{
+ MemFreeBlock *node = larger;
+
+ if (!node)
+ return node;
+
+ while (node->smaller)
+ node = node->smaller;
+
+ return node;
+}
+
+MemFreeBlock* MemFreeBlock::getNext(void)
+{
+ MemFreeBlock *node = larger;
+
+ if (node)
+ {
+ while (node->smaller)
+ node = node->smaller;
+
+ return node;
+ }
+
+ for (node = this; node && node->parent; node = node->parent)
+ if (node == parent->smaller)
+ return parent;
+
+ return NULL;
+}
+
+int MemFreeBlock::validate(void)
+{
+ int rightDepth = 0;
+ int leftDepth = 0;
+
+ if (smaller)
+ {
+ if (smaller->memHeader.length >= memHeader.length)
+ corrupt("out of order");
+
+ if (smaller->parent != this)
+ corrupt("bad parent");
+
+ leftDepth = smaller->validate();
+ }
+
+ if (larger)
+ {
+ if (larger->memHeader.length < memHeader.length)
+ corrupt("out of order");
+
+ if (larger->parent != this)
+ corrupt("bad right parent");
+
+ rightDepth = larger->validate();
+ }
+
+ if (parent && balance != rightDepth - leftDepth)
+ corrupt("bad balance");
+
+ return MAX(rightDepth, leftDepth) + 1;
+}
+
+void MemFreeBlock::corrupt(const char *text)
+{
+ ASSERT(false);
+}
+
+int MemFreeBlock::count(void)
+{
+ int count = 1;
+
+ for (MemFreeBlock *block = nextTwin; block != this; block = block->nextTwin)
+ ++count;
+
+ if (smaller)
+ count += smaller->count();
+
+ if (larger)
+ count += larger->count();
+
+ return count;
+}
diff -Nrup a/storage/falcon/MemFreeBlock.h b/storage/falcon/MemFreeBlock.h
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/storage/falcon/MemFreeBlock.h 2007-09-25 07:14:42 +02:00
@@ -0,0 +1,51 @@
+/* Copyright (C) 2007 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#ifndef _MEM_FREE_BLOCK_H_
+#define _MEM_FREE_BLOCK_H_
+
+class MemFreeBlock :
+ public MemBigObject
+{
+public:
+ MemFreeBlock(void);
+ ~MemFreeBlock(void);
+
+ MemFreeBlock *smaller;
+ MemFreeBlock *larger;
+ MemFreeBlock *parent;
+ MemFreeBlock *nextTwin;
+ MemFreeBlock *priorTwin;
+
+ int balance;
+
+ void rotateLeft(void);
+ void rotateRight(void);
+ void insert(MemFreeBlock *node);
+ MemFreeBlock* findNextLargest(int size);
+ void rebalance(void);
+ bool rebalanceDelete();
+ MemFreeBlock* getSuccessor(MemFreeBlock** parentPointer, bool* shallower);
+ void remove();
+ void rebalanceUpward(int delta);
+ MemFreeBlock* getFirst(void);
+ MemFreeBlock* getNext(void);
+ int validate(void);
+ void corrupt(const char *text);
+ int count(void);
+};
+
+#endif
diff -Nrup a/storage/falcon/MemMgr.cpp b/storage/falcon/MemMgr.cpp
--- a/storage/falcon/MemMgr.cpp 2007-09-24 12:56:42 +02:00
+++ b/storage/falcon/MemMgr.cpp 2007-09-25 07:14:41 +02:00
@@ -207,8 +207,6 @@ void MemMgrAnalyze(int mask, Stream *str
memoryManager.analyze (mask, stream, NULL, NULL);
stream->putSegment ("Records\n");
recordManager.analyze (mask, stream, NULL, NULL);
- stream->putSegment ("Record Objects\n");
- recordManager.analyze (mask, stream, NULL, NULL);
//LEAVE_CRITICAL_SECTION;
}
@@ -285,6 +283,7 @@ MemMgr::MemMgr(int rounding, int cutoff,
currentMemory = 0;
blocksAllocated = 0;
blocksActive = 0;
+ activeMemory = 0;
numberBigHunks = 0;
numberSmallHunks = 0;
bigHunks = NULL;
@@ -296,8 +295,9 @@ MemMgr::MemMgr(int rounding, int cutoff,
freeObjects = (MemBlock**) allocRaw (l);
memset (freeObjects, 0, l);
- freeBlocks.nextLarger = freeBlocks.priorSmaller = &freeBlocks;
- junk.nextLarger = junk.priorSmaller = &junk;
+ //freeBlocks.nextLarger = freeBlocks.priorSmaller = &freeBlocks;
+ //freeBlockTree = NULL;
+ junk.larger = junk.smaller = &junk;
}
@@ -402,50 +402,54 @@ MemBlock* MemMgr::alloc(int length)
*/
- //Sync sync (&mutex, "MemMgr::alloc");
- //sync.lock(Exclusive);
- MemFreeBlock *freeBlock;
if (length < (int) (OFFSET(MemBlock*, body) + sizeof (MemFreeBlock) - sizeof (MemBigObject)))
length = (int) (OFFSET(MemBlock*, body) + sizeof (MemFreeBlock) - sizeof (MemBigObject));
- for (freeBlock = freeBlocks.nextLarger; freeBlock != &freeBlocks; freeBlock = freeBlock->nextLarger)
- if (freeBlock->memHeader.length >= length)
- {
- remove (freeBlock);
- MemBlock *block = (MemBlock*) &freeBlock->memHeader;
-
- // Compute length (MemHeader + body) for new free block
-
- int tail = block->length - length;
-
- // If there isn't room to split off a new free block, allocate the whole thing
-
- if (tail < (int) sizeof (MemFreeBlock))
- {
- block->pool = this;
- return block;
- }
-
- // Otherwise, chop up the block
+ MemFreeBlock *freeBlock = freeBlockTree.findNextLargest(length);
+
+ if (!freeBlock && freeBlockTree.larger)
+ freeBlock = freeBlockTree.findNextLargest(length);
- MemBigObject *newBlock = freeBlock;
- freeBlock = (MemFreeBlock*) ((UCHAR*) block + length);
- freeBlock->memHeader.length = tail - sizeof (MemBigHeader);
- block->length = length;
+ if (freeBlock)
+ {
+ //freeBlockTree.validate();
+ MemBlock *block = (MemBlock*) &freeBlock->memHeader;
+
+ // Compute length (MemHeader + body) for new free block
+
+ int tail = block->length - length;
+
+ // If there isn't room to split off a new free block, allocate the whole thing
+
+ if (tail < (int) sizeof (MemFreeBlock))
+ {
block->pool = this;
-
- if ( (freeBlock->next = newBlock->next) )
- freeBlock->next->prior = freeBlock;
-
- newBlock->next = freeBlock;
- freeBlock->prior = newBlock;
- freeBlock->memHeader.pool = NULL; // indicate block is free
- insert (freeBlock);
- //validateFreeList();
+ activeMemory += block->length;
return block;
}
+
+ // Otherwise, chop up the block
+
+ MemBigObject *newBlock = freeBlock;
+ freeBlock = (MemFreeBlock*) ((UCHAR*) block + length);
+ freeBlock->memHeader.length = tail - sizeof (MemBigHeader);
+ block->length = length;
+ block->pool = this;
+ activeMemory += length;
+
+ if ( (freeBlock->next = newBlock->next) )
+ freeBlock->next->prior = freeBlock;
+
+ newBlock->next = freeBlock;
+ freeBlock->prior = newBlock;
+ freeBlock->memHeader.pool = NULL; // indicate block is free
+ insert (freeBlock);
+ //validateFreeList();
+
+ return block;
+ }
// Didn't find existing space -- allocate new hunk
@@ -478,6 +482,7 @@ MemBlock* MemMgr::alloc(int length)
MemBlock *block = (MemBlock*) &newBlock->memHeader;
block->pool = this;
block->length = length;
+ activeMemory += length;
// If there is space left over, create a free block
@@ -631,6 +636,8 @@ void MemMgr::releaseBlock(MemBlock *bloc
sync.lock(Exclusive);
//validateFreeList();
block->pool = NULL;
+ ASSERT(length <= activeMemory);
+ activeMemory -= length;
if (freeBlock->next && !freeBlock->next->memHeader.pool)
{
@@ -697,6 +704,20 @@ void* MemMgr::memoryIsExhausted(void)
void MemMgr::remove(MemFreeBlock* block)
{
+ //freeBlockTree.validate();
+ //int count = freeBlockTree.count();
+
+ block->remove();
+
+ /***
+ freeBlockTree.validate();
+ int count2 = freeBlockTree.count();
+
+ if (count - 1 != count2)
+ corrupt("bad count");
+ ***/
+
+ /***
// If this is junk, chop it out and be done with it
if (block->memHeader.length < threshold)
@@ -709,6 +730,7 @@ void MemMgr::remove(MemFreeBlock* block)
block->nextTwin->priorTwin = block->priorTwin;
block->priorTwin->nextTwin = block->nextTwin;
//validateFreeList();
+
return;
}
@@ -725,6 +747,7 @@ void MemMgr::remove(MemFreeBlock* block)
twin->priorSmaller->nextLarger = twin;
twin->nextLarger->priorSmaller = twin;
//validateFreeList();
+
return;
}
@@ -733,10 +756,25 @@ void MemMgr::remove(MemFreeBlock* block)
block->priorSmaller->nextLarger = block->nextLarger;
block->nextLarger->priorSmaller = block->priorSmaller;
//validateFreeList();
+ ***/
}
void MemMgr::insert(MemFreeBlock* freeBlock)
{
+ //freeBlockTree.validate();
+ //int count = freeBlockTree.count();
+
+ freeBlockTree.insert(freeBlock);
+
+ /***
+ freeBlockTree.validate();
+ int count2 = freeBlockTree.count();
+
+ if (count + 1 != count2)
+ corrupt("bad count");
+ ***/
+
+ /***
// If this is junk (too small for pool), stick it in junk
if (freeBlock->memHeader.length < threshold)
@@ -770,6 +808,7 @@ void MemMgr::insert(MemFreeBlock* freeBl
freeBlock->nextTwin = freeBlock->priorTwin = freeBlock;
//validateFreeList();
+ ***/
}
void* MemMgr::allocRaw(int length)
@@ -796,37 +835,40 @@ void MemMgr::validateFreeList(void)
int len = 0;
int count = 0;
MemFreeBlock *block;
- MemFreeBlock *prior = &freeBlocks;
- for (block = freeBlocks.nextLarger; block != &freeBlocks; prior = block, block = block->nextLarger)
+ for (block = freeBlockTree.getFirst(); block; block = block->getNext())
{
if (block->memHeader.length <= len)
corrupt ("bad free list\n");
- if (block->priorSmaller != prior)
- corrupt ("bad prior pointer");
+
len = block->memHeader.length;
++count;
int twins = 0;
MemFreeBlock *twin;
MemFreeBlock *priorTwin = block;
+
for (twin = block->nextTwin; twin != block; priorTwin = twin, twin = twin->nextTwin)
{
if (twin->priorTwin != priorTwin)
corrupt("bad priorTwin pointer");
+
++twins;
}
+
for (twin = block->priorTwin; twin != block; twin = twin->priorTwin)
--twins;
+
if (twins)
corrupt("bad twin list");
}
len += 1;
- for (block = freeBlocks.priorSmaller; block != &freeBlocks; block = block->priorSmaller)
+ for (block = freeBlockTree.getFirst(); block; block = block->getNext())
{
if (block->memHeader.length >= len)
corrupt ("bad free list\n");
+
len = block->memHeader.length;
}
@@ -1048,8 +1090,9 @@ void MemMgr::analyze(int mask, Stream *s
int batch = 0;
int64 orderedSpace = 0;
int sizes = 0;
-
- for (MemFreeBlock *blk = freeBlocks.nextLarger; blk != &freeBlocks; blk = blk->nextLarger)
+
+ //for (MemFreeBlock *blk = freeBlocks.nextLarger; blk != &freeBlocks; blk = blk->nextLarger)
+ for (MemFreeBlock *blk = freeBlockTree.getFirst(); blk; blk = blk->getNext())
{
++sizes;
int count = 1;
@@ -1087,7 +1130,9 @@ void MemMgr::analyze(int mask, Stream *s
{
int sizes = 0;
- for (MemFreeBlock *blk = freeBlocks.nextLarger; blk != &freeBlocks; blk = blk->nextLarger)
+
+ for (MemFreeBlock *blk = freeBlockTree.getFirst(); blk; blk = blk->getNext())
+ //for (MemFreeBlock *blk = freeBlocks.nextLarger; blk != &freeBlocks; blk = blk->nextLarger)
{
++sizes;
int count = 1;
diff -Nrup a/storage/falcon/MemMgr.h b/storage/falcon/MemMgr.h
--- a/storage/falcon/MemMgr.h 2007-09-20 17:41:59 +02:00
+++ b/storage/falcon/MemMgr.h 2007-09-25 07:14:41 +02:00
@@ -71,16 +71,20 @@ public:
MemHeader memHeader;
};
-
+/***
class MemFreeBlock : public MemBigObject
{
public:
- MemFreeBlock *nextLarger;
- MemFreeBlock *priorSmaller;
+ //MemFreeBlock *nextLarger;
+ //MemFreeBlock *priorSmaller;
+ MemFreeBlock *smaller;
+ MemFreeBlock *larger;
MemFreeBlock *nextTwin;
MemFreeBlock *priorTwin;
+ int balance;
};
-
+***/
+#include "MemFreeBlock.h"
class MemSmallHunk
{
@@ -117,10 +121,12 @@ public:
MemBigHunk *bigHunks;
MemSmallHunk *smallHunks;
MemControl *memControl;
- MemFreeBlock freeBlocks;
+ //MemFreeBlock freeBlocks;
+ MemFreeBlock freeBlockTree;
MemFreeBlock junk;
Mutex mutex; // Win32 critical regions are faster than SyncObject
int64 currentMemory;
+ uint64 activeMemory;
int blocksAllocated;
int blocksActive;
diff -Nrup a/storage/falcon/Record.cpp b/storage/falcon/Record.cpp
--- a/storage/falcon/Record.cpp 2007-09-20 17:42:11 +02:00
+++ b/storage/falcon/Record.cpp 2007-09-25 07:14:41 +02:00
@@ -59,15 +59,17 @@ static int offsetVectorSize;
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
-Record::Record(Table *tbl, int32 recordNum, Stream *stream)
+Record::Record(Table *table, int32 recordNum, Stream *stream)
{
- ASSERT (tbl);
+ //ASSERT (tbl);
useCount = 1;
- table = tbl;
+ //table = tbl;
+ format = table->getCurrentFormat();
state = recData;
recordNumber = recordNum;
const short *p = (short*) stream->segments->address;
size = sizeof (*this);
+ generation = table->database->currentGeneration;
#ifdef CHECK_RECORD_ACTIVITY
active = false;
#endif
@@ -78,8 +80,8 @@ Record::Record(Table *tbl, int32 recordN
data.record = stream->decompress(table->tableId, recordNumber);
format = table->getFormat (*(short*) data.record);
size += format->length;
- setAgeGroup();
-
+ //setAgeGroup();
+
if (stream->decompressedLength != format->length)
throw SQLEXCEPTION (RUNTIME_ERROR,
"wrong length record (got %d, expected %d), table %s.%s, section %d, record %d",
@@ -104,12 +106,15 @@ Record::Record(Table * tbl, Format *fmt)
{
ASSERT (tbl);
useCount = 1;
- format = fmt;
- table = tbl;
+
+ if ( !(format = fmt) )
+ format = tbl->getCurrentFormat();
+
+ //table = tbl;
size = sizeof (RecordVersion);
encoding = noEncoding;
state = recData;
- ageGroup = table->database->currentAgeGroup; // to avoid a Valgrind warning
+ generation = format->table->database->currentGeneration;
#ifdef CHECK_RECORD_ACTIVITY
active = false;
@@ -130,10 +135,11 @@ Record::~Record()
#ifdef CHECK_RECORD_ACTIVITY
ASSERT(!active);
#endif
-
+ /***
if (table)
unsetAgeGroup();
-
+ ***/
+
deleteData();
}
@@ -205,7 +211,7 @@ void Record::setValue(Transaction * tran
case Asciiblob:
case Binaryblob:
- *(int32*) ptr = table->getBlobId (value, *(int32*) ptr, cloneFlag, transaction);
+ *(int32*) ptr = format->table->getBlobId (value, *(int32*) ptr, cloneFlag, transaction);
break;
case Date:
@@ -282,7 +288,7 @@ Record* Record::fetchVersion(Transaction
void Record::getValue(int fieldId, Value * value)
{
- ASSERT (table);
+ //ASSERT (table);
ASSERT (format);
value->clear();
@@ -312,7 +318,7 @@ void Record::getValue(int fieldId, Value
{
case Asciiblob:
{
- AsciiBlob *blob = table->getAsciiBlob(value->getBlobId());
+ AsciiBlob *blob = format->table->getAsciiBlob(value->getBlobId());
value->setValue (blob);
blob->release();
}
@@ -320,7 +326,7 @@ void Record::getValue(int fieldId, Value
case Binaryblob:
{
- BinaryBlob *blob = table->getBinaryBlob(value->getBlobId());
+ BinaryBlob *blob = format->table->getBinaryBlob(value->getBlobId());
value->setValue (blob);
blob->release();
}
@@ -433,7 +439,7 @@ void Record::getValue(int fieldId, Value
case Asciiblob:
{
- AsciiBlob *blob = table->getAsciiBlob (*(int32*) ptr);
+ AsciiBlob *blob = format->table->getAsciiBlob (*(int32*) ptr);
value->setValue (blob);
blob->release();
}
@@ -441,7 +447,7 @@ void Record::getValue(int fieldId, Value
case Binaryblob:
{
- BinaryBlob *blob = table->getBinaryBlob (*(int32*) ptr);
+ BinaryBlob *blob = format->table->getBinaryBlob (*(int32*) ptr);
value->setValue (blob);
blob->release();
}
@@ -641,7 +647,7 @@ void Record::finalize(Transaction *trans
{
ASSERT(encoding == valueVector);
Stream stream;
- EncodedRecord encodedStream(table, transaction, &stream);
+ EncodedRecord encodedStream(format->table, transaction, &stream);
short version = (short) - format->version;
stream.putSegment(sizeof(version), (char*) &version, true);
Value *values = (Value*) data.record;
@@ -677,7 +683,6 @@ int Record::setEncodedRecord(Stream *str
encoding = shortVector;
int vectorLength = format->count * sizeof(short);
int totalLength = vectorLength + stream->totalLength;
- //char *dataBuffer = ALLOCATE_RECORD(totalLength);
char *dataBuffer = allocRecordData(totalLength);
memset(dataBuffer, 0, vectorLength);
stream->getSegment(0, stream->totalLength, dataBuffer + vectorLength);
@@ -685,7 +690,8 @@ int Record::setEncodedRecord(Stream *str
highWater = 0;
size += vectorLength + stream->totalLength;
- setAgeGroup();
+ //setAgeGroup();
+ generation = format->table->database->currentGeneration;
if (interlocked)
{
@@ -798,21 +804,21 @@ bool Record::isNull(int fieldId)
// Set age group and add size to database
+/***
void Record::setAgeGroup()
{
Database *database = table->database;
- ageGroup = database->currentAgeGroup;
+ generation = database->currentGeneration;
//database->ageGroupSizes [0] += size;
INTERLOCKED_ADD(database->ageGroupSizes + 0, size);
}
-
void Record::unsetAgeGroup(void)
{
if (table)
{
Database *database = table->database;
- int n = database->currentAgeGroup - ageGroup;
+ int n = database->currentGeneration - generation;
if (n >= AGE_GROUPS)
INTERLOCKED_ADD(&database->overflowSize, -size);
@@ -821,18 +827,25 @@ void Record::unsetAgeGroup(void)
}
}
+***/
void Record::poke()
{
+ int gen = format->table->database->currentGeneration;
+
+ if (generation != gen)
+ generation = gen;
+
+ /***
Database *database = table->database;
- int32 currentAgeGroup = database->currentAgeGroup;
- int32 n = currentAgeGroup - ageGroup;
+ int32 currentGeneration = database->currentGeneration;
+ int32 n = currentGeneration - generation;
if (n == 0)
return;
ASSERT (n > 0);
- ageGroup = currentAgeGroup;
+ generation = currentGeneration;
if (n >= AGE_GROUPS)
INTERLOCKED_ADD(&database->overflowSize, -size);
@@ -840,6 +853,7 @@ void Record::poke()
INTERLOCKED_ADD(database->ageGroupSizes + n, -size);
INTERLOCKED_ADD(database->ageGroupSizes + 0, size);
+ ***/
}
Record* Record::releaseNonRecursive(void)
@@ -885,10 +899,6 @@ int Record::setRecordData(const UCHAR *
return (totalLength);
}
-char* Record::getRecordData()
-{
- return data.record;
-}
void Record::deleteData(void)
{
@@ -911,7 +921,7 @@ void Record::deleteData(void)
void Record::print(void)
{
printf(" %p\tId %d, enc %d, state %d, use %d, grp %d\n",
- this, recordNumber, encoding, state, useCount, ageGroup);
+ this, recordNumber, encoding, state, useCount, generation);
}
void Record::printRecord(const char* header)
@@ -930,14 +940,14 @@ char* Record::allocRecordData(int length
for (int n = 0;; ++n)
try
{
- return POOL_NEW(table->database->recordDataPool) char[length];
+ return POOL_NEW(format->table->database->recordDataPool) char[length];
}
catch (SQLException& exception)
{
if (n > 2 || exception.getSqlcode() != OUT_OF_RECORD_MEMORY_ERROR)
throw;
- table->database->forceRecordScavenge();
+ format->table->database->forceRecordScavenge();
}
return NULL;
diff -Nrup a/storage/falcon/Record.h b/storage/falcon/Record.h
--- a/storage/falcon/Record.h 2007-09-20 17:42:11 +02:00
+++ b/storage/falcon/Record.h 2007-09-25 07:14:41 +02:00
@@ -29,17 +29,6 @@
#define CHECK_RECORD_ACTIVITY
-struct RecordScavenge
- {
- TransId transactionId;
- int age;
- uint recordsReclaimed;
- uint recordsRemaining;
- uint versionsRemaining;
- uint64 spaceReclaimed;
- uint64 spaceRemaining;
- };
-
enum RecordEncoding {
noEncoding = 0,
traditional,
@@ -64,6 +53,7 @@ class Transaction;
class Value;
class Stream;
class Database;
+class RecordScavenge;
CLASS(Field);
extern char *RecordAllocate (int size, const char *file, int line);
@@ -89,7 +79,7 @@ public:
virtual int thaw();
virtual const char* getEncodedRecord();
virtual int setRecordData(const UCHAR *dataIn, int dataLength);
- virtual char* getRecordData();
+ //virtual char* getRecordData();
const UCHAR* getEncoding (int index);
int setEncodedRecord(Stream *stream, bool interlocked);
@@ -104,11 +94,13 @@ public:
void getEncodedValue (int fieldId, Value *value);
void getRecord (Stream *stream);
int getEncodedSize();
- void setAgeGroup();
void deleteData(void);
void printRecord(const char* header);
void validateData(void);
char* allocRecordData(int length);
+
+ //void setAgeGroup();
+ //void unsetAgeGroup(void);
Record (Table *table, Format *recordFormat);
Record(Table *table, int32 recordNumber, Stream *stream);
@@ -117,6 +109,14 @@ public:
{
return data.record != NULL;
};
+
+ inline char* getRecordData()
+ {
+ if (state == recChilled)
+ thaw();
+
+ return data.record;
+ }
protected:
virtual ~Record();
@@ -128,11 +128,11 @@ protected:
public:
volatile INTERLOCK_TYPE useCount;
- Table *table;
+ //Table *table;
Format *format;
int recordNumber;
int size;
- int ageGroup;
+ int generation;
short highWater;
UCHAR encoding;
UCHAR state;
@@ -140,7 +140,6 @@ public:
#ifdef CHECK_RECORD_ACTIVITY
UCHAR active; // this is for debugging only
#endif
- void unsetAgeGroup(void);
};
#endif // !defined(AFX_RECORD_H__02AD6A50_A433_11D2_AB5B_0000C01D2301__INCLUDED_)
diff -Nrup a/storage/falcon/RecordGroup.cpp b/storage/falcon/RecordGroup.cpp
--- a/storage/falcon/RecordGroup.cpp 2007-09-20 17:42:11 +02:00
+++ b/storage/falcon/RecordGroup.cpp 2007-09-25 07:14:41 +02:00
@@ -184,3 +184,10 @@ bool RecordGroup::retireSections(Table *
return inactive();
}
+
+void RecordGroup::inventoryRecords(RecordScavenge* recordScavenge)
+{
+ for (RecordSection **section = records, **end = records + RECORD_SLOTS; section < end; ++section)
+ if (*section)
+ (*section)->inventoryRecords(recordScavenge);
+}
diff -Nrup a/storage/falcon/RecordGroup.h b/storage/falcon/RecordGroup.h
--- a/storage/falcon/RecordGroup.h 2007-09-20 17:42:11 +02:00
+++ b/storage/falcon/RecordGroup.h 2007-09-25 07:14:41 +02:00
@@ -29,15 +29,17 @@
class RecordGroup : public RecordSection
{
public:
- virtual int countActiveRecords();
- virtual int retireRecords(Table *table, int base, RecordScavenge *recordScavenge);
- virtual bool retireSections(Table * table, int id);
- virtual bool inactive();
RecordGroup(int32 base, int32 id, RecordSection *section);
RecordGroup(int32 base);
- virtual bool store (Record *record, Record *prior, int32 id, RecordSection **parentPtr);
- virtual Record* fetch (int32 id);
virtual ~RecordGroup();
+
+ virtual int countActiveRecords();
+ virtual bool store (Record *record, Record *prior, int32 id, RecordSection **parentPtr);
+ virtual void inventoryRecords(RecordScavenge* recordScavenge);
+ virtual Record* fetch (int32 id);
+ virtual int retireRecords(Table *table, int base, RecordScavenge *recordScavenge);
+ virtual bool retireSections(Table * table, int id);
+ virtual bool inactive();
RecordSection *records [RECORD_SLOTS];
int32 base;
diff -Nrup a/storage/falcon/RecordLeaf.cpp b/storage/falcon/RecordLeaf.cpp
--- a/storage/falcon/RecordLeaf.cpp 2007-09-20 17:42:12 +02:00
+++ b/storage/falcon/RecordLeaf.cpp 2007-09-25 07:14:41 +02:00
@@ -27,6 +27,7 @@
#include "Sync.h"
#include "Interlock.h"
#include "Bitmap.h"
+#include "RecordScavenge.h"
#ifdef _DEBUG
#undef THIS_FILE
@@ -119,7 +120,6 @@ int RecordLeaf::retireRecords (Table *ta
#ifdef NON_BLOCKING_SCAVENGING
Sync sync(&syncObject, "RecordLeaf::retireRecords");
sync.lock(Shared);
- bool redo = false;
// Get a shared lock to find at least one record to scavenge
@@ -132,27 +132,19 @@ int RecordLeaf::retireRecords (Table *ta
if (record->isVersion())
{
if ((record->scavenge(recordScavenge)) &&
- ((!record->hasRecord()) || ((record->useCount == 1) && (record->ageGroup <= recordScavenge->age))))
- {
- redo = true;
-
+ ((!record->hasRecord()) || ((record->useCount == 1) && (record->generation <= recordScavenge->scavengeGeneration))))
break;
- }
else
++count;
}
- else if (record->ageGroup <= recordScavenge->age && record->useCount == 1)
- {
- redo = true;
-
+ else if (record->generation <= recordScavenge->scavengeGeneration && record->useCount == 1)
break;
- }
else
++count;
}
}
- if (!redo)
+ if (ptr >= end)
return count;
// Get an exclusive lock and do the actual scavenging
@@ -162,7 +154,7 @@ int RecordLeaf::retireRecords (Table *ta
count = 0;
#endif
- for (ptr = records, end = records + RECORD_SLOTS; ptr < end; ++ptr)
+ for (ptr = records; ptr < end; ++ptr)
{
Record *record = *ptr;
@@ -171,7 +163,7 @@ int RecordLeaf::retireRecords (Table *ta
if (record->isVersion())
{
if ((record->scavenge(recordScavenge)) &&
- ((!record->hasRecord()) || ((record->useCount == 1) && (record->ageGroup <= recordScavenge->age))))
+ ((!record->hasRecord()) || ((record->useCount == 1) && (record->generation <= recordScavenge->scavengeGeneration))))
{
*ptr = NULL;
recordScavenge->spaceReclaimed += record->size;
@@ -188,7 +180,7 @@ int RecordLeaf::retireRecords (Table *ta
++count;
}
}
- else if (record->ageGroup <= recordScavenge->age && record->useCount == 1)
+ else if (record->generation <= recordScavenge->scavengeGeneration && record->useCount == 1)
{
*ptr = NULL;
recordScavenge->spaceReclaimed += record->size;
@@ -243,4 +235,14 @@ int RecordLeaf::countActiveRecords()
++count;
return count;
+}
+
+void RecordLeaf::inventoryRecords(RecordScavenge* recordScavenge)
+{
+ Sync sync(&syncObject, "RecordLeaf::inventoryRecords");
+ sync.lock(Shared);
+
+ for (Record **ptr = records, **end = records + RECORD_SLOTS; ptr < end; ++ptr)
+ if (*ptr)
+ recordScavenge->inventoryRecord(*ptr);
}
diff -Nrup a/storage/falcon/RecordLeaf.h b/storage/falcon/RecordLeaf.h
--- a/storage/falcon/RecordLeaf.h 2007-09-20 17:42:14 +02:00
+++ b/storage/falcon/RecordLeaf.h 2007-09-25 07:14:41 +02:00
@@ -42,6 +42,7 @@ public:
Record *records [RECORD_SLOTS];
SyncObject syncObject;
+ void inventoryRecords(RecordScavenge* recordScavenge);
};
#endif // !defined(AFX_RECORDLEAF_H__02AD6A56_A433_11D2_AB5B_0000C01D2301__INCLUDED_)
diff -Nrup a/storage/falcon/RecordScavenge.cpp b/storage/falcon/RecordScavenge.cpp
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/storage/falcon/RecordScavenge.cpp 2007-09-25 07:14:42 +02:00
@@ -0,0 +1,102 @@
+/* Copyright (C) 2007 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <memory.h>
+#include "Engine.h"
+#include "RecordScavenge.h"
+#include "Database.h"
+#include "Record.h"
+#include "Log.h"
+#include "MemMgr.h"
+
+
+RecordScavenge::RecordScavenge(Database *db, TransId oldestTransaction)
+{
+ database = db;
+ transactionId = oldestTransaction;
+ baseGeneration = database->currentGeneration;
+ memset(ageGroups, 0, sizeof(ageGroups));
+ recordsReclaimed = 0;
+ recordsRemaining = 0;
+ versionsRemaining = 0;
+ spaceReclaimed = 0;
+ spaceRemaining = 0;
+ overflowSpace = 0;
+ numberRecords = 0;
+ recordSpace = 0;
+}
+
+RecordScavenge::~RecordScavenge(void)
+{
+}
+
+void RecordScavenge::inventoryRecord(Record* record)
+{
+ for (Record *rec = record; rec; rec = rec->getPriorVersion())
+ {
+ ++numberRecords;
+ recordSpace += record->size;
+ int age = baseGeneration - record->generation;
+ int size = record->size + sizeof(MemBigHeader);
+
+ if (record->getRecordData())
+ size += sizeof(MemBigHeader);
+
+ if (age >= 0 && age < AGE_GROUPS)
+ ageGroups[age] += size;
+ else if (age >= AGE_GROUPS)
+ overflowSpace += size;
+ else
+ ageGroups[0] = size;
+ }
+}
+
+int RecordScavenge::computeThreshold(uint64 target)
+{
+ totalSpace = 0;
+ scavengeGeneration = 0;
+
+ for (int n = 0; n < AGE_GROUPS; ++n)
+ {
+ totalSpace += ageGroups[n];
+
+ if (totalSpace >= target && scavengeGeneration == 0)
+ scavengeGeneration = baseGeneration - n;
+ }
+
+ totalSpace += overflowSpace;
+
+ if (scavengeGeneration == 0 && totalSpace > target)
+ scavengeGeneration = baseGeneration + AGE_GROUPS;
+
+ return scavengeGeneration;
+}
+
+void RecordScavenge::printRecordMemory(void)
+{
+ Log::debug ("Record Memory usage for %s:\n", (const char*) database->name);
+ int max;
+
+ for (max = AGE_GROUPS - 1; max > 0; --max)
+ if (ageGroups[max])
+ break;
+
+ for (int n = 0; n <= max; ++n)
+ if (ageGroups [n])
+ Log::debug (" %d. %d\n", baseGeneration - n, ageGroups[n]);
+
+ Log::log(LogScavenge, " total: " I64FORMAT ", threshold %d%s\n", totalSpace, scavengeGeneration,
+ (scavengeGeneration > 0) ? " -- scavenge" : "");
+}
diff -Nrup a/storage/falcon/RecordScavenge.h b/storage/falcon/RecordScavenge.h
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/storage/falcon/RecordScavenge.h 2007-09-25 07:14:42 +02:00
@@ -0,0 +1,50 @@
+/* Copyright (C) 2007 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef _RECORD_SCAVENGE_H_
+#define _RECORD_SCAVENGE_H_
+
+static const int AGE_GROUPS = 20;
+
+class Database;
+class Record;
+
+class RecordScavenge
+{
+public:
+ Database *database;
+ TransId transactionId;
+ int scavengeGeneration;
+ int baseGeneration;
+ uint recordsReclaimed;
+ uint recordsRemaining;
+ uint numberRecords;
+ uint versionsRemaining;
+ uint64 spaceReclaimed;
+ uint64 spaceRemaining;
+ uint64 ageGroups[AGE_GROUPS];
+ uint64 overflowSpace;
+ uint64 totalSpace;
+ uint64 recordSpace;
+
+ RecordScavenge(Database *db, TransId oldestTransaction);
+ ~RecordScavenge(void);
+
+ void inventoryRecord(Record* record);
+ int computeThreshold(uint64 target);
+ void printRecordMemory(void);
+};
+
+#endif
diff -Nrup a/storage/falcon/RecordSection.h b/storage/falcon/RecordSection.h
--- a/storage/falcon/RecordSection.h 2007-09-20 17:42:14 +02:00
+++ b/storage/falcon/RecordSection.h 2007-09-25 07:14:41 +02:00
@@ -26,21 +26,23 @@
class Record;
class Table;
+class RecordScavenge;
-struct RecordScavenge;
#define RECORD_SLOTS 100
class RecordSection
{
public:
- virtual ~RecordSection();
- virtual Record* fetch (int32 id) = 0;
- virtual bool store (Record *record, Record *prior, int32 id, RecordSection **parentPtr) = 0;
- virtual int retireRecords(Table *table, int base, RecordScavenge *recordScavenge) = 0;
virtual bool retireSections(Table * table, int id) = 0;
virtual bool inactive() = 0;
- virtual int countActiveRecords() = 0;
+ virtual ~RecordSection();
+
+ virtual Record* fetch (int32 id) = 0;
+ virtual bool store (Record *record, Record *prior, int32 id, RecordSection **parentPtr) = 0;
+ virtual int retireRecords(Table *table, int base, RecordScavenge *recordScavenge) = 0;
+ virtual void inventoryRecords(RecordScavenge* recordScavenge) = 0;
+ virtual int countActiveRecords() = 0;
};
#endif // !defined(AFX_RECORDSECTION_H__02AD6A54_A433_11D2_AB5B_0000C01D2301__INCLUDED_)
diff -Nrup a/storage/falcon/RecordVersion.cpp b/storage/falcon/RecordVersion.cpp
--- a/storage/falcon/RecordVersion.cpp 2007-09-20 17:42:14 +02:00
+++ b/storage/falcon/RecordVersion.cpp 2007-09-25 07:14:41 +02:00
@@ -28,6 +28,9 @@
#include "SerialLogControl.h"
#include "Stream.h"
#include "Dbb.h"
+#include "RecordScavenge.h"
+#include "Format.h"
+
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
@@ -45,6 +48,7 @@ RecordVersion::RecordVersion(Table *tbl,
{
priorVersion->addRef();
recordNumber = oldVersion->recordNumber;
+
if (trans == priorVersion->getTransaction())
oldVersion->setSuperceded (true);
}
@@ -116,7 +120,7 @@ Record* RecordVersion::rollback()
if (superceded)
return NULL;
- return table->rollbackRecord (this);
+ return format->table->rollbackRecord (this);
}
bool RecordVersion::isVersion()
@@ -145,7 +149,7 @@ bool RecordVersion::scavenge(RecordScave
if (transaction || (transactionId >= recordScavenge->transactionId))
{
- table->activeVersions = true;
+ format->table->activeVersions = true;
if (priorVersion)
priorVersion->scavenge(recordScavenge);
@@ -154,7 +158,7 @@ bool RecordVersion::scavenge(RecordScave
}
if (priorVersion)
- table->expungeRecordVersions(this, recordScavenge);
+ format->table->expungeRecordVersions(this, recordScavenge);
return true;
}
@@ -194,7 +198,7 @@ void RecordVersion::scavenge(TransId tar
prior->addRef();
setPriorVersion(rec);
ptr->setPriorVersion(NULL);
- table->garbageCollect(prior, this, transaction, false);
+ format->table->garbageCollect(prior, this, transaction, false);
prior->release();
}
@@ -287,6 +291,7 @@ int RecordVersion::thaw()
if (bytesRestored == 0)
{
Stream stream;
+ Table *table = format->table;
if (table->dbb->fetchRecord(table->dataSection, recordNumber, &stream))
{
@@ -319,6 +324,7 @@ int RecordVersion::thaw()
return bytesRestored;
}
+/***
char* RecordVersion::getRecordData()
{
if (state == recChilled)
@@ -326,12 +332,13 @@ char* RecordVersion::getRecordData()
return data.record;
}
+***/
void RecordVersion::print(void)
{
Log::debug(" %p\tId %d, enc %d, state %d, tid %d, use %d, grp %d, prior %p\n",
this, recordNumber, encoding, state, transactionId, useCount,
- ageGroup, priorVersion);
+ generation, priorVersion);
if (priorVersion)
priorVersion->print();
diff -Nrup a/storage/falcon/RecordVersion.h b/storage/falcon/RecordVersion.h
--- a/storage/falcon/RecordVersion.h 2007-09-20 17:42:14 +02:00
+++ b/storage/falcon/RecordVersion.h 2007-09-25 07:14:41 +02:00
@@ -49,7 +49,7 @@ public:
virtual void setVirtualOffset(uint64 offset);
virtual uint64 getVirtualOffset();
virtual int thaw();
- virtual char* getRecordData();
+ //virtual char* getRecordData();
virtual void print(void);
void commit();
diff -Nrup a/storage/falcon/SRLUpdateRecords.cpp b/storage/falcon/SRLUpdateRecords.cpp
--- a/storage/falcon/SRLUpdateRecords.cpp 2007-09-20 17:42:26 +02:00
+++ b/storage/falcon/SRLUpdateRecords.cpp 2007-09-25 07:14:41 +02:00
@@ -26,6 +26,7 @@
#include "Log.h"
#include "Sync.h"
#include "SerialLogWindow.h"
+#include "Format.h"
SRLUpdateRecords::SRLUpdateRecords(void)
{
@@ -153,7 +154,7 @@ void SRLUpdateRecords::append(Transactio
if (record->state == recNoChill)
continue;
- Table *table = record->table;
+ Table *table = record->format->table;
tableSpaceId = table->dbb->tableSpaceId;
Stream stream;
diff -Nrup a/storage/falcon/SerialLog.cpp b/storage/falcon/SerialLog.cpp
--- a/storage/falcon/SerialLog.cpp 2007-09-20 17:42:34 +02:00
+++ b/storage/falcon/SerialLog.cpp 2007-09-25 07:14:41 +02:00
@@ -442,7 +442,7 @@ void SerialLog::overflowFlush(void)
writeBlock->length = (int) (writePtr - (UCHAR*) writeBlock);
writeWindow->setLastBlock(writeBlock);
lastReadBlock = writeBlock->readBlockNumber = getReadBlock();
- ASSERT(writeWindow->validate(writeBlock));
+ //ASSERT(writeWindow->validate(writeBlock));
// Keep track of what needs to be written
@@ -463,7 +463,7 @@ void SerialLog::overflowFlush(void)
throw;
}
- ASSERT(flushWindow->validate(flushBlock));
+ //ASSERT(flushWindow->validate(flushBlock));
++physicalFlushes;
mutex.unlock();
@@ -570,7 +570,7 @@ uint64 SerialLog::flush(bool forceNewWin
throw;
}
- ASSERT(flushWindow->validate(flushBlock));
+ //ASSERT(flushWindow->validate(flushBlock));
++physicalFlushes;
mutex.unlock();
@@ -581,7 +581,7 @@ uint64 SerialLog::flush(bool forceNewWin
wakeupFlushQueue(thread);
ASSERT(writer != thread);
ASSERT(writer || !srlQueue);
- ASSERT(writeWindow->validate(writeBlock));
+ //ASSERT(writeWindow->validate(writeBlock));
syncPtr->unlock();
return nextBlockNumber;
@@ -619,7 +619,7 @@ void SerialLog::createNewWindow(void)
writeWindow->firstBlockNumber = nextBlockNumber;
initializeWriteBlock(writeWindow->firstBlock());
ASSERT(writeWindow->firstBlockNumber == writeBlock->blockNumber);
- ASSERT(writeWindow->validate(writeBlock));
+ //ASSERT(writeWindow->validate(writeBlock));
}
void SerialLog::shutdown()
@@ -686,7 +686,7 @@ void SerialLog::putData(uint32 length, c
writeBlock->length = (int) (writePtr - (UCHAR*) writeBlock);
writeWindow->currentLength = (int) (writePtr - writeWindow->buffer);
recordStart = writeBlock->data;
- ASSERT(writeWindow->validate(writeBlock));
+ //ASSERT(writeWindow->validate(writeBlock));
}
void SerialLog::startRecord()
@@ -988,7 +988,7 @@ void SerialLog::initializeWriteBlock(Ser
writeBlock->length = (int) (writePtr - (UCHAR*) writeBlock);
writeWindow->setLastBlock(writeBlock);
writeWarningTrack = writeWindow->warningTrack;
- ASSERT(writeWindow->validate(writeBlock));
+ //ASSERT(writeWindow->validate(writeBlock));
}
diff -Nrup a/storage/falcon/SerialLogControl.cpp b/storage/falcon/SerialLogControl.cpp
--- a/storage/falcon/SerialLogControl.cpp 2007-09-20 17:42:34 +02:00
+++ b/storage/falcon/SerialLogControl.cpp 2007-09-25 07:14:41 +02:00
@@ -170,10 +170,10 @@ SerialLogRecord* SerialLogControl::getRe
void SerialLogControl::setWindow(SerialLogWindow *window, SerialLogBlock *block, int offset)
{
- ASSERT(window->validate(block));
+ //ASSERT(window->validate(block));
SerialLogWindow *priorWindow = inputWindow;
SerialLogBlock *priorBlock = inputBlock;
- ASSERT(!priorWindow || priorWindow->validate(priorBlock));
+ //ASSERT(!priorWindow || priorWindow->validate(priorBlock));
if (inputWindow != window)
{
@@ -186,8 +186,8 @@ void SerialLogControl::setWindow(SerialL
Sync sync(&log->syncWrite, "SerialLogControl::setWindow");
sync.lock(Shared);
- inputWindow->validate(block);
- ASSERT(inputWindow->validate(block));
+ //inputWindow->validate(block);
+ //ASSERT(inputWindow->validate(block));
inputBlock = block;
input = inputBlock->data;
inputEnd = (const UCHAR*) inputBlock + block->length;
@@ -196,7 +196,7 @@ void SerialLogControl::setWindow(SerialL
if (inputBlock == log->writeBlock && log->recordIncomplete)
inputEnd = log->recordStart;
- ASSERT(inputWindow->validate(inputEnd));
+ //ASSERT(inputWindow->validate(inputEnd));
version = srlVersion0;
if (input < inputEnd)
diff -Nrup a/storage/falcon/SerialLogWindow.cpp b/storage/falcon/SerialLogWindow.cpp
--- a/storage/falcon/SerialLogWindow.cpp 2007-09-20 17:42:36 +02:00
+++ b/storage/falcon/SerialLogWindow.cpp 2007-09-25 07:14:42 +02:00
@@ -184,7 +184,7 @@ SerialLogBlock* SerialLogWindow::nextBlo
nextBlk->creationTime == (uint32) log->creationTime &&
nextBlk->blockNumber == block->blockNumber + 1)
{
- ASSERT(validate(nextBlk));
+ //ASSERT(validate(nextBlk));
return nextBlk;
}
diff -Nrup a/storage/falcon/Table.cpp b/storage/falcon/Table.cpp
--- a/storage/falcon/Table.cpp 2007-09-20 17:42:43 +02:00
+++ b/storage/falcon/Table.cpp 2007-09-25 07:14:42 +02:00
@@ -52,6 +52,7 @@
#include "Interlock.h"
#include "Collation.h"
#include "TableSpace.h"
+#include "RecordScavenge.h"
#ifndef STORAGE_ENGINE
#include "Trigger.h"
@@ -331,7 +332,13 @@ void Table::insert(Transaction *transact
// Verify that record is valid
checkNullable(record);
- checkUniqueIndexes(transaction, record);
+ Sync sync(&syncUpdate, "Table::insert");
+
+ if (indexes)
+ {
+ sync.lock(Exclusive);
+ checkUniqueIndexes(transaction, record);
+ }
recordNumber = record->recordNumber = dbb->insertStub(dataSection, transaction);
transaction->addRecord(record);
@@ -392,7 +399,7 @@ Format* Table::getFormat(int version)
statement->setInt(1, tableId);
statement->setInt(2, version);
RSet set = statement->executeQuery();
- format = NEW Format(set);
+ format = NEW Format(this, set);
sync2.unlock();
addFormat(format);
@@ -583,7 +590,7 @@ Record* Table::fetchNext(int32 start)
Record* Table::databaseFetch(int32 recordNumber)
{
Stream stream;
- ageGroup = database->currentAgeGroup;
+ ageGroup = database->currentGeneration;
if (!dataSection)
dataSection = dbb->findSection(dataSectionId);
@@ -761,7 +768,7 @@ void Table::loadIndexes()
void Table::init(int id, const char *schema, const char *tableName, TableSpace *tblSpace)
{
- ageGroup = database->currentAgeGroup;
+ ageGroup = database->currentGeneration;
if ( (tableSpace = tblSpace) )
dbb = tableSpace->dbb;
@@ -1065,7 +1072,13 @@ void Table::update(Transaction * transac
// Make sure no uniqueness rules are violated
- checkUniqueIndexes(transaction, record);
+ Sync sync(&syncUpdate, "Table::update");
+
+ if (indexes)
+ {
+ sync.lock(Exclusive);
+ checkUniqueIndexes(transaction, record);
+ }
// Checkin with any table attachments
@@ -1258,7 +1271,7 @@ void Table::deleteRecord(Transaction * t
}
record->state = recDeleted;
- record->setAgeGroup();
+ //record->setAgeGroup();
fireTriggers(transaction, PreDelete, oldRecord, NULL);
// Do any necessary cascading
@@ -1589,9 +1602,19 @@ int Table::retireRecords(RecordScavenge
return count;
}
+void Table::inventoryRecords(RecordScavenge* recordScavenge)
+{
+ if (!records)
+ return;
+
+ Sync sync(&syncObject, "Table::inventoryRecords");
+ sync.lock(Shared);
+ records->inventoryRecords(recordScavenge);
+}
+
bool Table::insert(Record * record, Record *prior, int recordNumber)
{
- ageGroup = database->currentAgeGroup;
+ ageGroup = database->currentGeneration;
Sync sync(&syncObject, "Table::insert");
if (record)
@@ -2613,9 +2636,13 @@ uint Table::insert(Transaction *transact
record = allocRecordVersion(fmt, transaction, NULL);
record->setEncodedRecord(stream, false);
+ Sync sync(&syncUpdate, "Table::insert");
if (indexes)
+ {
+ sync.lock(Exclusive);
checkUniqueIndexes(transaction, record);
+ }
recordNumber = record->recordNumber = dbb->insertStub(dataSection, transaction);
transaction->addRecord(record);
@@ -2727,7 +2754,13 @@ void Table::update(Transaction * transac
// Make sure no uniqueness rules are violated
- checkUniqueIndexes(transaction, record);
+ Sync sync(&syncUpdate, "Table::update");
+
+ if (indexes)
+ {
+ sync.lock(Exclusive);
+ checkUniqueIndexes(transaction, record);
+ }
// Checkin with any table attachments
@@ -3243,4 +3276,9 @@ Record* Table::allocRecord(int recordNum
}
return NULL;
+}
+
+Format* Table::getCurrentFormat(void)
+{
+ return getFormat(formatVersion);;
}
diff -Nrup a/storage/falcon/Table.h b/storage/falcon/Table.h
--- a/storage/falcon/Table.h 2007-09-20 17:42:44 +02:00
+++ b/storage/falcon/Table.h 2007-09-25 07:14:42 +02:00
@@ -67,8 +67,7 @@ class AsciiBlob;
class BinaryBlob;
class Section;
class TableSpace;
-
-struct RecordScavenge;
+class RecordScavenge;
class Table : public PrivilegeObject
{
@@ -203,6 +202,7 @@ public:
SyncObject syncObject;
SyncObject syncTriggers;
SyncObject syncScavenge;
+ SyncObject syncUpdate;
SyncObject syncAlter; // prevent concurrent Alter statements.
Table *collision; // Hash collision in database
Table *idCollision; // mod(id) collision in database
@@ -247,6 +247,8 @@ protected:
public:
RecordVersion* allocRecordVersion(Format* format, Transaction* transaction, Record* priorVersion);
Record* allocRecord(int recordNumber, Stream* stream);
+ void inventoryRecords(RecordScavenge* recordScavenge);
+ Format* getCurrentFormat(void);
};
#endif // !defined(AFX_TABLE_H__02AD6A42_A433_11D2_AB5B_0000C01D2301__INCLUDED_)
diff -Nrup a/storage/falcon/Transaction.cpp b/storage/falcon/Transaction.cpp
--- a/storage/falcon/Transaction.cpp 2007-09-20 17:42:46 +02:00
+++ b/storage/falcon/Transaction.cpp 2007-09-25 07:14:42 +02:00
@@ -39,6 +39,7 @@
#include "SerialLogControl.h"
#include "InfoTable.h"
#include "Thread.h"
+#include "Format.h"
static const char *stateNames [] = {
"Active",
@@ -54,6 +55,8 @@ static const char *stateNames [] = {
"Initial"
};
+static const int INDENT = 5;
+
#ifdef _DEBUG
#undef THIS_FILE
static const char THIS_FILE[]=__FILE__;
@@ -113,6 +116,7 @@ void Transaction::initialize(Connection*
numberStates = 0;
blockedBy = 0;
inList = true;
+ thread = NULL;
//scavenged = false;
if (seq == 0)
@@ -131,6 +135,8 @@ void Transaction::initialize(Connection*
freeSavePoints = localSavePoints + n;
}
+ blockingRecord = NULL;
+ thread = Thread::getThread("Transaction::init");
syncActive.lock(NULL, Exclusive);
Transaction *oldest = transactionManager->findOldest();
oldestActive = (oldest) ? oldest->transactionId : transactionId;
@@ -264,12 +270,12 @@ void Transaction::commit()
for (RecordVersion *record = firstRecord; record; record = record->nextInTrans)
if (!record->isSuperceded() && record->state != recLock)
- record->table->updateRecord (record);
+ record->format->table->updateRecord (record);
if (commitTriggers)
for (RecordVersion *record = firstRecord; record; record = record->nextInTrans)
if (!record->isSuperceded() && record->state != recLock)
- record->table->postCommit (this, record);
+ record->format->table->postCommit (this, record);
releaseDependencies();
database->flushInversion(this);
@@ -278,9 +284,9 @@ void Transaction::commit()
for (RecordVersion *record = firstRecord; record; record = record->nextInTrans)
if (!record->priorVersion)
- ++record->table->cardinality;
- else if (record->state == recDeleted && record->table->cardinality > 0)
- --record->table->cardinality;
+ ++record->format->table->cardinality;
+ else if (record->state == recDeleted && record->format->table->cardinality > 0)
+ --record->format->table->cardinality;
syncActiveTransactions.unlock();
Sync syncCommitted(&transactionManager->committedTransactions.syncObject, "Transaction::commit");
@@ -413,7 +419,7 @@ void Transaction::rollback()
record->nextInTrans = NULL;
if (record->state == recLock)
- record->table->unlockRecord(record, false);
+ record->format->table->unlockRecord(record, false);
else
record->rollback();
@@ -747,7 +753,11 @@ void Transaction::commitRecords()
State Transaction::getRelativeState(Record* record, uint32 flags)
{
- return getRelativeState(record->getTransaction(), record->getTransactionId(), flags);
+ blockingRecord = record;
+ State state = getRelativeState(record->getTransaction(), record->getTransactionId(), flags);
+ blockingRecord = NULL;
+
+ return state;
}
/***
@@ -833,7 +843,7 @@ void Transaction::dropTable(Table* table
// Keep exclusive lock to avoid race condition with writeComplete
for (RecordVersion **ptr = &firstRecord, *rec; (rec = *ptr);)
- if (rec->table == table)
+ if (rec->format->table == table)
removeRecord(rec);
else
ptr = &rec->nextInTrans;
@@ -842,7 +852,7 @@ void Transaction::dropTable(Table* table
bool Transaction::hasUncommittedRecords(Table* table)
{
for (RecordVersion *rec = firstRecord; rec; rec = rec->nextInTrans)
- if (rec->table == table)
+ if (rec->format->table == table)
return true;
return false;
@@ -1091,7 +1101,7 @@ void Transaction::releaseRecordLocks(voi
for (ptr = &firstRecord; (record = *ptr);)
if (record->state == recLock)
{
- record->table->unlockRecord(record, false);
+ record->format->table->unlockRecord(record, false);
removeRecord(record);
}
else
@@ -1103,6 +1113,64 @@ void Transaction::print(void)
Log::debug(" %p Id %d, state %d, updates %d, wrtPend %d, states %d, dependencies %d, records %d\n",
this, transactionId, state, hasUpdates, writePending,
numberStates, dependencies, firstRecord != NULL);
+}
+
+void Transaction::printBlocking(int level)
+{
+ int locks = 0;
+ int updates = 0;
+ int inserts = 0;
+ int deletes = 0;
+ RecordVersion *record;
+
+ for (record = firstRecord; record; record = record->nextInTrans)
+ if (record->state == recLock)
+ ++locks;
+ else if (!record->hasRecord())
+ ++deletes;
+ else if (record->priorVersion)
+ ++updates;
+ else
+ ++inserts;
+
+ Log::debug ("%*s Trans %d, thread %d, locks %d, inserts %d, deleted %d, updates %d\n",
+ level * INDENT, "", transactionId,
+ thread->threadId, locks, inserts, deletes, updates);
+
+ ++level;
+
+ Table *table = blockingRecord->format->table;
+
+ if (blockingRecord)
+ Log::debug("%*s Blocking on %s.%s record %d\n",
+ level * INDENT, "",
+ table->name, table->schemaName,
+ blockingRecord->recordNumber);
+
+ for (record = firstRecord; record; record = record->nextInTrans)
+ {
+ const char *what;
+
+ if (record->state == recLock)
+ what = "locked";
+ else if (!record->hasRecord())
+ what = "deleted";
+ else if (record->priorVersion)
+ what = "updated";
+ else
+ what = "inserted";
+
+ Table *table = record->format->table;
+
+ Log::debug("%*s Record %s.%s number %d %s\n",
+ level * INDENT, "",
+ table->name,
+ table->schemaName,
+ record->recordNumber,
+ what);
+ }
+
+ database->transactionManager->printBlocking(this, level);
}
void Transaction::getInfo(InfoTable* infoTable)
diff -Nrup a/storage/falcon/Transaction.h b/storage/falcon/Transaction.h
--- a/storage/falcon/Transaction.h 2007-09-20 17:42:46 +02:00
+++ b/storage/falcon/Transaction.h 2007-09-25 07:14:42 +02:00
@@ -41,6 +41,7 @@ class Index;
class Bitmap;
class Record;
class InfoTable;
+class Thread;
// Transaction States
@@ -120,6 +121,12 @@ public:
void thaw(DeferredIndex* deferredIndex);
void print(void);
void getInfo(InfoTable* infoTable);
+ void fullyCommitted(void);
+ void releaseCommittedTransaction(void);
+ void commitNoUpdates(void);
+ void validateDependencies(bool noDependencies);
+ void releaseSavePoints(void);
+ void printBlocking(int level);
inline bool isActive()
{
@@ -139,6 +146,8 @@ public:
SavePoint *freeSavePoints;
SavePoint localSavePoints[LOCAL_SAVE_POINTS];
DeferredIndex *deferredIndexes;
+ Thread *thread;
+ Record *blockingRecord;
int deferredIndexCount;
int statesAllocated;
int isolationLevel;
@@ -171,7 +180,6 @@ public:
volatile INTERLOCK_TYPE dependencies;
volatile INTERLOCK_TYPE useCount;
volatile INTERLOCK_TYPE inList;
- //volatile INTERLOCK_TYPE cleanupNeeded;
protected:
RecordVersion *firstRecord;
@@ -179,12 +187,6 @@ protected:
RecordVersion **recordPtr;
virtual ~Transaction();
-public:
- void fullyCommitted(void);
- void releaseCommittedTransaction(void);
- void commitNoUpdates(void);
- void validateDependencies(bool noDependencies);
- void releaseSavePoints(void);
};
#endif // !defined(AFX_TRANSACTION_H__02AD6A4D_A433_11D2_AB5B_0000C01D2301__INCLUDED_)
diff -Nrup a/storage/falcon/TransactionManager.cpp b/storage/falcon/TransactionManager.cpp
--- a/storage/falcon/TransactionManager.cpp 2007-09-20 17:42:46 +02:00
+++ b/storage/falcon/TransactionManager.cpp 2007-09-25 07:14:42 +02:00
@@ -25,6 +25,7 @@
#include "Connection.h"
#include "InfoTable.h"
#include "Log.h"
+#include "LogLock.h"
static const int EXTRA_TRANSACTIONS = 10;
@@ -426,4 +427,22 @@ void TransactionManager::removeTransacti
break;
}
}
+}
+
+void TransactionManager::printBlockage(void)
+{
+ LogLock logLock;
+ Sync sync (&activeTransactions.syncObject, "TransactionManager::printBlockage");
+ sync.lock (Shared);
+
+ for (Transaction *trans = activeTransactions.first; trans; trans = trans->next)
+ if (trans->state == Active && !trans->waitingFor)
+ trans->printBlocking(1);
+}
+
+void TransactionManager::printBlocking(Transaction* transaction, int level)
+{
+ for (Transaction *trans = activeTransactions.first; trans; trans = trans->next)
+ if (trans->state == Active && trans->waitingFor == transaction)
+ trans->printBlocking(level);
}
diff -Nrup a/storage/falcon/TransactionManager.h b/storage/falcon/TransactionManager.h
--- a/storage/falcon/TransactionManager.h 2007-09-20 17:42:46 +02:00
+++ b/storage/falcon/TransactionManager.h 2007-09-25 07:14:42 +02:00
@@ -47,6 +47,8 @@ public:
void validateDependencies(void);
void removeCommittedTransaction(Transaction* transaction);
void removeTransaction(Transaction* transaction);
+ void printBlockage(void);
+ void printBlocking(Transaction* transaction, int level);
TransId transactionSequence;
Database *database;
| Thread |
|---|
| • bk commit into 6.0 tree (hakank:1.2596) | Hakan Kuecuekyilmaz | 25 Sep |