Bug #47392 NdbMem_{Allocate,Free} always uses the heap
Submitted: 17 Sep 2009 6:57 Modified: 31 Aug 2010 7:07
Reporter: jack andrews Email Updates:
Status: Won't fix Impact on me:
None 
Category:MySQL Cluster: Cluster (NDB) storage engine Severity:S3 (Non-critical)
Version:mysql-5.1-telco-7.0 OS:Windows
Assigned to: Jonas Oreland CPU Architecture:Any

[17 Sep 2009 6:57] jack andrews
Description:
this issue arose from bug 46061 and investigating atrt tests (run in mtr with magnus's script to convert atrt tests to a mtr 'suite').  with many ndbds running, lots of swapping was happening and sometimes out of memory.

How to repeat:
.

Suggested fix:
use VirtualAlloc for larger mem regions (just like the linux allocator.
[17 Sep 2009 7:02] jack andrews
=== modified file 'storage/ndb/src/common/portlib/NdbCondition.c'
--- storage/ndb/src/common/portlib/NdbCondition.c	2009-08-12 18:10:54 +0000
+++ storage/ndb/src/common/portlib/NdbCondition.c	2009-09-17 05:30:46 +0000
@@ -230,7 +230,7 @@
     return 1;
 
   result = pthread_cond_destroy(&p_cond->cond);
-  free(p_cond);
+  NdbMem_Free(p_cond);
 
   return 0;
 }

=== modified file 'storage/ndb/src/common/portlib/NdbMem.c'
--- storage/ndb/src/common/portlib/NdbMem.c	2009-05-26 18:53:34 +0000
+++ storage/ndb/src/common/portlib/NdbMem.c	2009-09-17 05:30:47 +0000
@@ -32,8 +32,65 @@
   /* Do nothing */
   return;
 }
-
-
+#ifdef _WIN32
+/*virtual alloc larger requests*/
+#define VMLIMIT 1024*1024
+static int pagesize=0; /*system page size*/
+static int pagemask=0;
+static int isvirt(char*p) {
+  my_ptrdiff_t pint=(my_ptrdiff_t)p;
+  return !(pint&pagemask);
+}
+void NdbMem_Free(void* p) {
+  if(isvirt(p))
+    VirtualFree(p,0,MEM_RELEASE);
+  else {
+    char*s=p,*origin=s-s[-1];
+    free(origin);
+  }
+}
+void* NdbMem_Allocate(size_t size) {
+  char*rv=0;
+  if(!pagesize) { //init
+    SYSTEM_INFO si;
+    GetSystemInfo(&si);
+    pagesize=si.dwPageSize;
+    pagemask=pagesize-1;
+  }
+  assert(size > 0);
+  if(size>VMLIMIT) {
+    rv = VirtualAlloc(0,size,MEM_COMMIT,PAGE_READWRITE);
+    assert(isvirt(rv));
+  }
+  else {
+    char one64=sizeof(uint64),two64=one64*2;
+    char*p=malloc(size+two64);
+    if(!p)
+      return p;
+    if(isvirt(p+two64)) {
+      rv=p+one64;
+      rv[-1]=one64;
+    } else {
+      rv=p+two64;
+      rv[-1]=two64;
+    }
+    assert(!isvirt(rv));
+    assert(rv-rv[-1]==p);
+  }
+  return rv;
+}
+
+void* NdbMem_AllocateAlign(size_t size, size_t alignment)
+{
+  (void)alignment; /* remove warning for unused parameter */
+  /*
+    return (void*)memalign(alignment, size);
+    TEMP fix
+  */
+  return NdbMem_Allocate(size);
+}
+
+#else
 void* NdbMem_Allocate(size_t size)
 {
   void* mem_allocated;
@@ -49,15 +106,14 @@
     return (void*)memalign(alignment, size);
     TEMP fix
   */
-  return (void*)malloc(size);
+  return NdbMem_Allocate(size);
 }
 
-
 void NdbMem_Free(void* ptr)
 {
   free(ptr);
 }
-
+#endif
  
 int NdbMem_MemLockAll(int i){
   if (i == 1)

=== modified file 'storage/ndb/src/common/portlib/NdbThread.c'
--- storage/ndb/src/common/portlib/NdbThread.c	2009-09-08 15:12:34 +0000
+++ storage/ndb/src/common/portlib/NdbThread.c	2009-09-17 05:30:47 +0000
@@ -269,7 +269,7 @@
   DBUG_ENTER("NdbThread_Destroy");
   if (*p_thread != NULL){
     DBUG_PRINT("enter",("*p_thread: 0x%lx", (long) *p_thread));
-    free(* p_thread); 
+    NdbMem_Free(* p_thread); 
     * p_thread = 0;
   }
   DBUG_VOID_RETURN;

=== modified file 'storage/ndb/src/kernel/error/ErrorReporter.cpp'
--- storage/ndb/src/kernel/error/ErrorReporter.cpp	2009-05-27 15:21:45 +0000
+++ storage/ndb/src/kernel/error/ErrorReporter.cpp	2009-09-17 06:18:52 +0000
@@ -69,7 +69,6 @@
   unsigned int traceFileNo;
   
   char *file_name= NdbConfig_NextTraceFileName(globalData.ownId);
-  NdbAutoPtr<char> tmp_aptr(file_name);
 
   /* 
    * Read last number from tracefile
@@ -105,6 +104,7 @@
     fclose(stream);
   }
 
+  NdbMem_Free(file_name);
   return traceFileNo;
 }
 
@@ -243,6 +243,7 @@
 	     const char* thrdProblemData, 
              const char* thrdObjRef,
              NdbShutdownType & nst){
+  int rv=0;
   FILE *stream;
   unsigned offset;
   unsigned long maxOffset;  // Maximum size of file.
@@ -260,7 +261,6 @@
   if (globalData.ownId > 0)
     theTraceFileName= NdbConfig_TraceFileName(globalData.ownId,
 					      ErrorReporter::get_trace_no());
-  NdbAutoPtr<char> tmp_aptr1(theTraceFileName);
   
   // The first 69 bytes is info about the current offset
   Uint32 noMsg = globalEmulatorData.theConfiguration->maxNoOfErrorLogs();
@@ -268,7 +268,6 @@
   maxOffset = (69 + (noMsg * MESSAGE_LENGTH));
   
   char *theErrorFileName= (char *)NdbConfig_ErrorFileName(globalData.ownId);
-  NdbAutoPtr<char> tmp_aptr2(theErrorFileName);
 
   stream = fopen(theErrorFileName, "r+");
   if (stream == NULL) { /* If the file could not be opened. */
@@ -279,7 +278,8 @@
     if(stream == NULL)
     {
       fprintf(stderr,"Unable to open error log file: %s\n", theErrorFileName);
-      return -1;
+      rv=-1;
+      goto end;
     }
     fprintf(stream, "%s%u%s", "Current byte-offset of file-pointer is: ", 69,
 	    "                        \n\n\n");   
@@ -364,8 +364,12 @@
       fclose(jamStream);
     }
   }
-
-  return 0;
+end:
+  if(theTraceFileName)
+    NdbMem_Free(theTraceFileName);
+  if(theErrorFileName)
+    NdbMem_Free(theErrorFileName);
+  return rv;
 }
 
 void 

=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.cpp'
--- storage/ndb/src/mgmsrv/MgmtSrvr.cpp	2009-09-08 15:12:34 +0000
+++ storage/ndb/src/mgmsrv/MgmtSrvr.cpp	2009-09-17 05:30:47 +0000
@@ -53,6 +53,7 @@
 #include <NdbConfig.h>
 
 #include <NdbAutoPtr.hpp>
+#include <NdbMem.h>
 
 #include <ndberror.h>
 
@@ -652,7 +653,7 @@
     char *clusterLog= NdbConfig_ClusterLogFileName(_ownNodeId);
     logdest.assfmt("FILE:filename=%s,maxsize=1000000,maxfiles=6",
 		   clusterLog);
-    free(clusterLog);
+    NdbMem_Free(clusterLog);
   }
 
   int err= 0;
[31 Aug 2010 7:07] Jonas Oreland
won't fix