From 0e5d6c6f4b28a75853d1020f07e493632031a054 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Fri, 12 Jul 2013 02:53:17 +0000 Subject: mgmt: support "SET mogstored.persist_client = $BOOL" This is Perlbal functionality which works in Perl mogstored, so we will also support it here, as it makes upgrading to new versions easier. --- cmogstored.h | 1 + http_parser.rl | 5 +++- mgmt_parser.rl | 19 +++++++++++++- svc.c | 1 + test/http-parser-1.c | 4 +-- test/mgmt_persist_client.rb | 64 +++++++++++++++++++++++++++++++++++++++++++++ test/ruby.mk | 2 +- 7 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 test/mgmt_persist_client.rb diff --git a/cmogstored.h b/cmogstored.h index 8bbff90..5b4493b 100644 --- a/cmogstored.h +++ b/cmogstored.h @@ -155,6 +155,7 @@ struct mog_svc; struct mog_svc { int docroot_fd; const char *docroot; + unsigned persist_client; size_t nmogdev; size_t user_set_aio_threads; /* only touched by main/notify thread */ size_t user_req_aio_threads; /* protected by aio_threads_lock */ diff --git a/http_parser.rl b/http_parser.rl index 0622d62..ef854ba 100644 --- a/http_parser.rl +++ b/http_parser.rl @@ -170,6 +170,9 @@ mog_http_parse(struct mog_http *http, char *buf, size_t len) assert(p <= pe && "buffer overflow after http parse"); assert(http->_p.buf_off <= len && "offset longer than len"); - if (http->cs == http_parser_first_final) return MOG_PARSER_DONE; + if (http->cs == http_parser_first_final) { + http->_p.persistent &= http->svc->persist_client; + return MOG_PARSER_DONE; + } return MOG_PARSER_CONTINUE; } diff --git a/mgmt_parser.rl b/mgmt_parser.rl index 075a057..e40e82b 100644 --- a/mgmt_parser.rl +++ b/mgmt_parser.rl @@ -62,13 +62,30 @@ static void set_prio_fsck(struct mog_mgmt *mgmt) eor > { mgmt->mark[1] = fpc - buf; } @ { mog_mgmt_fn_aio_threads(mgmt, buf); fbreak; } ); + + true_val = ('1'|'true'|'yes'|'on'); + false_val = ('0'|'false'|'no'|'off'); + + persist_client = ( + "set mogstored.persist_client"i ' '?'='(' ')? + ( + (true_val) @ { mgmt->svc->persist_client = true; } + | + (false_val) @ { mgmt->svc->persist_client = false; } + ) + eor + @ { + mog_mgmt_fn_blank(mgmt); + fbreak; + } + ); blank = [ \t]* eor @ { mog_mgmt_fn_blank(mgmt); fbreak; }; shutdown = "shutdown" (" "+"graceful")? eor @ { cmogstored_quit(); fbreak; }; - command = (digest|size|watch|aio_threads|shutdown|blank); + command = (digest|size|watch|aio_threads|persist_client|shutdown|blank); main := command $! { p = buf; fhold; diff --git a/svc.c b/svc.c index 47fb9f7..7d6a6ac 100644 --- a/svc.c +++ b/svc.c @@ -99,6 +99,7 @@ struct mog_svc * mog_svc_new(const char *docroot) svc_once(); svc = xzalloc(sizeof(struct mog_svc)); + svc->persist_client = 1; svc->docroot = docroot; svc->docroot_fd = fd; svc->dir = dir; diff --git a/test/http-parser-1.c b/test/http-parser-1.c index 053237a..138dc7f 100644 --- a/test/http-parser-1.c +++ b/test/http-parser-1.c @@ -3,7 +3,7 @@ * License: GPLv3 or later (see COPYING for details) */ #include "check.h" - +static struct mog_svc svc = { .persist_client = 1 }; static struct mog_http xhttp; static struct mog_http *http = &xhttp; static char *buf; @@ -21,7 +21,7 @@ static void assert_path_equal(const char *str) static void reset(void) { free(buf); - mog_http_init(http, NULL); + mog_http_init(http, &svc); } static void buf_set(const char *s) diff --git a/test/mgmt_persist_client.rb b/test/mgmt_persist_client.rb new file mode 100644 index 0000000..00c59f7 --- /dev/null +++ b/test/mgmt_persist_client.rb @@ -0,0 +1,64 @@ +#!/usr/bin/env ruby +# -*- encoding: binary -*- +require 'test/test_helper' +require 'net/http' + +class TestMgmtPersistClient < Test::Unit::TestCase + def setup + @tmpdir = Dir.mktmpdir('mgmt-persist-client-test') + @host = TEST_HOST + + srv = TCPServer.new(@host, 0) + @port = srv.addr[1] + srv.close + + srv = TCPServer.new(@host, 0) + @httpport = srv.addr[1] + srv.close + + @pid = nil + @to_close = [] + @err = Tempfile.new("stderr") + Dir.mkdir("#@tmpdir/dev666") + cmd = [ "cmogstored", "--docroot=#@tmpdir", "--mgmtlisten=#@host:#@port", + "--httplisten=#@host:#@httpport", + "--maxconns=500" ] + vg = ENV["VALGRIND"] and cmd = vg.split(/\s+/).concat(cmd) + @pid = fork { + $stderr.reopen(@err) + @err.close + exec(*cmd) + } + @client = get_client + end + + def test_persist_toggle + { + "off" => "on", + "false" => "true", + "0" => "1", + "no" => "yes", + }.each do |f,t| + @client.write "SET mogstored.persist_client = #{f}\r\n" + assert_equal "\r\n", @client.gets + Net::HTTP.start(@host, @httpport) do |http| + resp = http.request(Net::HTTP::Head.new('/')) + assert_kind_of Net::HTTPOK, resp + assert_equal "close", resp["Connection"] + end + + @client.write "SET mogstored.persist_client = #{t}\r\n" + assert_equal "\r\n", @client.gets + Net::HTTP.start(@host, @httpport) do |http| + resp = http.request(Net::HTTP::Head.new('/')) + assert_kind_of Net::HTTPOK, resp + assert_equal "keep-alive", resp["Connection"] + end + end + end + + def teardown + @to_close.each { |io| io.close unless io.closed? } + FileUtils.rm_rf(@tmpdir) + end +end diff --git a/test/ruby.mk b/test/ruby.mk index 5e1a1ca..9280414 100644 --- a/test/ruby.mk +++ b/test/ruby.mk @@ -1,6 +1,6 @@ RB_TESTS_FAST = test/cmogstored-cfg.rb test/http_dav.rb test/http_range.rb \ test/http_put.rb test/http_getonly.rb test/inherit.rb test/upgrade.rb \ - test/http_put6_fail.rb test/epoll_enospc.rb + test/http_put6_fail.rb test/epoll_enospc.rb test/mgmt_persist_client.rb RB_TESTS_SLOW = test/mgmt-usage.rb test/mgmt.rb test/mgmt-iostat.rb \ test/http.rb test/http_put_slow.rb test/http_chunked_put.rb \ test/graceful_quit.rb test/http_idle_expire.rb \ -- cgit v1.2.3-24-ge0c7