Author: gsim
Date: Fri Dec 10 09:17:18 2010
New Revision: 1044248

URL: http://svn.apache.org/viewvc?rev=1044248&view=rev
Log:
QPID-2966: Add QMF method to dynamically set the log level.

Added:
    qpid/trunk/qpid/cpp/src/tests/dynamic_log_level_test   (with props)
    qpid/trunk/qpid/cpp/src/tests/qpid-ctrl   (with props)
Modified:
    qpid/trunk/qpid/cpp/include/qpid/log/Logger.h
    qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp
    qpid/trunk/qpid/cpp/src/qpid/broker/Broker.h
    qpid/trunk/qpid/cpp/src/qpid/log/Logger.cpp
    qpid/trunk/qpid/cpp/src/qpid/sys/BlockingQueue.h
    qpid/trunk/qpid/cpp/src/qpid/sys/Waitable.h
    qpid/trunk/qpid/cpp/src/tests/CMakeLists.txt
    qpid/trunk/qpid/cpp/src/tests/Makefile.am
    qpid/trunk/qpid/cpp/src/tests/ssl_test
    qpid/trunk/qpid/specs/management-schema.xml

Modified: qpid/trunk/qpid/cpp/include/qpid/log/Logger.h
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/include/qpid/log/Logger.h?rev=1044248&r1=1044247&r2=1044248&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/include/qpid/log/Logger.h (original)
+++ qpid/trunk/qpid/cpp/include/qpid/log/Logger.h Fri Dec 10 09:17:18 2010
@@ -74,6 +74,9 @@ class Logger : private boost::noncopyabl
     /** Configure logger from Options */
     QPID_COMMON_EXTERN void configure(const Options& o);
 
+    /** Reset the log selectors */
+    QPID_COMMON_EXTERN void reconfigure(const std::vector<std::string>& 
selectors);
+
     /** Add a statement. */
     QPID_COMMON_EXTERN void add(Statement& s);
 

Modified: qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp?rev=1044248&r1=1044247&r2=1044248&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp Fri Dec 10 09:17:18 2010
@@ -34,10 +34,15 @@
 
 #include "qmf/org/apache/qpid/broker/Package.h"
 #include "qmf/org/apache/qpid/broker/ArgsBrokerEcho.h"
+#include "qmf/org/apache/qpid/broker/ArgsBrokerGetLogLevel.h"
 #include "qmf/org/apache/qpid/broker/ArgsBrokerQueueMoveMessages.h"
+#include "qmf/org/apache/qpid/broker/ArgsBrokerSetLogLevel.h"
 #include "qpid/management/ManagementDirectExchange.h"
 #include "qpid/management/ManagementTopicExchange.h"
+#include "qpid/log/Logger.h"
+#include "qpid/log/Options.h"
 #include "qpid/log/Statement.h"
+#include "qpid/log/posix/SinkOptions.h"
 #include "qpid/framing/AMQFrame.h"
 #include "qpid/framing/ProtocolInitiation.h"
 #include "qpid/framing/Uuid.h"
@@ -51,6 +56,7 @@
 #include "qpid/sys/TimeoutHandler.h"
 #include "qpid/sys/SystemInfo.h"
 #include "qpid/Address.h"
+#include "qpid/StringUtils.h"
 #include "qpid/Url.h"
 #include "qpid/Version.h"
 
@@ -388,17 +394,21 @@ Manageable::status_t Broker::ManagementM
 {
     Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD;
 
-    QPID_LOG (debug, "Broker::ManagementMethod [id=" << methodId << "]");
-
     switch (methodId)
     {
     case _qmf::Broker::METHOD_ECHO :
+        QPID_LOG (debug, "Broker::echo("
+                  << dynamic_cast<_qmf::ArgsBrokerEcho&>(args).io_sequence 
+                  << ", " 
+                  << dynamic_cast<_qmf::ArgsBrokerEcho&>(args).io_body 
+                  << ")");
         status = Manageable::STATUS_OK;
         break;
     case _qmf::Broker::METHOD_CONNECT : {
         _qmf::ArgsBrokerConnect& hp=
             dynamic_cast<_qmf::ArgsBrokerConnect&>(args);
 
+        QPID_LOG (debug, "Broker::connect()");
         string transport = hp.i_transport.empty() ? TCP_TRANSPORT : 
hp.i_transport;
         if (!getProtocolFactory(transport)) {
             QPID_LOG(error, "Transport '" << transport << "' not supported");
@@ -415,13 +425,25 @@ Manageable::status_t Broker::ManagementM
     case _qmf::Broker::METHOD_QUEUEMOVEMESSAGES : {
         _qmf::ArgsBrokerQueueMoveMessages& moveArgs=
             dynamic_cast<_qmf::ArgsBrokerQueueMoveMessages&>(args);
+        QPID_LOG (debug, "Broker::queueMoveMessages()");
        if (queueMoveMessages(moveArgs.i_srcQueue, moveArgs.i_destQueue, 
moveArgs.i_qty))
             status = Manageable::STATUS_OK;
        else
             return Manageable::STATUS_PARAMETER_INVALID;
         break;
       }
+    case _qmf::Broker::METHOD_SETLOGLEVEL :
+        setLogLevel(dynamic_cast<_qmf::ArgsBrokerSetLogLevel&>(args).i_level);
+        QPID_LOG (debug, "Broker::setLogLevel()");
+        status = Manageable::STATUS_OK;
+        break;
+    case _qmf::Broker::METHOD_GETLOGLEVEL :
+        dynamic_cast<_qmf::ArgsBrokerGetLogLevel&>(args).o_level = 
getLogLevel();
+        QPID_LOG (debug, "Broker::getLogLevel()");
+        status = Manageable::STATUS_OK;
+        break;
    default:
+        QPID_LOG (debug, "Broker ManagementMethod not implemented: id=" << 
methodId << "]");
         status = Manageable::STATUS_NOT_IMPLEMENTED;
         break;
     }
@@ -429,6 +451,25 @@ Manageable::status_t Broker::ManagementM
     return status;
 }
 
+void Broker::setLogLevel(const std::string& level)
+{
+    QPID_LOG(notice, "Changing log level to " << level);
+    std::vector<std::string> selectors;
+    split(selectors, level, ", ");
+    qpid::log::Logger::instance().reconfigure(selectors);
+}
+
+std::string Broker::getLogLevel()
+{
+    std::string level;
+    const std::vector<std::string>& selectors = 
qpid::log::Logger::instance().getOptions().selectors;
+    for (std::vector<std::string>::const_iterator i = selectors.begin(); i != 
selectors.end(); ++i) {
+        if (i != selectors.begin()) level += std::string(",");
+        level += *i;        
+    }
+    return level;
+}
+
 boost::shared_ptr<ProtocolFactory> Broker::getProtocolFactory(const 
std::string& name) const {
     ProtocolFactoryMap::const_iterator i
         = name.empty() ? protocolFactories.begin() : 
protocolFactories.find(name);

Modified: qpid/trunk/qpid/cpp/src/qpid/broker/Broker.h
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.h?rev=1044248&r1=1044247&r2=1044248&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/broker/Broker.h (original)
+++ qpid/trunk/qpid/cpp/src/qpid/broker/Broker.h Fri Dec 10 09:17:18 2010
@@ -145,6 +145,8 @@ public:
 
     void declareStandardExchange(const std::string& name, const std::string& 
type);
     void setStore ();
+    void setLogLevel(const std::string& level);
+    std::string getLogLevel();
 
     boost::shared_ptr<sys::Poller> poller;
     sys::Timer timer;

Modified: qpid/trunk/qpid/cpp/src/qpid/log/Logger.cpp
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/log/Logger.cpp?rev=1044248&r1=1044247&r2=1044248&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/log/Logger.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/log/Logger.cpp Fri Dec 10 09:17:18 2010
@@ -146,6 +146,11 @@ void Logger::configure(const Options& op
     options.sinkOptions->setup(this);
 }
 
+void Logger::reconfigure(const std::vector<std::string>& selectors) {
+    options.selectors = selectors;
+    select(Selector(options));
+}
+
 void Logger::setPrefix(const std::string& p) { prefix = p; }
 
 }} // namespace qpid::log

Modified: qpid/trunk/qpid/cpp/src/qpid/sys/BlockingQueue.h
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/sys/BlockingQueue.h?rev=1044248&r1=1044247&r2=1044248&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/sys/BlockingQueue.h (original)
+++ qpid/trunk/qpid/cpp/src/qpid/sys/BlockingQueue.h Fri Dec 10 09:17:18 2010
@@ -53,9 +53,13 @@ public:
             Waitable::ScopedWait w(waitable);
             if (timeout == TIME_INFINITE) {
                 while (queue.empty()) waitable.wait();
-            } else {
+            } else if (timeout) {
                 AbsTime deadline(now(),timeout);
                 while (queue.empty() && deadline > now()) 
waitable.wait(deadline);
+            } else {
+                //ensure zero timeout pop does not miss the fact that
+                //queue is closed
+                waitable.checkException();
             }
         }
         if (queue.empty()) return false;

Modified: qpid/trunk/qpid/cpp/src/qpid/sys/Waitable.h
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/sys/Waitable.h?rev=1044248&r1=1044247&r2=1044248&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/sys/Waitable.h (original)
+++ qpid/trunk/qpid/cpp/src/qpid/sys/Waitable.h Fri Dec 10 09:17:18 2010
@@ -79,6 +79,9 @@ class Waitable : public Monitor {
     /** True if the waitable has an exception */
     bool hasException() const { return exception; }
 
+    /** Throws if the waitable has an exception */
+    void checkException() const { exception.raise(); }
+
     /** Clear the exception if any */
     void resetException() { exception.reset(); }
 

Modified: qpid/trunk/qpid/cpp/src/tests/CMakeLists.txt
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/CMakeLists.txt?rev=1044248&r1=1044247&r2=1044248&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/CMakeLists.txt (original)
+++ qpid/trunk/qpid/cpp/src/tests/CMakeLists.txt Fri Dec 10 09:17:18 2010
@@ -292,6 +292,7 @@ if (PYTHON_EXECUTABLE)
 if (BUILD_ACL)
   add_test (acl_tests ${shell} 
${CMAKE_CURRENT_SOURCE_DIR}/run_acl_tests${test_script_suffix})
 endif (BUILD_ACL)
+add_test (dynamic_log_level_test ${shell} 
${CMAKE_CURRENT_SOURCE_DIR}/dynamic_log_level_test${test_script_suffix})
 if (BUILD_MSSQL)
   add_test (store_tests ${shell} 
${CMAKE_CURRENT_SOURCE_DIR}/run_store_tests${test_script_suffix} MSSQL)
 endif (BUILD_MSSQL)

Modified: qpid/trunk/qpid/cpp/src/tests/Makefile.am
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/Makefile.am?rev=1044248&r1=1044247&r2=1044248&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/Makefile.am (original)
+++ qpid/trunk/qpid/cpp/src/tests/Makefile.am Fri Dec 10 09:17:18 2010
@@ -310,7 +310,7 @@ TESTS_ENVIRONMENT = \
     $(srcdir)/run_test 
 
 system_tests = qpid-client-test quick_perftest quick_topictest run_header_test 
quick_txtest
-TESTS += start_broker $(system_tests) python_tests stop_broker 
run_federation_tests run_acl_tests run_cli_tests replication_test
+TESTS += start_broker $(system_tests) python_tests stop_broker 
run_federation_tests run_acl_tests run_cli_tests replication_test 
dynamic_log_level_test
 
 EXTRA_DIST +=                                                          \
   run_test vg_check                                                    \
@@ -335,6 +335,8 @@ EXTRA_DIST +=                                               
                \
   run_perftest                                                         \
   ring_queue_test                                                      \
   run_ring_queue_test                                                  \
+  dynamic_log_level_test                                               \
+  qpid-ctrl                                                            \
   CMakeLists.txt                                                       \
   cluster.cmake                                                                
\
   windows/DisableWin32ErrorWindows.cpp                                 \

Added: qpid/trunk/qpid/cpp/src/tests/dynamic_log_level_test
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/dynamic_log_level_test?rev=1044248&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/dynamic_log_level_test (added)
+++ qpid/trunk/qpid/cpp/src/tests/dynamic_log_level_test Fri Dec 10 09:17:18 
2010
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# Run a simple test to verify dynamic log level changes
+source ./test_env.sh
+
+LOG_FILE=log_test.log
+trap cleanup EXIT
+
+cleanup() {
+    test -n "$PORT" && $QPIDD_EXEC --no-module-dir --quit --port $PORT
+}
+
+error() { 
+    echo $*;
+    exit 1;
+}
+
+rm -rf $LOG_FILE
+PORT=$($QPIDD_EXEC --auth=no --no-module-dir --daemon --port=0 --log-to-file 
$LOG_FILE) || error "Could not start broker"
+
+echo Broker for log level test started on $PORT, pid is $($QPIDD_EXEC 
--no-module-dir --check --port $PORT)
+
+$srcdir/qpid-ctrl -b localhost:$PORT setLogLevel level='notice+' > /dev/null
+$srcdir/qpid-ctrl -b localhost:$PORT echo sequence=1 body=HIDDEN > /dev/null
+$srcdir/qpid-ctrl -b localhost:$PORT setLogLevel level='debug+:Broker' > 
/dev/null
+$srcdir/qpid-ctrl -b localhost:$PORT echo sequence=2 body=VISIBLE > /dev/null
+$srcdir/qpid-ctrl -b localhost:$PORT setLogLevel level='notice+' > /dev/null
+
+#check log includes debug statement for last echo, but not the first
+if [[ $(grep echo $LOG_FILE | wc -l) -ne 1 ]]; then 
+   cat $LOG_FILE
+   error "Log contents not as expected"
+else
+  rm -rf $LOG_FILE
+  echo OK
+fi
+

Propchange: qpid/trunk/qpid/cpp/src/tests/dynamic_log_level_test
------------------------------------------------------------------------------
    svn:executable = *

Added: qpid/trunk/qpid/cpp/src/tests/qpid-ctrl
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/qpid-ctrl?rev=1044248&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/qpid-ctrl (added)
+++ qpid/trunk/qpid/cpp/src/tests/qpid-ctrl Fri Dec 10 09:17:18 2010
@@ -0,0 +1,117 @@
+#!/usr/bin/env python
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+import optparse
+from qpid.messaging import *
+from qpid.util import URL
+from qpid.log import enable, DEBUG, WARN
+
+def nameval(st):
+  idx = st.find("=")
+  if idx >= 0:
+    name = st[0:idx]
+    value = st[idx+1:]
+  else:
+    name = st
+    value = None
+  return name, value
+
+def list_map_entries(m):
+  r = ""
+  for t in m:
+    r += "%s=%s " % (t, m[t]) 
+  return r
+
+def get_qmfv2_result(m):
+  if m.properties['x-amqp-0-10.app-id'] == 'qmf2':
+    if m.properties['qmf.opcode'] == '_method_response':
+      return m.content['_arguments']
+    elif m.properties['qmf.opcode'] == '_exception':
+      raise Exception("Error: %s" % list_map_entries(m.content['_values']))
+    else: raise Exception("Invalid response received, unexpected opcode: %s" % 
m)
+  else: raise Exception("Invalid response received, not a qmfv2 method: %s" % 
m)
+
+
+parser = optparse.OptionParser(usage="usage: %prog [options] COMMAND ...",
+                               description="Invoke the specified command.")
+parser.add_option("-b", "--broker", default="localhost",
+                  help="connect to specified BROKER (default %default)")
+parser.add_option("-c", "--class", dest="qmfclass", default="broker", 
+                  help="class of object on which command is being invoked 
(default %default)")
+parser.add_option("-p", "--package", default="org.apache.qpid.broker",
+                  help="package of object on which command is being invoked 
(default %default)")
+parser.add_option("-i", "--id", default="amqp-broker",
+                  help="identifier of object on which command is being invoked 
(default %default)")
+parser.add_option("-a", "--address", default="qmf.default.direct/broker",
+                  help="address to send commands to (default %default)")
+parser.add_option("-t", "--timeout", type="float", default=5,
+                  help="timeout in seconds to wait for response before exiting 
(default %default)")
+parser.add_option("-v", dest="verbose", action="store_true",
+                  help="enable logging")
+
+opts, args = parser.parse_args()
+
+if opts.verbose:
+  enable("qpid", DEBUG)
+else:
+  enable("qpid", WARN)
+
+if args:
+  command = args.pop(0)
+else:
+  parser.error("command is required")
+
+
+conn = Connection(opts.broker)
+try:
+  conn.open()
+  ssn = conn.session()
+  snd = ssn.sender(opts.address)
+  reply_to = "qmf.default.direct/%s; {node: {type: topic}}" % str(uuid4())
+  rcv = ssn.receiver(reply_to)
+
+  object_name = "%s:%s:%s" % (opts.package, opts.qmfclass, opts.id)
+  method_name = command
+  arguments = {}
+  for a in args:
+    name, val = nameval(a)
+    arguments[name] = val
+  content = {
+             "_object_id": {"_object_name": object_name},
+             "_method_name": method_name,
+             "_arguments": arguments
+            } 
+  msg = Message(reply_to=reply_to, content=content)
+  msg.properties["x-amqp-0-10.app-id"] = "qmf2"
+  msg.properties["qmf.opcode"] = "_method_request"
+  snd.send(msg)
+
+  try:
+    print list_map_entries(get_qmfv2_result(rcv.fetch(timeout=opts.timeout)))
+  except Empty:
+    print "No response received!"
+  except Exception, e:
+    print e
+except ReceiverError, e:
+  print e
+except KeyboardInterrupt:
+  pass
+
+conn.close()

Propchange: qpid/trunk/qpid/cpp/src/tests/qpid-ctrl
------------------------------------------------------------------------------
    svn:executable = *

Modified: qpid/trunk/qpid/cpp/src/tests/ssl_test
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/ssl_test?rev=1044248&r1=1044247&r2=1044248&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/ssl_test (original)
+++ qpid/trunk/qpid/cpp/src/tests/ssl_test Fri Dec 10 09:17:18 2010
@@ -103,7 +103,7 @@ PORT1=`pick_port`; ssl_cluster_broker $P
 PORT2=`pick_port`; ssl_cluster_broker $PORT2
 
 # Pipe receive output to uniq to remove duplicates
-./qpid-receive --connection-options "{reconnect-timeout:5}" --failover-updates 
-b amqp:ssl:$TEST_HOSTNAME:$PORT1 -a "foo;{create:always}" -f | uniq > 
ssl_test_receive.tmp &
+./qpid-receive --connection-options "{reconnect:true, reconnect-timeout:5}" 
--failover-updates -b amqp:ssl:$TEST_HOSTNAME:$PORT1 -a "foo;{create:always}" 
-f | uniq > ssl_test_receive.tmp &
 ./qpid-send -b amqp:ssl:$TEST_HOSTNAME:$PORT2 --content-string=one -a 
"foo;{create:always}"
 ../qpidd --no-module-dir -qp $PORT1 # Kill broker 1 receiver should fail-over.
 ./qpid-send -b amqp:ssl:$TEST_HOSTNAME:$PORT2 --content-string=two -a 
"foo;{create:always}" --send-eos 1

Modified: qpid/trunk/qpid/specs/management-schema.xml
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/specs/management-schema.xml?rev=1044248&r1=1044247&r2=1044248&view=diff
==============================================================================
--- qpid/trunk/qpid/specs/management-schema.xml (original)
+++ qpid/trunk/qpid/specs/management-schema.xml Fri Dec 10 09:17:18 2010
@@ -94,6 +94,14 @@
       <arg name="qty"               dir="I" type="uint32" desc="# of messages 
to move. 0 means all messages"/>
     </method>
 
+    <method name="setLogLevel" desc="Set the log level">
+      <arg name="level"     dir="I" type="sstr"/>
+    </method>
+
+    <method name="getLogLevel" desc="Get the current log level">
+      <arg name="level"     dir="O" type="sstr"/>
+    </method>
+
   </class>
 
   <!--



---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:commits-subscr...@qpid.apache.org

Reply via email to