[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