Created
August 20, 2013 20:31
-
-
Save autumnjolitz/6286877 to your computer and use it in GitHub Desktop.
A patch to make Aerospike 2.1.11 client for Python and Perl compile and be usable on MacOSX Lion. Wrote the missing kqueue handling code.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff -Naur citrusleaf_client_swig_2.1.11/include/citrusleaf/cf_byte_order.h citrusleaf_client_swig_2.1.11-macosx/include/citrusleaf/cf_byte_order.h | |
--- citrusleaf_client_swig_2.1.11/include/citrusleaf/cf_byte_order.h 2013-03-27 10:12:05.000000000 -0700 | |
+++ citrusleaf_client_swig_2.1.11-macosx/include/citrusleaf/cf_byte_order.h 2013-07-11 17:17:40.000000000 -0700 | |
@@ -12,8 +12,7 @@ | |
#include <libkern/OSByteOrder.h> | |
-#define cf_byteswap64p(_p) (OSSwapBigToHostInt64(*(_p))) | |
- | |
+#define cf_byteswap64p(_p) (OSSwapBigToHostInt64( *(uint64_t *) _p )) | |
#else | |
//==================================================================== | |
diff -Naur citrusleaf_client_swig_2.1.11/include/citrusleaf/cf_clock.h citrusleaf_client_swig_2.1.11-macosx/include/citrusleaf/cf_clock.h | |
--- citrusleaf_client_swig_2.1.11/include/citrusleaf/cf_clock.h 2013-03-27 10:12:05.000000000 -0700 | |
+++ citrusleaf_client_swig_2.1.11-macosx/include/citrusleaf/cf_clock.h 2013-07-11 17:16:48.000000000 -0700 | |
@@ -16,10 +16,16 @@ | |
//==================================================================== | |
// Linux | |
// | |
- | |
#include <time.h> | |
+#ifndef OSX | |
#include <bits/time.h> | |
+#endif | |
+#ifdef OSX | |
+#define CLOCK_PROCESS_CPUTIME_ID 2 | |
+#define CLOCK_REALTIME 0 | |
+#define CLOCK_MONOTONIC 1 | |
+#endif | |
#else // CF_WINDOWS | |
//==================================================================== | |
diff -Naur citrusleaf_client_swig_2.1.11/src/Makefile.in citrusleaf_client_swig_2.1.11-macosx/src/Makefile.in | |
--- citrusleaf_client_swig_2.1.11/src/Makefile.in 2013-03-27 10:12:05.000000000 -0700 | |
+++ citrusleaf_client_swig_2.1.11-macosx/src/Makefile.in 2013-07-11 17:08:32.000000000 -0700 | |
@@ -36,6 +36,7 @@ | |
LDFLAGS = -shared -Wl,-soname=$(SONAME) | |
# Linux auto-sets to 64, MacOS doesn't | |
ifeq ($(SYSTEM),Darwin) | |
+ LDFLAGS = -shared -lc -Wl,-install_name,$(SONAME) -Wl,-rpath,/usr/lib -L/usr/lib -Wl,-rpath,/usr/local/lib -L/usr/local/lib -lssl -lcrypto -lz -lpthread -framework IOKit | |
CFLAGS_64 += -m64 -v -D OSX | |
CFLAGS_NATIVE += -v -D OSX | |
endif | |
diff -Naur citrusleaf_client_swig_2.1.11/src/cf_socket.c citrusleaf_client_swig_2.1.11-macosx/src/cf_socket.c | |
--- citrusleaf_client_swig_2.1.11/src/cf_socket.c 2013-03-27 10:12:05.000000000 -0700 | |
+++ citrusleaf_client_swig_2.1.11-macosx/src/cf_socket.c 2013-07-11 17:08:32.000000000 -0700 | |
@@ -32,7 +32,13 @@ | |
#include <arpa/inet.h> | |
#include <netinet/in.h> | |
#include <netinet/tcp.h> | |
+#ifdef OSX | |
+ #include <sys/types.h> | |
+ #include <sys/event.h> | |
+ #include <sys/time.h> | |
+#else | |
#include <sys/epoll.h> | |
+#endif | |
#include <sys/socket.h> | |
@@ -94,7 +100,11 @@ | |
} | |
int f = 1; | |
+ #ifdef OSX | |
+ setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &f, sizeof(f)); | |
+ #else | |
setsockopt(fd, SOL_TCP, TCP_NODELAY, &f, sizeof(f)); | |
+ #endif | |
return fd; | |
} | |
@@ -149,30 +159,119 @@ | |
int rv = 0, epoll_fd = -1, busy = 0, try = 0; | |
size_t pos = 0; | |
uint64_t start = cf_getms(); | |
- | |
+ #ifdef OSX | |
+ if (0 > (epoll_fd = kqueue())) { | |
+ rv = errno; | |
+ cf_warn("%s: kqueue() failed (errno %d: \"%s\") ~~ Failing!", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
+ goto Fail; | |
+ } | |
+ #else | |
if (0 > (epoll_fd = epoll_create(1))) { | |
rv = errno; | |
cf_warn("%s: epoll_create() failed (errno %d: \"%s\") ~~ Failing!", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
goto Fail; | |
} | |
+ #endif | |
+ | |
+ | |
+ #ifdef OSX | |
+ struct kevent event; | |
+ memset(&event, 0, sizeof(struct kevent)); //pad the address of event with 0's. | |
+ event.ident = fd; | |
+ event.filter = EVFILT_READ; | |
+ event.flags = EV_ADD | EV_ENABLE; | |
+ | |
+ int num_events; | |
+ | |
+ | |
+ struct timespec wait_ms = { 0, /* block for 5 seconds at most */ | |
+ 1000000 }; /* 1 ms in nanoseconds */ | |
+ | |
+ do { | |
+ try++; | |
+ uint64_t now = cf_getms(); | |
+ if (now > deadline) { | |
+ #ifdef DEBUG_TIME | |
+ debug_time_printf("socket read timeout 1", try, busy, start, now, deadline); | |
+ #endif | |
+ rv = ETIMEDOUT; | |
+ goto Fail; | |
+ } | |
+ num_events = kevent(epoll_fd, &event, 1, &event, 1, &wait_ms); | |
+ | |
+ | |
+ if (num_events == -1) { | |
+ if ((rv = errno) == EINTR) { | |
+ cf_debug("%s: kevent() on socket encountered EINTR ~~ Retrying!", ctx); | |
+ busy++; | |
+ continue; | |
+ } else { | |
+ cf_warn("%s: kqueue() on socket failed (errno %d: \"%s\") ~~ Failing!", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
+ } | |
+ goto Fail; | |
+ } else if (num_events == 0) { | |
+ cf_debug("%s: kevent() on socket encountered an error!! ~~ Retrying!", ctx) | |
+ continue; | |
+ } else if (num_events > 0) { | |
+ if (num_events > 1) { | |
+ cf_warn("%s: kevent() returned %d events ~~ only 1 expected, so ignoring others!", ctx, num_events); | |
+ } | |
+ if (event.flags & EV_ERROR) { /* report any error */ | |
+ if ((rv = event.data) == EINTR) { | |
+ cf_debug("%s: kevent() on socket encountered EINTR ~~ Retrying!", ctx); | |
+ continue; | |
+ } else { | |
+ cf_debug("EV_ERROR: %s\n", strerror(event.data)); | |
+ goto Fail; | |
+ } | |
+ } | |
+ if (event.flags & EV_EOF) { | |
+ //remote socket has closed. | |
+ rv = EBADF; | |
+ goto Fail; | |
+ } | |
+ | |
+ int r_bytes = read(fd, buf + pos, buf_len - pos); | |
+ | |
+ if (r_bytes > 0) { | |
+ pos += r_bytes; | |
+ if (pos >= buf_len) { | |
+ goto Success; | |
+ } | |
+ } else if (r_bytes == 0) { | |
+ // It's likely the socket has been closed on the remote side. | |
+ rv = EBADF; | |
+ goto Fail; | |
+ } else if ((errno != ETIMEDOUT) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS) && (errno != EAGAIN)) { | |
+ #ifdef DEBUG_TIME | |
+ debug_time_printf("socket read timeout 2", try, busy, start, now, deadline); | |
+ #endif | |
+ rv = errno; | |
+ goto Fail; | |
+ } | |
+ | |
+ } | |
+ } while (pos < buf_len); | |
+ | |
+ #else | |
+ struct epoll_event event; | |
+ memset(&event, 0, sizeof(struct epoll_event)); | |
+ event.data.fd = fd; | |
+ event.events = EPOLLIN; | |
+ if (0 > epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &event)) { | |
+ rv = errno; | |
+ cf_warn("%s: epoll_ctl(ADD) of socket failed (errno %d: \"%s\") ~~ Failing!", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
+ goto Fail; | |
+ } | |
- struct epoll_event event; | |
- memset(&event, 0, sizeof(struct epoll_event)); | |
- event.data.fd = fd; | |
- event.events = EPOLLIN; | |
- if (0 > epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &event)) { | |
- rv = errno; | |
- cf_warn("%s: epoll_ctl(ADD) of socket failed (errno %d: \"%s\") ~~ Failing!", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
- goto Fail; | |
- } | |
do { | |
uint64_t now = cf_getms(); | |
if (now > deadline) { | |
-#ifdef DEBUG_TIME | |
- debug_time_printf("socket read timeout 1", try, busy, start, now, deadline); | |
-#endif | |
+ #ifdef DEBUG_TIME | |
+ debug_time_printf("socket read timeout 1", try, busy, start, now, deadline); | |
+ #endif | |
rv = ETIMEDOUT; | |
goto Fail; | |
} | |
@@ -244,11 +343,19 @@ | |
try++; | |
} while (pos < buf_len); | |
+ #endif | |
Success: | |
- if (0 > epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &event)) { | |
- cf_warn("%s: epoll_ctl(DEL) on socket failed (errno %d: \"%s\")", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
- } | |
+ #ifdef OSX | |
+ event.flags = EV_DISABLE; | |
+ if (0 > kevent(epoll_fd, &event, 1, NULL, 0, NULL)) { | |
+ cf_warn("%s: kqueue(DEL) on socket failed (errno %d: \"%s\")", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
+ } | |
+ #else | |
+ if (0 > epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &event)) { | |
+ cf_warn("%s: epoll_ctl(DEL) on socket failed (errno %d: \"%s\")", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
+ } | |
+ #endif | |
close(epoll_fd); | |
rv = 0; | |
@@ -258,9 +365,16 @@ | |
cf_debug("%s: socket read timeout fail: %d (%s)", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
if (epoll_fd > 0) { | |
+ #ifdef OSX | |
+ event.flags = EV_DISABLE; | |
+ if (0 > kevent(epoll_fd, &event, 1, NULL, 0, NULL)) { | |
+ cf_warn("%s: kqueue(DEL) on socket failed (errno %d: \"%s\")", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
+ } | |
+ #else | |
if (0 > epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &event)) { | |
cf_warn("%s: epoll_ctl(DEL) on socket failed (errno %d: \"%s\")", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
} | |
+ #endif | |
close(epoll_fd); | |
} | |
@@ -300,106 +414,197 @@ | |
int rv = 0, epoll_fd = -1, busy = 0, try = 0; | |
size_t pos = 0; | |
uint64_t start = cf_getms(); | |
- | |
- if (0 > (epoll_fd = epoll_create(1))) { | |
- rv = errno; | |
- cf_warn("%s: epoll_create() failed (errno %d: \"%s\") ~~ Failing!", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
- goto Fail; | |
- } | |
- | |
- struct epoll_event event; | |
- memset(&event, 0, sizeof(struct epoll_event)); | |
- event.data.fd = fd; | |
- event.events = EPOLLOUT; | |
- | |
- if (0 > epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &event)) { | |
- rv = errno; | |
- cf_warn("%s: epoll_ctl(ADD) of socket failed (errno %d: \"%s\") ~~ Failing!", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
- goto Fail; | |
- } | |
- | |
- do { | |
- uint64_t now = cf_getms(); | |
- if (now > deadline) { | |
-#ifdef DEBUG_TIME | |
- debug_time_printf("socket write timeout 1", try, busy, start, now, deadline); | |
-#endif | |
- rv = ETIMEDOUT; | |
+ #ifdef OSX | |
+ if (0 > (epoll_fd = kqueue())) { | |
+ rv = errno; | |
+ cf_warn("%s: kqueue() failed (errno %d: \"%s\") ~~ Failing!", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
+ goto Fail; | |
+ } | |
+ #else | |
+ if (0 > (epoll_fd = epoll_create(1))) { | |
+ rv = errno; | |
+ cf_warn("%s: epoll_create() failed (errno %d: \"%s\") ~~ Failing!", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
goto Fail; | |
} | |
+ #endif | |
- uint64_t ms_left = deadline - now; | |
+ #ifdef OSX | |
+ struct kevent event; | |
+ memset(&event, 0, sizeof(struct kevent)); //pad the address of event with 0's. | |
+ event.ident = fd; | |
+ event.filter = EVFILT_WRITE; | |
+ event.flags = EV_ADD | EV_ENABLE; | |
+ | |
+ int num_events; | |
+ | |
+ struct timespec wait_ms = { 0, /* block for 5 seconds at most */ | |
+ 1000000 }; /* 1 ms in nanoseconds */ | |
+ | |
+ do { | |
+ uint64_t now = cf_getms(); | |
+ if (now > deadline) { | |
+ #ifdef DEBUG_TIME | |
+ debug_time_printf("socket write timeout 1", try, busy, start, now, deadline); | |
+ #endif | |
+ rv = ETIMEDOUT; | |
+ goto Fail; | |
+ } | |
+ uint64_t ms_left = deadline - now; | |
- int nevents = 0; | |
- int max_events = 1; | |
- int wait_ms = 1; | |
- struct epoll_event events[max_events]; | |
+ num_events = kevent(epoll_fd, &event, 1, &event, 1, &wait_ms); | |
- if (0 > (nevents = epoll_wait(epoll_fd, events, max_events, wait_ms))) { | |
- if ((rv = errno) == EINTR) { | |
- cf_debug("%s: epoll_wait() on socket encountered EINTR ~~ Retrying!", ctx); | |
- busy++; | |
- goto Retry; | |
- } else { | |
- cf_warn("%s: epoll_wait() on socket failed (errno %d: \"%s\") ~~ Failing!", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
- } | |
- goto Fail; | |
- } else { | |
- if (nevents == 0) { | |
- cf_debug("%s: epoll_wait() returned no events ~~ Retrying!", ctx); | |
- busy++; | |
- goto Retry; | |
- } | |
- if (nevents != 1) { | |
- cf_warn("%s: epoll_wait() returned %d events ~~ only 1 expected, so ignoring others!", ctx, nevents); | |
- } | |
- if (events[0].data.fd == fd) { | |
- if (events[0].events & EPOLLOUT) { | |
- cf_debug("%s: epoll_wait() on socket ready for write detected ~~ Succeeding!", ctx); | |
+ if (num_events == -1) { | |
+ if ((rv = errno) == EINTR) { | |
+ cf_debug("%s: kevent()write on socket encountered EINTR ~~ Retrying!", ctx); | |
+ continue; | |
} else { | |
- // (Note: ERR and HUP events are automatically waited for as well.) | |
- if (events[0].events & (EPOLLERR | EPOLLHUP)) { | |
- cf_debug("%s: epoll_wait() on socket detected failure event 0x%x ~~ Failing!", ctx, events[0].events); | |
+ cf_warn("%s: kqueue()write on socket failed (errno %d: \"%s\") ~~ Failing!", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
+ } | |
+ goto Fail; | |
+ } else if (num_events == 0) { | |
+ cf_debug("%s: kevent()write on socket encountered an error!! ~~ Retrying!", ctx) | |
+ continue; | |
+ } else if (num_events > 0) { | |
+ if (num_events > 1) { | |
+ cf_warn("%s: kevent()write returned %d events ~~ only 1 expected, so ignoring others!", ctx, num_events); | |
+ } | |
+ if (event.flags & EV_ERROR) { /* report any error */ | |
+ if ((rv = event.data) == EINTR) { | |
+ cf_debug("%s: kevent()write on socket encountered EINTR ~~ Retrying!", ctx); | |
+ continue; | |
} else { | |
- cf_warn("%s: epoll_wait() on socket detected non-write events 0x%x ~~ Failing!", ctx, events[0].events); | |
+ cf_debug("write EV_ERROR: %s\n", strerror(event.data)); | |
+ goto Fail; | |
+ } | |
+ } | |
+ if (event.flags & EV_EOF) { | |
+ //remote socket has closed. | |
+ rv = EBADF; | |
+ goto Fail; | |
+ } | |
+ | |
+ int r_bytes = write(fd, buf + pos, buf_len - pos); | |
+ | |
+ if (r_bytes > 0) { | |
+ pos += r_bytes; | |
+ if (pos >= buf_len) { | |
+ goto Success; | |
} | |
+ } else if (r_bytes == 0) { | |
+ // It's likely the socket has been closed on the remote side. | |
rv = EBADF; | |
goto Fail; | |
+ } else if ((errno != ETIMEDOUT) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS) && (errno != EAGAIN)) { | |
+ #ifdef DEBUG_TIME | |
+ debug_time_printf("socket write timeout 2", try, busy, start, now, deadline); | |
+ #endif | |
+ rv = errno; | |
+ goto Fail; | |
} | |
- } else { | |
- cf_warn("%s: epoll_wait() on socket returned event on unknown socket %d ~~ Retrying!", ctx, events[0].data.fd); | |
- goto Retry; | |
} | |
+ } while (pos < buf_len); | |
+ #else | |
+ struct epoll_event event; | |
+ memset(&event, 0, sizeof(struct epoll_event)); | |
+ event.data.fd = fd; | |
+ event.events = EPOLLOUT; | |
+ | |
+ if (0 > epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &event)) { | |
+ rv = errno; | |
+ cf_warn("%s: epoll_ctl(ADD) of socket failed (errno %d: \"%s\") ~~ Failing!", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
+ goto Fail; | |
+ } | |
- int r_bytes = write(fd, buf + pos, buf_len - pos); | |
+ do { | |
+ uint64_t now = cf_getms(); | |
+ if (now > deadline) { | |
+ #ifdef DEBUG_TIME | |
+ debug_time_printf("socket write timeout 1", try, busy, start, now, deadline); | |
+ #endif | |
+ rv = ETIMEDOUT; | |
+ goto Fail; | |
+ } | |
- if (r_bytes > 0) { | |
- pos += r_bytes; | |
- if (pos >= buf_len) { | |
- goto Success; | |
+ uint64_t ms_left = deadline - now; | |
+ | |
+ int nevents = 0; | |
+ int max_events = 1; | |
+ int wait_ms = 1; | |
+ struct epoll_event events[max_events]; | |
+ | |
+ if (0 > (nevents = epoll_wait(epoll_fd, events, max_events, wait_ms))) { | |
+ if ((rv = errno) == EINTR) { | |
+ cf_debug("%s: epoll_wait() on socket encountered EINTR ~~ Retrying!", ctx); | |
+ busy++; | |
+ goto Retry; | |
+ } else { | |
+ cf_warn("%s: epoll_wait() on socket failed (errno %d: \"%s\") ~~ Failing!", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
} | |
- } else if (r_bytes == 0) { | |
- // It's likely the socket has been closed on the remote side. | |
- rv = EBADF; | |
- goto Fail; | |
- } else if ((errno != ETIMEDOUT) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS) && (errno != EAGAIN)) { | |
-#ifdef DEBUG_TIME | |
- debug_time_printf("socket write timeout 2", try, busy, start, now, deadline); | |
-#endif | |
- rv = errno; | |
goto Fail; | |
+ } else { | |
+ if (nevents == 0) { | |
+ cf_debug("%s: epoll_wait() returned no events ~~ Retrying!", ctx); | |
+ busy++; | |
+ goto Retry; | |
+ } | |
+ if (nevents != 1) { | |
+ cf_warn("%s: epoll_wait() returned %d events ~~ only 1 expected, so ignoring others!", ctx, nevents); | |
+ } | |
+ if (events[0].data.fd == fd) { | |
+ if (events[0].events & EPOLLOUT) { | |
+ cf_debug("%s: epoll_wait() on socket ready for write detected ~~ Succeeding!", ctx); | |
+ } else { | |
+ // (Note: ERR and HUP events are automatically waited for as well.) | |
+ if (events[0].events & (EPOLLERR | EPOLLHUP)) { | |
+ cf_debug("%s: epoll_wait() on socket detected failure event 0x%x ~~ Failing!", ctx, events[0].events); | |
+ } else { | |
+ cf_warn("%s: epoll_wait() on socket detected non-write events 0x%x ~~ Failing!", ctx, events[0].events); | |
+ } | |
+ rv = EBADF; | |
+ goto Fail; | |
+ } | |
+ } else { | |
+ cf_warn("%s: epoll_wait() on socket returned event on unknown socket %d ~~ Retrying!", ctx, events[0].data.fd); | |
+ goto Retry; | |
+ } | |
+ | |
+ int r_bytes = write(fd, buf + pos, buf_len - pos); | |
+ | |
+ if (r_bytes > 0) { | |
+ pos += r_bytes; | |
+ if (pos >= buf_len) { | |
+ goto Success; | |
+ } | |
+ } else if (r_bytes == 0) { | |
+ // It's likely the socket has been closed on the remote side. | |
+ rv = EBADF; | |
+ goto Fail; | |
+ } else if ((errno != ETIMEDOUT) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS) && (errno != EAGAIN)) { | |
+ #ifdef DEBUG_TIME | |
+ debug_time_printf("socket write timeout 2", try, busy, start, now, deadline); | |
+ #endif | |
+ rv = errno; | |
+ goto Fail; | |
+ } | |
} | |
- } | |
-Retry: | |
- try++; | |
+ Retry: | |
+ try++; | |
- } while (pos < buf_len); | |
+ } while (pos < buf_len); | |
+ #endif | |
Success: | |
- if (0 > epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &event)) { | |
- cf_warn("%s: epoll_ctl(DEL) on socket failed (errno %d: \"%s\")", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
- } | |
+ #ifdef OSX | |
+ event.flags = EV_DISABLE; | |
+ if (0 > kevent(epoll_fd, &event, 1, NULL, 0, NULL)) { | |
+ cf_warn("%s: kqueue(DEL) on socket failed (errno %d: \"%s\")", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
+ } | |
+ #else | |
+ if (0 > epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &event)) { | |
+ cf_warn("%s: epoll_ctl(DEL) on socket failed (errno %d: \"%s\")", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
+ } | |
+ #endif | |
close(epoll_fd); | |
rv = 0; | |
@@ -409,9 +614,16 @@ | |
cf_debug("%s: socket write timeout fail: %d (%s)", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
if (epoll_fd > 0) { | |
- if (0 > epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &event)) { | |
- cf_warn("%s: epoll_ctl(DEL) on socket failed (errno %d: \"%s\")", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
- } | |
+ #ifdef OSX | |
+ event.flags = EV_DISABLE; | |
+ if (0 > kevent(epoll_fd, &event, 1, NULL, 0, NULL)) { | |
+ cf_warn("%s: kqueue(DEL) on socket failed (errno %d: \"%s\")", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
+ } | |
+ #else | |
+ if (0 > epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &event)) { | |
+ cf_warn("%s: epoll_ctl(DEL) on socket failed (errno %d: \"%s\")", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len)); | |
+ } | |
+ #endif | |
close(epoll_fd); | |
} | |
diff -Naur citrusleaf_client_swig_2.1.11/src/citrusleaf.c citrusleaf_client_swig_2.1.11-macosx/src/citrusleaf.c | |
--- citrusleaf_client_swig_2.1.11/src/citrusleaf.c 2013-03-27 10:12:05.000000000 -0700 | |
+++ citrusleaf_client_swig_2.1.11-macosx/src/citrusleaf.c 2013-07-11 17:15:25.000000000 -0700 | |
@@ -26,10 +26,14 @@ | |
#ifdef OSX | |
#include <libkern/OSByteOrder.h> // for the 64-bit swap macro. | |
+#define __swab64(x) (unsigned long long) OSSwapInt64((uint64_t)x) | |
+#define __be64_to_cpu(x) (unsigned long long) OSSwapBigToHostInt64((uint64_t)x) | |
+#define __cpu_to_be64(x) (unsigned long long) OSSwapHostToBigInt64((uint64_t)x) | |
#else //Linux | |
#include <asm/byteorder.h> // 64-bit swap macro | |
#endif | |
+ | |
#include "citrusleaf/citrusleaf.h" | |
#include "citrusleaf/cl_cluster.h" | |
#include "citrusleaf/cl_shm.h" | |
diff -Naur citrusleaf_client_swig_2.1.11/src/cl_cluster.c citrusleaf_client_swig_2.1.11-macosx/src/cl_cluster.c | |
--- citrusleaf_client_swig_2.1.11/src/cl_cluster.c 2013-03-27 10:12:05.000000000 -0700 | |
+++ citrusleaf_client_swig_2.1.11-macosx/src/cl_cluster.c 2013-07-11 17:08:32.000000000 -0700 | |
@@ -892,7 +892,11 @@ | |
} | |
int f = 1; | |
+ #ifdef OSX | |
+ setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &f, sizeof(f)); | |
+ #else | |
setsockopt(fd, SOL_TCP, TCP_NODELAY, &f, sizeof(f)); | |
+ #endif | |
// loop over all known IP addresses for the server | |
for (uint i=0;i< cf_vector_size(&cn->sockaddr_in_v);i++) { | |
diff -Naur citrusleaf_client_swig_2.1.11/src/cl_shm.c citrusleaf_client_swig_2.1.11-macosx/src/cl_shm.c | |
--- citrusleaf_client_swig_2.1.11/src/cl_shm.c 2013-03-27 10:12:05.000000000 -0700 | |
+++ citrusleaf_client_swig_2.1.11-macosx/src/cl_shm.c 2013-07-11 17:08:32.000000000 -0700 | |
@@ -172,7 +172,9 @@ | |
pthread_mutexattr_t attr; | |
pthread_mutexattr_init (&attr); | |
pthread_mutexattr_setpshared (&attr, PTHREAD_PROCESS_SHARED); | |
+ #ifndef OSX | |
pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST_NP); | |
+ #endif | |
if(pthread_mutex_init (&(g_shm_pt->shm_lock), &attr)!=0) { | |
cf_error("Mutex init failed pid %d",getpid()); | |
pthread_mutexattr_destroy(&attr); | |
@@ -195,18 +197,22 @@ | |
if (status) { | |
/* Check if the lock is in recoverable state */ | |
+ #ifndef OSX | |
if (status == EOWNERDEAD){ | |
/* Make the lock consistent if the last owner of the lock died while holding the lock */ | |
/* We should ideally clean the memory here and then make the lock consistent */ | |
pthread_mutex_consistent_np(&shared_node->ninfo_lock); | |
} | |
else { | |
+ #endif | |
/* With Robust mutexes the lock gets in not recoverable state when the process holding the lock | |
* dies and the other process that gets the lock unlocks it without making it consistent | |
* (via pthread_mutex_consistent function) */ | |
cf_warn("Failed to lock shared memory node."); | |
return SHM_ERROR; | |
+ #ifndef OSX | |
} | |
+ #endif | |
} | |
return SHM_OK; | |
} | |
@@ -287,7 +293,9 @@ | |
pthread_mutexattr_t attr; | |
pthread_mutexattr_init(&attr); | |
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); | |
+ #ifndef OSX | |
pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST_NP); | |
+ #endif | |
if (pthread_mutex_init(&shared_node->ninfo_lock, &attr) != 0) { | |
cf_warn("Shared memory node level mutex init failed pid %d", getpid()); | |
@@ -484,16 +492,20 @@ | |
if (status != 0) { | |
/* Make the lock consistent if the last owner of the lock died while holding the lock */ | |
/* We should ideally clean the memory here and then make the lock consistent */ | |
+ #ifndef OSX | |
if (status == EOWNERDEAD) { | |
pthread_mutex_consistent_np(&(g_shm_pt->shm_lock)); | |
} | |
else { | |
+ #endif | |
/* With Robust mutexes the lock gets in not recoverable state when the process holding the lock | |
* dies and the other process that gets the lock unlocks it without making it consistent | |
* (via pthread_mutex_consistent function) */ | |
cf_error("Failed to lock shared memory in tend thread. Exiting thread."); | |
pthread_exit(0); | |
+ #ifndef OSX | |
} | |
+ #endif | |
} | |
cf_debug("Process %d took over control with pthread_mutex_lock returning %d", getpid(), status); | |
diff -Naur citrusleaf_client_swig_2.1.11/swig/Makefile citrusleaf_client_swig_2.1.11-macosx/swig/Makefile | |
--- citrusleaf_client_swig_2.1.11/swig/Makefile 2013-03-27 10:12:05.000000000 -0700 | |
+++ citrusleaf_client_swig_2.1.11-macosx/swig/Makefile 2013-07-11 17:22:37.000000000 -0700 | |
@@ -6,6 +6,7 @@ | |
AS_CFLAGS = -D_FILE_OFFSET_BITS=64 -std=gnu99 -D_REENTRANT | |
MARCH_NATIVE = $(shell uname -m) | |
+SYSTEM = $(shell uname -s) | |
CFLAGS_NATIVE = -g -O3 -fPIC -fno-common -fno-strict-aliasing -rdynamic -Wextra -Wno-missing-field-initializers $(AS_CFLAGS) -D MARCH_$(MARCH_NATIVE) -march=nocona | |
# Linux auto-sets to 64, MacOS doesn't | |
ifeq ($(SYSTEM),Darwin) | |
@@ -18,6 +19,10 @@ | |
TARGET_S = _citrusleaf.so | |
SOURCE = citrusleaf.i | |
+ifeq ($(SYSTEM),Darwin) | |
+ LDFLAGS += -lc -Wl,-rpath,/usr/lib -L/usr/lib -Wl,-rpath,/usr/local/lib -L/usr/local/lib -lpython -lssl -lcrypto -lc | |
+endif | |
+ | |
# Include path of each target language | |
#DIR_INCLUDE_PYTHON = /usr/include/python2.6/ | |
#DIR_INCLUDE_PERL = /usr/lib/perl/5.14/CORE/ | |
@@ -53,11 +58,15 @@ | |
TARGET_S = citrusleaf.so | |
endif | |
+LD=ld | |
+ifeq ($(SYSTEM), Darwin) | |
+ LD = $(CC) | |
+endif | |
all: $(TARGET_S) putobj | |
$(TARGET_S): citrusleaf_wrap.o $(C_LIB) | |
- ld $(LDFLAGS) citrusleaf_wrap.o -lrt -lz -lssl $(C_LIB) -o $(LANG)/$(TARGET_S) | |
+ $(LD) $(LDFLAGS) citrusleaf_wrap.o -lz -lssl $(C_LIB) -o $(LANG)/$(TARGET_S) | |
citrusleaf_wrap.o: citrusleaf_wrap.c $(DIR_INCLUDE_C) | |
$(CC) $(CFLAGS_NATIVE) -c -I$(DIR_INCLUDE_C) -I$(DIR_INCLUDE_TARGET) $(OPTS_CC_TARGET) $< |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment