#At file:///home/jonas/src/telco-7.0/ based on revid:jonas@stripped
4396 Jonas Oreland 2011-05-23
ndb - bug#12581213 fix accounting of MaxNoOfOpenFiles vs. unbound files (data files)
added:
mysql-test/suite/ndb/r/ndb_dd_bug12581213.result
mysql-test/suite/ndb/t/ndb_dd_bug12581213.cnf
mysql-test/suite/ndb/t/ndb_dd_bug12581213.test
modified:
storage/ndb/src/kernel/blocks/ndbfs/AsyncIoThread.cpp
storage/ndb/src/kernel/blocks/ndbfs/AsyncIoThread.hpp
storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp
storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.hpp
storage/ndb/src/kernel/blocks/ndbfs/Pool.hpp
=== added file 'mysql-test/suite/ndb/r/ndb_dd_bug12581213.result'
--- a/mysql-test/suite/ndb/r/ndb_dd_bug12581213.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/r/ndb_dd_bug12581213.result 2011-05-23 10:34:46 +0000
@@ -0,0 +1,17 @@
+CREATE LOGFILE GROUP lg1
+ADD UNDOFILE 'undofile.dat'
+INITIAL_SIZE 16M
+UNDO_BUFFER_SIZE = 1M
+ENGINE NDB;
+CREATE TABLESPACE ts1
+ADD DATAFILE 'datafile.dat'
+USE LOGFILE GROUP lg1
+INITIAL_SIZE 12M
+ENGINE NDB;
+alter tablespace ts1
+drop datafile 'datafile.dat'
+engine ndb;
+drop tablespace ts1
+engine ndb;
+drop logfile group lg1
+engine ndb;
=== added file 'mysql-test/suite/ndb/t/ndb_dd_bug12581213.cnf'
--- a/mysql-test/suite/ndb/t/ndb_dd_bug12581213.cnf 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/t/ndb_dd_bug12581213.cnf 2011-05-23 10:34:46 +0000
@@ -0,0 +1,7 @@
+!include suite/ndb/my.cnf
+
+[cluster_config.1]
+ndbd=
+NoOfReplicas=1
+MaxNoOfOpenFiles=27
+InitialNoOfOpenFiles=26
=== added file 'mysql-test/suite/ndb/t/ndb_dd_bug12581213.test'
--- a/mysql-test/suite/ndb/t/ndb_dd_bug12581213.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/t/ndb_dd_bug12581213.test 2011-05-23 10:34:46 +0000
@@ -0,0 +1,23 @@
+-- source include/have_ndb.inc
+
+CREATE LOGFILE GROUP lg1
+ADD UNDOFILE 'undofile.dat'
+INITIAL_SIZE 16M
+UNDO_BUFFER_SIZE = 1M
+ENGINE NDB;
+
+CREATE TABLESPACE ts1
+ADD DATAFILE 'datafile.dat'
+USE LOGFILE GROUP lg1
+INITIAL_SIZE 12M
+ENGINE NDB;
+
+alter tablespace ts1
+drop datafile 'datafile.dat'
+engine ndb;
+
+drop tablespace ts1
+engine ndb;
+
+drop logfile group lg1
+engine ndb;
=== modified file 'storage/ndb/src/kernel/blocks/ndbfs/AsyncIoThread.cpp'
--- a/storage/ndb/src/kernel/blocks/ndbfs/AsyncIoThread.cpp 2011-02-02 00:40:07 +0000
+++ b/storage/ndb/src/kernel/blocks/ndbfs/AsyncIoThread.cpp 2011-05-23 10:34:46 +0000
@@ -30,17 +30,17 @@
#include <EventLogger.hpp>
extern EventLogger * g_eventLogger;
-AsyncIoThread::AsyncIoThread(class Ndbfs& fs, AsyncFile* file)
+AsyncIoThread::AsyncIoThread(class Ndbfs& fs, bool bound)
: m_fs(fs)
{
- m_current_file = file;
- if (file)
+ m_current_file = 0;
+ if (bound)
{
- theMemoryChannelPtr = &theMemoryChannel;
+ theMemoryChannelPtr = &m_fs.theToBoundThreads;
}
else
{
- theMemoryChannelPtr = &m_fs.theToThreads;
+ theMemoryChannelPtr = &m_fs.theToUnboundThreads;
}
theReportTo = &m_fs.theFromThreads;
}
@@ -149,13 +149,17 @@ AsyncIoThread::run()
switch (request->action) {
case Request::open:
file->openReq(request);
+ if (request->error == 0 && request->m_do_bind)
+ attach(file);
break;
case Request::close:
file->closeReq(request);
+ detach(file);
break;
case Request::closeRemove:
file->closeReq(request);
file->removeReq(request);
+ detach(file);
break;
case Request::readPartial:
case Request::read:
@@ -265,3 +269,32 @@ AsyncIoThread::buildIndxReq(Request* req
req.buffer_size = request->file->m_page_cnt * sizeof(GlobalPage);
request->error = (* req.func_ptr)(&req);
}
+
+void
+AsyncIoThread::attach(AsyncFile* file)
+{
+ assert(m_current_file == 0);
+ assert(theMemoryChannelPtr == &m_fs.theToBoundThreads);
+ m_current_file = file;
+ theMemoryChannelPtr = &theMemoryChannel;
+ file->attach(this);
+ m_fs.cnt_active_bound(1);
+}
+
+void
+AsyncIoThread::detach(AsyncFile* file)
+{
+ if (m_current_file == 0)
+ {
+ assert(file->getThread() == 0);
+ }
+ else
+ {
+ assert(m_current_file == file);
+ assert(theMemoryChannelPtr = &theMemoryChannel);
+ m_current_file = 0;
+ theMemoryChannelPtr = &m_fs.theToBoundThreads;
+ file->detach(this);
+ m_fs.cnt_active_bound(-1);
+ }
+}
=== modified file 'storage/ndb/src/kernel/blocks/ndbfs/AsyncIoThread.hpp'
--- a/storage/ndb/src/kernel/blocks/ndbfs/AsyncIoThread.hpp 2011-04-21 09:21:18 +0000
+++ b/storage/ndb/src/kernel/blocks/ndbfs/AsyncIoThread.hpp 2011-05-23 10:34:46 +0000
@@ -43,6 +43,8 @@ class Request
public:
Request() {}
+ void atGet() { m_do_bind = false; }
+
enum Action {
open,
close,
@@ -113,6 +115,7 @@ public:
// Information for open, needed if the first open action fails.
AsyncFile* file;
Uint32 theTrace;
+ bool m_do_bind;
MemoryChannel<Request>::ListMember m_mem_channel;
};
@@ -134,7 +137,7 @@ class AsyncIoThread
friend class Ndbfs;
friend class AsyncFile;
public:
- AsyncIoThread(class Ndbfs&, AsyncFile* file);
+ AsyncIoThread(class Ndbfs&, bool bound);
virtual ~AsyncIoThread() {};
struct NdbThread* doStart();
@@ -174,6 +177,8 @@ private:
*/
void buildIndxReq(Request*);
+ void attach(AsyncFile*);
+ void detach(AsyncFile*);
};
#endif
=== modified file 'storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp'
--- a/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp 2011-04-21 09:21:18 +0000
+++ b/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp 2011-05-23 10:34:46 +0000
@@ -45,6 +45,8 @@
#include <EventLogger.hpp>
extern EventLogger * g_eventLogger;
+NdbMutex g_active_bound_threads_mutex;
+
inline
int pageSize( const NewVARIABLE* baseAddrRef )
{
@@ -62,10 +64,15 @@ Ndbfs::Ndbfs(Block_context& ctx) :
scanningInProgress(false),
theLastId(0),
theRequestPool(0),
- m_maxOpenedFiles(0)
+ m_maxOpenedFiles(0),
+ m_bound_threads_cnt(0),
+ m_unbounds_threads_cnt(0),
+ m_active_bound_threads_cnt(0)
{
BLOCK_CONSTRUCTOR(Ndbfs);
+ NdbMutex_Init(&g_active_bound_threads_mutex);
+
// Set received signals
addRecSignal(GSN_READ_CONFIG_REQ, &Ndbfs::execREAD_CONFIG_REQ);
addRecSignal(GSN_DUMP_STATE_ORD, &Ndbfs::execDUMP_STATE_ORD);
@@ -100,7 +107,8 @@ Ndbfs::~Ndbfs()
request.action = Request::end;
for (unsigned i = 0; i < theThreads.size(); i++)
{
- theToThreads.writeChannel(&request);
+ theToBoundThreads.writeChannel(&request);
+ theToUnboundThreads.writeChannel(&request);
}
for (unsigned i = 0; i < theThreads.size(); i++)
@@ -274,7 +282,12 @@ Ndbfs::execREAD_CONFIG_REQ(Signal* signa
// Create idle AsyncFiles
for (Uint32 i = 0; i < noIdleFiles; i++)
{
- theIdleBoundFiles.push_back(createAsyncFile(true /* bound */));
+ theIdleFiles.push_back(createAsyncFile());
+ AsyncIoThread * thr = createIoThread(/* bound */ true);
+ if (thr)
+ {
+ theThreads.push_back(thr);
+ }
}
Uint32 threadpool = 2;
@@ -283,7 +296,7 @@ Ndbfs::execREAD_CONFIG_REQ(Signal* signa
// Create IoThreads
for (Uint32 i = 0; i < threadpool; i++)
{
- AsyncIoThread * thr = createIoThread(0);
+ AsyncIoThread * thr = createIoThread(/* bound */ false);
if (thr)
{
jam();
@@ -339,7 +352,7 @@ Ndbfs::execSTTOR(Signal* signal)
ndbrequire(0);
}
-int
+int
Ndbfs::forward( AsyncFile * file, Request* request)
{
jam();
@@ -348,9 +361,13 @@ Ndbfs::forward( AsyncFile * file, Reques
{
thr->dispatch(request);
}
+ else if (request->m_do_bind)
+ {
+ theToBoundThreads.writeChannel(request);
+ }
else
{
- theToThreads.writeChannel(request);
+ theToUnboundThreads.writeChannel(request);
}
return 1;
}
@@ -444,7 +461,8 @@ Ndbfs::execFSOPENREQ(Signal* signal)
request->par.open.file_size <<= 32;
request->par.open.file_size |= fsOpenReq->file_size_lo;
request->par.open.auto_sync_size = fsOpenReq->auto_sync_size;
-
+ request->m_do_bind = bound;
+
ndbrequire(forward(file, request));
}
@@ -454,7 +472,8 @@ Ndbfs::execFSREMOVEREQ(Signal* signal)
jamEntry();
const FsRemoveReq * const req = (FsRemoveReq *)signal->getDataPtr();
const BlockReference userRef = req->userReference;
- AsyncFile* file = getIdleFile(true);
+ bool bound = true;
+ AsyncFile* file = getIdleFile(bound);
ndbrequire(file != NULL);
SectionHandle handle(this, signal);
@@ -479,7 +498,8 @@ Ndbfs::execFSREMOVEREQ(Signal* signal)
request->set(userRef, req->userPointer, newId() );
request->file = file;
request->theTrace = signal->getTrace();
-
+ request->m_do_bind = bound;
+
if (version == 6)
{
ndbrequire(bp < NDB_ARRAY_SIZE(m_base_path));
@@ -541,6 +561,7 @@ Ndbfs::execFSCLOSEREQ(Signal * signal)
request->file = openFile;
request->error = 0;
request->theTrace = signal->getTrace();
+ request->m_do_bind = false;
ndbrequire(forward(openFile, request));
}
@@ -584,6 +605,7 @@ Ndbfs::readWriteRequest(int action, Sign
request->file = openFile;
request->action = (Request::Action) action;
request->theTrace = signal->getTrace();
+ request->m_do_bind = false;
Uint32 format = fsRWReq->getFormatFlag(fsRWReq->operationFlag);
@@ -804,7 +826,8 @@ Ndbfs::execFSSYNCREQ(Signal * signal)
request->set(userRef, userPointer, filePointer);
request->file = openFile;
request->theTrace = signal->getTrace();
-
+ request->m_do_bind = false;
+
ndbrequire(forward(openFile,request));
}
@@ -832,6 +855,7 @@ Ndbfs::execFSSUSPENDORD(Signal * signal)
request->file = openFile;
request->theTrace = signal->getTrace();
request->par.suspend.milliseconds = millis;
+ request->m_do_bind = false;
ndbrequire(forward(openFile,request));
}
@@ -895,6 +919,7 @@ Ndbfs::execFSAPPENDREQ(Signal * signal)
request->action = Request::append;
else
request->action = Request::append_synch;
+ request->m_do_bind = false;
ndbrequire(forward(openFile, request));
return;
@@ -918,7 +943,8 @@ Ndbfs::execALLOC_MEM_REQ(Signal* signal)
AllocMemReq* req = (AllocMemReq*)signal->getDataPtr();
- AsyncFile* file = getIdleFile(true);
+ bool bound = true;
+ AsyncFile* file = getIdleFile(bound);
ndbrequire(file != NULL);
Request *request = theRequestPool->get();
@@ -932,6 +958,7 @@ Ndbfs::execALLOC_MEM_REQ(Signal* signal)
request->par.alloc.requestInfo = req->requestInfo;
request->par.alloc.bytes = (Uint64(req->bytes_hi) << 32) + req->bytes_lo;
request->action = Request::allocmem;
+ request->m_do_bind = bound;
ndbrequire(forward(file, request));
}
@@ -943,7 +970,8 @@ Ndbfs::execBUILD_INDX_IMPL_REQ(Signal* s
jamEntry();
mt_BuildIndxReq * req = (mt_BuildIndxReq*)signal->getDataPtr();
- AsyncFile* file = getIdleFile(true);
+ bool bound = true;
+ AsyncFile* file = getIdleFile(bound);
ndbrequire(file != NULL);
Request *request = theRequestPool->get();
@@ -972,6 +1000,7 @@ Ndbfs::execBUILD_INDX_IMPL_REQ(Signal* s
memcpy(&request->par.build.m_req, req, sizeof(* req));
request->action = Request::buildindx;
+ request->m_do_bind = bound;
ndbrequire(forward(file, request));
}
@@ -1000,8 +1029,8 @@ Ndbfs::newId()
}
AsyncFile*
-Ndbfs::createAsyncFile(bool bound){
-
+Ndbfs::createAsyncFile()
+{
// Check limit of open files
if (m_maxFiles !=0 && theFiles.size() == m_maxFiles)
{
@@ -1024,42 +1053,35 @@ Ndbfs::createAsyncFile(bool bound){
ERROR_SET(fatal, NDBD_EXIT_AFS_MAXOPEN,""," Ndbfs::createAsyncFile");
}
- if (bound)
- {
- AsyncIoThread * thr = createIoThread(file);
- theThreads.push_back(thr);
- file->attach(thr);
-
-#ifdef VM_TRACE
- ndbout_c("NDBFS: Created new file thread %d", theFiles.size());
-#endif
- }
-
theFiles.push_back(file);
-
return file;
}
void
Ndbfs::pushIdleFile(AsyncFile* file)
{
- if (file->getThread())
- {
- theIdleBoundFiles.push_back(file);
- }
- else
- {
- theIdleUnboundFiles.push_back(file);
- }
+ assert(file->getThread() == 0);
+ theIdleFiles.push_back(file);
}
AsyncIoThread*
-Ndbfs::createIoThread(AsyncFile* file)
+Ndbfs::createIoThread(bool bound)
{
- AsyncIoThread* thr = new AsyncIoThread(*this, file);
+ AsyncIoThread* thr = new AsyncIoThread(*this, bound);
+ if (thr)
+ {
+#ifdef VM_TRACE
+ ndbout_c("NDBFS: Created new file thread %d", theThreads.size());
+#endif
- struct NdbThread* thrptr = thr->doStart();
- globalEmulatorData.theConfiguration->addThread(thrptr, NdbfsThread);
+ struct NdbThread* thrptr = thr->doStart();
+ globalEmulatorData.theConfiguration->addThread(thrptr, NdbfsThread);
+
+ if (bound)
+ m_bound_threads_cnt++;
+ else
+ m_unbounds_threads_cnt++;
+ }
return thr;
}
@@ -1067,31 +1089,50 @@ Ndbfs::createIoThread(AsyncFile* file)
AsyncFile*
Ndbfs::getIdleFile(bool bound)
{
- if (bound)
+ AsyncFile* file = 0;
+ Uint32 sz = theIdleFiles.size();
+ if (sz)
{
- Uint32 sz = theIdleBoundFiles.size();
- if (sz)
- {
- AsyncFile* file = theIdleBoundFiles[sz - 1];
- theIdleBoundFiles.erase(sz - 1);
- return file;
- }
+ file = theIdleFiles[sz - 1];
+ theIdleFiles.erase(sz - 1);
}
else
{
- Uint32 sz = theIdleUnboundFiles.size();
- if (sz)
+ file = createAsyncFile();
+ }
+
+ if (bound)
+ {
+ /**
+ * Check if we should create thread
+ */
+ if (m_active_bound_threads_cnt == m_bound_threads_cnt)
{
- AsyncFile* file = theIdleUnboundFiles[sz - 1];
- theIdleUnboundFiles.erase(sz - 1);
- return file;
+ AsyncIoThread * thr = createIoThread(true);
+ if (thr)
+ {
+ theThreads.push_back(thr);
+ }
}
}
-
- return createAsyncFile(bound);
+ return file;
}
-
+void
+Ndbfs::cnt_active_bound(int val)
+{
+ Guard g(&g_active_bound_threads_mutex);
+ if (val < 0)
+ {
+ val = -val;
+ assert(m_active_bound_threads_cnt >= (Uint32)val);
+ m_active_bound_threads_cnt -= val;
+ }
+ else
+ {
+ m_active_bound_threads_cnt += val;
+ }
+}
void
Ndbfs::report(Request * request, Signal* signal)
@@ -1506,10 +1547,13 @@ Ndbfs::execDUMP_STATE_ORD(Signal* signal
infoEvent("NDBFS: Files: %d Open files: %d",
theFiles.size(),
theOpenFiles.size());
- infoEvent(" Idle files: (bound: %u unbound: %u) Max opened files: %d",
- theIdleBoundFiles.size(),
- theIdleUnboundFiles.size(),
+ infoEvent(" Idle files: %u Max opened files: %d",
+ theIdleFiles.size(),
m_maxOpenedFiles);
+ infoEvent(" Bound Threads: %u (active %u) Unbound threads: %u",
+ m_bound_threads_cnt,
+ m_active_bound_threads_cnt,
+ m_unbounds_threads_cnt);
infoEvent(" Max files: %d",
m_maxFiles);
infoEvent(" Requests: %d",
@@ -1522,7 +1566,10 @@ Ndbfs::execDUMP_STATE_ORD(Signal* signal
for (unsigned i = 0; i < theOpenFiles.size(); i++){
AsyncFile* file = theOpenFiles.getFile(i);
- infoEvent("%2d (0x%lx): %s", i, (long)file, file->theFileName.c_str());
+ infoEvent("%2d (0x%lx): %s thr: %lx", i,
+ (long)file,
+ file->theFileName.c_str(),
+ (long)file->getThread());
}
return;
}
@@ -1536,18 +1583,14 @@ Ndbfs::execDUMP_STATE_ORD(Signal* signal
return;
}
if(signal->theData[0] == DumpStateOrd::NdbfsDumpIdleFiles){
- infoEvent("NDBFS: Dump idle files: %d %u",
- theIdleBoundFiles.size(), theIdleUnboundFiles.size());
-
- for (unsigned i = 0; i < theIdleBoundFiles.size(); i++){
- AsyncFile* file = theIdleBoundFiles[i];
- infoEvent("%2d (0x%lx): %s", i, (long)file, file->isOpen()?"OPEN":"CLOSED");
- }
+ infoEvent("NDBFS: Dump idle files: %u",
+ theIdleFiles.size());
- for (unsigned i = 0; i < theIdleUnboundFiles.size(); i++){
- AsyncFile* file = theIdleUnboundFiles[i];
+ for (unsigned i = 0; i < theIdleFiles.size(); i++){
+ AsyncFile* file = theIdleFiles[i];
infoEvent("%2d (0x%lx): %s", i, (long)file, file->isOpen()?"OPEN":"CLOSED");
}
+
return;
}
=== modified file 'storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.hpp'
--- a/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.hpp 2011-02-01 23:27:25 +0000
+++ b/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.hpp 2011-05-23 10:34:46 +0000
@@ -79,19 +79,19 @@ private:
// Communication from/to files
MemoryChannel<Request> theFromThreads;
- MemoryChannel<Request> theToThreads;
+ MemoryChannel<Request> theToBoundThreads;
+ MemoryChannel<Request> theToUnboundThreads;
Pool<Request>* theRequestPool;
- AsyncIoThread* createIoThread(AsyncFile* file);
- AsyncFile* createAsyncFile(bool bound);
+ AsyncIoThread* createIoThread(bool bound);
+ AsyncFile* createAsyncFile();
AsyncFile* getIdleFile(bool bound);
void pushIdleFile(AsyncFile*);
Vector<AsyncIoThread*> theThreads;// List of all created threads
Vector<AsyncFile*> theFiles; // List all created AsyncFiles
- Vector<AsyncFile*> theIdleBoundFiles; // List of idle AsyncFiles
- Vector<AsyncFile*> theIdleUnboundFiles; // List of idle AsyncFiles
+ Vector<AsyncFile*> theIdleFiles; // List of idle AsyncFiles
OpenFiles theOpenFiles; // List of open AsyncFiles
BaseString m_base_path[FsOpenReq::BP_MAX];
@@ -105,6 +105,11 @@ private:
void readWriteRequest( int action, Signal * signal );
static Uint32 translateErrno(int aErrno);
+
+ Uint32 m_bound_threads_cnt;
+ Uint32 m_unbounds_threads_cnt;
+ Uint32 m_active_bound_threads_cnt;
+ void cnt_active_bound(int val);
public:
const BaseString& get_base_path(Uint32 no) const;
};
=== modified file 'storage/ndb/src/kernel/blocks/ndbfs/Pool.hpp'
--- a/storage/ndb/src/kernel/blocks/ndbfs/Pool.hpp 2011-02-01 23:27:25 +0000
+++ b/storage/ndb/src/kernel/blocks/ndbfs/Pool.hpp 2011-05-23 10:34:46 +0000
@@ -249,6 +249,7 @@ template <class T> inline T* Pool<T>::ge
}
--theTop;
tmp = theList[theTop];
+ tmp->atGet();
return tmp;
}
Attachment: [text/bzr-bundle] bzr/jonas@mysql.com-20110523103446-oer4qe9cvuagk3w9.bundle
| Thread |
|---|
| • bzr commit into mysql-5.1-telco-7.0 branch (jonas:4396) Bug#12581213 | Jonas Oreland | 23 May |