summaryrefslogtreecommitdiff
path: root/ndb/src/common/portlib
diff options
context:
space:
mode:
Diffstat (limited to 'ndb/src/common/portlib')
-rw-r--r--ndb/src/common/portlib/Makefile43
-rw-r--r--ndb/src/common/portlib/memtest/Makefile12
-rw-r--r--ndb/src/common/portlib/memtest/memtest.c245
-rw-r--r--ndb/src/common/portlib/memtest/munmaptest/Makefile14
-rw-r--r--ndb/src/common/portlib/memtest/munmaptest/munmaptest.cpp251
-rw-r--r--ndb/src/common/portlib/mmstest/mmslist.cpp103
-rw-r--r--ndb/src/common/portlib/mmstest/mmstest.cpp76
-rw-r--r--ndb/src/common/portlib/ose/Makefile31
-rw-r--r--ndb/src/common/portlib/ose/NdbCondition.c244
-rw-r--r--ndb/src/common/portlib/ose/NdbConditionOSE.h103
-rw-r--r--ndb/src/common/portlib/ose/NdbEnv.c55
-rw-r--r--ndb/src/common/portlib/ose/NdbHost.c55
-rw-r--r--ndb/src/common/portlib/ose/NdbMem.c183
-rw-r--r--ndb/src/common/portlib/ose/NdbMem_SoftOse.cpp53
-rw-r--r--ndb/src/common/portlib/ose/NdbMutex.c86
-rw-r--r--ndb/src/common/portlib/ose/NdbOut.cpp99
-rw-r--r--ndb/src/common/portlib/ose/NdbSleep.c36
-rw-r--r--ndb/src/common/portlib/ose/NdbTCP.c38
-rw-r--r--ndb/src/common/portlib/ose/NdbThread.c184
-rw-r--r--ndb/src/common/portlib/ose/NdbTick.c64
-rw-r--r--ndb/src/common/portlib/test/Makefile15
-rw-r--r--ndb/src/common/portlib/test/NdbPortLibTest.cpp621
-rw-r--r--ndb/src/common/portlib/unix/Makefile27
-rw-r--r--ndb/src/common/portlib/unix/NdbCondition.c179
-rw-r--r--ndb/src/common/portlib/unix/NdbDaemon.c170
-rw-r--r--ndb/src/common/portlib/unix/NdbEnv.c34
-rw-r--r--ndb/src/common/portlib/unix/NdbHost.c34
-rw-r--r--ndb/src/common/portlib/unix/NdbMem.c76
-rw-r--r--ndb/src/common/portlib/unix/NdbMutex.c93
-rw-r--r--ndb/src/common/portlib/unix/NdbSleep.c48
-rw-r--r--ndb/src/common/portlib/unix/NdbTCP.c60
-rw-r--r--ndb/src/common/portlib/unix/NdbThread.c119
-rw-r--r--ndb/src/common/portlib/unix/NdbTick.c110
-rw-r--r--ndb/src/common/portlib/win32/Makefile30
-rw-r--r--ndb/src/common/portlib/win32/NdbCondition.c184
-rw-r--r--ndb/src/common/portlib/win32/NdbDaemon.c44
-rw-r--r--ndb/src/common/portlib/win32/NdbEnv.c33
-rw-r--r--ndb/src/common/portlib/win32/NdbHost.c53
-rw-r--r--ndb/src/common/portlib/win32/NdbMem.c237
-rw-r--r--ndb/src/common/portlib/win32/NdbMutex.c78
-rw-r--r--ndb/src/common/portlib/win32/NdbSleep.c35
-rw-r--r--ndb/src/common/portlib/win32/NdbTCP.c39
-rw-r--r--ndb/src/common/portlib/win32/NdbThread.c118
-rw-r--r--ndb/src/common/portlib/win32/NdbTick.c64
44 files changed, 4476 insertions, 0 deletions
diff --git a/ndb/src/common/portlib/Makefile b/ndb/src/common/portlib/Makefile
new file mode 100644
index 00000000000..a928fc1e6d7
--- /dev/null
+++ b/ndb/src/common/portlib/Makefile
@@ -0,0 +1,43 @@
+include .defs.mk
+
+DIRS :=
+
+ifeq ($(NDB_OS), SOFTOSE)
+DIRS += ose
+endif
+
+ifeq ($(NDB_OS), OSE)
+DIRS += ose
+endif
+
+ifeq ($(NDB_OS), SIMCELLO)
+DIRS += ose
+endif
+
+ifeq ($(NDB_OS), LINUX)
+DIRS += unix
+endif
+
+ifeq ($(NDB_OS), MACOSX)
+DIRS += unix
+endif
+
+ifeq ($(NDB_OS), SOLARIS)
+DIRS += unix
+endif
+
+ifeq ($(NDB_OS), SOLARIS6)
+DIRS += unix
+endif
+
+ifeq ($(NDB_OS), HPUX)
+DIRS += unix
+endif
+
+ifeq ($(NDB_OS), WIN32)
+DIRS += win32
+endif
+
+
+include $(NDB_TOP)/Epilogue.mk
+
diff --git a/ndb/src/common/portlib/memtest/Makefile b/ndb/src/common/portlib/memtest/Makefile
new file mode 100644
index 00000000000..716cdbdea82
--- /dev/null
+++ b/ndb/src/common/portlib/memtest/Makefile
@@ -0,0 +1,12 @@
+CC=gcc
+LD=$(CC)
+SOURCES=memtest.c
+OUTPUT=memtest
+all:
+ $(CC) $(SOURCES) -o $(OUTPUT)
+
+debug:
+ $(CC) -g $(SOURCES) -o $(OUTPUT)
+
+clean: rm -rf *.o
+ rm -rf core*
diff --git a/ndb/src/common/portlib/memtest/memtest.c b/ndb/src/common/portlib/memtest/memtest.c
new file mode 100644
index 00000000000..d23235b7aa2
--- /dev/null
+++ b/ndb/src/common/portlib/memtest/memtest.c
@@ -0,0 +1,245 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 <unistd.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+long long getMilli();
+long long getMicro();
+void malloctest(int loopcount, int memsize, int touch);
+void freetest(int loopcount, int memsize);
+void mmaptest(int loopcount, int memsize, int touch);
+void unmaptest(int loopcount, int memsize);
+
+
+main(int argc, char ** argv)
+{
+
+ int loopcount;
+ int memsize;
+ if(argc < 4) {
+ printf("Usage: memtest X loopcount memsize(MB)\n");
+ printf("where X = \n");
+ printf("1 : malloc test \n");
+ printf("2 : mmap test \n");
+ printf("3 : malloc test + touch pages\n");
+ printf("4 : mmap test + touch pages\n");
+ printf("5 : malloc/free test \n");
+ printf("6 : mmap/munmap test \n");
+ printf("loopcount - number of loops\n");
+ printf("memsize - memory segment size to allocate in MB.\n");
+ exit(1);
+ }
+
+
+ loopcount = atoi(argv[2]);
+ memsize = atoi(argv[3]);
+ switch(atoi(argv[1])) {
+ case 1: malloctest(loopcount, memsize , 0 );
+ break;
+ case 2: mmaptest(loopcount, memsize,0);
+ break;
+ case 3: malloctest(loopcount, memsize,1);
+ break;
+ case 4: mmaptest(loopcount, memsize,1);
+ break;
+ case 5: freetest(loopcount, memsize);
+ break;
+ case 6: unmaptest(loopcount, memsize);
+ break;
+ default:
+ break;
+ }
+}
+
+long long getMilli() {
+ struct timeval tick_time;
+ gettimeofday(&tick_time, 0);
+
+ return
+ ((long long)tick_time.tv_sec) * ((long long)1000) +
+ ((long long)tick_time.tv_usec) / ((long long)1000);
+}
+
+long long getMicro(){
+ struct timeval tick_time;
+ int res = gettimeofday(&tick_time, 0);
+
+ long long secs = tick_time.tv_sec;
+ long long micros = tick_time.tv_usec;
+
+ micros = secs*1000000+micros;
+ return micros;
+}
+
+void malloctest(int loopcount, int memsize, int touch) {
+ long long start=0;
+ int total=0;
+ int i=0, j=0;
+ int size=memsize*1024*1024; //bytes;
+ float mean;
+ char * ptr =0;
+
+ printf("Staring malloctest ");
+ if(touch)
+ printf("with touch\n");
+ else
+ printf("\n");
+
+ start=getMicro();
+
+ for(i=0; i<loopcount; i++){
+ ptr=(char *)malloc((size_t)(size));
+ if(ptr==0) {
+ printf("failed to malloc!\n");
+ return;
+ }
+ if(touch) {
+ for(j=0; j<size; j=j+4096)
+ ptr[j]=1;
+ }
+ }
+ total=(int)(getMicro()-start);
+
+ mean=(float)((float)total/(float)loopcount);
+ printf("Total time malloc %d bytes: %2.3f microsecs loopcount %d touch %d \n",
+ size, mean,loopcount, touch);
+}
+
+
+void mmaptest(int loopcount, int memsize, int touch) {
+ long long start=0;
+ int total=0;
+ int i=0, j=0;
+ char * ptr;
+ int size=memsize*1024*1024; //bytes;
+ float mean;
+
+ printf("Staring mmaptest ");
+ if(touch)
+ printf("with touch \n");
+ else
+ printf("\n");
+
+ start=getMicro();
+ for(i=0; i<loopcount; i++){
+ ptr = mmap(0,
+ size,
+ PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS,
+ 0,
+ 0);
+ if(ptr<0) {
+ printf("failed to mmap!\n");
+ return;
+ }
+
+ if(touch) {
+ for(j=0; j<size; j=j+4096)
+ ptr[j]=1;
+ }
+ }
+ total=(int)(getMicro()-start);
+ mean=(float)((float)total/(float)loopcount);
+ printf("Total time mmap %d bytes: %2.3f microsecs \n",size, mean);
+}
+
+
+void unmaptest(loopcount, memsize)
+{
+ long long start=0;
+ int total=0;
+ int i=0, j=0;
+ char * ptr;
+ int size=memsize*1024*1024; //bytes;
+ float mean;
+
+ printf("Staring munmap test (loopcount = 1 no matter what you prev. set)\n");
+
+ loopcount = 1;
+
+
+ for(i=0; i<loopcount; i++){
+ ptr =(char*) mmap(0,
+ size,
+ PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS,
+ 0,
+ 0);
+ if(ptr<0) {
+ printf("failed to mmap!\n");
+ return;
+ }
+
+
+ for(j=0; j<size; j=j+1)
+ ptr[j]='1';
+ start=getMicro();
+ if(munmap(ptr, size)<0) {
+ printf("failed to munmap!\n");
+ return;
+ }
+
+ total=(int)(getMicro()-start);
+ /*
+ for(j=8192; j<size; j=j+4096) {
+
+ *(ptr+j)='1';
+ }
+
+ for(j=0; j<4096; j=j+4096) {
+ *(ptr+j)='1';
+ }
+
+ */
+ }
+ mean=(float)((float)total/(float)loopcount);
+ printf("Total time unmap %d bytes: %2.3f microsecs \n",size, mean);
+}
+
+void freetest(int loopcount, int memsize) {
+ long long start=0;
+ int total=0;
+ int i=0, j=0;
+ int size=memsize*1024*1024; //bytes;
+ float mean;
+ char * ptr =0;
+
+ loopcount = 1;
+ printf("Staring free test (loopcount = 1 no matter what you prev. set)\n");
+
+
+ for(i=0; i<loopcount; i++){
+ ptr=(char*)malloc((size_t)(size));
+ if(ptr==0) {
+ printf("failed to malloc!\n");
+ return;
+ }
+ for(j=0; j<size; j=j+4096)
+ ptr[j]='1';
+ start=getMicro();
+ free(ptr);
+ total=(int)(getMicro()-start);
+ }
+
+
+ mean=(float)((float)total/(float)loopcount);
+ printf("Total time free %d bytes: %2.3f microsecs loopcount %d \n",
+ size, mean,loopcount);
+}
diff --git a/ndb/src/common/portlib/memtest/munmaptest/Makefile b/ndb/src/common/portlib/memtest/munmaptest/Makefile
new file mode 100644
index 00000000000..ea8c5238d1c
--- /dev/null
+++ b/ndb/src/common/portlib/memtest/munmaptest/Makefile
@@ -0,0 +1,14 @@
+include .defs.mk
+
+TYPE := ndbapitest
+BIN_TARGET := munmaptest
+
+
+SOURCES = munmaptest.cpp
+
+include $(NDB_TOP)/Epilogue.mk
+
+
+
+
+
diff --git a/ndb/src/common/portlib/memtest/munmaptest/munmaptest.cpp b/ndb/src/common/portlib/memtest/munmaptest/munmaptest.cpp
new file mode 100644
index 00000000000..9e396cd98ee
--- /dev/null
+++ b/ndb/src/common/portlib/memtest/munmaptest/munmaptest.cpp
@@ -0,0 +1,251 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 <NdbOut.hpp>
+#include <NdbThread.h>
+#include <NdbMutex.h>
+#include <NdbCondition.h>
+#include <NdbSleep.h>
+#include <NdbTick.h>
+#include <NdbEnv.h>
+#include <NdbHost.h>
+#include <NdbMain.h>
+#include <getarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+
+
+struct ThreadData
+{
+ char * mapAddr;
+ Uint32 mapSize;
+ Uint32 chunk;
+ Uint32 idx;
+
+};
+
+long long getMilli();
+long long getMicro();
+
+
+void* mapSegment(void * arg);
+void* unmapSegment(void * arg);
+
+
+void* mapSegment(void * arg) {
+
+ ThreadData * threadArgs;
+ long long start=0;
+ int total=0;
+ int id = *(int *)arg;
+ threadArgs = new ThreadData [1];
+ Uint32 size=5*1024*1024;
+ struct NdbThread* unmapthread_var;
+ void *status = 0;
+ int run = 1;
+ int max=0, min =100000000, sum=0;
+ while(run < 1001) {
+ start=getMicro();
+ char * ptr =(char*) mmap(0,
+ size,
+ PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS,
+ 0,
+ 0);
+
+ total=(int)(getMicro()-start);
+
+ ndbout << "T" << id << ": mmap took : " << total << " microsecs. "
+ << " Run: " << run ;
+ ndbout_c(" mapped @ %p \n", ptr);
+
+ if(total>max)
+ max = total;
+ if(total<min)
+ min=total;
+
+ sum+=total;
+
+ if(ptr<0) {
+ ndbout << "failed to mmap!" << endl;
+ exit(1);
+ }
+
+
+ threadArgs[0].mapAddr = (char *)ptr;
+ threadArgs[0].mapSize = size;
+ threadArgs[0].chunk = 4096;
+ threadArgs[0].idx = 0;
+
+
+ for(Uint32 j=0; j<size; j=j+4096)
+ ptr[j]='1';
+
+ unmapthread_var = NdbThread_Create(unmapSegment, // Function
+ (void**)&threadArgs[0],// Arg
+ 32768, // Stacksize
+ (char*)"unmapthread", // Thread name
+ NDB_THREAD_PRIO_MEAN); // Thread prio
+
+
+ if(NdbThread_WaitFor(unmapthread_var, &status) != 0) {
+ ndbout << "test failed - exitting " << endl;
+ exit(1);
+ }
+ run++;
+ }
+
+ ndbout << "MAX: " << max << " MIN: " << min;
+ float mean = (float) ((float)sum/(float)run);
+ ndbout_c(" AVERAGE: %2.5f\n",mean);
+}
+
+
+
+void* unmapSegment(void * arg)
+{
+
+ char * freeAddr;
+ char * mapAddr;
+ ThreadData * threadData = (ThreadData*) arg;
+ int start=0;
+ int total=0;
+ Uint32 mapSize = threadData->mapSize;
+ Uint32 chunk = threadData->chunk;
+ mapAddr = threadData->mapAddr;
+
+
+
+ freeAddr = mapAddr+mapSize-chunk;
+ NdbSleep_MilliSleep(100);
+ for(Uint32 i=0;i<mapSize; i = i+chunk) {
+ start=getMicro();
+ if(munmap(freeAddr, chunk) < 0){
+ ndbout << "munmap failed" << endl;
+ exit(1);
+ }
+ total=(int)(getMicro()-start);
+ freeAddr = freeAddr - chunk;
+ NdbSleep_MilliSleep(10);
+ ndbout << "unmap 4096 bytes : " << total << "microsecs" << endl;
+ }
+ return NULL;
+}
+
+
+static int trash;
+static int segmentsize=1;
+
+
+static struct getargs args[] = {
+ { "trash", 't', arg_integer, &trash,
+ "trash the memory before (1 to trash 0 to not trash)", "trash"},
+ { "segment", 's', arg_integer, &segmentsize,
+ "segment size (in MB)", "segment"},
+};
+
+
+static const int num_args = sizeof(args) / sizeof(args[0]);
+
+NDB_MAIN(munmaptest) {
+
+ const char *progname = "munmaptest";
+ int optind = 0;
+
+ if(getarg(args, num_args, argc, argv, &optind)) {
+ arg_printusage(args, num_args, progname, "");
+ exit(1);
+ }
+
+ int size;
+ char * ptr;
+ if(trash) {
+ for(int i=0; i<100; i++) {
+ size=1+(int) (10.0*rand()/(RAND_MAX+1.0));
+ NdbSleep_MilliSleep(10);
+ ptr =(char*) mmap(0,
+ size*1024*1024,
+ PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS,
+ 0,
+ 0);
+ for(int i=0;i<(size*1024*1024); i=i+4096) {
+ *(ptr+i)='1';
+ }
+ NdbSleep_MilliSleep(10);
+
+ munmap(ptr,size);
+
+ }
+
+
+ }
+
+ int noThreads = 1;
+ struct NdbThread* mapthread_var;
+ int id[noThreads];
+ void *status=0;
+
+ ThreadData * threadArgs = new ThreadData[noThreads];
+
+
+
+
+ for(int i=0; i < noThreads; i++) {
+ threadArgs[i].mapSize = segmentsize*1024*1024;
+ threadArgs[i].idx = i;
+ mapthread_var = NdbThread_Create(mapSegment, // Function
+ (void**)&threadArgs[i],// Arg
+ 32768, // Stacksize
+ (char*)"mapthread", // Thread name
+ NDB_THREAD_PRIO_MEAN); // Thread prio
+
+ }
+
+
+ if(NdbThread_WaitFor(mapthread_var, &status) != 0) {
+ ndbout << "test failed - exitting " << endl;
+ exit(1);
+ }
+
+}
+
+long long getMilli() {
+ struct timeval tick_time;
+ gettimeofday(&tick_time, 0);
+
+ return
+ ((long long)tick_time.tv_sec) * ((long long)1000) +
+ ((long long)tick_time.tv_usec) / ((long long)1000);
+}
+
+long long getMicro(){
+ struct timeval tick_time;
+ int res = gettimeofday(&tick_time, 0);
+
+ long long secs = tick_time.tv_sec;
+ long long micros = tick_time.tv_usec;
+
+ micros = secs*1000000+micros;
+ return micros;
+}
diff --git a/ndb/src/common/portlib/mmstest/mmslist.cpp b/ndb/src/common/portlib/mmstest/mmslist.cpp
new file mode 100644
index 00000000000..bd00211445c
--- /dev/null
+++ b/ndb/src/common/portlib/mmstest/mmslist.cpp
@@ -0,0 +1,103 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 <NdbOut.hpp>
+#include <NdbMain.h>
+
+#include <ose.h>
+#include <mms.sig>
+#include <mms_err.h>
+#include <string.h>
+#include <stdio.h>
+#include <NdbOut.hpp>
+
+/**
+ * NOTE: To use NdbMem from a OSE system ose_mms has to be defined
+ * as a "Required External Process"(see OSE Kernel User's Guide/R1.1(p. 148)),
+ * like this:
+ * EXT_PROC(ose_mms, ose_mms, 50000)
+ * This will create a global variable ose_mms_ that is used from here.
+ */
+
+union SIGNAL
+{
+ SIGSELECT sigNo;
+ struct MmsListDomainRequest mmsListDomainRequest;
+ struct MmsListDomainReply mmsListDomainReply;
+}; /* union SIGNAL */
+
+extern PROCESS ose_mms_;
+
+struct ARegion
+{
+ unsigned long int address;
+ unsigned long int size;
+ char name[32];
+
+ U32 resident; /* Boolean, nonzero if resident. */
+ U32 access; /* See values for AccessType (above) .*/
+ U32 type; /* either RAM-mem (1) or Io-mem (2) */
+ U32 cache; /* 0-copyback,1-writethrough, 2-CacheInhibit.*/
+};
+
+NDB_COMMAND(mmslist, "mmslist", "mmslist", "LIst the MMS memory segments", 4096){
+ if (argc == 1){
+
+ static SIGSELECT allocate_sig[] = {1,MMS_LIST_DOMAIN_REPLY};
+ union SIGNAL *sig;
+
+ /* Send request to list all segments and regions. */
+ sig = alloc(sizeof(struct MmsListDomainRequest),
+ MMS_LIST_DOMAIN_REQUEST);
+ send(&sig, ose_mms_);
+
+ while (true){
+ sig = receive(allocate_sig);
+ if (sig != NIL){
+ if (sig->mmsListDomainReply.status == MMS_SUCCESS){
+ /* Print domain info */
+ ndbout << "=================================" << endl;
+ ndbout << "domain: " << sig->mmsListDomainReply.domain << endl;
+ ndbout << "name : " << sig->mmsListDomainReply.name << endl;
+ ndbout << "used : " << sig->mmsListDomainReply.used << endl;
+ ndbout << "lock : " << sig->mmsListDomainReply.lock << endl;
+ ndbout << "numOfRegions:" << sig->mmsListDomainReply.numOfRegions << endl;
+ struct ARegion * tmp = (struct ARegion*)&sig->mmsListDomainReply.regions[0];
+ for (int i = 0; i < sig->mmsListDomainReply.numOfRegions && i < 256; i++){
+ ndbout << i << ": adress=" << tmp->address <<
+ ", size=" << tmp->size <<
+ ", name=" << tmp->name <<
+ ", resident=" << tmp->resident <<
+ ", access=" << tmp->access <<
+ ", type=" << tmp->type <<
+ ", cache=" << tmp->cache << endl;
+ tmp++;
+ }
+
+ free_buf(&sig);
+ }else{
+ free_buf(&sig);
+ break;
+ }
+ }
+
+ }
+
+ }else{
+ ndbout << "Usage: mmslist" << endl;
+ }
+ return NULL;
+}
diff --git a/ndb/src/common/portlib/mmstest/mmstest.cpp b/ndb/src/common/portlib/mmstest/mmstest.cpp
new file mode 100644
index 00000000000..6ebb5064aaf
--- /dev/null
+++ b/ndb/src/common/portlib/mmstest/mmstest.cpp
@@ -0,0 +1,76 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 <NdbOut.hpp>
+#include "NdbThread.h"
+#include <NdbMem.h>
+#include <NdbMain.h>
+
+#include <stdlib.h>
+
+NDB_COMMAND(ndbmem, "ndbmem", "ndbmem", "Test the ndbmem functionality", 4096){
+
+ ndbout << "Starting test of NdbMem" << endl;
+ ndbout << "=======================" << endl;
+
+ ndbout << "Creating NdbMem" << endl;
+ NdbMem_Create();
+
+
+ ndbout << "NdbMem - test 1" << endl;
+ if (argc == 2){
+ int size1 = atoi(argv[1]);
+ ndbout << "Allocate and test "<<size1<<" bytes of memory" << endl;
+ char* mem1 = (char*)NdbMem_Allocate(size1);
+ ndbout << "mem1 = " << hex << (int)mem1 << endl;
+ if (mem1 != NULL){
+ char* p1;
+
+ // Write to the memory allocated
+ p1 = mem1;
+ for(int i = 0; i < size1; i++){
+ *p1 = (char)(i%256);
+ p1++;
+ }
+
+ // Read from the memory and check value
+ char read1;
+ char* pread1;
+ pread1 = mem1;
+ for(int i = 0; i < size1; i++){
+ read1 = *pread1;
+ //ndbout << i << "=" << read1 << endl;
+ if (read1 != (i%256))
+ ndbout << "Byte " << i << " was not correct, read1=" << read1 << endl;
+ pread1++;
+ }
+
+ ndbout << "Freeing NdbMem" << endl;
+ NdbMem_Free(mem1);
+ }
+
+ ndbout << "Destroying NdbMem" << endl;
+ NdbMem_Destroy();
+ }else{
+ ndbout << "Usage: ndbmem <size(bytes)>"<< endl;
+ }
+
+ return NULL;
+
+}
+
+
+
diff --git a/ndb/src/common/portlib/ose/Makefile b/ndb/src/common/portlib/ose/Makefile
new file mode 100644
index 00000000000..4ef93b7824a
--- /dev/null
+++ b/ndb/src/common/portlib/ose/Makefile
@@ -0,0 +1,31 @@
+include .defs.mk
+
+TYPE :=
+
+PIC_ARCHIVE := Y
+ARCHIVE_TARGET := portlib
+
+SOURCES = NdbOut.cpp
+
+SOURCES.c = NdbCondition.c \
+ NdbMutex.c \
+ NdbSleep.c \
+ NdbTick.c \
+ NdbEnv.c \
+ NdbThread.c \
+ NdbHost.c \
+ NdbTCP.c
+
+ifeq ($(NDB_OS), SOFTOSE)
+ SOURCES += NdbMem_SoftOse.cpp
+else
+ SOURCES.c += NdbMem.c
+endif
+
+include $(NDB_TOP)/Epilogue.mk
+
+
+
+
+
+
diff --git a/ndb/src/common/portlib/ose/NdbCondition.c b/ndb/src/common/portlib/ose/NdbCondition.c
new file mode 100644
index 00000000000..2ab6e49006b
--- /dev/null
+++ b/ndb/src/common/portlib/ose/NdbCondition.c
@@ -0,0 +1,244 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbCondition.h"
+#include <pthread.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <malloc.h>
+
+#include <NdbMutex.h>
+
+#include "NdbConditionOSE.h"
+struct NdbCondition
+{
+ PROCESS condserv_pid;
+};
+
+
+OS_PROCESS(ndbcond_serv){
+
+ union SIGNAL* sig;
+ union SIGNAL* sig2;
+
+ static const SIGSELECT sel_signal[] = {2, NDBCOND_SIGNAL, NDBCOND_BROADCAST};
+ static const SIGSELECT sel_cond[] = {2, NDBCOND_WAIT, NDBCOND_WAITTIMEOUT};
+
+ for(;;){
+ /* Receive condition wait signal */
+ sig = receive((SIGSELECT*)sel_cond);
+ if (sig != NIL){
+ switch (sig->sigNo){
+
+ case NDBCOND_WAIT:
+ /* Wait for a SIGNAL or BROADCAST from anyone */
+ sig2 = receive((SIGSELECT*)sel_signal);
+ if (sig2 != NIL){
+ switch(sig2->sigNo){
+
+ case NDBCOND_SIGNAL:
+ ((struct NdbCondWait*)sig)->status = NDBCOND_SIGNALED;
+ /* Send signal back to the one waiting for this condition */
+ send(&sig, sender(&sig));
+ break;
+ case NDBCOND_BROADCAST:
+ /* Not handled yet */
+ assert(1==0);
+ break;
+ default:
+ assert(1==0);
+ break;
+ }
+ free_buf(&sig2);
+ }
+ break;
+
+ case NDBCOND_WAITTIMEOUT:
+ /* Wait for a SIGNAL or BROADCAST from anyone */
+ sig2 = receive_w_tmo(((struct NdbCondWaitTimeout*)sig)->timeout, (SIGSELECT*)sel_signal);
+ if (sig2 != NIL){
+ switch(sig2->sigNo){
+
+ case NDBCOND_SIGNAL:
+ ((struct NdbCondWaitTimeout*)sig)->status = NDBCOND_SIGNALED;
+ /* Send signal back to the one waiting for this condition */
+ send(&sig, sender(&sig));
+ break;
+ case NDBCOND_BROADCAST:
+ /* Not handled yet */
+ assert(1==0);
+ break;
+ default:
+ assert(1==0);
+ break;
+ }
+ free_buf(&sig2);
+ }else{
+ ((struct NdbCondWaitTimeout*)sig)->status = NDBCOND_TIMEOUT;
+ send(&sig, sender(&sig));
+ }
+ break;
+
+ default:
+ assert(1==0);
+ break;
+
+ }
+ }
+
+ }
+}
+
+
+struct NdbCondition*
+NdbCondition_Create(void)
+{
+ struct NdbCondition* tmpCond;
+
+
+ tmpCond = (struct NdbCondition*)malloc(sizeof(struct NdbCondition));
+
+ if (tmpCond == NULL)
+ return NULL;
+
+ /**
+ * Start this process with a quite high
+ * priority, we want it to be responsive
+ */
+ tmpCond->condserv_pid = create_process(OS_PRI_PROC, /* Process type */
+ "ndbcond_serv", /* Name */
+ ndbcond_serv, /* Entry point */
+ 2048, /* Stack size */
+ 10, /* Priority */
+ 0, /* Time slice */
+ get_bid(current_process()), /* Block */
+ NULL, /* Redir table */
+ 0,
+ 0);
+
+ start(tmpCond->condserv_pid);
+
+ return tmpCond;
+}
+
+
+int
+NdbCondition_Wait(struct NdbCondition* p_cond,
+ NdbMutex* p_mutex)
+{
+ static const SIGSELECT sel_cond[] = {1, NDBCOND_WAIT};
+ union SIGNAL* sig;
+ int result;
+ if (p_cond == NULL || p_mutex == NULL)
+ return 0;
+
+ sig = alloc(sizeof(struct NdbCondWait), NDBCOND_WAIT);
+ send(&sig, p_cond->condserv_pid);
+
+ NdbMutex_Unlock(p_mutex);
+
+ result = 1;
+ while(NIL == (sig = receive_from((OSTIME)-1, (SIGSELECT*)sel_cond, p_cond->condserv_pid)));
+ if (sig != NIL){
+ if (sig->sigNo == NDBCOND_WAIT){
+ /* Condition is signaled */
+ result = 0;
+ }else{
+ assert(1==0);
+ }
+ free_buf(&sig);
+
+ }
+ NdbMutex_Lock(p_mutex);
+
+ return result;
+}
+
+
+int
+NdbCondition_WaitTimeout(struct NdbCondition* p_cond,
+ NdbMutex* p_mutex,
+ int msecs){
+ static const SIGSELECT sel_cond[] = {1, NDBCOND_WAITTIMEOUT};
+ union SIGNAL* sig;
+ int result;
+ if (p_cond == NULL || p_mutex == NULL)
+ return 0;
+
+ sig = alloc(sizeof(struct NdbCondWaitTimeout), NDBCOND_WAITTIMEOUT);
+ ((struct NdbCondWaitTimeout*)sig)->timeout = msecs;
+ send(&sig, p_cond->condserv_pid);
+
+ NdbMutex_Unlock(p_mutex);
+
+ result = 1;
+ while(NIL == (sig = receive_from((OSTIME)-1, (SIGSELECT*)sel_cond, p_cond->condserv_pid)));
+ if (sig != NIL){
+ if (sig->sigNo == NDBCOND_WAITTIMEOUT){
+ /* Condition is signaled */
+ result = 0;
+ }else{
+ assert(1==0);
+ }
+ free_buf(&sig);
+
+ }
+
+ NdbMutex_Lock(p_mutex);
+
+ return result;
+}
+
+
+int
+NdbCondition_Signal(struct NdbCondition* p_cond){
+
+ union SIGNAL* sig;
+ if (p_cond == NULL)
+ return 1;
+
+ sig = alloc(sizeof(struct NdbCondSignal), NDBCOND_SIGNAL);
+ send(&sig, p_cond->condserv_pid);
+
+ return 0;
+}
+
+
+int NdbCondition_Broadcast(struct NdbCondition* p_cond)
+{
+ union SIGNAL* sig;
+ if (p_cond == NULL)
+ return 1;
+
+ sig = alloc(sizeof(struct NdbCondBroadcast), NDBCOND_BROADCAST);
+ send(&sig, p_cond->condserv_pid);
+
+ return 0;
+}
+
+
+int NdbCondition_Destroy(struct NdbCondition* p_cond)
+{
+ if (p_cond == NULL)
+ return 1;
+
+ kill_proc(p_cond->condserv_pid);
+ free(p_cond);
+
+ return 0;
+}
+
diff --git a/ndb/src/common/portlib/ose/NdbConditionOSE.h b/ndb/src/common/portlib/ose/NdbConditionOSE.h
new file mode 100644
index 00000000000..bd0306261cc
--- /dev/null
+++ b/ndb/src/common/portlib/ose/NdbConditionOSE.h
@@ -0,0 +1,103 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 NDB_CONDITIONOSE_H
+#define NDB_CONDITIONOSE_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define NDBCOND_SIGBASE 4000
+
+#define NDBCOND_WAIT (NDBCOND_SIGBASE + 1) /* !-SIGNO(struct NdbCondWait)-! */
+#define NDBCOND_WAITTIMEOUT (NDBCOND_SIGBASE + 2) /* !-SIGNO(struct NdbCondWaitTimeOut)-! */
+#define NDBCOND_SIGNAL (NDBCOND_SIGBASE + 3) /* !-SIGNO(struct NdbCondSignal)-! */
+#define NDBCOND_BROADCAST (NDBCOND_SIGBASE + 4) /* !-SIGNO(struct NdbCondBroadcast)-! */
+
+
+const char *
+sigNo2String(SIGSELECT sigNo){
+ switch(sigNo){
+ case NDBCOND_WAIT:
+ return "NDBCOND_WAIT";
+ break;
+ case NDBCOND_WAITTIMEOUT:
+ return "NDBCOND_WAITTIMEOUT";
+ break;
+ case NDBCOND_SIGNAL:
+ return "NDBCOND_SIGNAL";
+ break;
+ case NDBCOND_BROADCAST:
+ return "NDBCOND_BROADCAST";
+ break;
+ }
+ return "UNKNOWN";
+}
+
+struct NdbCondWait
+{
+ SIGSELECT sigNo;
+ int status;
+};
+
+/**
+ * Signal received
+ */
+#define NDBCOND_SIGNALED 1
+
+/**
+ * Timeout occured
+ */
+#define NDBCOND_TIMEOUT 2
+
+struct NdbCondWaitTimeout
+{
+ SIGSELECT sigNo;
+ int timeout;
+ int status;
+
+};
+
+struct NdbCondSignal
+{
+ SIGSELECT sigNo;
+};
+
+struct NdbCondBroadcast
+{
+ SIGSELECT sigNo;
+};
+
+
+union SIGNAL
+{
+ SIGSELECT sigNo;
+ struct NdbCondWait condWait;
+ struct NdbCondWaitTimeout condWaitTimeout;
+ struct NdbCondSignal condSignal;
+ struct NdbCondBroadcast condBroadcast;
+};
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ndb/src/common/portlib/ose/NdbEnv.c b/ndb/src/common/portlib/ose/NdbEnv.c
new file mode 100644
index 00000000000..e2ac4d879d2
--- /dev/null
+++ b/ndb/src/common/portlib/ose/NdbEnv.c
@@ -0,0 +1,55 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbEnv.h"
+#include <string.h>
+#include <stdlib.h>
+
+const char* NdbEnv_GetEnv(const char* name, char * buf, int buflen)
+{
+ /**
+ * All environment variables are associated with a process
+ * it's important to read env from the correct process
+ * for now read from own process, own block and last the "ose_shell" process.
+ *
+ * TODO! What process should this be read from in the future?
+ *
+ */
+ PROCESS proc_;
+ char* p = NULL;
+ /* Look in own process */
+ p = get_env(current_process(), (char*)name);
+ if (p == NULL){
+ /* Look in block process */
+ p = get_env(get_bid(current_process()), (char*)name);
+ if (p == NULL){
+ /* Look in ose_shell process */
+ if (hunt("ose_shell", 0, &proc_, NULL)){
+ p = get_env(proc_, (char*)name);
+ }
+ }
+ }
+
+ if (p != NULL){
+ strncpy(buf, p, buflen);
+ buf[buflen-1] = 0;
+ free_buf((union SIGNAL **)&p);
+ p = buf;
+ }
+ return p;
+}
+
diff --git a/ndb/src/common/portlib/ose/NdbHost.c b/ndb/src/common/portlib/ose/NdbHost.c
new file mode 100644
index 00000000000..f5e1e511c16
--- /dev/null
+++ b/ndb/src/common/portlib/ose/NdbHost.c
@@ -0,0 +1,55 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbHost.h"
+#include <unistd.h>
+
+
+#include <inet.sig>
+#include <string.h>
+
+union SIGNAL
+{
+ SIGSELECT sigNo;
+ struct InetIfUp inetIfUp;
+};
+
+int NdbHost_GetHostName(char* buf)
+{
+#if 0
+ extern PROCESS ose_inet_;
+ union SIGNAL *signal;
+ static const SIGSELECT select_if_up_reply[] = { 1, INET_IF_UP_REPLY };
+
+ signal = alloc(sizeof(struct InetIfUp), INET_IF_UP_REQUEST);
+ strcpy(signal->inetIfUp.ifName, "*");
+ send((union SIGNAL **)&signal, ose_inet_);
+ signal = receive((SIGSELECT *)select_if_up_reply);
+ strcpy(buf, signal->inetIfUp.ifName);
+ free_buf(&signal);
+ return 0;
+#else
+ return -1;
+#endif
+}
+
+
+int NdbHost_GetProcessId(void)
+{
+ return current_process();
+}
+
diff --git a/ndb/src/common/portlib/ose/NdbMem.c b/ndb/src/common/portlib/ose/NdbMem.c
new file mode 100644
index 00000000000..6d922e4c073
--- /dev/null
+++ b/ndb/src/common/portlib/ose/NdbMem.c
@@ -0,0 +1,183 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbMem.h"
+
+#include <assert.h>
+
+#if defined NDB_OSE
+#include <ose.h>
+#include <mms.sig>
+#include <mms_err.h>
+#include <string.h>
+#include <stdio.h>
+#include <NdbOut.hpp>
+
+// Page size for mp750 is 4096 bytes.
+#define PAGE_SIZE 4096
+
+/**
+ * NOTE: To use NdbMem from a OSE system ose_mms has to be defined
+ * as a "Required External Process"(see OSE Kernel User's Guide/R1.1(p. 148)),
+ * like this in osemain.con:
+ * EXT_PROC(ose_mms, ose_mms, 50000)
+ * This will create a global variable ose_mms_ that is used from here.
+ */
+
+union SIGNAL
+{
+ SIGSELECT sigNo;
+ struct MmsAllocateRegionRequest mmsAllocateRegionRequest;
+ struct MmsAllocateRegionReply mmsAllocateRegionReply;
+ struct MmsFreeRegionRequest mmsFreeRegionRequest;
+ struct MmsFreeRegionReply mmsFreeRegionReply;
+}; /* union SIGNAL */
+
+extern PROCESS ose_mms_;
+
+void NdbMem_Create(void)
+{
+ /* Do nothing */
+ return;
+}
+
+void NdbMem_Destroy(void)
+{
+ /* Do nothing */
+ return;
+}
+
+void* NdbMem_Allocate(size_t size)
+{
+ static SIGSELECT allocate_sig[] = {1,MMS_ALLOCATE_REGION_REPLY};
+ union SIGNAL *sig;
+ U32 allocatedAdress;
+
+ assert(size > 0);
+
+ // Only allowed to allocate multiples of the page size.
+ if(size % PAGE_SIZE != 0) {
+ size += PAGE_SIZE - size%PAGE_SIZE;
+ }
+
+ /* Allocate a new region in the callers memory segment. */
+ sig = alloc(sizeof(struct MmsAllocateRegionRequest),
+ MMS_ALLOCATE_REGION_REQUEST);
+ /* -1: The callers domain is used */
+ sig->mmsAllocateRegionRequest.domain = (MemoryDomain)-1;
+ sig->mmsAllocateRegionRequest.useAddr = False;
+ sig->mmsAllocateRegionRequest.size = size;
+ sig->mmsAllocateRegionRequest.access = SuperRW_UserRW;
+ sig->mmsAllocateRegionRequest.resident = False;
+ sig->mmsAllocateRegionRequest.memory = CodeData;
+ sig->mmsAllocateRegionRequest.cache = CopyBack;
+ strcpy(sig->mmsAllocateRegionRequest.name, "NDB_DATA");
+ send(&sig, ose_mms_);
+ sig = receive(allocate_sig);
+
+ if (sig->mmsAllocateRegionReply.status != MMS_SUCCESS){
+ /* Memory allocation failed, make sure this function returns NULL */
+ allocatedAdress = NULL;
+ }
+ else{
+ allocatedAdress = sig->mmsAllocateRegionReply.address;
+ }
+ free_buf(&sig);
+ return (void*)allocatedAdress;
+}
+
+void* NdbMem_AllocateAlign(size_t size, size_t alignment)
+{
+ return NdbMem_Allocate(size);
+}
+
+
+void NdbMem_Free(void* ptr)
+{
+ static SIGSELECT free_sig[] = {1,MMS_FREE_REGION_REPLY};
+ union SIGNAL *sig;
+
+ /* Free a region in the callers domain. */
+ sig = alloc(sizeof(struct MmsFreeRegionRequest),
+ MMS_FREE_REGION_REQUEST);
+ sig->mmsFreeRegionRequest.address = (U32)ptr;
+ send(&sig, ose_mms_);
+ sig = receive(free_sig);
+
+ if (sig->mmsFreeRegionReply.status != MMS_SUCCESS){
+ ndbout_c("The MMS Region could not be deallocated.\r\n");
+ error(sig->mmsFreeRegionReply.status);
+ };
+ free_buf(&sig);
+}
+
+int NdbMem_MemLockAll(){
+ return -1;
+}
+
+int NdbMem_MemUnlockAll(){
+ return -1;
+}
+
+#else
+#include <assert.h>
+#include <stdlib.h>
+
+
+void NdbMem_Create()
+{
+ /* Do nothing */
+ return;
+}
+
+void NdbMem_Destroy()
+{
+ /* Do nothing */
+ return;
+}
+
+void* NdbMem_Allocate(size_t size)
+{
+ assert(size > 0);
+ return (void*)malloc(size);
+}
+
+void* NdbMem_AllocateAlign(size_t size, size_t alignment)
+{
+ /*
+ return (void*)memalign(alignment, size);
+ TEMP fix
+ */
+ return (void*)malloc(size);
+}
+
+
+void NdbMem_Free(void* ptr)
+{
+ free(ptr);
+}
+
+
+int NdbMem_MemLockAll(){
+ return -1;
+}
+
+int NdbMem_MemUnlockAll(){
+ return -1;
+}
+
+#endif
diff --git a/ndb/src/common/portlib/ose/NdbMem_SoftOse.cpp b/ndb/src/common/portlib/ose/NdbMem_SoftOse.cpp
new file mode 100644
index 00000000000..cad22c0474b
--- /dev/null
+++ b/ndb/src/common/portlib/ose/NdbMem_SoftOse.cpp
@@ -0,0 +1,53 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbMem.h"
+
+extern "C"
+void NdbMem_Create()
+{
+}
+extern "C"
+void NdbMem_Destroy()
+{
+}
+
+extern "C"
+void* NdbMem_Allocate(size_t size)
+{
+ return new char[size];
+}
+
+extern "C"
+void* NdbMem_AllocateAlign(size_t size, size_t alignment)
+{
+ return NdbMem_Allocate(size);
+}
+
+extern "C"
+void NdbMem_Free(void* ptr)
+{
+ delete [] (char *)(ptr);
+}
+
+int NdbMem_MemLockAll(){
+ return -1;
+}
+
+int NdbMem_MemUnlockAll(){
+ return -1;
+}
+
diff --git a/ndb/src/common/portlib/ose/NdbMutex.c b/ndb/src/common/portlib/ose/NdbMutex.c
new file mode 100644
index 00000000000..859ddefd536
--- /dev/null
+++ b/ndb/src/common/portlib/ose/NdbMutex.c
@@ -0,0 +1,86 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbMutex.h"
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+
+
+NdbMutex* NdbMutex_Create(void)
+{
+ NdbMutex* pNdbMutex;
+
+ pNdbMutex = create_sem(1);
+
+ return pNdbMutex;
+}
+
+
+int NdbMutex_Destroy(NdbMutex* p_mutex)
+{
+
+ if (p_mutex == NULL)
+ return -1;
+
+ kill_sem(p_mutex);
+
+ return 0;
+
+}
+
+
+int NdbMutex_Lock(NdbMutex* p_mutex)
+{
+ if (p_mutex == NULL)
+ return -1;
+
+ wait_sem(p_mutex);
+
+ return 0;
+}
+
+
+int NdbMutex_Unlock(NdbMutex* p_mutex)
+{
+
+ if (p_mutex == NULL)
+ return -1;
+
+ signal_sem(p_mutex);
+
+ return 0;
+}
+
+
+int NdbMutex_Trylock(NdbMutex* p_mutex)
+{
+ int result = -1;
+
+ if (p_mutex != NULL) {
+ OSSEMVAL semvalue = get_sem(p_mutex);
+ if (semvalue > 0) {
+ wait_sem(p_mutex);
+ result = 0;
+ }
+ }
+
+ return result;
+
+}
+
diff --git a/ndb/src/common/portlib/ose/NdbOut.cpp b/ndb/src/common/portlib/ose/NdbOut.cpp
new file mode 100644
index 00000000000..0ee12249ff5
--- /dev/null
+++ b/ndb/src/common/portlib/ose/NdbOut.cpp
@@ -0,0 +1,99 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbOut.hpp"
+#include <NdbStdio.h>
+#include <stdarg.h>
+#include <NdbUnistd.h>
+#include <string.h>
+
+
+#if defined NDB_SOFTOSE
+#include <dbgprintf.h>
+#define printfunc dbgprintf
+#else
+#define printfunc printf
+#endif
+
+static char const* const endlineString = "\r\n";
+
+static int CtrlC = 0;
+NdbOut ndbout;
+
+
+NdbOut& NdbOut::operator<<(int aVal)
+{
+ char* format;
+ char HexFormat[] = "0x%08x";
+ char DecFormat[] = "%d";
+ if (isHexFormat == 1)
+ format = HexFormat;
+ else
+ format = DecFormat;
+
+ printfunc(format, aVal);
+ return *this;
+}
+
+NdbOut& NdbOut::operator<<(char* pVal)
+{
+ printfunc("%s", pVal);
+ return *this;
+}
+
+NdbOut& NdbOut::endline()
+{
+ isHexFormat = 0; // Reset hex to normal, if user forgot this
+ printfunc(endlineString);
+ return *this;
+}
+
+NdbOut& NdbOut::flushline()
+{
+ isHexFormat = 0; // Reset hex to normal, if user forgot this
+ return *this;
+}
+
+NdbOut& NdbOut::setHexFormat(int _format)
+{
+ isHexFormat = _format;
+ return *this;
+}
+
+NdbOut::NdbOut()
+{
+ CtrlC = 0;
+ isHexFormat = 0;
+}
+
+NdbOut::~NdbOut()
+{
+}
+
+
+
+extern "C"
+void
+ndbout_c(const char * fmt, ...){
+ va_list ap;
+ char buf[1000];
+
+ va_start(ap, fmt);
+ if (fmt != 0)
+ vsnprintf(buf, sizeof(buf)-1, fmt, ap);
+ ndbout << buf << endl;
+ va_end(ap);
+}
diff --git a/ndb/src/common/portlib/ose/NdbSleep.c b/ndb/src/common/portlib/ose/NdbSleep.c
new file mode 100644
index 00000000000..70fd83117ef
--- /dev/null
+++ b/ndb/src/common/portlib/ose/NdbSleep.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbSleep.h"
+
+#include <ose.h>
+
+
+int
+NdbSleep_MilliSleep(int milliseconds){
+ const OSTIME millisecond_delay = milliseconds;
+ delay(millisecond_delay);
+ return 0;
+}
+
+int
+NdbSleep_SecSleep(int seconds){
+ const OSTIME millisecond_delay = seconds*1000;
+ delay(millisecond_delay);
+ return 0;
+}
+
diff --git a/ndb/src/common/portlib/ose/NdbTCP.c b/ndb/src/common/portlib/ose/NdbTCP.c
new file mode 100644
index 00000000000..9994697b3f8
--- /dev/null
+++ b/ndb/src/common/portlib/ose/NdbTCP.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbTCP.h"
+
+
+int
+Ndb_getInAddr(struct in_addr * dst, const char *address) {
+ struct hostent * host;
+ host = gethostbyname_r(address);
+ if(host != 0){
+ dst->s_addr = ((struct in_addr *) *host->h_addr_list)->s_addr;
+ free_buf((union SIGNAL **)&host);
+ return 0;
+ }
+ /* Try it as aaa.bbb.ccc.ddd. */
+ dst->s_addr = inet_addr(address);
+ if (dst->s_addr != INADDR_NONE) {
+ return 0;
+ }
+ return -1;
+}
+
+
diff --git a/ndb/src/common/portlib/ose/NdbThread.c b/ndb/src/common/portlib/ose/NdbThread.c
new file mode 100644
index 00000000000..41a5f181c40
--- /dev/null
+++ b/ndb/src/common/portlib/ose/NdbThread.c
@@ -0,0 +1,184 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbThread.h"
+#include <pthread.h>
+#include <malloc.h>
+#include <assert.h>
+#include <string.h>
+#include <NdbOut.hpp>
+
+#define MAX_THREAD_NAME 16
+
+
+struct NdbThread
+{
+ PROCESS pid;
+ char thread_name[MAX_THREAD_NAME];
+};
+
+#define NDBTHREAD_SIGBASE 4010
+
+#define NDBTHREAD_START (NDBTHREAD_SIGBASE + 1) /* !-SIGNO(struct NdbThreadStart)-! */
+
+struct NdbThreadStart
+{
+ SIGSELECT sigNo;
+ NDB_THREAD_FUNC* func;
+ NDB_THREAD_ARG arg;
+};
+
+struct NdbThreadStopped
+{
+ SIGSELECT sigNo;
+};
+
+union SIGNAL
+{
+ SIGSELECT sigNo;
+ struct NdbThreadStart threadStart;
+ struct NdbThreadStopped threadStopped;
+};
+
+OS_PROCESS(thread_starter){
+ static const SIGSELECT sel_start[] = {1, NDBTHREAD_START};
+ struct NdbThreadStart* sigstart;
+ union SIGNAL* sig;
+
+ /* Receive function adress and params */
+ sig = receive((SIGSELECT*)sel_start);
+ if (sig != NIL){
+ if (sig->sigNo == NDBTHREAD_START){
+ sigstart = ((struct NdbThreadStart*)sig);
+ /* Execute function with arg */
+ (*sigstart->func)(sigstart->arg);
+ }else{
+ assert(1==0);
+ }
+ free_buf(&sig);
+ }
+}
+
+struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC* p_thread_func,
+ NDB_THREAD_ARG *p_thread_arg,
+ const NDB_THREAD_STACKSIZE thread_stack_size,
+ const char* p_thread_name,
+ NDB_THREAD_PRIO thread_prio)
+{
+ struct NdbThread* tmpThread;
+ union SIGNAL* sig;
+ int ose_prio;
+
+ if (p_thread_func == NULL)
+ return 0;
+
+ tmpThread = (struct NdbThread*)malloc(sizeof(struct NdbThread));
+ if (tmpThread == NULL)
+ return NULL;
+
+ strncpy((char*)&tmpThread->thread_name, p_thread_name, MAX_THREAD_NAME);
+
+ switch(thread_prio){
+ case NDB_THREAD_PRIO_HIGHEST:
+ ose_prio = 1;
+ break;
+ case NDB_THREAD_PRIO_HIGH:
+ ose_prio = 10;
+ break;
+ case NDB_THREAD_PRIO_MEAN:
+ ose_prio = 16;
+ break;
+ case NDB_THREAD_PRIO_LOW:
+ ose_prio = 23;
+ break;
+ case NDB_THREAD_PRIO_LOWEST:
+ ose_prio = 31;
+ break;
+ default:
+ return NULL;
+ break;
+ }
+
+ /* Create process */
+ tmpThread->pid = create_process(OS_PRI_PROC, /* Process type */
+ (char*)p_thread_name, /* Name */
+ thread_starter, /* Entry point */
+ thread_stack_size, /* Stack size */
+ ose_prio, /* Priority */
+ 0, /* Time slice */
+ get_bid(current_process()), /* Block */
+ NULL, /* Redir table */
+ 0,
+ 0);
+
+ /* Send params to process */
+ sig = alloc(sizeof(struct NdbThreadStart), NDBTHREAD_START);
+ ((struct NdbThreadStart*)sig)->func = p_thread_func;
+ ((struct NdbThreadStart*)sig)->arg = p_thread_arg;
+ send(&sig, tmpThread->pid);
+
+ /* Enable NDB_HOME environment variable for the thread */
+ {
+ /* Hardcoded NDB_HOME...*/
+ char* ndb_home_env = get_env(current_process(), "NDB_HOME");
+ if (ndb_home_env != NULL)
+ {
+ /* Set NDB_HOME */
+ int rc = set_env(tmpThread->pid, "NDB_HOME", ndb_home_env);
+ if (rc != 0)
+ {
+ /* Not really a problem */
+ }
+ } /* Enable NDB_HOME */
+ }
+
+ /* Start process */
+ start(tmpThread->pid);
+
+ return tmpThread;
+}
+
+
+
+void NdbThread_Destroy(struct NdbThread** p_thread)
+{
+ free(* p_thread); * p_thread = 0;
+}
+
+
+int NdbThread_WaitFor(struct NdbThread* p_wait_thread, void** status)
+{
+ while(hunt(p_wait_thread->thread_name, 0, NULL, NULL) != 0)
+ delay(1000);
+
+ * status = 0;
+
+ return 0;
+}
+
+
+void NdbThread_Exit(int a)
+{
+ kill_proc(current_process());
+}
+
+
+int NdbThread_SetConcurrencyLevel(int level)
+{
+ return 0;
+}
+
diff --git a/ndb/src/common/portlib/ose/NdbTick.c b/ndb/src/common/portlib/ose/NdbTick.c
new file mode 100644
index 00000000000..c3deae2bec3
--- /dev/null
+++ b/ndb/src/common/portlib/ose/NdbTick.c
@@ -0,0 +1,64 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbTick.h"
+#include <time.h>
+
+#define NANOSEC_PER_SEC 1000000000
+#define MICROSEC_PER_SEC 1000000
+#define MILLISEC_PER_SEC 1000
+#define MICROSEC_PER_MILLISEC 1000
+#define MILLISEC_PER_NANOSEC 1000000
+
+#ifdef NDB_OSE
+NDB_TICKS NdbTick_CurrentMillisecond(void)
+{
+ return get_ticks()*4;
+}
+#include <rtc.h>
+int
+NdbTick_CurrentMicrosecond(NDB_TICKS * secs, Uint32 * micros){
+ struct TimePair tvp;
+ rtc_get_time(&tvp);
+ * secs = tvp.seconds;
+ * micros = tvp.micros;
+ return 0;
+}
+
+#endif
+
+#if defined NDB_SOFTOSE
+NDB_TICKS NdbTick_CurrentMillisecond(void)
+{
+ /**
+ * Depends on the interval counter in solaris
+ * that means each "tick" in OSE is really 10 milliseconds
+ */
+ return get_ticks()*10;
+}
+
+#include <rtc.h>
+int
+NdbTick_CurrentMicrosecond(NDB_TICKS * secs, Uint32 * micros){
+ struct TimePair tvp;
+ rtc_get_time(&tvp);
+ * secs = tvp.seconds;
+ * micros = tvp.micros;
+ return 0;
+}
+#endif
+
diff --git a/ndb/src/common/portlib/test/Makefile b/ndb/src/common/portlib/test/Makefile
new file mode 100644
index 00000000000..4edc98ede75
--- /dev/null
+++ b/ndb/src/common/portlib/test/Makefile
@@ -0,0 +1,15 @@
+include .defs.mk
+
+TYPE := kernel
+
+BIN_TARGET := PortLibTest
+BIN_TARGET_ARCHIVES := portlib general
+
+SOURCES = NdbPortLibTest.cpp
+
+include $(NDB_TOP)/Epilogue.mk
+
+
+
+
+
diff --git a/ndb/src/common/portlib/test/NdbPortLibTest.cpp b/ndb/src/common/portlib/test/NdbPortLibTest.cpp
new file mode 100644
index 00000000000..8a5c8f4a878
--- /dev/null
+++ b/ndb/src/common/portlib/test/NdbPortLibTest.cpp
@@ -0,0 +1,621 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+/**
+ * NdbPortLibTest.cpp
+ * Test the functionality of portlib
+ * TODO - Add tests for NdbMem
+ */
+
+
+
+#include "NdbOut.hpp"
+#include "NdbThread.h"
+#include "NdbMutex.h"
+#include "NdbCondition.h"
+#include "NdbSleep.h"
+#include "NdbTick.h"
+#include "NdbEnv.h"
+#include "NdbHost.h"
+#include "NdbMain.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+int TestHasFailed;
+int verbose = 0;
+
+static void fail(const char* test, const char* cause)
+{
+ TestHasFailed = 1;
+ ndbout << test << " failed, " << cause << endl;
+}
+
+// test 1 variables and funcs
+
+extern "C" void* thread1func(void* arg)
+{
+ int arg1;
+ int returnvalue = 8;
+ arg1 = *(int*)arg;
+ ndbout << "thread1: thread1func called with arg = " << arg1 << endl;
+
+ // delay(1000);
+ if (arg1 != 7)
+ fail("TEST1", "Wrong arg");
+
+ NdbThread_Exit(returnvalue);
+
+ return NULL;
+
+}
+
+// test 2 variables and funcs
+
+NdbMutex* test2mutex;
+
+extern "C" void* test2func(void* arg)
+{
+
+ int arg1;
+ arg1 = *(int*)arg;
+ ndbout << "thread" << arg1 << " started in test2func" << endl;
+
+ if (NdbMutex_Lock(test2mutex) != 0)
+ fail("TEST2", "Failed to lock mutex");
+
+ ndbout << "thread" << arg1 << ", test2func " << endl;
+
+ if (NdbMutex_Unlock(test2mutex) != 0)
+ fail("TEST2", "Failed to unlock mutex");
+
+ int returnvalue = arg1;
+ NdbThread_Exit(returnvalue);
+
+ return NULL;
+
+}
+
+
+// test 3 and 7 variables and funcs
+
+NdbMutex* testmutex;
+NdbCondition* testcond;
+int testthreadsdone;
+
+extern "C" void* testfunc(void* arg)
+{
+ int tmpVar;
+ int threadno;
+ int result;
+
+ threadno = *(int*)arg;
+
+ ndbout << "Thread" << threadno << " started in testfunc" << endl;
+ do
+ {
+
+ if ((threadno % 2) == 0)
+ result = NdbSleep_SecSleep(1);
+ else
+ result = NdbSleep_MilliSleep(100);
+
+ if (result != 0)
+ fail("TEST3", "Wrong result from sleep function");
+
+ if (NdbMutex_Lock(testmutex) != 0)
+ fail("TEST3", "Wrong result from NdbMutex_Lock function");
+
+ ndbout << "thread" << threadno << ", testfunc " << endl;
+ testthreadsdone++;
+ tmpVar = testthreadsdone;
+
+ if (NdbCondition_Signal(testcond) != 0)
+ fail("TEST3", "Wrong result from NdbCondition_Signal function");
+
+ if (NdbMutex_Unlock(testmutex) != 0)
+ fail("TEST3", "Wrong result from NdbMutex_Unlock function");
+
+ }
+ while(tmpVar<100);
+
+ NdbThread_Exit(0);
+ return NULL;
+}
+
+extern "C" void* testTryLockfunc(void* arg)
+{
+ int tmpVar = 0;
+ int threadno;
+ int result;
+
+ threadno = *(int*)arg;
+
+ ndbout << "Thread" << threadno << " started" << endl;
+ do
+ {
+
+ if ((threadno % 2) == 0)
+ result = NdbSleep_SecSleep(1);
+ else
+ result = NdbSleep_MilliSleep(100);
+
+ if (result != 0)
+ fail("TEST3", "Wrong result from sleep function");
+
+ if (NdbMutex_Trylock(testmutex) == 0){
+
+ ndbout << "thread" << threadno << ", testTryLockfunc locked" << endl;
+ testthreadsdone++;
+ tmpVar = testthreadsdone;
+
+ if (NdbCondition_Signal(testcond) != 0)
+ fail("TEST3", "Wrong result from NdbCondition_Signal function");
+
+ if (NdbMutex_Unlock(testmutex) != 0)
+ fail("TEST3", "Wrong result from NdbMutex_Unlock function");
+ }
+
+ }
+ while(tmpVar<100);
+
+ NdbThread_Exit(0);
+ return NULL;
+}
+
+
+
+void testMicros(int count);
+Uint64 time_diff(Uint64 s1, Uint64 s2, Uint32 m1, Uint32 m2);
+
+NDB_COMMAND(PortLibTest, "portlibtest", "portlibtest", "Test the portable function layer", 4096){
+
+ ndbout << "= TESTING ARGUMENT PASSING ============" << endl;
+ ndbout << "ARGC: " << argc << endl;
+ for(int i = 1; i < argc; i++){
+ ndbout << " ARGV"<<i<<": " << (char*)argv[i] << endl;
+ }
+ ndbout << endl << endl;
+
+
+ struct NdbThread* thread1var;
+ void *status = 0;
+ int arg = 7;
+
+ TestHasFailed = 0;
+ // create one thread and wait for it to return
+ ndbout << "= TEST1 ===============================" << endl;
+
+ thread1var = NdbThread_Create(thread1func, // Function
+ (void**)&arg,// Arg
+ 2048, // Stacksize
+ (char*)"thread1", // Thread name
+ NDB_THREAD_PRIO_MEAN); // Thread priority
+
+
+ if(NdbThread_WaitFor(thread1var, &status) != 0)
+ fail("TEST1", "NdbThread_WaitFor failed");
+ // NOTE! thread return value is not yet used in Ndb and thus not tested(does not work)
+ //ndbout << "thread1 returned, status = " << status << endl;
+ //if (status != 8)
+ // fail("TEST1", "Wrong status");
+ ndbout << "TEST1 completed" << endl;
+
+
+ NdbThread_Destroy(&thread1var);
+
+ // Create 10 threads that will wait for a mutex before printing it's message to screen
+ ndbout << "= TEST2 ===============================" << endl;
+#define T2_THREADS 10
+ NdbThread* threads[T2_THREADS];
+ int args[T2_THREADS];
+ void *status2 = 0;
+ test2mutex = NdbMutex_Create();
+ NdbMutex_Lock(test2mutex);
+
+ for (int i = 0; i < T2_THREADS; i++)
+ {
+ args[i] = i;
+ threads[i] = NdbThread_Create(test2func, // Function
+ (void**)&args[i],// Arg
+ 2048, // Stacksize
+ (char*)"test2thread", // Thread name
+ NDB_THREAD_PRIO_MEAN); // Thread priority
+ if (threads[i] == NULL)
+ fail("TEST2", "NdbThread_Create failed");
+ }
+
+ ndbout << "All threads created" << endl;
+
+ NdbMutex_Unlock(test2mutex);
+
+ for (int i = 0; i < T2_THREADS; i++)
+ {
+ if (NdbThread_WaitFor(threads[i], &status2))
+ fail("TEST2", "NdbThread_WaitFor failed");
+
+ NdbThread_Destroy(&threads[i]);
+ // Don't test return values
+ // ndbout << "thread" << i << " returned, status = " << status2 << endl;
+ // if (status2 != i)
+ // fail("TEST2", "Wrong status");
+ }
+
+ if (NdbMutex_Lock(test2mutex) != 0)
+ fail("TEST2", "NdbMutex_Lock failed");
+ if (NdbMutex_Unlock(test2mutex) != 0)
+ fail("TEST2", "NdbMutex_Unlock failed");
+ if (NdbMutex_Destroy(test2mutex) != 0)
+ fail("TEST2", "NdbMutex_Destroy failed");
+ ndbout << "TEST2 completed" << endl;
+
+ ndbout << "= TEST3 ===============================" << endl;
+ // Create 10 threads that will by synchronised by a condition
+ // When they are awakened and have the mutex they will increment a global variable
+#define T3_THREADS 10
+ NdbThread* t3threads[T3_THREADS];
+ int t3args[T3_THREADS];
+ void *status3 = 0;
+
+ testmutex = NdbMutex_Create();
+ testcond = NdbCondition_Create();
+ testthreadsdone = 0;
+
+ for (int i = 0; i < T3_THREADS; i++)
+ {
+ t3args[i] = i;
+ t3threads[i] = NdbThread_Create(testfunc, // Function
+ (void**)&t3args[i],// Arg
+ 2048, // Stacksize
+ (char*)"test3thread", // Thread name
+ NDB_THREAD_PRIO_MEAN); // Thread priority
+ }
+
+ ndbout << "All threads created" << endl;
+
+ if (NdbMutex_Lock(testmutex) != 0)
+ fail("TEST3", "NdbMutex_Lock failed");
+
+ while (testthreadsdone < T3_THREADS*10)
+ {
+ if(NdbCondition_Wait(testcond, testmutex) != 0)
+ fail("TEST3", "NdbCondition_Wait failed");
+ ndbout << "Condition signaled, there are " << testthreadsdone << " completed threads" << endl;
+ }
+ if (NdbMutex_Unlock(testmutex) != 0)
+ fail("TEST3", "NdbMutex_Unlock failed");
+
+ for (int i = 0; i < T3_THREADS; i++)
+ {
+ if (NdbThread_WaitFor(t3threads[i], &status3) != 0)
+ fail("TEST3", "NdbThread_WaitFor failed");
+
+ NdbThread_Destroy(&t3threads[i]);
+ //ndbout << "thread" << i << " returned, status = " << status3 << endl;
+ //if (status3 != i)
+ // fail("TEST3", "Wrong status");
+ }
+
+ NdbMutex_Destroy(testmutex);
+ NdbCondition_Destroy(testcond);
+ ndbout << "TEST3 completed" << endl;
+
+ ndbout << "= TEST4 ===============================" << endl;
+ // Check tick functions
+
+ //#if 0
+
+ int sleeptimes[] = {78, 12, 199, 567, 899};
+
+
+ for (int i = 0; i < 5; i++)
+ {
+ ndbout << "*------------------------------- Measure" << i << endl;
+
+ NDB_TICKS millisec_now;
+ NDB_TICKS millisec_now2;
+
+ millisec_now = NdbTick_CurrentMillisecond();
+ NdbSleep_MilliSleep(sleeptimes[i]);
+ millisec_now2 = NdbTick_CurrentMillisecond();
+
+ ndbout << " Time before sleep = " << millisec_now << endl;
+ ndbout << " Time after sleep = " << millisec_now2 << endl;
+ ndbout << " Tried to sleep "<<sleeptimes[i]<<" milliseconds." << endl;
+ ndbout << " Sleep time was " << millisec_now2 -millisec_now <<" milliseconds." << endl;
+
+ }
+
+ ndbout << "TEST4 completed" << endl;
+
+ ndbout << "= TEST5 ===============================" << endl;
+ // Check NdbOut
+
+ ndbout << "Testing hex and dec functions of NdbOut" << endl;
+
+ for (int i = 0; i<= 0xFF; i++)
+ {
+ ndbout << i << "=" <<hex << i << "="<<dec << i << ", ";
+ }
+
+ ndbout << endl<< "Testing that hex is reset to dec by endl" << endl;
+ ndbout << hex << 67 << endl;
+ ndbout << 67 << endl;
+
+ ndbout << "TEST5 completed" << endl;
+
+
+ ndbout << "= TEST6 ===============================" << endl;
+ const char* theEnvHostNamePtr;
+ char buf[255];
+ char theHostHostName[256];
+ theEnvHostNamePtr = NdbEnv_GetEnv("HOSTNAME", buf, 255);
+ if(theEnvHostNamePtr == NULL)
+ fail("TEST6", "Could not get HOSTNAME from env");
+ else{
+ ndbout << "HOSTNAME from GetEnv" << theEnvHostNamePtr << endl;
+
+ NdbHost_GetHostName(theHostHostName);
+
+ ndbout << "HOSTNAME from GetHostName" <<theHostHostName << endl;
+
+ if (strcmp(theEnvHostNamePtr, theHostHostName) != 0)
+ fail("TEST6", "NdbHost_GetHostName or NdbEnv_GetEnv failed");
+ }
+
+ ndbout << "= TEST7 ===============================" << endl;
+
+ testmutex = NdbMutex_Create();
+ testcond = NdbCondition_Create();
+ testthreadsdone = 0;
+
+ for (int i = 0; i < T3_THREADS; i++)
+ {
+ t3args[i] = i;
+ t3threads[i] = NdbThread_Create(testfunc, // Function
+ (void**)&t3args[i],// Arg
+ 2048, // Stacksize
+ (char*)"test7thread", // Thread name
+ NDB_THREAD_PRIO_MEAN); // Thread priority
+ }
+
+ ndbout << "All threads created" << endl;
+
+ if (NdbMutex_Lock(testmutex) != 0)
+ fail("TEST7", "NdbMutex_Lock failed");
+
+ while (testthreadsdone < T3_THREADS*10)
+ {
+ // just testing the functionality without timing out, therefor 20 sec.
+ if(NdbCondition_WaitTimeout(testcond, testmutex, 20000) != 0)
+ fail("TEST7", "NdbCondition_WaitTimeout failed");
+ ndbout << "Condition signaled, there are " << testthreadsdone << " completed threads" << endl;
+ }
+ if (NdbMutex_Unlock(testmutex) != 0)
+ fail("TEST7", "NdbMutex_Unlock failed");
+
+ for (int i = 0; i < T3_THREADS; i++)
+ {
+ if (NdbThread_WaitFor(t3threads[i], &status3) != 0)
+ fail("TEST7", "NdbThread_WaitFor failed");
+
+ NdbThread_Destroy(&t3threads[i]);
+ }
+
+ NdbMutex_Destroy(testmutex);
+ NdbCondition_Destroy(testcond);
+
+ ndbout << "TEST7 completed" << endl;
+
+
+ ndbout << "= TEST8 ===============================" << endl;
+ ndbout << " NdbCondition_WaitTimeout" << endl;
+ testmutex = NdbMutex_Create();
+ testcond = NdbCondition_Create();
+
+ for (int i = 0; i < 5; i++)
+ {
+ ndbout << "*------------------------------- Measure" << i << endl;
+
+ NDB_TICKS millisec_now;
+ NDB_TICKS millisec_now2;
+
+ millisec_now = NdbTick_CurrentMillisecond();
+ if (NdbCondition_WaitTimeout(testcond, testmutex, sleeptimes[i]) != 0)
+ fail("TEST8", "NdbCondition_WaitTimeout failed");
+ millisec_now2 = NdbTick_CurrentMillisecond();
+
+ ndbout << " Time before WaitTimeout = " << millisec_now << endl;
+ ndbout << " Time after WaitTimeout = " << millisec_now2 << endl;
+ ndbout << " Tried to wait "<<sleeptimes[i]<<" milliseconds." << endl;
+ ndbout << " Wait time was " << millisec_now2 -millisec_now <<" milliseconds." << endl;
+
+ }
+
+ ndbout << "TEST8 completed" << endl;
+
+
+ ndbout << "= TEST9 ===============================" << endl;
+ ndbout << " NdbTick_CurrentXXXXXsecond compare" << endl;
+
+ for (int i = 0; i < 5; i++)
+ {
+ ndbout << "*------------------------------- Measure" << i << endl;
+
+ NDB_TICKS millisec_now;
+ NDB_TICKS millisec_now2;
+ Uint32 usec_now, usec_now2;
+ Uint64 msec_now, msec_now2;
+
+
+ millisec_now = NdbTick_CurrentMillisecond();
+ NdbTick_CurrentMicrosecond( &msec_now, &usec_now);
+
+ NdbSleep_MilliSleep(sleeptimes[i]);
+
+ millisec_now2 = NdbTick_CurrentMillisecond();
+ NdbTick_CurrentMicrosecond( &msec_now2, &usec_now2);
+
+ Uint64 usecdiff = time_diff(msec_now,msec_now2,usec_now,usec_now2);
+ NDB_TICKS msecdiff = millisec_now2 -millisec_now;
+
+ ndbout << " Slept "<<sleeptimes[i]<<" milliseconds." << endl;
+ ndbout << " Measured " << msecdiff <<" milliseconds with milli function ." << endl;
+ ndbout << " Measured " << usecdiff/1000 << "," << usecdiff%1000<<" milliseconds with micro function ." << endl;
+ }
+
+ ndbout << "TEST9 completed" << endl;
+
+
+ const int iter = 20;
+ ndbout << "Testing microsecond timer - " << iter << " iterations" << endl;
+ testMicros(iter);
+ ndbout << "Testing microsecond timer - COMPLETED" << endl;
+
+#if defined NDB_OSE || defined NDB_SOFTOSE
+ ndbout << "system_tick() = " << system_tick() << " us per tick" << endl;
+#endif
+
+
+ ndbout << "= TEST10 ===============================" << endl;
+
+ testmutex = NdbMutex_Create();
+ testcond = NdbCondition_Create();
+ testthreadsdone = 0;
+
+ for (int i = 0; i < T3_THREADS; i++)
+ {
+ t3args[i] = i;
+ t3threads[i] = NdbThread_Create(testTryLockfunc, // Function
+ (void**)&t3args[i],// Arg
+ 2048, // Stacksize
+ (char*)"test10thread", // Thread name
+ NDB_THREAD_PRIO_MEAN); // Thread priority
+ }
+
+ ndbout << "All threads created" << endl;
+
+ if (NdbMutex_Lock(testmutex) != 0)
+ fail("TEST10", "NdbMutex_Lock failed");
+
+ while (testthreadsdone < T3_THREADS*10)
+ {
+ if(NdbCondition_Wait(testcond, testmutex) != 0)
+ fail("TEST10", "NdbCondition_WaitTimeout failed");
+ ndbout << "Condition signaled, there are " << testthreadsdone << " completed threads" << endl;
+ }
+ if (NdbMutex_Unlock(testmutex) != 0)
+ fail("TEST10", "NdbMutex_Unlock failed");
+
+ for (int i = 0; i < T3_THREADS; i++)
+ {
+ if (NdbThread_WaitFor(t3threads[i], &status3) != 0)
+ fail("TEST10", "NdbThread_WaitFor failed");
+
+ NdbThread_Destroy(&t3threads[i]);
+ }
+
+ NdbMutex_Destroy(testmutex);
+ NdbCondition_Destroy(testcond);
+
+ ndbout << "TEST10 completed" << endl;
+
+
+ // Check total status of test
+
+ if (TestHasFailed == 1)
+ ndbout << endl << "TEST FAILED!" << endl;
+ else
+ ndbout << endl << "TEST PASSED!" << endl;
+
+ return TestHasFailed;
+
+};
+
+Uint64 time_diff(Uint64 s1, Uint64 s2, Uint32 m1, Uint32 m2){
+
+ Uint64 diff = 0;
+ diff += (s2 - s1) * 1000000;
+ if(m2 >= m1)
+ diff += (m2 - m1);
+ else {
+ diff += m2;
+ diff -= m1;
+ }
+
+ // if(0)
+ // ndbout("(s1,m1) = (%d, %d) (s2,m2) = (%d, %d) -> diff = %d\n",
+ // (Uint32)s1,m1,(Uint32)s2,m2, (Uint32)diff);
+
+ return diff;
+};
+
+void
+testMicros(int count){
+ Uint32 avg = 0;
+ Uint32 sum2 = 0;
+
+ for(int i = 0; i<count; i++){
+ Uint64 s1, s2;
+ Uint32 m1, m2;
+ if(NdbTick_CurrentMicrosecond(&s1, &m1) != 0){
+ ndbout << "Failed to get current micro" << endl;
+ TestHasFailed = 1;
+ return;
+ }
+ Uint32 r = (rand() % 1000) + 1;
+ NdbSleep_MilliSleep(r);
+ if(NdbTick_CurrentMicrosecond(&s2, &m2) != 0){
+ ndbout << "Failed to get current micro" << endl;
+ TestHasFailed = 1;
+ return;
+ }
+ Uint64 m = time_diff(s1,s2,m1,m2);
+ if(verbose)
+ ndbout << "Slept for " << r << " ms"
+ << " - Measured " << m << " us" << endl;
+
+ if(m > (r*1000)){
+ avg += (m - (r*1000));
+ sum2 += (m - (r*1000)) * (m - (r*1000));
+ } else {
+ avg += ((r*1000) - m);
+ sum2 += ((r*1000) - m) * ((r*1000) - m);
+ }
+#if 0
+ m /= 1000;
+ if(m > r && ((m - r) > 10)){
+ ndbout << "Difference to big: " << (m - r) << " - Test failed" << endl;
+ TestHasFailed = 1;
+ }
+ if(m < r && ((r - m) > 10)){
+ ndbout << "Difference to big: " << (r - m) << " - Test failed" << endl;
+ TestHasFailed = 1;
+ }
+#endif
+ }
+
+ Uint32 dev = (avg * avg - sum2) / count; dev /= count;
+ avg /= count;
+
+ Uint32 t = 0;
+ while((t*t)<dev) t++;
+ ndbout << "NOTE - measure are compared to NdbSleep_MilliSleep(...)" << endl;
+ ndbout << "Average error = " << avg << " us" << endl;
+ ndbout << "Stddev error = " << t << " us" << endl;
+}
diff --git a/ndb/src/common/portlib/unix/Makefile b/ndb/src/common/portlib/unix/Makefile
new file mode 100644
index 00000000000..452196d9f08
--- /dev/null
+++ b/ndb/src/common/portlib/unix/Makefile
@@ -0,0 +1,27 @@
+include .defs.mk
+
+TYPE := util
+
+PIC_ARCHIVE := Y
+ARCHIVE_TARGET := portlib
+
+SOURCES.c = NdbCondition.c \
+ NdbMutex.c \
+ NdbSleep.c \
+ NdbTick.c \
+ NdbEnv.c \
+ NdbThread.c \
+ NdbHost.c \
+ NdbTCP.c \
+ NdbDaemon.c
+
+ifeq ($(NDB_OS), SOFTOSE)
+ SOURCES += NdbMem_SoftOse.cpp
+else
+ SOURCES.c += NdbMem.c
+endif
+
+include $(NDB_TOP)/Epilogue.mk
+
+testNdbDaemon: NdbDaemon.c
+ $(CC) -o $@ NdbDaemon.c $(CCFLAGS) -DNDB_DAEMON_TEST -L$(NDB_TOP)/lib
diff --git a/ndb/src/common/portlib/unix/NdbCondition.c b/ndb/src/common/portlib/unix/NdbCondition.c
new file mode 100644
index 00000000000..35b80821052
--- /dev/null
+++ b/ndb/src/common/portlib/unix/NdbCondition.c
@@ -0,0 +1,179 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 <NdbCondition.h>
+#include <pthread.h>
+#include <assert.h>
+#include <sys/types.h>
+#if defined NDB_MACOSX
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+
+#include <NdbMutex.h>
+
+struct NdbCondition
+{
+ pthread_cond_t cond;
+};
+
+
+
+struct NdbCondition*
+NdbCondition_Create(void)
+{
+ struct NdbCondition* tmpCond;
+ int result;
+
+ tmpCond = (struct NdbCondition*)malloc(sizeof(struct NdbCondition));
+
+ if (tmpCond == NULL)
+ return NULL;
+
+ result = pthread_cond_init(&tmpCond->cond, NULL);
+
+ assert(result==0);
+ return tmpCond;
+}
+
+
+
+int
+NdbCondition_Wait(struct NdbCondition* p_cond,
+ NdbMutex* p_mutex)
+{
+ int result;
+
+ if (p_cond == NULL || p_mutex == NULL)
+ return 1;
+
+ result = pthread_cond_wait(&p_cond->cond, p_mutex);
+
+ return result;
+}
+
+#if defined NDB_SOLARIS || defined NDB_HPUX
+#include <time.h>
+int
+NdbCondition_WaitTimeout(struct NdbCondition* p_cond,
+ NdbMutex* p_mutex,
+ int msecs){
+ int result;
+ struct timespec abstime;
+ int secs = 0;
+
+ if (p_cond == NULL || p_mutex == NULL)
+ return 1;
+
+ clock_gettime(CLOCK_REALTIME, &abstime);
+
+ if(msecs >= 1000){
+ secs = msecs / 1000;
+ msecs = msecs % 1000;
+ }
+
+ abstime.tv_sec += secs;
+ abstime.tv_nsec += msecs * 1000000;
+ if (abstime.tv_nsec >= 1000000000) {
+ abstime.tv_sec += 1;
+ abstime.tv_nsec -= 1000000000;
+ }
+
+ result = pthread_cond_timedwait(&p_cond->cond, p_mutex, &abstime);
+
+ return result;
+}
+#endif
+
+#if defined NDB_LINUX || defined NDB_MACOSX
+#include <unistd.h>
+#include <sys/time.h>
+
+int
+NdbCondition_WaitTimeout(struct NdbCondition* p_cond,
+ NdbMutex* p_mutex,
+ int msecs){
+ int result;
+ struct timespec abstime;
+ struct timeval tick_time;
+ int secs = 0;
+
+ if (p_cond == NULL || p_mutex == NULL)
+ return 1;
+
+ gettimeofday(&tick_time, 0);
+
+ if(msecs >= 1000){
+ secs = msecs / 1000;
+ msecs = msecs % 1000;
+ }
+
+
+ abstime.tv_sec = tick_time.tv_sec + secs;
+ abstime.tv_nsec = tick_time.tv_usec * 1000 + msecs * 1000000;
+ if (abstime.tv_nsec >= 1000000000) {
+ abstime.tv_sec += 1;
+ abstime.tv_nsec -= 1000000000;
+ }
+
+ result = pthread_cond_timedwait(&p_cond->cond, p_mutex, &abstime);
+
+ return result;
+}
+#endif
+
+
+int
+NdbCondition_Signal(struct NdbCondition* p_cond){
+ int result;
+
+ if (p_cond == NULL)
+ return 1;
+
+ result = pthread_cond_signal(&p_cond->cond);
+
+ return result;
+}
+
+
+int NdbCondition_Broadcast(struct NdbCondition* p_cond)
+{
+ int result;
+
+ if (p_cond == NULL)
+ return 1;
+
+ result = pthread_cond_broadcast(&p_cond->cond);
+
+ return result;
+}
+
+
+int NdbCondition_Destroy(struct NdbCondition* p_cond)
+{
+ int result;
+
+ if (p_cond == NULL)
+ return 1;
+
+ result = pthread_cond_destroy(&p_cond->cond);
+ free(p_cond);
+
+ return 0;
+}
+
diff --git a/ndb/src/common/portlib/unix/NdbDaemon.c b/ndb/src/common/portlib/unix/NdbDaemon.c
new file mode 100644
index 00000000000..fc114266c9d
--- /dev/null
+++ b/ndb/src/common/portlib/unix/NdbDaemon.c
@@ -0,0 +1,170 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbDaemon.h"
+#include <assert.h>
+
+#ifdef NDB_LINUX
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#endif
+
+#ifdef NDB_SOLARIS
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#endif
+
+#define NdbDaemon_ErrorSize 500
+#if defined(NDB_LINUX) || defined(NDB_SOLARIS)
+long NdbDaemon_DaemonPid;
+int NdbDaemon_ErrorCode;
+char NdbDaemon_ErrorText[NdbDaemon_ErrorSize];
+#endif
+int
+NdbDaemon_Make(const char* lockfile, const char* logfile, unsigned flags)
+{
+ /* XXX fix other unixes */
+#if defined(NDB_LINUX) || defined(NDB_SOLARIS)
+ int lockfd = -1, logfd = -1, n;
+ char buf[64];
+
+ /* Check that we have write access to lock file */
+ assert(lockfile != NULL);
+ lockfd = open(lockfile, O_CREAT|O_RDWR, 0644);
+ if (lockfd == -1) {
+ NdbDaemon_ErrorCode = errno;
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "%s: open for write failed: %s", lockfile, strerror(errno));
+ return -1;
+ }
+ /* Read any old pid from lock file */
+ buf[0] = 0;
+ n = read(lockfd, buf, sizeof(buf));
+ if (n < 0) {
+ NdbDaemon_ErrorCode = errno;
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "%s: read failed: %s", lockfile, strerror(errno));
+ return -1;
+ }
+ NdbDaemon_DaemonPid = atol(buf);
+ if (lseek(lockfd, 0, SEEK_SET) == -1) {
+ NdbDaemon_ErrorCode = errno;
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "%s: lseek failed: %s", lockfile, strerror(errno));
+ return -1;
+ }
+ /* Test for lock before becoming daemon */
+ if (lockf(lockfd, F_TEST, 0) == -1) {
+ if (errno == EACCES || errno == EAGAIN) { /* results may vary */
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "%s: already locked by pid=%ld", lockfile, NdbDaemon_DaemonPid);
+ return -1;
+ }
+ NdbDaemon_ErrorCode = errno;
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "%s: lock test failed: %s", lockfile, strerror(errno));
+ return -1;
+ }
+ /* Test open log file before becoming daemon */
+ if (logfile != NULL) {
+ logfd = open(logfile, O_CREAT|O_WRONLY|O_APPEND, 0644);
+ if (logfd == -1) {
+ NdbDaemon_ErrorCode = errno;
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "%s: open for write failed: %s", logfile, strerror(errno));
+ return -1;
+ }
+ }
+ /* Fork */
+ n = fork();
+ if (n == -1) {
+ NdbDaemon_ErrorCode = errno;
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "fork failed: %s", strerror(errno));
+ return -1;
+ }
+ /* Exit if we are the parent */
+ if (n != 0) {
+ exit(0);
+ }
+ /* Running in child process */
+ NdbDaemon_DaemonPid = getpid();
+ /* Lock the lock file (likely to succeed due to test above) */
+ if (lockf(lockfd, F_LOCK, 0) == -1) {
+ NdbDaemon_ErrorCode = errno;
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "%s: lock failed: %s", lockfile, strerror(errno));
+ return -1;
+ }
+ /* Become process group leader */
+ if (setsid() == -1) {
+ NdbDaemon_ErrorCode = errno;
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "setsid failed: %s", strerror(errno));
+ return -1;
+ }
+ /* Write pid to lock file */
+ if (ftruncate(lockfd, 0) == -1) {
+ NdbDaemon_ErrorCode = errno;
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "%s: ftruncate failed: %s", lockfile, strerror(errno));
+ return -1;
+ }
+ sprintf(buf, "%ld\n", NdbDaemon_DaemonPid);
+ n = strlen(buf);
+ if (write(lockfd, buf, n) != n) {
+ NdbDaemon_ErrorCode = errno;
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "%s: write failed: %s", lockfile, strerror(errno));
+ return -1;
+ }
+ /* Do input/output redirections (assume fd 0,1,2 not in use) */
+ close(0);
+ open("/dev/null", O_RDONLY);
+ if (logfile != 0) {
+ dup2(logfd, 1);
+ dup2(logfd, 2);
+ close(logfd);
+ }
+#endif
+ /* Success */
+ return 0;
+}
+
+#ifdef NDB_DAEMON_TEST
+
+int
+main()
+{
+ if (NdbDaemon_Make("test.pid", "test.log", 0) == -1) {
+ fprintf(stderr, "NdbDaemon_Make: %s\n", NdbDaemon_ErrorText);
+ return 1;
+ }
+ sleep(10);
+ return 0;
+}
+
+#endif
diff --git a/ndb/src/common/portlib/unix/NdbEnv.c b/ndb/src/common/portlib/unix/NdbEnv.c
new file mode 100644
index 00000000000..b01e3b239ca
--- /dev/null
+++ b/ndb/src/common/portlib/unix/NdbEnv.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbEnv.h"
+#include <string.h>
+#include <stdlib.h>
+
+const char* NdbEnv_GetEnv(const char* name, char * buf, int buflen)
+{
+ char* p = NULL;
+ p = getenv(name);
+
+ if (p != NULL && buf != NULL){
+ strncpy(buf, p, buflen);
+ buf[buflen-1] = 0;
+ }
+ return p;
+
+}
+
diff --git a/ndb/src/common/portlib/unix/NdbHost.c b/ndb/src/common/portlib/unix/NdbHost.c
new file mode 100644
index 00000000000..8d2a23fccda
--- /dev/null
+++ b/ndb/src/common/portlib/unix/NdbHost.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbHost.h"
+#include <unistd.h>
+
+int NdbHost_GetHostName(char* buf)
+{
+ if (gethostname(buf, MAXHOSTNAMELEN) != 0)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+int NdbHost_GetProcessId(void)
+{
+ return getpid();
+}
+
diff --git a/ndb/src/common/portlib/unix/NdbMem.c b/ndb/src/common/portlib/unix/NdbMem.c
new file mode 100644
index 00000000000..a18cf30cc8a
--- /dev/null
+++ b/ndb/src/common/portlib/unix/NdbMem.c
@@ -0,0 +1,76 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbMem.h"
+
+#include <assert.h>
+#include <assert.h>
+#include <stdlib.h>
+#ifndef NDB_MACOSX
+#include <sys/mman.h>
+#endif
+
+void NdbMem_Create()
+{
+ /* Do nothing */
+ return;
+}
+
+void NdbMem_Destroy()
+{
+ /* Do nothing */
+ return;
+}
+
+void* NdbMem_Allocate(size_t size)
+{
+ assert(size > 0);
+ return (void*)malloc(size);
+}
+
+void* NdbMem_AllocateAlign(size_t size, size_t alignment)
+{
+ /*
+ return (void*)memalign(alignment, size);
+ TEMP fix
+ */
+ return (void*)malloc(size);
+}
+
+
+void NdbMem_Free(void* ptr)
+{
+ free(ptr);
+}
+
+
+int NdbMem_MemLockAll(){
+#if defined NDB_MACOSX
+ return 0;
+#else
+ return mlockall(MCL_CURRENT | MCL_FUTURE);
+#endif
+}
+
+int NdbMem_MemUnlockAll(){
+#if defined NDB_MACOSX
+ return 0;
+#else
+ return munlockall();
+#endif
+}
+
diff --git a/ndb/src/common/portlib/unix/NdbMutex.c b/ndb/src/common/portlib/unix/NdbMutex.c
new file mode 100644
index 00000000000..3cadc0667e7
--- /dev/null
+++ b/ndb/src/common/portlib/unix/NdbMutex.c
@@ -0,0 +1,93 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbMutex.h"
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+
+NdbMutex* NdbMutex_Create(void)
+{
+ NdbMutex* pNdbMutex;
+ int result;
+
+ pNdbMutex = (NdbMutex*)malloc(sizeof(NdbMutex));
+
+ if (pNdbMutex == NULL)
+ return NULL;
+
+ result = pthread_mutex_init(pNdbMutex, NULL);
+ assert(result == 0);
+
+ return pNdbMutex;
+
+}
+
+
+int NdbMutex_Destroy(NdbMutex* p_mutex)
+{
+ int result;
+
+ if (p_mutex == NULL)
+ return -1;
+
+ result = pthread_mutex_destroy(p_mutex);
+ free(p_mutex);
+
+ return result;
+
+}
+
+
+int NdbMutex_Lock(NdbMutex* p_mutex)
+{
+ int result;
+
+ if (p_mutex == NULL)
+ return -1;
+
+ result = pthread_mutex_lock(p_mutex);
+
+ return result;
+}
+
+
+int NdbMutex_Unlock(NdbMutex* p_mutex)
+{
+ int result;
+
+ if (p_mutex == NULL)
+ return -1;
+
+ result = pthread_mutex_unlock(p_mutex);
+
+ return result;
+}
+
+
+int NdbMutex_Trylock(NdbMutex* p_mutex)
+{
+ int result = -1;
+
+ if (p_mutex != NULL) {
+ result = pthread_mutex_trylock(p_mutex);
+ }
+
+ return result;
+}
+
diff --git a/ndb/src/common/portlib/unix/NdbSleep.c b/ndb/src/common/portlib/unix/NdbSleep.c
new file mode 100644
index 00000000000..35132d7f9c7
--- /dev/null
+++ b/ndb/src/common/portlib/unix/NdbSleep.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbSleep.h"
+
+
+#ifdef NDB_SOLARIS
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+#if defined NDB_LINUX || defined NDB_HPUX || defined NDB_MACOSX
+#include <time.h>
+#include <unistd.h>
+#endif
+
+int
+NdbSleep_MilliSleep(int milliseconds){
+ int result = 0;
+ struct timespec sleeptime;
+ sleeptime.tv_sec = milliseconds / 1000;
+ sleeptime.tv_nsec = (milliseconds - (sleeptime.tv_sec * 1000)) * 1000000;
+ result = nanosleep(&sleeptime, NULL);
+ return result;
+}
+
+int
+NdbSleep_SecSleep(int seconds){
+ int result = 0;
+ result = sleep(seconds);
+ return result;
+}
+
+
diff --git a/ndb/src/common/portlib/unix/NdbTCP.c b/ndb/src/common/portlib/unix/NdbTCP.c
new file mode 100644
index 00000000000..c2613c211c5
--- /dev/null
+++ b/ndb/src/common/portlib/unix/NdbTCP.c
@@ -0,0 +1,60 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbTCP.h"
+
+
+#ifdef NDB_SOLARIS
+int
+Ndb_getInAddr(struct in_addr * dst, const char *address) {
+ struct hostent host, * hostPtr;
+ char buf[1024];
+ int h_errno;
+ hostPtr = gethostbyname_r(address, &host, &buf[0], 1024, &h_errno);
+ if (hostPtr != NULL) {
+ dst->s_addr = ((struct in_addr *) *hostPtr->h_addr_list)->s_addr;
+ return 0;
+ }
+
+ /* Try it as aaa.bbb.ccc.ddd. */
+ dst->s_addr = inet_addr(address);
+ if (dst->s_addr != -1) {
+ return 0;
+ }
+ return -1;
+}
+#endif
+
+#if defined NDB_LINUX || defined NDB_HPUX || defined NDB_MACOSX
+int
+Ndb_getInAddr(struct in_addr * dst, const char *address) {
+ struct hostent * hostPtr;
+ hostPtr = gethostbyname(address);
+ if (hostPtr != NULL) {
+ dst->s_addr = ((struct in_addr *) *hostPtr->h_addr_list)->s_addr;
+ return 0;
+ }
+
+ /* Try it as aaa.bbb.ccc.ddd. */
+ dst->s_addr = inet_addr(address);
+ if (dst->s_addr != -1) {
+ return 0;
+ }
+ return -1;
+}
+#endif
+
diff --git a/ndb/src/common/portlib/unix/NdbThread.c b/ndb/src/common/portlib/unix/NdbThread.c
new file mode 100644
index 00000000000..3665c4c9159
--- /dev/null
+++ b/ndb/src/common/portlib/unix/NdbThread.c
@@ -0,0 +1,119 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbThread.h"
+#include <pthread.h>
+#ifdef NDB_MACOSX
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+#include <assert.h>
+#include <string.h>
+#include <NdbStdio.h>
+
+#define MAX_THREAD_NAME 16
+
+
+struct NdbThread
+{
+ pthread_t thread;
+ char thread_name[MAX_THREAD_NAME];
+};
+
+
+
+struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC *p_thread_func,
+ NDB_THREAD_ARG *p_thread_arg,
+ const NDB_THREAD_STACKSIZE thread_stack_size,
+ const char* p_thread_name,
+ NDB_THREAD_PRIO thread_prio)
+{
+ struct NdbThread* tmpThread;
+ int result;
+ pthread_attr_t thread_attr;
+
+ if (p_thread_func == NULL)
+ return 0;
+
+ tmpThread = (struct NdbThread*)malloc(sizeof(struct NdbThread));
+ if (tmpThread == NULL)
+ return NULL;
+
+ snprintf(tmpThread->thread_name, sizeof(tmpThread->thread_name),
+ "%s", p_thread_name);
+
+ pthread_attr_init(&thread_attr);
+ pthread_attr_setstacksize(&thread_attr, thread_stack_size);
+#if defined NDB_SOLARIS
+#if !defined NDB_SOLARIS6
+ /* Guard stack overflow with a 2k databuffer */
+ pthread_attr_setguardsize(&thread_attr, 2048);
+#endif
+#endif
+
+ pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
+ result = pthread_create(&tmpThread->thread,
+ &thread_attr,
+ p_thread_func,
+ p_thread_arg);
+ assert(result==0);
+
+ pthread_attr_destroy(&thread_attr);
+ return tmpThread;
+}
+
+
+void NdbThread_Destroy(struct NdbThread** p_thread)
+{
+ if (*p_thread != NULL){
+ free(* p_thread);
+ * p_thread = 0;
+ }
+}
+
+
+int NdbThread_WaitFor(struct NdbThread* p_wait_thread, void** status)
+{
+ int result;
+
+ if (p_wait_thread == NULL)
+ return 0;
+
+ if (p_wait_thread->thread == NULL)
+ return 0;
+
+ result = pthread_join(p_wait_thread->thread, status);
+
+ return result;
+}
+
+
+void NdbThread_Exit(int status)
+{
+ pthread_exit(&status);
+}
+
+
+int NdbThread_SetConcurrencyLevel(int level)
+{
+#ifndef NDB_SOLARIS6
+ return pthread_setconcurrency(level);
+#else
+ return 0;
+#endif
+}
diff --git a/ndb/src/common/portlib/unix/NdbTick.c b/ndb/src/common/portlib/unix/NdbTick.c
new file mode 100644
index 00000000000..5adb4ec80c2
--- /dev/null
+++ b/ndb/src/common/portlib/unix/NdbTick.c
@@ -0,0 +1,110 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbTick.h"
+#include <time.h>
+
+#define NANOSEC_PER_SEC 1000000000
+#define MICROSEC_PER_SEC 1000000
+#define MILLISEC_PER_SEC 1000
+#define MICROSEC_PER_MILLISEC 1000
+#define MILLISEC_PER_NANOSEC 1000000
+
+
+#if defined NDB_SOLARIS || NDB_HPUX
+NDB_TICKS NdbTick_CurrentMillisecond(void)
+{
+ struct timespec tick_time;
+ clock_gettime(CLOCK_REALTIME, &tick_time);
+
+ return
+ ((NDB_TICKS)tick_time.tv_sec) * ((NDB_TICKS)MILLISEC_PER_SEC) +
+ ((NDB_TICKS)tick_time.tv_nsec) / ((NDB_TICKS)MILLISEC_PER_NANOSEC);
+}
+
+int
+NdbTick_CurrentMicrosecond(NDB_TICKS * secs, Uint32 * micros){
+ struct timespec t;
+ int res = clock_gettime(CLOCK_REALTIME, &t);
+ * secs = t.tv_sec;
+ * micros = t.tv_nsec / 1000;
+ return res;
+}
+#endif
+
+#if defined NDB_LINUX || NDB_MACOSX
+#include <unistd.h>
+#include <sys/time.h>
+NDB_TICKS NdbTick_CurrentMillisecond(void)
+{
+ struct timeval tick_time;
+ gettimeofday(&tick_time, 0);
+
+ return
+ ((NDB_TICKS)tick_time.tv_sec) * ((NDB_TICKS)MILLISEC_PER_SEC) +
+ ((NDB_TICKS)tick_time.tv_usec) / ((NDB_TICKS)MICROSEC_PER_MILLISEC);
+}
+
+int
+NdbTick_CurrentMicrosecond(NDB_TICKS * secs, Uint32 * micros){
+ struct timeval tick_time;
+ int res = gettimeofday(&tick_time, 0);
+
+ if(secs==0) {
+ NDB_TICKS secs = tick_time.tv_sec;
+ *micros = tick_time.tv_usec;
+ *micros = secs*1000000+*micros;
+ } else {
+ * secs = tick_time.tv_sec;
+ * micros = tick_time.tv_usec;
+ }
+ return res;
+}
+
+#endif
+#ifdef TIME_MEASUREMENT
+int
+NdbTick_getMicroTimer(struct MicroSecondTimer* input_timer)
+{
+ NDB_TICKS secs;
+ Uint32 mics;
+ int ret_value;
+ ret_value = NdbTick_CurrentMicrosecond(&secs, &mics);
+ input_timer->seconds = secs;
+ input_timer->micro_seconds = (NDB_TICKS)mics;
+ return ret_value;
+}
+
+NDB_TICKS
+NdbTick_getMicrosPassed(struct MicroSecondTimer start,
+ struct MicroSecondTimer stop)
+{
+ NDB_TICKS ret_value = (NDB_TICKS)0;
+ if (start.seconds < stop.seconds) {
+ NDB_TICKS sec_passed = stop.seconds - start.seconds;
+ ret_value = ((NDB_TICKS)MICROSEC_PER_SEC) * sec_passed;
+ } else if (start.seconds > stop.seconds) {
+ return ret_value;
+ }//if
+ if (start.micro_seconds < stop.micro_seconds) {
+ ret_value += (stop.micro_seconds - start.micro_seconds);
+ } else if (ret_value != (NDB_TICKS)0) {
+ ret_value -= (start.micro_seconds - stop.micro_seconds);
+ }//if
+ return ret_value;
+}
+#endif
diff --git a/ndb/src/common/portlib/win32/Makefile b/ndb/src/common/portlib/win32/Makefile
new file mode 100644
index 00000000000..bb29ac5547e
--- /dev/null
+++ b/ndb/src/common/portlib/win32/Makefile
@@ -0,0 +1,30 @@
+include .defs.mk
+
+TYPE := util
+
+PIC_ARCHIVE := Y
+ARCHIVE_TARGET := portlib
+
+SOURCES.c = NdbCondition.c \
+ NdbMutex.c \
+ NdbSleep.c \
+ NdbTick.c \
+ NdbEnv.c \
+ NdbThread.c \
+ NdbHost.c \
+ NdbTCP.c \
+ NdbDaemon.c
+
+ifeq ($(NDB_OS), SOFTOSE)
+ SOURCES += NdbMem_SoftOse.cpp
+else
+ SOURCES.c += NdbMem.c
+endif
+
+include $(NDB_TOP)/Epilogue.mk
+
+
+
+
+
+
diff --git a/ndb/src/common/portlib/win32/NdbCondition.c b/ndb/src/common/portlib/win32/NdbCondition.c
new file mode 100644
index 00000000000..12b508cf33b
--- /dev/null
+++ b/ndb/src/common/portlib/win32/NdbCondition.c
@@ -0,0 +1,184 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 <winsock2.h>
+#include <ws2tcpip.h>
+#include <windows.h>
+#include <assert.h>
+#include <sys/types.h>
+
+#include "NdbCondition.h"
+#include <NdbMutex.h>
+
+
+struct NdbCondition
+{
+ long nWaiters;
+ NdbMutex* pNdbMutexWaitersLock;
+ HANDLE hSemaphore;
+ HANDLE hEventWaitersDone;
+ int bWasBroadcast;
+};
+
+
+struct NdbCondition*
+NdbCondition_Create(void)
+{
+ int result = 0;
+ struct NdbCondition* pNdbCondition = (struct NdbCondition*)malloc(sizeof(struct NdbCondition));
+ if(!pNdbCondition)
+ return 0;
+
+ pNdbCondition->nWaiters = 0;
+ pNdbCondition->bWasBroadcast = 0;
+ if(!(pNdbCondition->hSemaphore = CreateSemaphore(0, 0, MAXLONG, 0)))
+ result = -1;
+ else if(!(pNdbCondition->pNdbMutexWaitersLock = NdbMutex_Create()))
+ result = -1;
+ else if(!(pNdbCondition->hEventWaitersDone = CreateEvent(0, 0, 0, 0)))
+ result = -1;
+
+ assert(!result);
+ return pNdbCondition;
+}
+
+
+int
+NdbCondition_Wait(struct NdbCondition* p_cond,
+ NdbMutex* p_mutex)
+{
+ int result;
+ int bLastWaiter;
+ if(!p_cond || !p_mutex)
+ return 1;
+
+ NdbMutex_Lock(p_cond->pNdbMutexWaitersLock);
+ p_cond->nWaiters++;
+ NdbMutex_Unlock(p_cond->pNdbMutexWaitersLock);
+
+ if(NdbMutex_Unlock(p_mutex))
+ return -1;
+ result = WaitForSingleObject (p_cond->hSemaphore, INFINITE);
+
+ NdbMutex_Lock(p_cond->pNdbMutexWaitersLock);
+ p_cond->nWaiters--;
+ bLastWaiter = (p_cond->bWasBroadcast && p_cond->nWaiters==0);
+ NdbMutex_Unlock(p_cond->pNdbMutexWaitersLock);
+
+ if(result==WAIT_OBJECT_0 && bLastWaiter)
+ SetEvent(p_cond->hEventWaitersDone);
+
+ NdbMutex_Lock(p_mutex);
+ return result;
+}
+
+
+int
+NdbCondition_WaitTimeout(struct NdbCondition* p_cond,
+ NdbMutex* p_mutex,
+ int msecs)
+{
+ int result;
+ int bLastWaiter;
+ if (!p_cond || !p_mutex)
+ return 1;
+
+ NdbMutex_Lock(p_cond->pNdbMutexWaitersLock);
+ p_cond->nWaiters++;
+ NdbMutex_Unlock(p_cond->pNdbMutexWaitersLock);
+ if(msecs<0)
+ msecs = 0;
+
+ if(NdbMutex_Unlock(p_mutex))
+ return -1;
+ result = WaitForSingleObject(p_cond->hSemaphore, msecs);
+
+ NdbMutex_Lock(p_cond->pNdbMutexWaitersLock);
+ p_cond->nWaiters--;
+ bLastWaiter = (p_cond->bWasBroadcast && p_cond->nWaiters==0);
+ NdbMutex_Unlock(p_cond->pNdbMutexWaitersLock);
+
+ if(result!=WAIT_OBJECT_0)
+ result = -1;
+
+ if(bLastWaiter)
+ SetEvent(p_cond->hEventWaitersDone);
+
+ NdbMutex_Lock(p_mutex);
+ return result;
+}
+
+
+int
+NdbCondition_Signal(struct NdbCondition* p_cond)
+{
+ int bHaveWaiters;
+ if(!p_cond)
+ return 1;
+
+ NdbMutex_Lock(p_cond->pNdbMutexWaitersLock);
+ bHaveWaiters = (p_cond->nWaiters > 0);
+ NdbMutex_Unlock(p_cond->pNdbMutexWaitersLock);
+
+ if(bHaveWaiters)
+ return (ReleaseSemaphore(p_cond->hSemaphore, 1, 0) ? 0 : -1);
+ else
+ return 0;
+}
+
+
+int NdbCondition_Broadcast(struct NdbCondition* p_cond)
+{
+ int bHaveWaiters;
+ int result = 0;
+ if(!p_cond)
+ return 1;
+
+ NdbMutex_Lock(p_cond->pNdbMutexWaitersLock);
+ bHaveWaiters = 0;
+ if(p_cond->nWaiters > 0)
+ {
+ p_cond->bWasBroadcast = !0;
+ bHaveWaiters = 1;
+ }
+ NdbMutex_Unlock(p_cond->pNdbMutexWaitersLock);
+ if(bHaveWaiters)
+ {
+ if(!ReleaseSemaphore(p_cond->hSemaphore, p_cond->nWaiters, 0))
+ result = -1;
+ else if(WaitForSingleObject (p_cond->hEventWaitersDone, INFINITE) != WAIT_OBJECT_0)
+ result = -1;
+ p_cond->bWasBroadcast = 0;
+ }
+ return result;
+}
+
+
+int NdbCondition_Destroy(struct NdbCondition* p_cond)
+{
+ int result;
+ if(!p_cond)
+ return 1;
+
+ CloseHandle(p_cond->hEventWaitersDone);
+ NdbMutex_Destroy(p_cond->pNdbMutexWaitersLock);
+ result = (CloseHandle(p_cond->hSemaphore) ? 0 : -1);
+
+ free(p_cond);
+ return 0;
+}
+
diff --git a/ndb/src/common/portlib/win32/NdbDaemon.c b/ndb/src/common/portlib/win32/NdbDaemon.c
new file mode 100644
index 00000000000..b96d4c20260
--- /dev/null
+++ b/ndb/src/common/portlib/win32/NdbDaemon.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbDaemon.h"
+
+#define NdbDaemon_ErrorSize 500
+long NdbDaemon_DaemonPid;
+int NdbDaemon_ErrorCode;
+char NdbDaemon_ErrorText[NdbDaemon_ErrorSize];
+
+int
+NdbDaemon_Make(const char* lockfile, const char* logfile, unsigned flags)
+{
+ // XXX do something
+ return 0;
+}
+
+#ifdef NDB_DAEMON_TEST
+
+int
+main()
+{
+ if (NdbDaemon_Make("test.pid", "test.log", 0) == -1) {
+ fprintf(stderr, "NdbDaemon_Make: %s\n", NdbDaemon_ErrorText);
+ return 1;
+ }
+ sleep(10);
+ return 0;
+}
+
+#endif
diff --git a/ndb/src/common/portlib/win32/NdbEnv.c b/ndb/src/common/portlib/win32/NdbEnv.c
new file mode 100644
index 00000000000..0df703a5e97
--- /dev/null
+++ b/ndb/src/common/portlib/win32/NdbEnv.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbEnv.h"
+#include <string.h>
+#include <stdlib.h>
+
+const char* NdbEnv_GetEnv(const char* name, char * buf, int buflen)
+{
+ char* p = NULL;
+ p = getenv(name);
+
+ if (p != NULL && buf != NULL){
+ strncpy(buf, p, buflen);
+ buf[buflen-1] = 0;
+ }
+ return p;
+}
+
diff --git a/ndb/src/common/portlib/win32/NdbHost.c b/ndb/src/common/portlib/win32/NdbHost.c
new file mode 100644
index 00000000000..f91dd1a531c
--- /dev/null
+++ b/ndb/src/common/portlib/win32/NdbHost.c
@@ -0,0 +1,53 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbHost.h"
+#include <windows.h>
+#include <process.h>
+
+
+int NdbHost_GetHostName(char* buf)
+{
+ /* We must initialize TCP/IP if we want to call gethostname */
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+
+ wVersionRequested = MAKEWORD( 2, 0 );
+ err = WSAStartup( wVersionRequested, &wsaData );
+ if ( err != 0 ) {
+ /**
+ * Tell the user that we couldn't find a usable
+ * WinSock DLL.
+ */
+ return -1;
+ }
+
+ /* Get host name */
+ if(gethostname(buf, MAXHOSTNAMELEN))
+ {
+ return -1;
+ }
+ return 0;
+}
+
+
+int NdbHost_GetProcessId(void)
+{
+ return _getpid();
+}
+
diff --git a/ndb/src/common/portlib/win32/NdbMem.c b/ndb/src/common/portlib/win32/NdbMem.c
new file mode 100644
index 00000000000..274dc31353f
--- /dev/null
+++ b/ndb/src/common/portlib/win32/NdbMem.c
@@ -0,0 +1,237 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 <windows.h>
+#include <assert.h>
+#include <NdbStdio.h>
+
+#include "NdbMem.h"
+
+
+struct AWEINFO
+{
+ SIZE_T dwSizeInBytesRequested;
+ ULONG_PTR nNumberOfPagesRequested;
+ ULONG_PTR nNumberOfPagesActual;
+ ULONG_PTR nNumberOfPagesFreed;
+ ULONG_PTR* pnPhysicalMemoryPageArray;
+ void* pRegionReserved;
+};
+
+const size_t cNdbMem_nMaxAWEinfo = 256;
+size_t gNdbMem_nAWEinfo = 0;
+
+struct AWEINFO* gNdbMem_pAWEinfo = 0;
+
+
+void ShowLastError(const char* szContext, const char* szFunction)
+{
+ DWORD dwError = GetLastError();
+ LPVOID lpMsgBuf;
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ dwError,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR)&lpMsgBuf,
+ 0,
+ NULL
+ );
+ printf("%s : %s failed : %lu : %s\n", szContext, szFunction, dwError, (char*)lpMsgBuf);
+ LocalFree(lpMsgBuf);
+}
+
+
+
+void NdbMem_Create()
+{
+ // Address Windowing Extensions
+ struct PRIVINFO
+ {
+ DWORD Count;
+ LUID_AND_ATTRIBUTES Privilege[1];
+ } Info;
+
+ HANDLE hProcess = GetCurrentProcess();
+ HANDLE hToken;
+ if(!OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken))
+ {
+ ShowLastError("NdbMem_Create", "OpenProcessToken");
+ }
+
+ Info.Count = 1;
+ Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
+ if(!LookupPrivilegeValue(0, SE_LOCK_MEMORY_NAME, &(Info.Privilege[0].Luid)))
+ {
+ ShowLastError("NdbMem_Create", "LookupPrivilegeValue");
+ }
+
+ if(!AdjustTokenPrivileges(hToken, FALSE, (PTOKEN_PRIVILEGES)&Info, 0, 0, 0))
+ {
+ ShowLastError("NdbMem_Create", "AdjustTokenPrivileges");
+ }
+
+ if(!CloseHandle(hToken))
+ {
+ ShowLastError("NdbMem_Create", "CloseHandle");
+ }
+
+ return;
+}
+
+void NdbMem_Destroy()
+{
+ /* Do nothing */
+ return;
+}
+
+void* NdbMem_Allocate(size_t size)
+{
+ // Address Windowing Extensions
+ struct AWEINFO* pAWEinfo;
+ HANDLE hProcess;
+ SYSTEM_INFO sysinfo;
+
+ if(!gNdbMem_pAWEinfo)
+ {
+ gNdbMem_pAWEinfo = VirtualAlloc(0,
+ sizeof(struct AWEINFO)*cNdbMem_nMaxAWEinfo,
+ MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
+ }
+
+ assert(gNdbMem_nAWEinfo < cNdbMem_nMaxAWEinfo);
+ pAWEinfo = gNdbMem_pAWEinfo+gNdbMem_nAWEinfo++;
+
+ hProcess = GetCurrentProcess();
+ GetSystemInfo(&sysinfo);
+ pAWEinfo->nNumberOfPagesRequested = (size+sysinfo.dwPageSize-1)/sysinfo.dwPageSize;
+ pAWEinfo->pnPhysicalMemoryPageArray = VirtualAlloc(0,
+ sizeof(ULONG_PTR)*pAWEinfo->nNumberOfPagesRequested,
+ MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
+ pAWEinfo->nNumberOfPagesActual = pAWEinfo->nNumberOfPagesRequested;
+ if(!AllocateUserPhysicalPages(hProcess, &(pAWEinfo->nNumberOfPagesActual), pAWEinfo->pnPhysicalMemoryPageArray))
+ {
+ ShowLastError("NdbMem_Allocate", "AllocateUserPhysicalPages");
+ return 0;
+ }
+ if(pAWEinfo->nNumberOfPagesRequested != pAWEinfo->nNumberOfPagesActual)
+ {
+ ShowLastError("NdbMem_Allocate", "nNumberOfPagesRequested != nNumberOfPagesActual");
+ return 0;
+ }
+
+ pAWEinfo->dwSizeInBytesRequested = size;
+ pAWEinfo->pRegionReserved = VirtualAlloc(0, pAWEinfo->dwSizeInBytesRequested, MEM_RESERVE | MEM_PHYSICAL, PAGE_READWRITE);
+ if(!pAWEinfo->pRegionReserved)
+ {
+ ShowLastError("NdbMem_Allocate", "VirtualAlloc");
+ return 0;
+ }
+
+ if(!MapUserPhysicalPages(pAWEinfo->pRegionReserved, pAWEinfo->nNumberOfPagesActual, pAWEinfo->pnPhysicalMemoryPageArray))
+ {
+ ShowLastError("NdbMem_Allocate", "MapUserPhysicalPages");
+ return 0;
+ }
+
+ /*
+ printf("allocate AWE memory: %lu bytes, %lu pages, address %lx\n",
+ pAWEinfo->dwSizeInBytesRequested,
+ pAWEinfo->nNumberOfPagesActual,
+ pAWEinfo->pRegionReserved);
+ */
+ return pAWEinfo->pRegionReserved;
+}
+
+
+void* NdbMem_AllocateAlign(size_t size, size_t alignment)
+{
+ /*
+ return (void*)memalign(alignment, size);
+ TEMP fix
+ */
+ return NdbMem_Allocate(size);
+}
+
+
+void NdbMem_Free(void* ptr)
+{
+ // VirtualFree(ptr, 0, MEM_DECOMMIT|MEM_RELEASE);
+
+ // Address Windowing Extensions
+ struct AWEINFO* pAWEinfo = 0;
+ size_t i;
+ HANDLE hProcess;
+
+ for(i=0; i<gNdbMem_nAWEinfo; ++i)
+ {
+ if(ptr==gNdbMem_pAWEinfo[i].pRegionReserved)
+ {
+ pAWEinfo = gNdbMem_pAWEinfo+i;
+ }
+ }
+ if(!pAWEinfo)
+ {
+ ShowLastError("NdbMem_Free", "ptr is not AWE memory");
+ }
+
+ hProcess = GetCurrentProcess();
+ if(!MapUserPhysicalPages(ptr, pAWEinfo->nNumberOfPagesActual, 0))
+ {
+ ShowLastError("NdbMem_Free", "MapUserPhysicalPages");
+ }
+
+ if(!VirtualFree(ptr, 0, MEM_RELEASE))
+ {
+ ShowLastError("NdbMem_Free", "VirtualFree");
+ }
+
+ pAWEinfo->nNumberOfPagesFreed = pAWEinfo->nNumberOfPagesActual;
+ if(!FreeUserPhysicalPages(hProcess, &(pAWEinfo->nNumberOfPagesFreed), pAWEinfo->pnPhysicalMemoryPageArray))
+ {
+ ShowLastError("NdbMem_Free", "FreeUserPhysicalPages");
+ }
+
+ VirtualFree(pAWEinfo->pnPhysicalMemoryPageArray, 0, MEM_DECOMMIT|MEM_RELEASE);
+}
+
+
+int NdbMem_MemLockAll()
+{
+ /*
+ HANDLE hProcess = GetCurrentProcess();
+ SIZE_T nMinimumWorkingSetSize;
+ SIZE_T nMaximumWorkingSetSize;
+ GetProcessWorkingSetSize(hProcess, &nMinimumWorkingSetSize, &nMaximumWorkingSetSize);
+ ndbout << "nMinimumWorkingSetSize=" << nMinimumWorkingSetSize << ", nMaximumWorkingSetSize=" << nMaximumWorkingSetSize << endl;
+
+ SetProcessWorkingSetSize(hProcess, 50000000, 100000000);
+
+ GetProcessWorkingSetSize(hProcess, &nMinimumWorkingSetSize, &nMaximumWorkingSetSize);
+ ndbout << "nMinimumWorkingSetSize=" << nMinimumWorkingSetSize << ", nMaximumWorkingSetSize=" << nMaximumWorkingSetSize << endl;
+ */
+ return -1;
+}
+
+int NdbMem_MemUnlockAll()
+{
+ //VirtualUnlock();
+ return -1;
+}
+
diff --git a/ndb/src/common/portlib/win32/NdbMutex.c b/ndb/src/common/portlib/win32/NdbMutex.c
new file mode 100644
index 00000000000..c93384d91db
--- /dev/null
+++ b/ndb/src/common/portlib/win32/NdbMutex.c
@@ -0,0 +1,78 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 <winsock2.h>
+#include <ws2tcpip.h>
+#include <windows.h>
+#include <time.h>
+#include <assert.h>
+
+#include "NdbMutex.h"
+
+
+NdbMutex* NdbMutex_Create(void)
+{
+ NdbMutex* pNdbMutex = (NdbMutex*)malloc(sizeof(NdbMutex));
+ if(!pNdbMutex)
+ return 0;
+
+ InitializeCriticalSection(pNdbMutex);
+ return pNdbMutex;
+}
+
+
+int NdbMutex_Destroy(NdbMutex* p_mutex)
+{
+ if(!p_mutex)
+ return -1;
+
+ DeleteCriticalSection(p_mutex);
+ free(p_mutex);
+ return 0;
+}
+
+
+int NdbMutex_Lock(NdbMutex* p_mutex)
+{
+ if(!p_mutex)
+ return -1;
+
+ EnterCriticalSection (p_mutex);
+ return 0;
+}
+
+
+int NdbMutex_Unlock(NdbMutex* p_mutex)
+{
+ if(!p_mutex)
+ return -1;
+
+ LeaveCriticalSection(p_mutex);
+ return 0;
+}
+
+
+int NdbMutex_Trylock(NdbMutex* p_mutex)
+{
+ int result = -1;
+ if(p_mutex)
+ {
+ result = (TryEnterCriticalSection(p_mutex) ? 0 : -1);
+ }
+ return result;
+}
+
diff --git a/ndb/src/common/portlib/win32/NdbSleep.c b/ndb/src/common/portlib/win32/NdbSleep.c
new file mode 100644
index 00000000000..ac0f44dd07f
--- /dev/null
+++ b/ndb/src/common/portlib/win32/NdbSleep.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbSleep.h"
+
+#include <windows.h>
+
+
+int
+NdbSleep_MilliSleep(int milliseconds)
+{
+ Sleep(milliseconds);
+ return 0;
+}
+
+int
+NdbSleep_SecSleep(int seconds)
+{
+ return NdbSleep_MilliSleep(seconds*1000);
+}
+
diff --git a/ndb/src/common/portlib/win32/NdbTCP.c b/ndb/src/common/portlib/win32/NdbTCP.c
new file mode 100644
index 00000000000..483a53bd606
--- /dev/null
+++ b/ndb/src/common/portlib/win32/NdbTCP.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 "NdbTCP.h"
+
+int
+Ndb_getInAddr(struct in_addr * dst, const char *address)
+{
+ struct hostent * hostPtr;
+
+ /* Try it as aaa.bbb.ccc.ddd. */
+ dst->s_addr = inet_addr(address);
+ if (dst->s_addr != -1) {
+ return 0;
+ }
+
+ hostPtr = gethostbyname(address);
+ if (hostPtr != NULL) {
+ dst->s_addr = ((struct in_addr *) *hostPtr->h_addr_list)->s_addr;
+ return 0;
+ }
+
+ return -1;
+}
+
diff --git a/ndb/src/common/portlib/win32/NdbThread.c b/ndb/src/common/portlib/win32/NdbThread.c
new file mode 100644
index 00000000000..ae3c74be70d
--- /dev/null
+++ b/ndb/src/common/portlib/win32/NdbThread.c
@@ -0,0 +1,118 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 <windows.h>
+#include <process.h>
+#include <assert.h>
+
+#include "NdbThread.h"
+
+
+#define MAX_THREAD_NAME 16
+
+typedef unsigned (WINAPI* NDB_WIN32_THREAD_FUNC)(void*);
+
+
+struct NdbThread
+{
+ HANDLE hThread;
+ unsigned nThreadId;
+ char thread_name[MAX_THREAD_NAME];
+};
+
+
+struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC *p_thread_func,
+ NDB_THREAD_ARG *p_thread_arg,
+ const NDB_THREAD_STACKSIZE thread_stack_size,
+ const char* p_thread_name,
+ NDB_THREAD_PRIO thread_prio)
+{
+ struct NdbThread* tmpThread;
+ unsigned initflag;
+ int nPriority = 0;
+
+ if(!p_thread_func)
+ return 0;
+
+ tmpThread = (struct NdbThread*)malloc(sizeof(struct NdbThread));
+ if(!tmpThread)
+ return 0;
+
+ strncpy((char*)&tmpThread->thread_name, p_thread_name, MAX_THREAD_NAME);
+
+ switch(thread_prio)
+ {
+ case NDB_THREAD_PRIO_HIGHEST: nPriority=THREAD_PRIORITY_HIGHEST; break;
+ case NDB_THREAD_PRIO_HIGH: nPriority=THREAD_PRIORITY_ABOVE_NORMAL; break;
+ case NDB_THREAD_PRIO_MEAN: nPriority=THREAD_PRIORITY_NORMAL; break;
+ case NDB_THREAD_PRIO_LOW: nPriority=THREAD_PRIORITY_BELOW_NORMAL; break;
+ case NDB_THREAD_PRIO_LOWEST: nPriority=THREAD_PRIORITY_LOWEST; break;
+ }
+ initflag = (nPriority ? CREATE_SUSPENDED : 0);
+
+ tmpThread->hThread = (HANDLE)_beginthreadex(0, thread_stack_size,
+ (NDB_WIN32_THREAD_FUNC)p_thread_func, p_thread_arg,
+ initflag, &tmpThread->nThreadId);
+
+ if(nPriority && tmpThread->hThread)
+ {
+ SetThreadPriority(tmpThread->hThread, nPriority);
+ ResumeThread (tmpThread->hThread);
+ }
+
+ assert(tmpThread->hThread);
+ return tmpThread;
+}
+
+
+void NdbThread_Destroy(struct NdbThread** p_thread)
+{
+ CloseHandle((*p_thread)->hThread);
+ (*p_thread)->hThread = 0;
+ free(*p_thread);
+ *p_thread = 0;
+}
+
+
+int NdbThread_WaitFor(struct NdbThread* p_wait_thread, void** status)
+{
+ void *local_status = 0;
+ if (status == 0)
+ status = &local_status;
+
+ if(WaitForSingleObject(p_wait_thread->hThread, INFINITE) == WAIT_OBJECT_0
+ && GetExitCodeThread(p_wait_thread->hThread, (LPDWORD)status))
+ {
+ CloseHandle(p_wait_thread->hThread);
+ p_wait_thread->hThread = 0;
+ return 0;
+ }
+ return -1;
+}
+
+
+void NdbThread_Exit(int status)
+{
+ _endthreadex((DWORD) status);
+}
+
+
+int NdbThread_SetConcurrencyLevel(int level)
+{
+ return 0;
+}
+
diff --git a/ndb/src/common/portlib/win32/NdbTick.c b/ndb/src/common/portlib/win32/NdbTick.c
new file mode 100644
index 00000000000..e3a67d8437d
--- /dev/null
+++ b/ndb/src/common/portlib/win32/NdbTick.c
@@ -0,0 +1,64 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 <windows.h>
+#include "NdbTick.h"
+
+/*
+#define FILETIME_PER_MICROSEC 10
+#define FILETIME_PER_MILLISEC 10000
+#define FILETIME_PER_SEC 10000000
+
+
+NDB_TICKS NdbTick_CurrentMillisecond(void)
+{
+ ULONGLONG ullTime;
+ GetSystemTimeAsFileTime((LPFILETIME)&ullTime);
+ return (ullTime / FILETIME_PER_MILLISEC);
+}
+
+int
+NdbTick_CurrentMicrosecond(NDB_TICKS * secs, Uint32 * micros)
+{
+ ULONGLONG ullTime;
+ GetSystemTimeAsFileTime((LPFILETIME)&ullTime);
+ *secs = (ullTime / FILETIME_PER_SEC);
+ *micros = (Uint32)((ullTime % FILETIME_PER_SEC) / FILETIME_PER_MICROSEC);
+ return 0;
+}
+*/
+
+
+NDB_TICKS NdbTick_CurrentMillisecond(void)
+{
+ LARGE_INTEGER liCount, liFreq;
+ QueryPerformanceCounter(&liCount);
+ QueryPerformanceFrequency(&liFreq);
+ return (liCount.QuadPart*1000) / liFreq.QuadPart;
+}
+
+int
+NdbTick_CurrentMicrosecond(NDB_TICKS * secs, Uint32 * micros)
+{
+ LARGE_INTEGER liCount, liFreq;
+ QueryPerformanceCounter(&liCount);
+ QueryPerformanceFrequency(&liFreq);
+ *secs = liCount.QuadPart / liFreq.QuadPart;
+ liCount.QuadPart -= *secs * liFreq.QuadPart;
+ *micros = (liCount.QuadPart*1000000) / liFreq.QuadPart;
+ return 0;
+}