[iwhd] avoid warning from logrotate about "postrotate without endscript"
by Jim Meyering
commit 80f9671bb52214a441ddda20cd318d2c8f85d154
Author: Jim Meyering <meyering(a)redhat.com>
Date: Fri Sep 30 09:05:29 2011 +0200
avoid warning from logrotate about "postrotate without endscript"
* iwhd.logrotate: Add "endscript" to delimit end of "postrotate" command.
iwhd.logrotate | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
---
diff --git a/iwhd.logrotate b/iwhd.logrotate
index 164d536..59c8c32 100644
--- a/iwhd.logrotate
+++ b/iwhd.logrotate
@@ -5,4 +5,5 @@
# kill -HUP `cat /var/run/iwhd.pid` <--- we haven't got a pidfile yet
postrotate
/usr/bin/killall -HUP iwhd 2>/dev/null || true
+ endscript
}
12 years, 7 months
[iwhd] iwhd: use /var/cache/iwhd for tiny temporary files, not /tmp
by Jim Meyering
commit a49c60a2f7a84972be4e31881182625dcc0b3ee4
Author: Jim Meyering <meyering(a)redhat.com>
Date: Wed Sep 28 14:14:43 2011 +0200
iwhd: use /var/cache/iwhd for tiny temporary files, not /tmp
* iwhd.init.in (TMPDIR): Set it to /var/cache/iwhd, overriding the
default of /tmp. Francesco Vollero reported the SELinux issue.
iwhd.init.in | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
---
diff --git a/iwhd.init.in b/iwhd.init.in
index 9a7d9b6..b2d2f9d 100644
--- a/iwhd.init.in
+++ b/iwhd.init.in
@@ -31,6 +31,11 @@ MONGOD_SERVER_SPEC=localhost:27017
# How many seconds to wait for mongod to become usable before giving up.
MONGOD_N_SECONDS=2
+# Tell iwhd to use /var/cache/iwhd, not /tmp for a small S3-related
+# temporary file. This avoids conflict with SELinux policy that discourages
+# writing in /tmp.
+export TMPDIR=@localstatedir@/cache/iwhd
+
IWHD_ARGS="-d $MONGOD_SERVER_SPEC -l /var/log/iwhd.log"
test -r @sysconfdir@/sysconfig/iwhd && . @sysconfdir@/sysconfig/iwhd
12 years, 7 months
[iwhd] tests: add a test to exercise mongo-reconnect processing
by Jim Meyering
commit b7fd87644470ecb8d2cefc89188291f4b5ca4899
Author: Jim Meyering <meyering(a)redhat.com>
Date: Wed Sep 21 17:55:33 2011 +0200
tests: add a test to exercise mongo-reconnect processing
* t/mongo-restart: New test.
* t/Makefile.am (TESTS): Add it here.
* NEWS (Bug fixes): Mention it.
NEWS | 3 ++
t/Makefile.am | 1 +
t/mongo-restart | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 84 insertions(+), 0 deletions(-)
---
diff --git a/NEWS b/NEWS
index be681f9..c7467a9 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,9 @@ iwhd NEWS -*- outline -*-
** Bug fixes
+ iwhd now continues to work properly when mongo dies and is restarted.
+ Before, it would dump core due to an unhandled SocketException.
+
iwhd's /etc/init.d startup script now reports failure reliably, for
example when failing to start because no MongoDB server is running.
Before it would print [FAILED], but mistakenly exit 0 (successful).
diff --git a/t/Makefile.am b/t/Makefile.am
index ae2bdf3..a3b39d7 100644
--- a/t/Makefile.am
+++ b/t/Makefile.am
@@ -20,6 +20,7 @@ TESTS = \
creation-code \
delete-missing \
exercise \
+ mongo-restart \
provider \
replication \
auto \
diff --git a/t/mongo-restart b/t/mongo-restart
new file mode 100755
index 0000000..1447952
--- /dev/null
+++ b/t/mongo-restart
@@ -0,0 +1,80 @@
+#!/bin/sh
+# Ensure iwhd recovers after mongo stop/restart.
+# Before 0.99 it did not.
+
+. "${srcdir=.}/init.sh"; path_prepend_ ..
+
+mkdir FS mongod iwhd || framework_failure_ mkdir failed
+
+ulimit -c unlimited
+m_port=$(get_port $mongo_base_port $lock_dir/m-) \
+ || fail_ "failed to get mongodb port"
+
+mongod --help > /dev/null || fail_ "the mongod program is not installed"
+
+mongod --port $m_port --pidfilepath mongod/pid --dbpath mongod > mongod.log 2>&1 &
+mongo_pid=$!
+cleanup_() { kill -9 $mongo_pid; }
+
+# Wait for up to 5 seconds for mongod to begin listening.
+wait_for .1 50 'mongo localhost:$m_port < /dev/null' \
+ || framework_failure_ mongod failed to start
+
+port=$(get_port 9095 $lock_dir/i-) || fail_ "failed to get iwhd port"
+
+printf '[{"path": "FS", "type": "fs", "name": "primary"}]\n' \
+ > iwhd.cfg || fail=1
+
+iwhd -v -p $port -c iwhd.cfg -d localhost:$m_port &
+iwhd_pid=$!
+cleanup_() { kill -9 $mongo_pid; kill $iwhd_pid; }
+
+# Wait for up to 5 seconds for iwhd to begin listening on $port.
+wait_for .1 50 "curl -s http://localhost:$port" \
+ || fail_ iwhd failed to listen
+
+curl_w() { curl --write-out '%{http_code}' "$@"; }
+
+# Show that bucket,object,attribute-creation all evoke 201.
+creation_evokes_201()
+{
+ local bucket_name=$1
+
+ # Create a bucket.
+ local b=http://localhost:$port/$bucket_name
+ curl_w -XPUT $b > http-code || fail=1
+ test "$(cat http-code)" = 201 || fail=1
+
+ # Create an object in that bucket.
+ local obj=$b/obj
+ curl_w -XPUT $obj > http-code || fail=1
+ test "$(cat http-code)" = 201 || fail=1
+
+ # Create an attribute.
+ local attr=$obj/color
+ printf blue | curl_w -T - $attr > http-code || fail=1
+ test "$(cat http-code)" = 201 || fail=1
+}
+
+
+creation_evokes_201 b1
+
+# So far, this is identical to the creation-code test.
+# But now, we kill mongo and restart it, and then repeat the test.
+
+kill $mongo_pid
+
+# Wait for mongo to stop listening.
+no_mongo() { mongo localhost:$m_port < /dev/null; test $? != 0; }
+wait_for .1 50 no_mongo || fail_ failed to kill mongo
+
+mongod --port $m_port --pidfilepath mongod/pid --dbpath mongod &
+mongo_pid=$!
+
+# Wait for up to 5 seconds for mongod to begin listening.
+wait_for .1 50 'mongo localhost:$m_port < /dev/null' \
+ || framework_failure_ mongod failed to start
+
+creation_evokes_201 b2
+
+Exit $fail
12 years, 7 months
[iwhd] iwhd: handle a lost-then-restored mongo connection
by Jim Meyering
commit 4a5a4c5c48a7316955d2e1bfde041351a823985a
Author: Pete Zaitcev <zaitcev(a)redhat.com>
Date: Wed Sep 21 06:45:20 2011 +0200
iwhd: handle a lost-then-restored mongo connection
If I read the code right, the intent was that client.connect() reset
the .failed flag. But actually it does not. So, although we actually
reconnect, isFailed() always evaluates to true and we get no cursor.
Unfortunately, it seems that there is NO WAY to reset .failed, except
through checkConnect(), and that 1) works only if auto-reconnect is
enabled, and 2) is not a public method. It is called by query()
itself though.
This patch deals with all this simply by enabling auto-reconnect,
which basically does exactly what we did explicitly before, only it
happens inside query() now.
* meta.cpp: Handle SocketException, too
However, this is not the complete solution. Further testing suggests
that if you bombard iwhd with requests when mongo is not responding,
eventually, iwhd will crash.
meta.cpp | 46 ++++++++++++++++++++++------------------------
1 files changed, 22 insertions(+), 24 deletions(-)
---
diff --git a/meta.cpp b/meta.cpp
index 7b3a5d7..fa2c591 100644
--- a/meta.cpp
+++ b/meta.cpp
@@ -118,7 +118,8 @@ public:
static RepoMeta *it;
-RepoMeta::RepoMeta ()
+RepoMeta::RepoMeta () :
+ client(true)
{
if (!verbose) {
cout.rdbuf(0);
@@ -155,27 +156,18 @@ auto_ptr<DBClientCursor>
RepoMeta::GetCursor (Query &q)
{
auto_ptr<DBClientCursor> curs;
- bool looping = false;
-
- for (;;) {
- if (!client.isFailed()) {
- curs = client.query(MAIN_TBL,q);
- if (curs.get()) {
- break;
- }
- }
- if (looping) {
- break;
- }
- try {
- client.connect(addr);
- }
- catch (ConnectException &ce) {
- log_msg(IW_LOG_INFO, "reconnection to %s failed", addr);
- }
- looping = true;
- }
+ try {
+ curs = client.query(MAIN_TBL,q);
+ }
+ catch (ConnectException &ce) {
+ log_msg(IW_LOG_INFO, "reconnection to %s failed", addr);
+ curs.reset();
+ }
+ catch (SocketException &ce) {
+ log_msg(IW_LOG_INFO, "reconnection to %s failed", addr);
+ curs.reset();
+ }
return curs;
}
@@ -434,7 +426,13 @@ RepoQuery::RepoQuery (const char *bucket, const char *key, const char *qstr,
expr = NULL;
}
- curs = parent.GetCursor(q).release();
+ tmp = parent.GetCursor(q);
+ if (!tmp.get()) {
+ /* TBD: What to do if this happens? */
+ log_msg(IW_LOG_INFO, "no cursor");
+ return;
+ }
+ curs = tmp.release();
bucket = NULL;
key = NULL;
}
@@ -582,7 +580,7 @@ RepoMeta::GetSize (const char *bucket, const char *key)
q = QUERY("_bucket"<<bucket<<"_key"<<key);
curs = GetCursor(q);
-
+ /* TBD: What to do if GetCursor() fails to reconnect? */
if (!curs->more()) {
return 0;
}
@@ -651,7 +649,7 @@ RepoMeta::GetAttrList (const char *bucket, const char *key)
q = QUERY("_bucket"<<bucket<<"_key"<<key);
curs = GetCursor(q);
-
+ /* TBD: What to do if GetCursor() fails to reconnect? */
if (!curs->more()) {
return NULL;
}
12 years, 7 months
[iwhd] build: fix the "make rpm" rules
by Jim Meyering
commit 5b6585d668c8eba50b6c451b14c3a6fed066dbbb
Author: Jim Meyering <meyering(a)redhat.com>
Date: Mon Sep 19 15:48:24 2011 +0200
build: fix the "make rpm" rules
* Makefile.am (rpm): Build "all" before "dist".
Otherwise, "make rpm" would fail if certain normally-built
files were not present. Reported by James Laska.
Makefile.am | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 22c096f..7cf2e54 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -85,6 +85,7 @@ iwhd.spec: iwhd.spec.in Makefile
rpm:
$(MAKE) clean
$(MAKE) _version
+ umask 022; $(MAKE) LDFLAGS='-Wl,--build-id'
umask 022; $(MAKE) LDFLAGS='-Wl,--build-id' dist
umask 022; export LDFLAGS='-Wl,--build-id'; \
case $(VERSION) in \
12 years, 7 months
[iwhd] make iwhd's startup script report failure reliably
by Jim Meyering
commit af161e18fbf58669ba1d6dca6de20fd211bd4b76
Author: Pete Zaitcev <zaitcev(a)redhat.com>
Date: Wed Sep 14 16:22:47 2011 +0200
make iwhd's startup script report failure reliably
iwhd's startup script would mistakenly exit successfully even
though it failed, e.g., because it failed to find a usable
instance of Mongo.
* iwhd.init.in (start, stop): Return success indicator.
(main): Propagate success/failure from case stmt to script "exit".
* NEWS (Bug fixes): Mention it.
NEWS | 5 +++++
iwhd.init.in | 7 +++++--
2 files changed, 10 insertions(+), 2 deletions(-)
---
diff --git a/NEWS b/NEWS
index c827c0e..be681f9 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,11 @@ iwhd NEWS -*- outline -*-
** Bug fixes
+ iwhd's /etc/init.d startup script now reports failure reliably, for
+ example when failing to start because no MongoDB server is running.
+ Before it would print [FAILED], but mistakenly exit 0 (successful).
+ Now it exits with status 1.
+
Adapt to a slight variation in the status report of a template import
action in RHEV-M 2.x.
diff --git a/iwhd.init.in b/iwhd.init.in
index 306fcf7..9a7d9b6 100644
--- a/iwhd.init.in
+++ b/iwhd.init.in
@@ -89,6 +89,7 @@ start() {
failure
fi
echo
+ return $RETVAL
}
stop() {
@@ -99,6 +100,7 @@ stop() {
rm -f $PIDFILE
rm -rf @localstatedir@/cache/iwhd/*
fi
+ return $RETVAL
}
restart() {
@@ -122,7 +124,6 @@ case "$1" in
;;
status)
status -p $PIDFILE $PROCESS
- RETVAL=$?
;;
force-reload)
reload
@@ -135,4 +136,6 @@ case "$1" in
exit 2
;;
esac
-exit $RETVAL
+
+# Exit with the result of the "case" statement.
+exit $?
12 years, 7 months
[iwhd] don't hard-code the use of /tmp for a small temporary file
by Jim Meyering
commit 5ca32f6ffd606513d0bdc02aac0ee7012cf69a05
Author: Jim Meyering <meyering(a)redhat.com>
Date: Mon Sep 12 12:56:00 2011 +0200
don't hard-code the use of /tmp for a small temporary file
* iwh.h (tmpfile_template): New global.
* rest.c: Include "xvasprintf.h".
(main): Define it.
* backend.c (s3_init_tmpfile): Use it, in place of
hard-coded "/tmp/iwh.XXXXXX".
* bootstrap.conf (gnulib_modules): Use xvasprintf.
* man/iwhd.x (FILES): Mention $TMPDIR and the default of /tmp.
backend.c | 3 +--
bootstrap.conf | 1 +
gnulib-tests/.gitignore | 4 ++++
iwh.h | 1 +
lib/.gitignore | 18 ++++++++++++++++++
man/iwhd.x | 3 +++
rest.c | 5 +++++
7 files changed, 33 insertions(+), 2 deletions(-)
---
diff --git a/backend.c b/backend.c
index 20a5d1c..5a38cca 100644
--- a/backend.c
+++ b/backend.c
@@ -331,8 +331,7 @@ s3_init_tmpfile (const char *value)
size_t len;
ssize_t written;
- /* FIXME: do not hard-code /tmp. */
- path = strdup("/tmp/iwtmp.XXXXXX");
+ path = strdup(tmpfile_template);
if (!path) {
return NULL;
}
diff --git a/bootstrap.conf b/bootstrap.conf
index 49c2dfb..23703d1 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -78,6 +78,7 @@ xalloc
xalloc-die
xalloc-oversized
xstrtoumax
+xvasprintf
'
gnulib_name=libiwhd
diff --git a/gnulib-tests/.gitignore b/gnulib-tests/.gitignore
index cbae675..8e013fa 100644
--- a/gnulib-tests/.gitignore
+++ b/gnulib-tests/.gitignore
@@ -11,6 +11,7 @@
/float+.h
/float.h
/float.in.h
+/fpucw.h
/fpurge.c
/fseeko.c
/ftell.c
@@ -89,6 +90,7 @@
/test-fflush2.sh
/test-file-has-acl.c
/test-file-has-acl.sh
+/test-float.c
/test-fpending.c
/test-fpending.sh
/test-fpurge.c
@@ -189,6 +191,7 @@
/test-unsetenv.c
/test-update-copyright.sh
/test-vasnprintf.c
+/test-vasprintf.c
/test-vc-list-files-cvs.sh
/test-vc-list-files-git.sh
/test-verify.c
@@ -214,6 +217,7 @@
/test-xstrtoul.c
/test-xstrtoumax.c
/test-xstrtoumax.sh
+/test-xvasprintf.c
/time.h
/time.in.h
/uinttostr.c
diff --git a/iwh.h b/iwh.h
index e18a7a0..ed2e01d 100644
--- a/iwh.h
+++ b/iwh.h
@@ -27,6 +27,7 @@ GLOBAL(unsigned short, master_port, MY_PORT);
GLOBAL(char *, db_host, NULL);
GLOBAL(unsigned short, db_port, 0);
GLOBAL(const char *, me, "here");
+GLOBAL(char *, tmpfile_template, NULL);
#ifndef __attribute__
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
diff --git a/lib/.gitignore b/lib/.gitignore
index 05bc38e..14f2de4 100644
--- a/lib/.gitignore
+++ b/lib/.gitignore
@@ -4,6 +4,8 @@
/alloca.h
/alloca.in.h
/arg-nonnull.h
+/asnprintf.c
+/asprintf.c
/base64.c
/base64.h
/basename-lgpl.c
@@ -48,6 +50,10 @@
/fd-hook.h
/fflush.c
/file-has-acl.c
+/float+.h
+/float.c
+/float.h
+/float.in.h
/fpending.c
/fpending.h
/fpurge.c
@@ -113,6 +119,10 @@
/mkstemp.c
/open.c
/pipe.c
+/printf-args.c
+/printf-args.h
+/printf-parse.c
+/printf-parse.h
/progname.c
/progname.h
/propername.c
@@ -132,6 +142,7 @@
/safe-write.c
/safe-write.h
/set-mode-acl.c
+/size_max.h
/stat.c
/stdarg.h
/stdarg.in.h
@@ -193,6 +204,9 @@
/uniwidth.in.h
/unlink.c
/unlocked-io.h
+/vasnprintf.c
+/vasnprintf.h
+/vasprintf.c
/verify.h
/version-etc-fsf.c
/version-etc.c
@@ -207,7 +221,9 @@
/xalloc-die.c
/xalloc-oversized.h
/xalloc.h
+/xasprintf.c
/xmalloc.c
+/xsize.h
/xstriconv.c
/xstriconv.h
/xstrndup.c
@@ -217,3 +233,5 @@
/xstrtol.h
/xstrtoul.c
/xstrtoumax.c
+/xvasprintf.c
+/xvasprintf.h
diff --git a/man/iwhd.x b/man/iwhd.x
index 415ca29..0b797bb 100644
--- a/man/iwhd.x
+++ b/man/iwhd.x
@@ -2,3 +2,6 @@
.TP
.I /var/log/iwhd.log
Log file established by default /etc/init file.
+.I /tmp
+Directory for small temporary files, configurable via the $TMPDIR
+environment variable.
diff --git a/rest.c b/rest.c
index eeae361..92f36cb 100644
--- a/rest.c
+++ b/rest.c
@@ -52,6 +52,7 @@
#include "state_defs.h"
#include "version-etc.h"
#include "xstrtol.h"
+#include "xvasprintf.h"
const char version_etc_copyright[] =
/* Do *not* mark this string for translation. %s is a copyright
@@ -2365,6 +2366,10 @@ args_done:
usage (EXIT_FAILURE);
}
+ char *t;
+ char const *tmpdir = ((t = getenv ("TMPDIR")) ? t : "/tmp");
+ tmpfile_template = xasprintf ("%s/iwhd.XXXXXX", tmpdir);
+
sem_init(&the_sem,0,0);
if (verbose) {
12 years, 7 months