[Sheepdog] [PATCH] Autotoolize sheepdog
Steven Dake
sdake at redhat.com
Mon May 17 17:47:24 CEST 2010
This patch contains the initial work to autotoolize sheepdog. To generate the
configure script, run the autogen.sh script. Then run ./configure followed by
make. make install also works properly.
Then run configure as normal. The configure.ac supports several options
including --enable-profiling and --enable-debug as well as the standard GNU
automake setup.
The warnings list is a pretty standard list of warning catches, but does
generate alot of warning output.
One thing that is missing is using the git version field rather then
PACKAGE_VERSION generated from configure.ac.
Finally, if you want to generate an output tarball, run make dist.
make distcheck verifies the make system included all the proper files to
support a self-build.
Signed-off-by: Steven Dake <sdake at redhat.com>
---
Makefile | 40 ----
Makefile.am | 23 ++
autogen.sh | 5 +
collie/Makefile | 30 ---
collie/Makefile.am | 42 ++++
configure.ac | 326 ++++++++++++++++++++++++++
include/Makefile.am | 3 +
lib/Makefile | 3 -
lib/Makefile.am | 3 +
script/Makefile.am | 3 +
sheep/Makefile | 30 ---
sheep/Makefile.am | 42 ++++
sheep/net.c | 643 ---------------------------------------------------
sheep/sdnet.c | 643 +++++++++++++++++++++++++++++++++++++++++++++++++++
sheep/sheep.c | 7 +-
sheep/store.c | 3 +
16 files changed, 1098 insertions(+), 748 deletions(-)
delete mode 100644 Makefile
create mode 100644 Makefile.am
create mode 100755 autogen.sh
delete mode 100644 collie/Makefile
create mode 100644 collie/Makefile.am
create mode 100644 configure.ac
create mode 100644 include/Makefile.am
delete mode 100644 lib/Makefile
create mode 100644 lib/Makefile.am
create mode 100644 script/Makefile.am
delete mode 100644 sheep/Makefile
create mode 100644 sheep/Makefile.am
delete mode 100644 sheep/net.c
create mode 100644 sheep/sdnet.c
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 6f4f0c3..0000000
--- a/Makefile
+++ /dev/null
@@ -1,40 +0,0 @@
-VERSION ?= $(shell git log -1 --pretty=format:%h-%p || echo "unknown-version")
-
-PREFIX ?= /usr
-
-CHECK_CC = cgcc
-CHECK_CC_FLAGS = '$(CHECK_CC) -Wbitwise -Wno-return-void -no-compile $(ARCH)'
-
-export VERSION PREFIX
-
-.PHONY:all
-all:
- $(MAKE) -C sheep
- $(MAKE) -C collie
-
-.PHONY:clean
-clean:
- $(MAKE) -C sheep clean
- $(MAKE) -C collie clean
- $(MAKE) -C lib clean
-
-.PHONY:install
-install:
- $(MAKE) -C sheep install
- $(MAKE) -C collie install
-
-.PHONY:check
-check: ARCH=$(shell sh script/checkarch.sh)
-check:
- CC=$(CHECK_CC_FLAGS) $(MAKE) all
-
-.PHONY:check32
-check32: override ARCH=-m32
-check32:
- CC=$(CHECK_CC_FLAGS) $(MAKE) all
-
-.PHONY:check64
-check64: override ARCH=-m64
-check64:
- CC=$(CHECK_CC_FLAGS) $(MAKE) all
-
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..fedd5ab
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,23 @@
+EXTRA_DIST =
+
+AUTOMAKE_OPTIONS = foreign
+
+MAINTAINERCLEANFILES = Makefile.in aclocal.m4 configure depcomp \
+ config.guess config.sub missing install-sh \
+ autoheader automake autoconf config.status \
+ config.log
+
+dist_doc_DATA =
+
+sheepdogsysconfdir = ${SHEEPDOGCONFDIR}
+
+sheepdogsysconf_DATA =
+
+SUBDIRS = collie sheep include script lib
+
+install-exec-local:
+
+uninstall-local:
+
+dist-clean-local:
+ rm -f autoconf automake autoheader
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..83770a1
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+echo Building configuration system...
+autoreconf -i && echo Now run ./configure and make
diff --git a/collie/Makefile b/collie/Makefile
deleted file mode 100644
index 98ef2b1..0000000
--- a/collie/Makefile
+++ /dev/null
@@ -1,30 +0,0 @@
-sbindir ?= $(PREFIX)/sbin
-
-CFLAGS += -g -O2 -Wall -Wstrict-prototypes -I../include
-CFLAGS += -D_GNU_SOURCE
-LIBS += -lncurses
-
-PROGRAMS = collie
-COLLIE_OBJS = collie.o treeview.o ../lib/event.o ../lib/net.o ../lib/logger.o
-COLLIE_DEP = $(COLLIE_OBJS:.o=.d)
-
-.PHONY:all
-all: $(PROGRAMS)
-
-collie: $(COLLIE_OBJS)
- $(CC) $^ -o $@ $(LIBS)
-
--include $(COLLIE_DEP)
-
-%.o: %.c
- $(CC) -c $(CFLAGS) $*.c -o $*.o
- @$(CC) -MM $(CFLAGS) -MF $*.d -MT $*.o $*.c
-
-.PHONY:clean
-clean:
- rm -f *.[od] $(PROGRAMS)
-
-.PHONY:install
-install: $(PROGRAMS)
- install -d -m 755 $(DESTDIR)$(sbindir)
- install -m 755 $(PROGRAMS) $(DESTDIR)$(sbindir)
diff --git a/collie/Makefile.am b/collie/Makefile.am
new file mode 100644
index 0000000..d90eda8
--- /dev/null
+++ b/collie/Makefile.am
@@ -0,0 +1,42 @@
+#
+# Copyright 2010 Red Hat, Inc.
+#
+# 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.
+#
+# 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; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CFLAGS =
+
+INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include $(ncurses_CFLAGS)
+
+sbin_PROGRAMS = collie
+
+collie_SOURCES = collie.c treeview.c ../lib/event.c ../lib/net.c ../lib/logger.c
+collie_LDADD = $(ncurses_LIBS)
+collie_DEPENDENCIES =
+
+
+noinst_HEADERS = treeview.h
+
+EXTRA_DIST =
+
+lint:
+ -splint $(INCLUDES) $(LINT_FLAGS) $(CFLAGS) *.c
+
+all-local:
+ @echo Built collie
+
+clean-local:
+ rm -f collie *.o gmon.out *.da *.bb *.bbg
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..309ae79
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,326 @@
+#
+# Copyright 2010 Red Hat, Inc.
+#
+# 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.
+#
+# 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; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+# bootstrap / init
+AC_PREREQ([2.61])
+
+AC_INIT([sheepdog], [0.0.1], [sheepdog at lists.wpkg.org])
+AM_INIT_AUTOMAKE([-Wno-portability])
+
+AC_CONFIG_SRCDIR([collie/collie.c])
+AC_CONFIG_HEADER([include/config.h])
+
+AC_CANONICAL_HOST
+
+AC_LANG([C])
+
+dnl Fix default variables - "prefix" variable if not specified
+if test "$prefix" = "NONE"; then
+ prefix="/usr"
+
+ dnl Fix "localstatedir" variable if not specified
+ if test "$localstatedir" = "\${prefix}/var"; then
+ localstatedir="/var"
+ fi
+ dnl Fix "sysconfdir" variable if not specified
+ if test "$sysconfdir" = "\${prefix}/etc"; then
+ sysconfdir="/etc"
+ fi
+ dnl Fix "libdir" variable if not specified
+ if test "$libdir" = "\${exec_prefix}/lib"; then
+ if test -e /usr/lib64; then
+ libdir="/usr/lib64"
+ else
+ libdir="/usr/lib"
+ fi
+ fi
+fi
+
+# check stolen from gnulib/m4/gnu-make.m4
+if ! ${MAKE-make} --version /cannot/make/this >/dev/null 2>&1; then
+ AC_MSG_ERROR([you don't seem to have GNU make; it is required])
+fi
+
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+AC_PROG_RANLIB
+AC_CHECK_PROGS([GROFF], [groff])
+
+# Checks for libraries.
+AC_CHECK_LIB([socket], [socket])
+
+# Checks for header files.
+AC_FUNC_ALLOCA
+AC_HEADER_DIRENT
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h netdb.h netinet/in.h stdint.h \
+ stdlib.h string.h sys/ioctl.h sys/param.h sys/socket.h \
+ sys/time.h syslog.h unistd.h sys/types.h getopt.h malloc.h \
+ sys/sockio.h utmpx.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_TYPE_UID_T
+AC_C_INLINE
+AC_TYPE_INT16_T
+AC_TYPE_INT32_T
+AC_TYPE_INT64_T
+AC_TYPE_INT8_T
+AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+AC_HEADER_TIME
+AC_TYPE_UINT16_T
+AC_TYPE_UINT32_T
+AC_TYPE_UINT64_T
+AC_TYPE_UINT8_T
+AC_C_VOLATILE
+
+# Checks for library functions.
+AC_FUNC_CLOSEDIR_VOID
+AC_FUNC_ERROR_AT_LINE
+AC_REPLACE_FNMATCH
+AC_FUNC_FORK
+AC_PROG_GCC_TRADITIONAL
+AC_FUNC_MALLOC
+AC_FUNC_MEMCMP
+AC_FUNC_REALLOC
+AC_FUNC_SELECT_ARGTYPES
+AC_TYPE_SIGNAL
+AC_FUNC_VPRINTF
+AC_CHECK_FUNCS([alarm alphasort atexit bzero dup2 endgrent endpwent fcntl \
+ getcwd getpeerucred getpeereid gettimeofday inet_ntoa memmove \
+ memset mkdir scandir select socket strcasecmp strchr strdup \
+ strerror strrchr strspn strstr])
+
+AC_CONFIG_FILES([Makefile
+ collie/Makefile
+ sheep/Makefile
+ include/Makefile
+ script/Makefile
+ lib/Makefile])
+
+### Local business
+
+# ===============================================
+# Helpers
+# ===============================================
+
+## helper for CC stuff
+cc_supports_flag() {
+ local CFLAGS="$@"
+ AC_MSG_CHECKING([whether $CC supports "$@"])
+ AC_COMPILE_IFELSE([int main(){return 0;}] ,
+ [RC=0; AC_MSG_RESULT([yes])],
+ [RC=1; AC_MSG_RESULT([no])])
+ return $RC
+}
+
+## cleanup
+AC_MSG_NOTICE(Sanitizing prefix: ${prefix})
+case $prefix in
+ NONE) prefix=/usr/local;;
+esac
+
+AC_MSG_NOTICE(Sanitizing exec_prefix: ${exec_prefix})
+case $exec_prefix in
+ dnl For consistency with Sheepdog, map NONE->$prefix
+ NONE) exec_prefix=$prefix;;
+ prefix) exec_prefix=$prefix;;
+esac
+
+## local defines
+PACKAGE_FEATURES=""
+
+LINT_FLAGS="-weak -unrecog +posixlib +ignoresigns -fcnuse \
+ -badflag -D__gnuc_va_list=va_list -D__attribute\(x\)="
+
+AC_ARG_ENABLE([fatal-warnings],
+ [ --enable-fatal-warnings : enable fatal warnings. ],
+ [ default="no" ])
+
+AC_ARG_ENABLE([debug],
+ [ --enable-debug : enable debug build. ],
+ [ default="no" ])
+
+AC_ARG_ENABLE([coverage],
+ [ --enable-coverage : coverage analysis of the codebase. ],
+ [ default="no" ])
+
+AC_ARG_WITH([initddir],
+ [ --with-initddir=DIR : path to init script directory. ],
+ [ INITDDIR="$withval" ],
+ [ INITDDIR="$sysconfdir/init.d" ])
+
+CP=cp
+OS_LDL="-ldl"
+case "$host_os" in
+ *linux*)
+ AC_DEFINE_UNQUOTED([SHEEPDOG_LINUX], [1],
+ [Compiling for Linux platform])
+ OS_CFLAGS=""
+ OS_CPPFLAGS=""
+ OS_LDFLAGS=""
+ OS_DYFLAGS=""
+ DARWIN_OPTS=""
+ ;;
+ *)
+ AC_MSG_ERROR([Unsupported OS? hmmmm])
+ ;;
+esac
+
+AC_SUBST(CP)
+# *FLAGS handling goes here
+
+ENV_CFLAGS="$CFLAGS"
+ENV_CPPFLAGS="$CPPFLAGS"
+ENV_LDFLAGS="$LDFLAGS"
+
+# debug build stuff
+if test "x${enable_debug}" = xyes; then
+ AC_DEFINE_UNQUOTED([DEBUG], [1], [Compiling Debugging code])
+ OPT_CFLAGS="-O0"
+ PACKAGE_FEATURES="$PACKAGE_FEATURES debug"
+fi
+
+# gdb flags
+if test "x${GCC}" = xyes; then
+ GDB_FLAGS="-ggdb3"
+else
+ GDB_FLAGS="-g"
+fi
+
+PKG_CHECK_MODULES([ncurses],[ncurses])
+PKG_CHECK_MODULES([corosync],[corosync])
+PKG_CHECK_MODULES([libcpg],[libcpg])
+PKG_CHECK_MODULES([libcfg],[libcfg])
+
+# extra warnings
+EXTRA_WARNINGS=""
+
+WARNLIST="
+ all
+ shadow
+ missing-prototypes
+ missing-declarations
+ strict-prototypes
+ declaration-after-statement
+ pointer-arith
+ write-strings
+ cast-align
+ bad-function-cast
+ missing-format-attribute
+ format=2
+ format-security
+ format-nonliteral
+ no-long-long
+ unsigned-char
+ gnu89-inline
+ no-strict-aliasing
+ "
+
+for j in $WARNLIST; do
+ if cc_supports_flag -W$j; then
+ EXTRA_WARNINGS="$EXTRA_WARNINGS -W$j";
+ fi
+done
+
+if test "x${enable_coverage}" = xyes && \
+ cc_supports_flag -ftest-coverage && \
+ cc_supports_flag -fprofile-arcs ; then
+ AC_MSG_NOTICE([Enabling Coverage (enable -O0 by default)])
+ OPT_CFLAGS="-O0"
+ COVERAGE_CFLAGS="-ftest-coverage -fprofile-arcs"
+ COVERAGE_LDFLAGS="-ftest-coverage -fprofile-arcs"
+ PACKAGE_FEATURES="$PACKAGE_FEATURES coverage"
+else
+ COVERAGE_CFLAGS=""
+ COVERAGE_LDFLAGS=""
+fi
+
+
+if test "x${enable_fatal_warnings}" = xyes && \
+ cc_supports_flag -Werror ; then
+ AC_MSG_NOTICE([Enabling Fatal Warnings (-Werror)])
+ WERROR_CFLAGS="-Werror"
+ PACKAGE_FEATURES="$PACKAGE_FEATURES fatal-warnings"
+else
+ WERROR_CFLAGS=""
+fi
+
+# final build of *FLAGS
+CFLAGS="$ENV_CFLAGS $OPT_CFLAGS $GDB_FLAGS $OS_CFLAGS \
+ $COVERAGE_CFLAGS $EXTRA_WARNINGS $WERROR_CFLAGS $NSS_CFLAGS"
+CPPFLAGS="$ENV_CPPFLAGS $ANSI_CPPFLAGS $OS_CPPFLAGS"
+LDFLAGS="$ENV_LDFLAGS $COVERAGE_LDFLAGS $OS_LDFLAGS"
+
+# substitute what we need:
+AC_SUBST([OS_DYFLAGS])
+
+AM_CONDITIONAL(BUILD_HTML_DOCS, test -n "${GROFF}")
+
+AC_SUBST([LINT_FLAGS])
+
+AC_DEFINE_UNQUOTED([LOCALSTATEDIR], "$(eval echo ${localstatedir})", [localstate directory])
+
+COROSYSCONFDIR=${sysconfdir}/sheepdog
+AC_SUBST([COROSYSCONFDIR])
+AC_DEFINE_UNQUOTED([COROSYSCONFDIR], "$(eval echo ${COROSYSCONFDIR})", [sheepdog config directory])
+
+AC_DEFINE_UNQUOTED([PACKAGE_FEATURES], "${PACKAGE_FEATURES}", [sheepdog built-in features])
+
+AC_OUTPUT
+
+AC_MSG_RESULT([])
+AC_MSG_RESULT([$PACKAGE configuration:])
+AC_MSG_RESULT([ Version = ${VERSION}])
+AC_MSG_RESULT([ Prefix = ${prefix}])
+AC_MSG_RESULT([ Executables = ${sbindir}])
+AC_MSG_RESULT([ Man pages = ${mandir}])
+AC_MSG_RESULT([ Doc dir = ${docdir}])
+AC_MSG_RESULT([ Libraries = ${libdir}])
+AC_MSG_RESULT([ Header files = ${includedir}])
+AC_MSG_RESULT([ Arch-independent files = ${datadir}])
+AC_MSG_RESULT([ State information = ${localstatedir}])
+AC_MSG_RESULT([ System configuration = ${sysconfdir}])
+AC_MSG_RESULT([ System init.d directory = ${INITDDIR}])
+AC_MSG_RESULT([ sheepdog config dir = ${COROSYSCONFDIR}])
+AC_MSG_RESULT([ Features =${PACKAGE_FEATURES}])
+AC_MSG_RESULT([])
+AC_MSG_RESULT([$PACKAGE build info:])
+AC_MSG_RESULT([ Library SONAME = ${SONAME}])
+LIB_MSG_RESULT(m4_shift(local_soname_list))dnl
+AC_MSG_RESULT([ Default optimization = ${OPT_CFLAGS}])
+AC_MSG_RESULT([ Default debug options = ${GDB_CFLAGS}])
+AC_MSG_RESULT([ Extra compiler warnings = ${EXTRA_WARNING}])
+AC_MSG_RESULT([ Env. defined CFLAG = ${ENV_CFLAGS}])
+AC_MSG_RESULT([ Env. defined CPPFLAGS = ${ENV_CPPFLAGS}])
+AC_MSG_RESULT([ Env. defined LDFLAGS = ${ENV_LDFLAGS}])
+AC_MSG_RESULT([ OS defined CFLAGS = ${OS_CFLAGS}])
+AC_MSG_RESULT([ OS defined CPPFLAGS = ${OS_CPPFLAGS}])
+AC_MSG_RESULT([ OS defined LDFLAGS = ${OS_LDFLAGS}])
+AC_MSG_RESULT([ OS defined LDL = ${OS_LDL}])
+AC_MSG_RESULT([ OS defined DYFLAGS = ${OS_DYFLAGS}])
+AC_MSG_RESULT([ ANSI defined CPPFLAGS = ${ANSI_CPPFLAGS}])
+AC_MSG_RESULT([ Coverage CFLAGS = ${COVERAGE_CFLAGS}])
+AC_MSG_RESULT([ Coverage LDFLAGS = ${COVERAGE_LDFLAGS}])
+AC_MSG_RESULT([ Fatal War. CFLAGS = ${WERROR_CFLAGS}])
+AC_MSG_RESULT([ Final CFLAGS = ${CFLAGS}])
+AC_MSG_RESULT([ Final CPPFLAGS = ${CPPFLAGS}])
+AC_MSG_RESULT([ Final LDFLAGS = ${LDFLAGS}])
diff --git a/include/Makefile.am b/include/Makefile.am
new file mode 100644
index 0000000..94c530e
--- /dev/null
+++ b/include/Makefile.am
@@ -0,0 +1,3 @@
+MAINTAINERCLEANFILES = Makefile.in config.h.in
+
+noinst_HEADERS = bitops.h event.h logger.h sheepdog_proto.h util.h list.h net.h sheep.h
diff --git a/lib/Makefile b/lib/Makefile
deleted file mode 100644
index ad4245b..0000000
--- a/lib/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-.PHONY:clean
-clean:
- rm -f *.[od]
diff --git a/lib/Makefile.am b/lib/Makefile.am
new file mode 100644
index 0000000..2375b68
--- /dev/null
+++ b/lib/Makefile.am
@@ -0,0 +1,3 @@
+MAINTAINERCLEANFILES = Makefile.in config.h.in
+
+noinst_HEADERS = event.c logger.c net.c
diff --git a/script/Makefile.am b/script/Makefile.am
new file mode 100644
index 0000000..3e6c380
--- /dev/null
+++ b/script/Makefile.am
@@ -0,0 +1,3 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+noinst_HEADERS = bash_completion_collie checkarch.sh check-dog.pl start-sheepdog stop-sheepdog vditest
diff --git a/sheep/Makefile b/sheep/Makefile
deleted file mode 100644
index 089bb7d..0000000
--- a/sheep/Makefile
+++ /dev/null
@@ -1,30 +0,0 @@
-sbindir ?= $(PREFIX)/sbin
-
-CFLAGS += -g -O2 -Wall -Wstrict-prototypes -I../include
-CFLAGS += -D_GNU_SOURCE -DSD_VERSION=\"$(VERSION)\"
-LIBS += -lpthread -lcpg -lcfg
-
-PROGRAMS = sheep
-SHEEP_OBJS = sheep.o net.o vdi.o group.o store.o work.o ../lib/event.o ../lib/net.o ../lib/logger.o
-SHEEP_DEP = $(SHEEP_OBJS:.o=.d)
-
-.PHONY:all
-all: $(PROGRAMS)
-
-sheep: $(SHEEP_OBJS)
- $(CC) $^ -o $@ $(LIBS)
-
--include $(SHEEP_DEP)
-
-%.o: %.c
- $(CC) -c $(CFLAGS) $*.c -o $*.o
- @$(CC) -MM $(CFLAGS) -MF $*.d -MT $*.o $*.c
-
-.PHONY:clean
-clean:
- rm -f *.[od] $(PROGRAMS)
-
-.PHONY:install
-install: $(PROGRAMS)
- install -d -m 755 $(DESTDIR)$(sbindir)
- install -m 755 $(PROGRAMS) $(DESTDIR)$(sbindir)
diff --git a/sheep/Makefile.am b/sheep/Makefile.am
new file mode 100644
index 0000000..4f68683
--- /dev/null
+++ b/sheep/Makefile.am
@@ -0,0 +1,42 @@
+#
+# Copyright 2010 Red Hat, Inc.
+#
+# 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.
+#
+# 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; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CFLAGS =
+
+INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include $(libcpg_CFLAGS) $(libcfg_CFLAGS)
+
+sbin_PROGRAMS = sheep
+
+sheep_SOURCES = sheep.c group.c sdnet.c store.c vdi.c work.c ../lib/event.c ../lib/logger.c ../lib/net.c
+sheep_LDADD = $(libcpg_LIBS) $(libcfg_LIBS)
+sheep_DEPENDENCIES =
+
+
+noinst_HEADERS = work.h sheep_priv.h
+
+EXTRA_DIST =
+
+lint:
+ -splint $(INCLUDES) $(LINT_FLAGS) $(CFLAGS) *.c
+
+all-local:
+ @echo Built sheep
+
+clean-local:
+ rm -f sheep *.o gmon.out *.da *.bb *.bbg
diff --git a/sheep/net.c b/sheep/net.c
deleted file mode 100644
index f1ce8ea..0000000
--- a/sheep/net.c
+++ /dev/null
@@ -1,643 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Nippon Telegraph and Telephone Corporation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <netinet/tcp.h>
-#include <sys/epoll.h>
-
-#include "sheep_priv.h"
-
-int is_io_request(unsigned op)
-{
- int ret = 0;
-
- switch (op) {
- case SD_OP_CREATE_AND_WRITE_OBJ:
- case SD_OP_REMOVE_OBJ:
- case SD_OP_READ_OBJ:
- case SD_OP_WRITE_OBJ:
- ret = 1;
- break;
- default:
- break;
- }
-
- return ret;
-}
-
-void resume_pending_requests(void)
-{
- struct request *next, *tmp;
-
- list_for_each_entry_safe(next, tmp, &sys->req_wait_for_obj_list,
- r_wlist) {
- struct cpg_event *cevent = &next->cev;
-
- list_del(&next->r_wlist);
- list_add_tail(&cevent->cpg_event_list, &sys->cpg_event_siblings);
- }
-
- if (!list_empty(&sys->cpg_event_siblings))
- start_cpg_event_work();
-}
-
-static int is_access_local(struct sheepdog_node_list_entry *e, int nr_nodes,
- uint64_t oid, int copies)
-{
- int i, n;
-
- for (i = 0; i < copies; i++) {
- n = obj_to_sheep(e, nr_nodes, oid, i);
-
- if (is_myself(&e[n]))
- return 1;
- }
-
- return 0;
-}
-
-static void setup_access_to_local_objects(struct request *req)
-{
- struct sd_obj_req *hdr = (struct sd_obj_req *)&req->rq;
- int copies;
-
- if (hdr->flags & SD_FLAG_CMD_DIRECT) {
- req->local_oid[0] = hdr->oid;
-
- if (hdr->flags & SD_FLAG_CMD_COW)
- req->local_oid[1] = hdr->cow_oid;
-
- return;
- }
-
- copies = hdr->copies;
- if (!copies)
- copies = sys->nr_sobjs;
-
- if (is_access_local(req->entry, req->nr_nodes, hdr->oid, copies))
- req->local_oid[0] = hdr->oid;
-
- if ((hdr->flags & SD_FLAG_CMD_COW) &&
- is_access_local(req->entry, req->nr_nodes, hdr->cow_oid, copies))
- req->local_oid[1] = hdr->cow_oid;
-}
-
-static void __done(struct work *work, int idx)
-{
- struct request *req = container_of(work, struct request, work);
- struct sd_req *hdr = (struct sd_req *)&req->rq;
- int again = 0;
-
- switch (hdr->opcode) {
- case SD_OP_NEW_VDI:
- case SD_OP_DEL_VDI:
- case SD_OP_LOCK_VDI:
- case SD_OP_RELEASE_VDI:
- case SD_OP_GET_VDI_INFO:
- case SD_OP_MAKE_FS:
- case SD_OP_SHUTDOWN:
- /* request is forwarded to cpg group */
- return;
- }
-
- if (is_io_request(hdr->opcode)) {
- struct cpg_event *cevent = &req->cev;
-
- list_del(&req->r_wlist);
-
- sys->nr_outstanding_io--;
- /*
- * TODO: if the request failed due to epoch unmatch,
- * we should retry here (adds this request to the tail
- * of sys->cpg_event_siblings.
- */
-
- if (!(req->rq.flags & SD_FLAG_CMD_DIRECT) &&
- (req->rp.result == SD_RES_OLD_NODE_VER ||
- req->rp.result == SD_RES_NEW_NODE_VER)) {
-
-
- req->rq.epoch = sys->epoch;
- req->nr_nodes = setup_ordered_sd_node_list(req);
- setup_access_to_local_objects(req);
-
- list_add_tail(&cevent->cpg_event_list, &sys->cpg_event_siblings);
- again = 1;
- }
-
- resume_pending_requests();
- resume_recovery_work();
- }
-
- if (!again)
- req->done(req);
-}
-
-static void queue_request(struct request *req)
-{
- struct cpg_event *cevent = &req->cev;
-
- struct sd_req *hdr = (struct sd_req *)&req->rq;
- struct sd_rsp *rsp = (struct sd_rsp *)&req->rp;
-
- if (hdr->opcode == SD_OP_KILL_NODE) {
- log_close();
- exit(1);
- }
-
- if (sys->status == SD_STATUS_SHUTDOWN) {
- rsp->result = SD_RES_SHUTDOWN;
- req->done(req);
- return;
- }
-
- if (sys->status == SD_STATUS_JOIN_FAILED) {
- rsp->result = SD_RES_JOIN_FAILED;
- req->done(req);
- return;
- }
-
- if (sys->status == SD_STATUS_WAIT_FOR_FORMAT ||
- sys->status == SD_STATUS_WAIT_FOR_JOIN) {
- /* TODO: cleanup */
- switch (hdr->opcode) {
- case SD_OP_STAT_CLUSTER:
- case SD_OP_MAKE_FS:
- case SD_OP_GET_NODE_LIST:
- case SD_OP_READ_VDIS:
- break;
- default:
- if (sys->status == SD_STATUS_WAIT_FOR_FORMAT)
- rsp->result = SD_RES_WAIT_FOR_FORMAT;
- else
- rsp->result = SD_RES_WAIT_FOR_JOIN;
- req->done(req);
- return;
- }
- }
-
- switch (hdr->opcode) {
- case SD_OP_CREATE_AND_WRITE_OBJ:
- case SD_OP_REMOVE_OBJ:
- case SD_OP_READ_OBJ:
- case SD_OP_WRITE_OBJ:
- case SD_OP_STAT_SHEEP:
- case SD_OP_GET_OBJ_LIST:
- req->work.fn = store_queue_request;
- break;
- case SD_OP_GET_NODE_LIST:
- case SD_OP_GET_VM_LIST:
- case SD_OP_NEW_VDI:
- case SD_OP_DEL_VDI:
- case SD_OP_LOCK_VDI:
- case SD_OP_RELEASE_VDI:
- case SD_OP_GET_VDI_INFO:
- case SD_OP_MAKE_FS:
- case SD_OP_SHUTDOWN:
- case SD_OP_STAT_CLUSTER:
- req->work.fn = cluster_queue_request;
- break;
- case SD_OP_READ_VDIS:
- rsp->result = read_vdis(req->data, hdr->data_length, &rsp->data_length);
- req->done(req);
- return;
- default:
- eprintf("unknown operation %d\n", hdr->opcode);
- rsp->result = SD_RES_SYSTEM_ERROR;
- req->done(req);
- return;
- }
-
- req->work.done = __done;
-
- list_del(&req->r_wlist);
-
- /*
- * we set epoch for non direct requests here. Note that we
- * can't access to sys->epoch after calling
- * start_cpg_event_work(that is, passing requests to work
- * threads).
- */
- if (!(hdr->flags & SD_FLAG_CMD_DIRECT))
- hdr->epoch = sys->epoch;
-
- req->nr_nodes = setup_ordered_sd_node_list(req);
- setup_access_to_local_objects(req);
-
- cevent->ctype = CPG_EVENT_REQUEST;
- list_add_tail(&cevent->cpg_event_list, &sys->cpg_event_siblings);
- start_cpg_event_work();
-}
-
-static struct request *alloc_request(struct client_info *ci, int data_length)
-{
- struct request *req;
-
- req = zalloc(sizeof(struct request) + data_length);
- if (!req)
- return NULL;
-
- req->ci = ci;
- if (data_length)
- req->data = (char *)req + sizeof(*req);
-
- list_add(&req->r_siblings, &ci->reqs);
- INIT_LIST_HEAD(&req->r_wlist);
-
- return req;
-}
-
-static void free_request(struct request *req)
-{
- list_del(&req->r_siblings);
- free(req);
-}
-
-static void req_done(struct request *req)
-{
- list_add(&req->r_wlist, &req->ci->done_reqs);
- conn_tx_on(&req->ci->conn);
-}
-
-static void init_rx_hdr(struct client_info *ci)
-{
- ci->conn.c_rx_state = C_IO_HEADER;
- ci->rx_req = NULL;
- ci->conn.rx_length = sizeof(struct sd_req);
- ci->conn.rx_buf = &ci->conn.rx_hdr;
-}
-
-static void client_rx_handler(struct client_info *ci)
-{
- int ret;
- uint64_t data_len;
- struct connection *conn = &ci->conn;
- struct sd_req *hdr = &conn->rx_hdr;
- struct request *req;
-
- switch (conn->c_rx_state) {
- case C_IO_HEADER:
- ret = rx(conn, C_IO_DATA_INIT);
- if (!ret || conn->c_rx_state != C_IO_DATA_INIT)
- break;
- case C_IO_DATA_INIT:
- data_len = hdr->data_length;
-
- req = alloc_request(ci, data_len);
- if (!req) {
- conn->c_rx_state = C_IO_CLOSED;
- break;
- }
- ci->rx_req = req;
-
- /* use le_to_cpu */
- memcpy(&req->rq, hdr, sizeof(req->rq));
-
- if (data_len && hdr->flags & SD_FLAG_CMD_WRITE) {
- conn->c_rx_state = C_IO_DATA;
- conn->rx_length = data_len;
- conn->rx_buf = req->data;
- } else {
- conn->c_rx_state = C_IO_END;
- break;
- }
- case C_IO_DATA:
- ret = rx(conn, C_IO_END);
- break;
- default:
- eprintf("BUG: unknown state %d\n", conn->c_rx_state);
- }
-
- if (is_conn_dead(conn) || conn->c_rx_state != C_IO_END)
- return;
-
- /* now we have a complete command */
-
- req = ci->rx_req;
-
- init_rx_hdr(ci);
-
- if (hdr->flags & SD_FLAG_CMD_WRITE)
- req->rp.data_length = 0;
- else
- req->rp.data_length = hdr->data_length;
-
- req->done = req_done;
-
- queue_request(req);
-}
-
-static void init_tx_hdr(struct client_info *ci)
-{
- struct sd_rsp *rsp = (struct sd_rsp *)&ci->conn.tx_hdr;
- struct request *req;
-
- if (ci->tx_req || list_empty(&ci->done_reqs))
- return;
-
- memset(rsp, 0, sizeof(*rsp));
-
- req = list_first_entry(&ci->done_reqs, struct request, r_wlist);
- list_del(&req->r_wlist);
-
- ci->tx_req = req;
- ci->conn.tx_length = sizeof(*rsp);
- ci->conn.c_tx_state = C_IO_HEADER;
- ci->conn.tx_buf = rsp;
-
- /* use cpu_to_le */
- memcpy(rsp, &req->rp, sizeof(*rsp));
-
- rsp->epoch = sys->epoch;
- rsp->opcode = req->rq.opcode;
- rsp->id = req->rq.id;
-}
-
-static void client_tx_handler(struct client_info *ci)
-{
- int ret, opt;
- struct sd_rsp *rsp = (struct sd_rsp *)&ci->conn.tx_hdr;
-
-again:
- init_tx_hdr(ci);
- if (!ci->tx_req) {
- conn_tx_off(&ci->conn);
- return;
- }
-
- opt = 1;
- setsockopt(ci->conn.fd, SOL_TCP, TCP_CORK, &opt, sizeof(opt));
-
- switch (ci->conn.c_tx_state) {
- case C_IO_HEADER:
- if (rsp->data_length)
- ret = tx(&ci->conn, C_IO_DATA_INIT, MSG_MORE);
- else
- ret = tx(&ci->conn, C_IO_DATA_INIT, 0);
-
- if (!ret)
- break;
-
- if (rsp->data_length) {
- ci->conn.tx_length = rsp->data_length;
- ci->conn.tx_buf = ci->tx_req->data;
- ci->conn.c_tx_state = C_IO_DATA;
- } else {
- ci->conn.c_tx_state = C_IO_END;
- break;
- }
- case C_IO_DATA:
- ret = tx(&ci->conn, C_IO_END, 0);
- if (!ret)
- break;
- default:
- break;
- }
-
- opt = 0;
- setsockopt(ci->conn.fd, SOL_TCP, TCP_CORK, &opt, sizeof(opt));
-
- if (is_conn_dead(&ci->conn) || ci->conn.c_tx_state != C_IO_END)
- return;
-
- if (ci->conn.c_tx_state == C_IO_END) {
- free_request(ci->tx_req);
- ci->tx_req = NULL;
- goto again;
- }
-}
-
-static void destroy_client(struct client_info *ci)
-{
- close(ci->conn.fd);
- free(ci);
-}
-
-static struct client_info *create_client(int fd, struct cluster_info *cluster)
-{
- struct client_info *ci;
-
- ci = zalloc(sizeof(*ci));
- if (!ci)
- return NULL;
-
- ci->conn.fd = fd;
-
- INIT_LIST_HEAD(&ci->reqs);
- INIT_LIST_HEAD(&ci->done_reqs);
-
- init_rx_hdr(ci);
-
- return ci;
-}
-
-static void client_handler(int fd, int events, void *data)
-{
- struct client_info *ci = (struct client_info *)data;
-
- if (events & EPOLLIN)
- client_rx_handler(ci);
-
- if (!is_conn_dead(&ci->conn) && events & EPOLLOUT)
- client_tx_handler(ci);
-
- if (is_conn_dead(&ci->conn)) {
- dprintf("closed a connection, %d\n", fd);
- unregister_event(fd);
- destroy_client(ci);
- }
-}
-
-static void listen_handler(int listen_fd, int events, void *data)
-{
- struct sockaddr_storage from;
- socklen_t namesize;
- int fd, ret, opt;
- struct client_info *ci;
-
- namesize = sizeof(from);
- fd = accept(listen_fd, (struct sockaddr *)&from, &namesize);
- if (fd < 0) {
- eprintf("can't accept a new connection, %m\n");
- return;
- }
-
- opt = 1;
- ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
- if (ret) {
- close(fd);
- return;
- }
-
- ci = create_client(fd, data);
- if (!ci) {
- close(fd);
- return;
- }
-
- ret = register_event(fd, client_handler, ci);
- if (ret) {
- destroy_client(ci);
- return;
- }
-
- dprintf("accepted a new connection, %d\n", fd);
-}
-
-static int create_listen_port_fn(int fd, void *data)
-{
- return register_event(fd, listen_handler, data);
-}
-
-int create_listen_port(int port, void *data)
-{
- return create_listen_ports(port, create_listen_port_fn, data);
-}
-
-int write_object(struct sheepdog_node_list_entry *e,
- int nodes, uint32_t node_version,
- uint64_t oid, char *data, unsigned int datalen,
- uint64_t offset, int nr, int create)
-{
- struct sd_obj_req hdr;
- int i, n, fd, ret, success = 0;
- uint16_t vosts[3];
- char name[128];
-
- for (i = 0; i < nr; i++) {
- unsigned rlen = 0, wlen = datalen;
-
- n = obj_to_sheep(e, nodes, oid, i);
-
- addr_to_str(name, sizeof(name), e[n].addr, 0);
-
- fd = connect_to(name, e[n].port);
- if (fd < 0) {
- eprintf("can't connect to vost %u, %s\n", vosts[i], name);
- continue;
- }
-
- memset(&hdr, 0, sizeof(hdr));
- hdr.epoch = node_version;
- if (create)
- hdr.opcode = SD_OP_CREATE_AND_WRITE_OBJ;
- else
- hdr.opcode = SD_OP_WRITE_OBJ;
-
- hdr.oid = oid;
- hdr.copies = nr;
-
- hdr.flags = SD_FLAG_CMD_WRITE | SD_FLAG_CMD_DIRECT;
- hdr.data_length = wlen;
- hdr.offset = offset;
-
- ret = exec_req(fd, (struct sd_req *)&hdr, data, &wlen, &rlen);
- close(fd);
- if (ret)
- eprintf("can't update vost %u, %s\n", vosts[i], name);
- else
- success++;
- }
-
- return !success;
-}
-
-int read_object(struct sheepdog_node_list_entry *e,
- int nodes, uint32_t node_version,
- uint64_t oid, char *data, unsigned int datalen,
- uint64_t offset, int nr)
-{
- struct sd_obj_req hdr;
- struct sd_obj_rsp *rsp = (struct sd_obj_rsp *)&hdr;
- char name[128];
- int i = 0, n, fd, ret;
-
- for (i = 0; i < nr; i++) {
- unsigned wlen = 0, rlen = datalen;
-
- n = obj_to_sheep(e, nodes, oid, i);
-
- addr_to_str(name, sizeof(name), e[n].addr, 0);
-
- fd = connect_to(name, e[n].port);
- if (fd < 0) {
- printf("%s(%d): %s, %m\n", __func__, __LINE__,
- name);
- return -1;
- }
-
- memset(&hdr, 0, sizeof(hdr));
- hdr.epoch = node_version;
- hdr.opcode = SD_OP_READ_OBJ;
- hdr.oid = oid;
-
- hdr.flags = SD_FLAG_CMD_DIRECT;
- hdr.data_length = rlen;
- hdr.offset = offset;
-
- ret = exec_req(fd, (struct sd_req *)&hdr, data, &wlen, &rlen);
- close(fd);
-
- if (!ret) {
- if (rsp->result == SD_RES_SUCCESS)
- return rsp->data_length;
- }
- }
-
- return -1;
-}
-
-int remove_object(struct sheepdog_node_list_entry *e,
- int nodes, uint32_t node_version,
- uint64_t oid, int nr)
-{
- char name[128];
- struct sd_obj_req hdr;
- struct sd_obj_rsp *rsp = (struct sd_obj_rsp *)&hdr;
- int i = 0, n, fd, ret;
-
- if (nr > nodes)
- nr = nodes;
-
- for (i = 0; i < nr; i++) {
- unsigned wlen = 0, rlen = 0;
-
- n = obj_to_sheep(e, nodes, oid, i);
-
- addr_to_str(name, sizeof(name), e[n].addr, 0);
-
- fd = connect_to(name, e[n].port);
- if (fd < 0) {
- rsp->result = SD_RES_EIO;
- return -1;
- }
-
- memset(&hdr, 0, sizeof(hdr));
- hdr.epoch = node_version;
- hdr.opcode = SD_OP_REMOVE_OBJ;
- hdr.oid = oid;
-
- hdr.flags = 0;
- hdr.data_length = rlen;
-
- ret = exec_req(fd, (struct sd_req *)&hdr, NULL, &wlen, &rlen);
- close(fd);
-
- if (ret)
- return -1;
- }
-
- if (rsp->result != SD_RES_SUCCESS)
- return -1;
-
- return 0;
-}
diff --git a/sheep/sdnet.c b/sheep/sdnet.c
new file mode 100644
index 0000000..f1ce8ea
--- /dev/null
+++ b/sheep/sdnet.c
@@ -0,0 +1,643 @@
+/*
+ * Copyright (C) 2009-2010 Nippon Telegraph and Telephone Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netinet/tcp.h>
+#include <sys/epoll.h>
+
+#include "sheep_priv.h"
+
+int is_io_request(unsigned op)
+{
+ int ret = 0;
+
+ switch (op) {
+ case SD_OP_CREATE_AND_WRITE_OBJ:
+ case SD_OP_REMOVE_OBJ:
+ case SD_OP_READ_OBJ:
+ case SD_OP_WRITE_OBJ:
+ ret = 1;
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+void resume_pending_requests(void)
+{
+ struct request *next, *tmp;
+
+ list_for_each_entry_safe(next, tmp, &sys->req_wait_for_obj_list,
+ r_wlist) {
+ struct cpg_event *cevent = &next->cev;
+
+ list_del(&next->r_wlist);
+ list_add_tail(&cevent->cpg_event_list, &sys->cpg_event_siblings);
+ }
+
+ if (!list_empty(&sys->cpg_event_siblings))
+ start_cpg_event_work();
+}
+
+static int is_access_local(struct sheepdog_node_list_entry *e, int nr_nodes,
+ uint64_t oid, int copies)
+{
+ int i, n;
+
+ for (i = 0; i < copies; i++) {
+ n = obj_to_sheep(e, nr_nodes, oid, i);
+
+ if (is_myself(&e[n]))
+ return 1;
+ }
+
+ return 0;
+}
+
+static void setup_access_to_local_objects(struct request *req)
+{
+ struct sd_obj_req *hdr = (struct sd_obj_req *)&req->rq;
+ int copies;
+
+ if (hdr->flags & SD_FLAG_CMD_DIRECT) {
+ req->local_oid[0] = hdr->oid;
+
+ if (hdr->flags & SD_FLAG_CMD_COW)
+ req->local_oid[1] = hdr->cow_oid;
+
+ return;
+ }
+
+ copies = hdr->copies;
+ if (!copies)
+ copies = sys->nr_sobjs;
+
+ if (is_access_local(req->entry, req->nr_nodes, hdr->oid, copies))
+ req->local_oid[0] = hdr->oid;
+
+ if ((hdr->flags & SD_FLAG_CMD_COW) &&
+ is_access_local(req->entry, req->nr_nodes, hdr->cow_oid, copies))
+ req->local_oid[1] = hdr->cow_oid;
+}
+
+static void __done(struct work *work, int idx)
+{
+ struct request *req = container_of(work, struct request, work);
+ struct sd_req *hdr = (struct sd_req *)&req->rq;
+ int again = 0;
+
+ switch (hdr->opcode) {
+ case SD_OP_NEW_VDI:
+ case SD_OP_DEL_VDI:
+ case SD_OP_LOCK_VDI:
+ case SD_OP_RELEASE_VDI:
+ case SD_OP_GET_VDI_INFO:
+ case SD_OP_MAKE_FS:
+ case SD_OP_SHUTDOWN:
+ /* request is forwarded to cpg group */
+ return;
+ }
+
+ if (is_io_request(hdr->opcode)) {
+ struct cpg_event *cevent = &req->cev;
+
+ list_del(&req->r_wlist);
+
+ sys->nr_outstanding_io--;
+ /*
+ * TODO: if the request failed due to epoch unmatch,
+ * we should retry here (adds this request to the tail
+ * of sys->cpg_event_siblings.
+ */
+
+ if (!(req->rq.flags & SD_FLAG_CMD_DIRECT) &&
+ (req->rp.result == SD_RES_OLD_NODE_VER ||
+ req->rp.result == SD_RES_NEW_NODE_VER)) {
+
+
+ req->rq.epoch = sys->epoch;
+ req->nr_nodes = setup_ordered_sd_node_list(req);
+ setup_access_to_local_objects(req);
+
+ list_add_tail(&cevent->cpg_event_list, &sys->cpg_event_siblings);
+ again = 1;
+ }
+
+ resume_pending_requests();
+ resume_recovery_work();
+ }
+
+ if (!again)
+ req->done(req);
+}
+
+static void queue_request(struct request *req)
+{
+ struct cpg_event *cevent = &req->cev;
+
+ struct sd_req *hdr = (struct sd_req *)&req->rq;
+ struct sd_rsp *rsp = (struct sd_rsp *)&req->rp;
+
+ if (hdr->opcode == SD_OP_KILL_NODE) {
+ log_close();
+ exit(1);
+ }
+
+ if (sys->status == SD_STATUS_SHUTDOWN) {
+ rsp->result = SD_RES_SHUTDOWN;
+ req->done(req);
+ return;
+ }
+
+ if (sys->status == SD_STATUS_JOIN_FAILED) {
+ rsp->result = SD_RES_JOIN_FAILED;
+ req->done(req);
+ return;
+ }
+
+ if (sys->status == SD_STATUS_WAIT_FOR_FORMAT ||
+ sys->status == SD_STATUS_WAIT_FOR_JOIN) {
+ /* TODO: cleanup */
+ switch (hdr->opcode) {
+ case SD_OP_STAT_CLUSTER:
+ case SD_OP_MAKE_FS:
+ case SD_OP_GET_NODE_LIST:
+ case SD_OP_READ_VDIS:
+ break;
+ default:
+ if (sys->status == SD_STATUS_WAIT_FOR_FORMAT)
+ rsp->result = SD_RES_WAIT_FOR_FORMAT;
+ else
+ rsp->result = SD_RES_WAIT_FOR_JOIN;
+ req->done(req);
+ return;
+ }
+ }
+
+ switch (hdr->opcode) {
+ case SD_OP_CREATE_AND_WRITE_OBJ:
+ case SD_OP_REMOVE_OBJ:
+ case SD_OP_READ_OBJ:
+ case SD_OP_WRITE_OBJ:
+ case SD_OP_STAT_SHEEP:
+ case SD_OP_GET_OBJ_LIST:
+ req->work.fn = store_queue_request;
+ break;
+ case SD_OP_GET_NODE_LIST:
+ case SD_OP_GET_VM_LIST:
+ case SD_OP_NEW_VDI:
+ case SD_OP_DEL_VDI:
+ case SD_OP_LOCK_VDI:
+ case SD_OP_RELEASE_VDI:
+ case SD_OP_GET_VDI_INFO:
+ case SD_OP_MAKE_FS:
+ case SD_OP_SHUTDOWN:
+ case SD_OP_STAT_CLUSTER:
+ req->work.fn = cluster_queue_request;
+ break;
+ case SD_OP_READ_VDIS:
+ rsp->result = read_vdis(req->data, hdr->data_length, &rsp->data_length);
+ req->done(req);
+ return;
+ default:
+ eprintf("unknown operation %d\n", hdr->opcode);
+ rsp->result = SD_RES_SYSTEM_ERROR;
+ req->done(req);
+ return;
+ }
+
+ req->work.done = __done;
+
+ list_del(&req->r_wlist);
+
+ /*
+ * we set epoch for non direct requests here. Note that we
+ * can't access to sys->epoch after calling
+ * start_cpg_event_work(that is, passing requests to work
+ * threads).
+ */
+ if (!(hdr->flags & SD_FLAG_CMD_DIRECT))
+ hdr->epoch = sys->epoch;
+
+ req->nr_nodes = setup_ordered_sd_node_list(req);
+ setup_access_to_local_objects(req);
+
+ cevent->ctype = CPG_EVENT_REQUEST;
+ list_add_tail(&cevent->cpg_event_list, &sys->cpg_event_siblings);
+ start_cpg_event_work();
+}
+
+static struct request *alloc_request(struct client_info *ci, int data_length)
+{
+ struct request *req;
+
+ req = zalloc(sizeof(struct request) + data_length);
+ if (!req)
+ return NULL;
+
+ req->ci = ci;
+ if (data_length)
+ req->data = (char *)req + sizeof(*req);
+
+ list_add(&req->r_siblings, &ci->reqs);
+ INIT_LIST_HEAD(&req->r_wlist);
+
+ return req;
+}
+
+static void free_request(struct request *req)
+{
+ list_del(&req->r_siblings);
+ free(req);
+}
+
+static void req_done(struct request *req)
+{
+ list_add(&req->r_wlist, &req->ci->done_reqs);
+ conn_tx_on(&req->ci->conn);
+}
+
+static void init_rx_hdr(struct client_info *ci)
+{
+ ci->conn.c_rx_state = C_IO_HEADER;
+ ci->rx_req = NULL;
+ ci->conn.rx_length = sizeof(struct sd_req);
+ ci->conn.rx_buf = &ci->conn.rx_hdr;
+}
+
+static void client_rx_handler(struct client_info *ci)
+{
+ int ret;
+ uint64_t data_len;
+ struct connection *conn = &ci->conn;
+ struct sd_req *hdr = &conn->rx_hdr;
+ struct request *req;
+
+ switch (conn->c_rx_state) {
+ case C_IO_HEADER:
+ ret = rx(conn, C_IO_DATA_INIT);
+ if (!ret || conn->c_rx_state != C_IO_DATA_INIT)
+ break;
+ case C_IO_DATA_INIT:
+ data_len = hdr->data_length;
+
+ req = alloc_request(ci, data_len);
+ if (!req) {
+ conn->c_rx_state = C_IO_CLOSED;
+ break;
+ }
+ ci->rx_req = req;
+
+ /* use le_to_cpu */
+ memcpy(&req->rq, hdr, sizeof(req->rq));
+
+ if (data_len && hdr->flags & SD_FLAG_CMD_WRITE) {
+ conn->c_rx_state = C_IO_DATA;
+ conn->rx_length = data_len;
+ conn->rx_buf = req->data;
+ } else {
+ conn->c_rx_state = C_IO_END;
+ break;
+ }
+ case C_IO_DATA:
+ ret = rx(conn, C_IO_END);
+ break;
+ default:
+ eprintf("BUG: unknown state %d\n", conn->c_rx_state);
+ }
+
+ if (is_conn_dead(conn) || conn->c_rx_state != C_IO_END)
+ return;
+
+ /* now we have a complete command */
+
+ req = ci->rx_req;
+
+ init_rx_hdr(ci);
+
+ if (hdr->flags & SD_FLAG_CMD_WRITE)
+ req->rp.data_length = 0;
+ else
+ req->rp.data_length = hdr->data_length;
+
+ req->done = req_done;
+
+ queue_request(req);
+}
+
+static void init_tx_hdr(struct client_info *ci)
+{
+ struct sd_rsp *rsp = (struct sd_rsp *)&ci->conn.tx_hdr;
+ struct request *req;
+
+ if (ci->tx_req || list_empty(&ci->done_reqs))
+ return;
+
+ memset(rsp, 0, sizeof(*rsp));
+
+ req = list_first_entry(&ci->done_reqs, struct request, r_wlist);
+ list_del(&req->r_wlist);
+
+ ci->tx_req = req;
+ ci->conn.tx_length = sizeof(*rsp);
+ ci->conn.c_tx_state = C_IO_HEADER;
+ ci->conn.tx_buf = rsp;
+
+ /* use cpu_to_le */
+ memcpy(rsp, &req->rp, sizeof(*rsp));
+
+ rsp->epoch = sys->epoch;
+ rsp->opcode = req->rq.opcode;
+ rsp->id = req->rq.id;
+}
+
+static void client_tx_handler(struct client_info *ci)
+{
+ int ret, opt;
+ struct sd_rsp *rsp = (struct sd_rsp *)&ci->conn.tx_hdr;
+
+again:
+ init_tx_hdr(ci);
+ if (!ci->tx_req) {
+ conn_tx_off(&ci->conn);
+ return;
+ }
+
+ opt = 1;
+ setsockopt(ci->conn.fd, SOL_TCP, TCP_CORK, &opt, sizeof(opt));
+
+ switch (ci->conn.c_tx_state) {
+ case C_IO_HEADER:
+ if (rsp->data_length)
+ ret = tx(&ci->conn, C_IO_DATA_INIT, MSG_MORE);
+ else
+ ret = tx(&ci->conn, C_IO_DATA_INIT, 0);
+
+ if (!ret)
+ break;
+
+ if (rsp->data_length) {
+ ci->conn.tx_length = rsp->data_length;
+ ci->conn.tx_buf = ci->tx_req->data;
+ ci->conn.c_tx_state = C_IO_DATA;
+ } else {
+ ci->conn.c_tx_state = C_IO_END;
+ break;
+ }
+ case C_IO_DATA:
+ ret = tx(&ci->conn, C_IO_END, 0);
+ if (!ret)
+ break;
+ default:
+ break;
+ }
+
+ opt = 0;
+ setsockopt(ci->conn.fd, SOL_TCP, TCP_CORK, &opt, sizeof(opt));
+
+ if (is_conn_dead(&ci->conn) || ci->conn.c_tx_state != C_IO_END)
+ return;
+
+ if (ci->conn.c_tx_state == C_IO_END) {
+ free_request(ci->tx_req);
+ ci->tx_req = NULL;
+ goto again;
+ }
+}
+
+static void destroy_client(struct client_info *ci)
+{
+ close(ci->conn.fd);
+ free(ci);
+}
+
+static struct client_info *create_client(int fd, struct cluster_info *cluster)
+{
+ struct client_info *ci;
+
+ ci = zalloc(sizeof(*ci));
+ if (!ci)
+ return NULL;
+
+ ci->conn.fd = fd;
+
+ INIT_LIST_HEAD(&ci->reqs);
+ INIT_LIST_HEAD(&ci->done_reqs);
+
+ init_rx_hdr(ci);
+
+ return ci;
+}
+
+static void client_handler(int fd, int events, void *data)
+{
+ struct client_info *ci = (struct client_info *)data;
+
+ if (events & EPOLLIN)
+ client_rx_handler(ci);
+
+ if (!is_conn_dead(&ci->conn) && events & EPOLLOUT)
+ client_tx_handler(ci);
+
+ if (is_conn_dead(&ci->conn)) {
+ dprintf("closed a connection, %d\n", fd);
+ unregister_event(fd);
+ destroy_client(ci);
+ }
+}
+
+static void listen_handler(int listen_fd, int events, void *data)
+{
+ struct sockaddr_storage from;
+ socklen_t namesize;
+ int fd, ret, opt;
+ struct client_info *ci;
+
+ namesize = sizeof(from);
+ fd = accept(listen_fd, (struct sockaddr *)&from, &namesize);
+ if (fd < 0) {
+ eprintf("can't accept a new connection, %m\n");
+ return;
+ }
+
+ opt = 1;
+ ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
+ if (ret) {
+ close(fd);
+ return;
+ }
+
+ ci = create_client(fd, data);
+ if (!ci) {
+ close(fd);
+ return;
+ }
+
+ ret = register_event(fd, client_handler, ci);
+ if (ret) {
+ destroy_client(ci);
+ return;
+ }
+
+ dprintf("accepted a new connection, %d\n", fd);
+}
+
+static int create_listen_port_fn(int fd, void *data)
+{
+ return register_event(fd, listen_handler, data);
+}
+
+int create_listen_port(int port, void *data)
+{
+ return create_listen_ports(port, create_listen_port_fn, data);
+}
+
+int write_object(struct sheepdog_node_list_entry *e,
+ int nodes, uint32_t node_version,
+ uint64_t oid, char *data, unsigned int datalen,
+ uint64_t offset, int nr, int create)
+{
+ struct sd_obj_req hdr;
+ int i, n, fd, ret, success = 0;
+ uint16_t vosts[3];
+ char name[128];
+
+ for (i = 0; i < nr; i++) {
+ unsigned rlen = 0, wlen = datalen;
+
+ n = obj_to_sheep(e, nodes, oid, i);
+
+ addr_to_str(name, sizeof(name), e[n].addr, 0);
+
+ fd = connect_to(name, e[n].port);
+ if (fd < 0) {
+ eprintf("can't connect to vost %u, %s\n", vosts[i], name);
+ continue;
+ }
+
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.epoch = node_version;
+ if (create)
+ hdr.opcode = SD_OP_CREATE_AND_WRITE_OBJ;
+ else
+ hdr.opcode = SD_OP_WRITE_OBJ;
+
+ hdr.oid = oid;
+ hdr.copies = nr;
+
+ hdr.flags = SD_FLAG_CMD_WRITE | SD_FLAG_CMD_DIRECT;
+ hdr.data_length = wlen;
+ hdr.offset = offset;
+
+ ret = exec_req(fd, (struct sd_req *)&hdr, data, &wlen, &rlen);
+ close(fd);
+ if (ret)
+ eprintf("can't update vost %u, %s\n", vosts[i], name);
+ else
+ success++;
+ }
+
+ return !success;
+}
+
+int read_object(struct sheepdog_node_list_entry *e,
+ int nodes, uint32_t node_version,
+ uint64_t oid, char *data, unsigned int datalen,
+ uint64_t offset, int nr)
+{
+ struct sd_obj_req hdr;
+ struct sd_obj_rsp *rsp = (struct sd_obj_rsp *)&hdr;
+ char name[128];
+ int i = 0, n, fd, ret;
+
+ for (i = 0; i < nr; i++) {
+ unsigned wlen = 0, rlen = datalen;
+
+ n = obj_to_sheep(e, nodes, oid, i);
+
+ addr_to_str(name, sizeof(name), e[n].addr, 0);
+
+ fd = connect_to(name, e[n].port);
+ if (fd < 0) {
+ printf("%s(%d): %s, %m\n", __func__, __LINE__,
+ name);
+ return -1;
+ }
+
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.epoch = node_version;
+ hdr.opcode = SD_OP_READ_OBJ;
+ hdr.oid = oid;
+
+ hdr.flags = SD_FLAG_CMD_DIRECT;
+ hdr.data_length = rlen;
+ hdr.offset = offset;
+
+ ret = exec_req(fd, (struct sd_req *)&hdr, data, &wlen, &rlen);
+ close(fd);
+
+ if (!ret) {
+ if (rsp->result == SD_RES_SUCCESS)
+ return rsp->data_length;
+ }
+ }
+
+ return -1;
+}
+
+int remove_object(struct sheepdog_node_list_entry *e,
+ int nodes, uint32_t node_version,
+ uint64_t oid, int nr)
+{
+ char name[128];
+ struct sd_obj_req hdr;
+ struct sd_obj_rsp *rsp = (struct sd_obj_rsp *)&hdr;
+ int i = 0, n, fd, ret;
+
+ if (nr > nodes)
+ nr = nodes;
+
+ for (i = 0; i < nr; i++) {
+ unsigned wlen = 0, rlen = 0;
+
+ n = obj_to_sheep(e, nodes, oid, i);
+
+ addr_to_str(name, sizeof(name), e[n].addr, 0);
+
+ fd = connect_to(name, e[n].port);
+ if (fd < 0) {
+ rsp->result = SD_RES_EIO;
+ return -1;
+ }
+
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.epoch = node_version;
+ hdr.opcode = SD_OP_REMOVE_OBJ;
+ hdr.oid = oid;
+
+ hdr.flags = 0;
+ hdr.data_length = rlen;
+
+ ret = exec_req(fd, (struct sd_req *)&hdr, NULL, &wlen, &rlen);
+ close(fd);
+
+ if (ret)
+ return -1;
+ }
+
+ if (rsp->result != SD_RES_SUCCESS)
+ return -1;
+
+ return 0;
+}
diff --git a/sheep/sheep.c b/sheep/sheep.c
index b14c5c6..b95b436 100644
--- a/sheep/sheep.c
+++ b/sheep/sheep.c
@@ -8,6 +8,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
+#include "../include/config.h"
+
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
@@ -49,7 +52,7 @@ Sheepdog Daemon, version %s\n\
-l, --loglevel specify the message level printed by default\n\
-d, --debug print debug messages\n\
-h, --help display this help and exit\n\
-", SD_VERSION);
+", PACKAGE_VERSION);
}
exit(status);
}
@@ -127,7 +130,7 @@ int main(int argc, char **argv)
exit(1);
}
- vprintf(SDOG_NOTICE "Sheepdog daemon (version %s) started\n", SD_VERSION);
+ vprintf(SDOG_NOTICE "Sheepdog daemon (version %s) started\n", PACKAGE_VERSION);
while (sys->status != SD_STATUS_SHUTDOWN)
event_loop(-1);
diff --git a/sheep/store.c b/sheep/store.c
index c5552bb..72cd287 100644
--- a/sheep/store.c
+++ b/sheep/store.c
@@ -18,6 +18,9 @@
#include <poll.h>
#include <sys/xattr.h>
#include <sys/statvfs.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include "sheep_priv.h"
--
1.6.2.5
More information about the sheepdog
mailing list