From d9fee38cc28348da5e4f842359625d0630a1d69b Mon Sep 17 00:00:00 2001
From: Roman Tsisyk <roman@tsisyk.com>
Date: Tue, 13 May 2014 17:10:52 +0400
Subject: [PATCH] Add support for native uuid library on FreeBSD

---
 cmake/FindLibUUID.cmake   | 36 ++++++++-------
 src/CMakeLists.txt        |  2 +-
 src/replica.cc            | 15 ++++---
 src/replication.cc        | 18 ++++----
 src/trivia/config.h.cmake |  3 ++
 src/tt_uuid.c             |  4 +-
 src/tt_uuid.h             | 94 +++++++++++++++++++++++++++++++++++----
 test/unit/CMakeLists.txt  |  2 +-
 8 files changed, 130 insertions(+), 44 deletions(-)

diff --git a/cmake/FindLibUUID.cmake b/cmake/FindLibUUID.cmake
index d6c4163e96..0db8ae7e5e 100644
--- a/cmake/FindLibUUID.cmake
+++ b/cmake/FindLibUUID.cmake
@@ -3,25 +3,29 @@ if(NOT LIBUUID_FOUND)
         NAMES uuid.h
         PATH_SUFFIXES uuid
     )
-    find_library(LIBUUID_LIBRARIES
-        NAMES uuid
-    )
-
-    if (LIBUUID_INCLUDE_DIR AND LIBUUID_LIBRARIES)
-        set(LIBUUID_FOUND ON)
-    endif(LIBUUID_INCLUDE_DIR AND LIBUUID_LIBRARIES)
-
-    if(LIBUUID_FOUND)
+    if (LIBUUID_INCLUDE_DIR)
         if (NOT LIBUUID_FIND_QUIETLY)
             message(STATUS "Found libuuid includes: ${LIBUUID_INCLUDE_DIR}")
-            message(STATUS "Found libuuid library: ${LIBUUID_LIBRARIES}")
-        endif (NOT LIBUUID_FIND_QUIETLY)
+        endif ()
         set(LIBUUID_INCLUDE_DIRS ${LIBUUID_INCLUDE_DIR})
-    else(LIBUUID_FOUND)
-        if (LIBUUID_FIND_REQUIRED)
-            message(FATAL_ERROR "Could not find libuuid development files")
-        endif (LIBUUID_FIND_REQUIRED)
-    endif(LIBUUID_FOUND)
+        check_library_exists(uuid uuid_is_null "" HAVE_LIBUUID_LINUX)
+        if (HAVE_LIBUUID_LINUX)
+            if (NOT LIBUUID_FIND_QUIETLY)
+                message(STATUS "Found libuuid library: ${LIBUUID_LIBRARIES}")
+            endif ()
+            set(LIBUUID_FOUND ON)
+            set(LIBUUID_LIBRARIES uuid)
+        else()
+            check_library_exists(c uuid_is_nil "" HAVE_LIBUUID_BSD)
+            if (HAVE_LIBUUID_BSD)
+                set(LIBUUID_FOUND ON)
+            elseif (LIBUUID_FIND_REQUIRED)
+                message(FATAL_ERROR "Could not find uuid libraries")
+            endif()
+    endif()
+    elseif(LIBUUID_FIND_REQUIRED)
+         message(FATAL_ERROR "Could not find uuid development files")
+    endif()
 endif (NOT LIBUUID_FOUND)
 
 mark_as_advanced(LIBUUID_LIBRARIES LIBUUID_INCLUDE_DIRS)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index cc437eb7cd..543ac6eddb 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -139,7 +139,7 @@ if (ENABLE_BACKTRACE AND HAVE_BFD)
     endif()
 endif()
 
-set (common_libraries ${common_libraries} uuid)
+set (common_libraries ${common_libraries} ${LIBUUID_LIBRARIES})
 set (common_libraries ${common_libraries} PARENT_SCOPE)
 
 add_subdirectory(lib)
diff --git a/src/replica.cc b/src/replica.cc
index 7ae0355eec..cdd3bb12f9 100644
--- a/src/replica.cc
+++ b/src/replica.cc
@@ -154,8 +154,9 @@ replica_bootstrap(struct recovery_state *r, const char *replication_source)
 	char *data = buf;
 	data = mp_encode_map(data, 1);
 	data = mp_encode_uint(data, IPROTO_NODE_UUID);
-	data = mp_encode_str(data, (const char *) &recovery_state->node_uuid,
-			     sizeof(tt_uuid));
+	data = mp_encode_strl(data, UUID_LEN);
+	tt_uuid_enc_be(&recovery_state->node_uuid, data);
+	data += UUID_LEN;
 
 	assert(data <= buf + sizeof(buf));
 	packet.body[0].iov_base = buf;
@@ -212,11 +213,13 @@ remote_connect(struct recovery_state *r, struct ev_io *coio,const char **err)
 	char *data = buf;
 	data = mp_encode_map(data, 3);
 	data = mp_encode_uint(data, IPROTO_CLUSTER_UUID);
-	data = mp_encode_str(data, (const char *) &r->cluster_uuid,
-			     sizeof(tt_uuid));
+	data = mp_encode_strl(data, UUID_LEN);
+	tt_uuid_enc_be(&r->cluster_uuid, data);
+	data += UUID_LEN;
 	data = mp_encode_uint(data, IPROTO_NODE_UUID);
-	data = mp_encode_str(data, (const char *) &r->node_uuid,
-			     sizeof(tt_uuid));
+	data = mp_encode_strl(data, UUID_LEN);
+	tt_uuid_enc_be(&recovery_state->node_uuid, data);
+	data += UUID_LEN;
 	data = mp_encode_uint(data, IPROTO_LSNMAP);
 	data = mp_encode_map(data, cluster_size);
 	uint32_t k;
diff --git a/src/replication.cc b/src/replication.cc
index 5f72b453a4..ce303d6707 100644
--- a/src/replication.cc
+++ b/src/replication.cc
@@ -239,12 +239,12 @@ replication_join(int fd, struct iproto_packet *packet)
 		uint8_t key = mp_decode_uint(&d);
 		if (key == IPROTO_NODE_UUID) {
 			if (mp_typeof(*d) != MP_STR ||
-			    mp_decode_strl(&d) != sizeof(tt_uuid)) {
+			    mp_decode_strl(&d) != UUID_LEN) {
 				tnt_raise(ClientError, ER_INVALID_MSGPACK,
 					  "invalid Node-UUID");
 			}
-			tt_uuid_set(&node_uuid, d);
-			d += sizeof(node_uuid);
+			tt_uuid_dec_be(d, &node_uuid);
+			d += UUID_LEN;
 		} else {
 			mp_next(&d); /* value */
 		}
@@ -302,21 +302,21 @@ replication_subscribe(int fd, struct iproto_packet *packet)
 		switch (key) {
 		case IPROTO_CLUSTER_UUID:
 			if (mp_typeof(*d) != MP_STR ||
-			    mp_decode_strl(&d) != sizeof(cluster_uuid)) {
+			    mp_decode_strl(&d) != UUID_LEN) {
 				tnt_raise(ClientError, ER_INVALID_MSGPACK,
 					  "invalid Cluster-UUID");
 			}
-			tt_uuid_set(&cluster_uuid, d);
-			d += sizeof(cluster_uuid);
+			tt_uuid_dec_be(d, &cluster_uuid);
+			d += UUID_LEN;
 			break;
 		case IPROTO_NODE_UUID:
 			if (mp_typeof(*d) != MP_STR ||
-			    mp_decode_strl(&d) != sizeof(node_uuid)) {
+			    mp_decode_strl(&d) != UUID_LEN) {
 				tnt_raise(ClientError, ER_INVALID_MSGPACK,
 					  "invalid Node-UUID");
 			}
-			tt_uuid_set(&node_uuid, d);
-			d += sizeof(node_uuid);
+			tt_uuid_dec_be(d, &node_uuid);
+			d += UUID_LEN;
 			break;
 		case IPROTO_LSNMAP:
 			if (mp_typeof(*d) != MP_MAP) {
diff --git a/src/trivia/config.h.cmake b/src/trivia/config.h.cmake
index d2d675cb72..9f19173ce8 100644
--- a/src/trivia/config.h.cmake
+++ b/src/trivia/config.h.cmake
@@ -133,6 +133,9 @@
 #cmakedefine HAVE_OPEN_MEMSTREAM 1
 #cmakedefine HAVE_FMEMOPEN 1
 
+#cmakedefine HAVE_LIBUUID_LINUX 1
+#cmakedefine HAVE_LIBUUID_BSD 1
+
 /*
  * predefined /etc directory prefix.
  */
diff --git a/src/tt_uuid.c b/src/tt_uuid.c
index 502809c672..6127f5258a 100644
--- a/src/tt_uuid.c
+++ b/src/tt_uuid.c
@@ -28,10 +28,10 @@
  */
 #include "tt_uuid.h"
 /* Zeroed by the linker. */
-tt_uuid uuid_nil;
+const tt_uuid uuid_nil;
 
 char *
-tt_uuid_str(const struct tt_uuid *uu)
+tt_uuid_str(const tt_uuid *uu)
 {
 	static __thread char buf[UUID_STR_LEN + 1];
 	tt_uuid_to_string(uu, buf);
diff --git a/src/tt_uuid.h b/src/tt_uuid.h
index 2e934ebf25..3f584008ce 100644
--- a/src/tt_uuid.h
+++ b/src/tt_uuid.h
@@ -28,22 +28,26 @@
  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#include <uuid/uuid.h>
+#include <trivia/config.h>
 #include <string.h>
 #include <stdbool.h>
+#include <stdlib.h>
+#include <assert.h>
 
 #if defined(__cplusplus)
 extern "C" {
 #endif
 
-enum { UUID_STR_LEN = 36 };
+enum { UUID_LEN = 16, UUID_STR_LEN = 36 };
+
+#if defined(HAVE_LIBUUID_LINUX)
+
+#include <uuid/uuid.h>
 
 typedef struct tt_uuid {
 	uuid_t id;
 } tt_uuid;
 
-extern tt_uuid uuid_nil;
-
 static inline void
 tt_uuid_create(tt_uuid *uu)
 {
@@ -63,13 +67,22 @@ tt_uuid_to_string(const tt_uuid *uu, char *out)
 }
 
 static inline void
-tt_uuid_set(tt_uuid *uu, const void *data)
+tt_uuid_dec_be(const void *in, tt_uuid *uu)
 {
-	memcpy(uu->id, data, sizeof(uu->id));
+	memcpy(uu->id, in, sizeof(uu->id));
 }
 
-char *
-tt_uuid_str(const struct tt_uuid *uu);
+static inline void
+tt_uuid_enc_be(const tt_uuid *uu, void *out)
+{
+	memcpy(out, uu->id, sizeof(uu->id));
+}
+
+static inline bool
+tt_uuid_is_nil(const tt_uuid *uu)
+{
+	return uuid_is_null(uu->id);
+}
 
 static inline bool
 tt_uuid_cmp(const tt_uuid *lhs, const tt_uuid *rhs)
@@ -77,12 +90,75 @@ tt_uuid_cmp(const tt_uuid *lhs, const tt_uuid *rhs)
 	return uuid_compare(lhs->id, rhs->id);
 }
 
+#elif defined(HAVE_LIBUUID_BSD)
+
+#include <uuid.h>
+
+typedef struct uuid tt_uuid;
+
+static inline int
+tt_uuid_create(tt_uuid *uu)
+{
+	uint32_t status;
+	uuid_create(uu, &status);
+	return status == uuid_s_ok;
+}
+
+static inline int
+tt_uuid_from_string(const char *in, tt_uuid *uu)
+{
+	uint32_t status;
+	uuid_from_string(in, uu, &status);
+	return status == uuid_s_ok;
+}
+
+static inline void
+tt_uuid_to_string(const tt_uuid *uu, char *out)
+{
+	uint32_t status;
+	char *buf = NULL;
+	uuid_to_string(uu, &buf, &status);
+	assert(status == uuid_s_ok);
+	strncpy(out, buf, UUID_STR_LEN);
+	out[UUID_STR_LEN] = '\0';
+	free(buf);
+}
+
+static inline bool
+tt_uuid_cmp(const tt_uuid *lhs, const tt_uuid *rhs)
+{
+	uint32_t status;
+	return uuid_compare(lhs, rhs, &status);
+}
+
 static inline bool
 tt_uuid_is_nil(const tt_uuid *uu)
 {
-	return uuid_is_null(uu->id);
+	uint32_t status;
+	return uuid_is_nil(uu, &status);
 }
 
+static inline void
+tt_uuid_dec_be(const void *in, tt_uuid *uu)
+{
+	uuid_dec_be(in, uu);
+
+}
+
+static inline void
+tt_uuid_enc_be(const tt_uuid *uu, void *out)
+{
+	uuid_enc_be(out, uu);
+}
+#else
+#error Unsupported libuuid
+#endif /* HAVE_LIBUUID_XXX */
+
+extern const tt_uuid uuid_nil;
+
+char *
+tt_uuid_str(const tt_uuid *uu);
+
 #if defined(__cplusplus)
 } /* extern "C" */
 #endif
diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt
index 41ac98c10e..e0ba1a678e 100644
--- a/test/unit/CMakeLists.txt
+++ b/test/unit/CMakeLists.txt
@@ -38,7 +38,7 @@ target_link_libraries(arena_mt.test small pthread)
 add_executable(pt_alloc.test pt_alloc.cc)
 target_link_libraries(pt_alloc.test small)
 add_executable(log_dir.test log_dir.cc test.c)
-target_link_libraries(log_dir.test  uuid core small salad misc bitset msgpuck
+target_link_libraries(log_dir.test ${LIBUUID_LIBRARIES} core small salad misc bitset msgpuck
     ${LIBEV_LIBRARIES}
     ${LIBEIO_LIBRARIES}
     ${LIBCORO_LIBRARIES})
-- 
GitLab