summaryrefslogtreecommitdiffstats
path: root/sca-cpp/trunk/components
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--sca-cpp/trunk/components/log/Makefile.am42
-rw-r--r--sca-cpp/trunk/components/log/client-test.cpp96
-rw-r--r--sca-cpp/trunk/components/log/fb303.thrift112
-rw-r--r--sca-cpp/trunk/components/log/log.composite2
-rw-r--r--sca-cpp/trunk/components/log/log.cpp94
-rwxr-xr-xsca-cpp/trunk/components/log/scribe-cat32
-rwxr-xr-xsca-cpp/trunk/components/log/scribe-test43
-rw-r--r--sca-cpp/trunk/components/log/scribe.hpp138
-rw-r--r--sca-cpp/trunk/components/log/scribe.thrift39
-rw-r--r--sca-cpp/trunk/components/log/scribecat.py44
-rwxr-xr-xsca-cpp/trunk/components/log/scribed-central-conf66
-rwxr-xr-xsca-cpp/trunk/components/log/scribed-central-start27
-rwxr-xr-xsca-cpp/trunk/components/log/scribed-central-stop28
-rwxr-xr-xsca-cpp/trunk/components/log/scribed-client-conf60
-rwxr-xr-xsca-cpp/trunk/components/log/scribed-client-start27
-rwxr-xr-xsca-cpp/trunk/components/log/scribed-client-stop28
-rwxr-xr-xsca-cpp/trunk/components/log/server-test53
17 files changed, 911 insertions, 20 deletions
diff --git a/sca-cpp/trunk/components/log/Makefile.am b/sca-cpp/trunk/components/log/Makefile.am
index e9e742d8c8..5083ac48a2 100644
--- a/sca-cpp/trunk/components/log/Makefile.am
+++ b/sca-cpp/trunk/components/log/Makefile.am
@@ -17,30 +17,34 @@
if WANT_LOG
-INCLUDES = -I${SCRIBE_INCLUDE}
+INCLUDES = -I${THRIFT_INCLUDE} -I${FB303_INCLUDE}
-#comp_SCRIPTS = qpidd-start qpidd-stop
+comp_SCRIPTS = scribed-central-conf scribed-client-conf scribed-central-start scribed-central-stop scribed-client-start scribed-client-stop
compdir=$(prefix)/components/log
-comp_DATA = scribe.prefix
+comp_DATA = scribe.prefix thrift.prefix
scribe.prefix: $(top_builddir)/config.status
echo ${SCRIBE_PREFIX} >scribe.prefix
-#comp_LTLIBRARIES = libqueue-sender.la libqueue-listener.la
-#
-#libqueue_sender_la_SOURCES = queue-sender.cpp
-#libqueue_sender_la_LDFLAGS = -L${QPIDC_LIB} -R${QPIDC_LIB} -lqpidclient -lqpidcommon
-#
-#libqueue_listener_la_SOURCES = queue-listener.cpp
-#libqueue_listener_la_LDFLAGS = -L${QPIDC_LIB} -R${QPIDC_LIB} -lqpidclient -lqpidcommon
-#
-#qpid_test_SOURCES = qpid-test.cpp
-#qpid_test_LDFLAGS = -L${QPIDC_LIB} -R${QPIDC_LIB} -lqpidclient -lqpidcommon
-#
-#client_test_SOURCES = client-test.cpp
-#client_test_LDFLAGS = -lxml2 -lcurl -lmozjs -L${QPIDC_LIB} -R${QPIDC_LIB} -lqpidclient -lqpidcommon
-#
-#noinst_PROGRAMS = qpid-test client-test
-#TESTS = send-test server-test
+thrift.prefix: $(top_builddir)/config.status
+ echo ${THRIFT_PREFIX} >thrift.prefix
+
+BUILT_SOURCES=gen-cpp/fb303_constants.cpp gen-cpp/fb303_types.cpp gen-cpp/scribe_constants.cpp gen-cpp/scribe.cpp gen-cpp/scribe_types.cpp gen-cpp/FacebookService.cpp gen-cpp/scribe.h
+gen-cpp/fb303_constants.cpp gen-cpp/fb303_types.cpp gen-cpp/scribe_constants.cpp gen-cpp/scribe.cpp gen-cpp/scribe_types.cpp gen-cpp/FacebookService.cpp gen-cpp/scribe.h: scribe.thrift
+ ${THRIFT_PREFIX}/bin/thrift -r --gen cpp scribe.thrift
+
+CLEANFILES = gen-cpp/*
+
+comp_LTLIBRARIES = liblog.la
+nodist_liblog_la_SOURCES = gen-cpp/fb303_constants.cpp gen-cpp/fb303_types.cpp gen-cpp/scribe_constants.cpp gen-cpp/scribe.cpp gen-cpp/scribe_types.cpp gen-cpp/FacebookService.cpp gen-cpp/scribe.h
+liblog_la_CXXFLAGS = -Wno-unused-parameter
+liblog_la_SOURCES = log.cpp
+liblog_la_LDFLAGS = -L${THRIFT_LIB} -R${THRIFT_LIB} -lthrift -L${FB303_LIB} -R${FB303_LIB} -lfb303 -L${SCRIBE_LIB} -R${SCRIBE_LIB} -lscribe
+
+client_test_SOURCES = client-test.cpp
+client_test_LDFLAGS = -lxml2 -lcurl -lmozjs
+
+noinst_PROGRAMS = client-test
+TESTS = scribe-test server-test
endif
diff --git a/sca-cpp/trunk/components/log/client-test.cpp b/sca-cpp/trunk/components/log/client-test.cpp
new file mode 100644
index 0000000000..685534df8a
--- /dev/null
+++ b/sca-cpp/trunk/components/log/client-test.cpp
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+/* $Rev$ $Date$ */
+
+/**
+ * Test log component.
+ */
+
+#include <assert.h>
+#include "stream.hpp"
+#include "string.hpp"
+
+#include "list.hpp"
+#include "value.hpp"
+#include "monad.hpp"
+#include "perf.hpp"
+#include "../../modules/http/curl.hpp"
+
+namespace tuscany {
+namespace log {
+
+const string uri("http://localhost:8090/log");
+
+bool testLog() {
+ http::CURLSession cs;
+
+ const list<value> i = list<value>()
+ + (list<value>() + "name" + string("Apple"))
+ + (list<value>() + "price" + string("$2.99"));
+ const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
+
+ const failable<value> id = http::post(a, uri, cs);
+ assert(hasContent(id));
+
+ return true;
+}
+
+struct logLoop {
+ const value a;
+ const string uri;
+ http::CURLSession cs;
+ logLoop(const value& a, const string& uri, http::CURLSession cs) : a(a), uri(uri), cs(cs) {
+ }
+ const bool operator()() const {
+ const failable<value> id = http::post(a, uri, cs);
+ assert(hasContent(id));
+ return true;
+ }
+};
+
+bool testLogPerf() {
+ const list<value> i = list<value>()
+ + (list<value>() + "name" + string("Apple"))
+ + (list<value>() + "price" + string("$4.55"));
+ const value a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
+
+ http::CURLSession cs;
+ const failable<value> id = http::post(a, uri, cs);
+ assert(hasContent(id));
+
+ const lambda<bool()> ll = logLoop(a, uri, cs);
+ cout << "Log test " << time(ll, 5, 200) << " ms" << endl;
+
+ return true;
+}
+
+}
+}
+
+int main() {
+ tuscany::cout << "Testing..." << tuscany::endl;
+
+ tuscany::log::testLog();
+ tuscany::log::testLogPerf();
+
+ tuscany::cout << "OK" << tuscany::endl;
+
+ return 0;
+}
diff --git a/sca-cpp/trunk/components/log/fb303.thrift b/sca-cpp/trunk/components/log/fb303.thrift
new file mode 100644
index 0000000000..66c8315274
--- /dev/null
+++ b/sca-cpp/trunk/components/log/fb303.thrift
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+/**
+ * fb303.thrift
+ */
+
+namespace java com.facebook.fb303
+namespace cpp facebook.fb303
+namespace perl Facebook.FB303
+
+/**
+ * Common status reporting mechanism across all services
+ */
+enum fb_status {
+ DEAD = 0,
+ STARTING = 1,
+ ALIVE = 2,
+ STOPPING = 3,
+ STOPPED = 4,
+ WARNING = 5,
+}
+
+/**
+ * Standard base service
+ */
+service FacebookService {
+
+ /**
+ * Returns a descriptive name of the service
+ */
+ string getName(),
+
+ /**
+ * Returns the version of the service
+ */
+ string getVersion(),
+
+ /**
+ * Gets the status of this service
+ */
+ fb_status getStatus(),
+
+ /**
+ * User friendly description of status, such as why the service is in
+ * the dead or warning state, or what is being started or stopped.
+ */
+ string getStatusDetails(),
+
+ /**
+ * Gets the counters for this service
+ */
+ map<string, i64> getCounters(),
+
+ /**
+ * Gets the value of a single counter
+ */
+ i64 getCounter(1: string key),
+
+ /**
+ * Sets an option
+ */
+ void setOption(1: string key, 2: string value),
+
+ /**
+ * Gets an option
+ */
+ string getOption(1: string key),
+
+ /**
+ * Gets all options
+ */
+ map<string, string> getOptions(),
+
+ /**
+ * Returns a CPU profile over the given time interval (client and server
+ * must agree on the profile format).
+ */
+ string getCpuProfile(1: i32 profileDurationInSec),
+
+ /**
+ * Returns the unix time that the server has been running since
+ */
+ i64 aliveSince(),
+
+ /**
+ * Tell the server to reload its configuration, reopen log files, etc
+ */
+ oneway void reinitialize(),
+
+ /**
+ * Suggest a shutdown to the server
+ */
+ oneway void shutdown(),
+
+}
diff --git a/sca-cpp/trunk/components/log/log.composite b/sca-cpp/trunk/components/log/log.composite
index 2b0a557e4e..9b3747d142 100644
--- a/sca-cpp/trunk/components/log/log.composite
+++ b/sca-cpp/trunk/components/log/log.composite
@@ -24,7 +24,7 @@
<component name="log">
<implementation.cpp path=".libs" library="liblog"/>
- <property name="file">sample.log</property>property>
+ <property name="category">default</property>
<service name="log">
<t:binding.http uri="log"/>
</service>
diff --git a/sca-cpp/trunk/components/log/log.cpp b/sca-cpp/trunk/components/log/log.cpp
new file mode 100644
index 0000000000..24a5844c45
--- /dev/null
+++ b/sca-cpp/trunk/components/log/log.cpp
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+/* $Rev$ $Date$ */
+
+/**
+ * Scribe-based log component implementation.
+ */
+
+#include "string.hpp"
+#include "function.hpp"
+#include "list.hpp"
+#include "value.hpp"
+#include "monad.hpp"
+#include "scribe.hpp"
+
+namespace tuscany {
+namespace log {
+
+/**
+ * Post an item to the Scribe log.
+ */
+const failable<value> post(const list<value>& params, const value& category, scribe::Scribe& sc) {
+ debug(cadr(params), "log::post::value");
+ const failable<bool> val = scribe::log(cadr(params), category, sc);
+ if (!hasContent(val))
+ return mkfailure<value>(reason(val));
+ return value(mklist<value>(true));
+}
+
+/**
+ * Component implementation lambda function.
+ */
+class applyLog {
+public:
+ applyLog(const value& category, scribe::Scribe& sc) : category(category), sc(sc) {
+ }
+
+ const value operator()(const list<value>& params) const {
+ const value func(car(params));
+ if (func == "post")
+ return post(cdr(params), category, sc);
+ return tuscany::mkfailure<tuscany::value>();
+ }
+
+private:
+ const value category;
+ scribe::Scribe& sc;
+};
+
+/**
+ * Start the component.
+ */
+const failable<value> start(unused const list<value>& params) {
+ // Connect to Scribe
+ scribe::Scribe& sc = *(new (gc_new<scribe::Scribe>()) scribe::Scribe("localhost", 1464));
+
+ // Extract the configured category
+ const value category = ((lambda<value(list<value>)>)car(params))(list<value>());
+ debug(category, "log::start::category");
+
+ // Return the component implementation lambda function
+ return value(lambda<value(const list<value>&)>(applyLog(category, sc)));
+}
+
+}
+}
+
+extern "C" {
+
+const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
+ const tuscany::value func(car(params));
+ if (func == "start")
+ return tuscany::log::start(cdr(params));
+ return tuscany::mkfailure<tuscany::value>();
+}
+
+}
diff --git a/sca-cpp/trunk/components/log/scribe-cat b/sca-cpp/trunk/components/log/scribe-cat
new file mode 100755
index 0000000000..812e7e7a54
--- /dev/null
+++ b/sca-cpp/trunk/components/log/scribe-cat
@@ -0,0 +1,32 @@
+#!/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.
+
+# Write messages to Scribe
+here=`readlink -f $0`; here=`dirname $here`
+category=$1
+if [ "$category" = "" ]; then
+ category="default"
+fi
+
+python_prefix=`cat $here/../../modules/python/python.prefix`
+scribe_prefix=`cat $here/scribe.prefix`
+thrift_prefix=`cat $here/thrift.prefix`
+export PYTHONPATH=$PYTHONPATH:${thrift_prefix}/lib/python2.6/site-packages:${thrift_prefix}/contrib/fb303/lib/python2.6/site-packages:${scribe_prefix}/lib/python2.6/site-packages
+$python_prefix/bin/python $here/scribecat.py $category
+
diff --git a/sca-cpp/trunk/components/log/scribe-test b/sca-cpp/trunk/components/log/scribe-test
new file mode 100755
index 0000000000..77bf795c9f
--- /dev/null
+++ b/sca-cpp/trunk/components/log/scribe-test
@@ -0,0 +1,43 @@
+#!/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.
+
+echo "Testing..."
+
+# Setup
+rm -rf tmp
+./scribed-central-conf tmp
+./scribed-client-conf tmp localhost
+./scribed-central-start tmp
+./scribed-client-start tmp
+sleep 1
+
+# Test logging a message
+echo test | ./scribe-cat
+sleep 4
+grep test tmp/scribe/logs/central/default/* >/dev/null
+rc=$?
+
+# Cleanup
+./scribed-client-stop tmp
+./scribed-central-stop tmp
+sleep 1
+if [ "$rc" = "0" ]; then
+ echo "OK"
+fi
+return $rc
diff --git a/sca-cpp/trunk/components/log/scribe.hpp b/sca-cpp/trunk/components/log/scribe.hpp
new file mode 100644
index 0000000000..a0cb11fe8e
--- /dev/null
+++ b/sca-cpp/trunk/components/log/scribe.hpp
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+
+/* $Rev$ $Date$ */
+
+#ifndef tuscany_scribe_hpp
+#define tuscany_scribe_hpp
+
+/**
+ * Scribe logging functions.
+ */
+
+// Work around redundant defines in Scribe headers
+#undef PACKAGE
+#undef PACKAGE_BUGREPORT
+#undef PACKAGE_NAME
+#undef PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#undef PACKAGE_VERSION
+#undef VERSION
+
+#include <protocol/TBinaryProtocol.h>
+#include <transport/TSocket.h>
+#include <transport/TTransportUtils.h>
+
+#include "gen-cpp/scribe.h"
+
+#include "string.hpp"
+#include "list.hpp"
+#include "value.hpp"
+#include "monad.hpp"
+#include "../../modules/scheme/eval.hpp"
+
+namespace tuscany {
+namespace scribe {
+
+/**
+ * Represents a Scribe connection.
+ */
+class Scribe {
+public:
+ Scribe() : owner(false) {
+ }
+
+ Scribe(const string host, const int port) : owner(true) {
+ init(host, port);
+ }
+
+ Scribe(const Scribe& c) : owner(false) {
+ client = c.client;
+ transport = c.transport;
+ }
+
+ ~Scribe() {
+ if (!owner)
+ return;
+ try {
+ transport->close();
+ delete client;
+ } catch (const std::exception& e) {
+ mkfailure<bool>(e.what());
+ }
+ }
+
+private:
+ bool owner;
+ ::scribe::thrift::scribeClient* client;
+ boost::shared_ptr<apache::thrift::transport::TTransport> transport;
+
+ friend const failable<bool> log(const value& val, const value& category, const Scribe& sc);
+
+ /**
+ * Initialize the Scribe connection.
+ */
+ const failable<bool> init(const string& host, const int port) {
+ try {
+ boost::shared_ptr<apache::thrift::transport::TTransport> sock(new apache::thrift::transport::TSocket(c_str(host), port));
+ boost::shared_ptr<apache::thrift::transport::TFramedTransport> framedSock(new apache::thrift::transport::TFramedTransport(sock));
+ transport = framedSock;
+ boost::shared_ptr<apache::thrift::protocol::TProtocol> proto(new apache::thrift::protocol::TBinaryProtocol(transport));
+ client = new ::scribe::thrift::scribeClient(proto);
+ transport->open();
+ return true;
+ } catch (const std::exception& e) {
+ return mkfailure<bool>(e.what());
+ }
+ }
+};
+
+/**
+ * Log an item.
+ */
+const failable<bool> log(const value& val, const value& category, const Scribe& sc) {
+ debug(val, "scribe::log::value");
+ debug(category, "scribe::log::category");
+
+ const value cat = isString(category)? value(c_str(category)):category;
+ const string cs(scheme::writeValue(cat));
+ const string vs(scheme::writeValue(val));
+
+ try {
+ ::scribe::thrift::LogEntry entry;
+ entry.category = c_str(cs);
+ entry.message = c_str(vs);
+ std::vector< ::scribe::thrift::LogEntry> msgs;
+ msgs.push_back(entry);
+
+ int result = sc.client->Log(msgs);
+ if (result != ::scribe::thrift::OK)
+ return mkfailure<bool>("Could not log value, retry later");
+ } catch (const std::exception& e) {
+ return mkfailure<bool>(e.what());
+ }
+
+ debug(true, "scribe::log::result");
+ return true;
+}
+
+}
+}
+
+#endif /* tuscany_scribe_hpp */
diff --git a/sca-cpp/trunk/components/log/scribe.thrift b/sca-cpp/trunk/components/log/scribe.thrift
new file mode 100644
index 0000000000..592e8b630e
--- /dev/null
+++ b/sca-cpp/trunk/components/log/scribe.thrift
@@ -0,0 +1,39 @@
+#!/usr/local/bin/thrift --cpp --php
+
+## Copyright (c) 2007-2008 Facebook
+##
+## Licensed 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.
+##
+## See accompanying file LICENSE or visit the Scribe site at:
+## http://developers.facebook.com/scribe/
+
+include "fb303.thrift"
+
+namespace cpp scribe.thrift
+
+enum ResultCode
+{
+ OK,
+ TRY_LATER
+}
+
+struct LogEntry
+{
+ 1: string category,
+ 2: string message
+}
+
+service scribe extends fb303.FacebookService
+{
+ ResultCode Log(1: list<LogEntry> messages);
+}
diff --git a/sca-cpp/trunk/components/log/scribecat.py b/sca-cpp/trunk/components/log/scribecat.py
new file mode 100644
index 0000000000..b0fef42fbf
--- /dev/null
+++ b/sca-cpp/trunk/components/log/scribecat.py
@@ -0,0 +1,44 @@
+# 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.
+
+# Write messages to Scribe
+
+import sys
+from scribe import scribe
+from thrift.transport import TTransport, TSocket
+from thrift.protocol import TBinaryProtocol
+
+category = sys.argv[1]
+host = 'localhost'
+port = 1464
+
+entry = scribe.LogEntry(category=category, message=sys.stdin.read())
+socket = TSocket.TSocket(host=host, port=port)
+transport = TTransport.TFramedTransport(socket)
+protocol = TBinaryProtocol.TBinaryProtocol(trans=transport, strictRead=False, strictWrite=False)
+client = scribe.Client(iprot=protocol, oprot=protocol)
+transport.open()
+result = client.Log(messages=[entry])
+transport.close()
+
+if result == scribe.ResultCode.OK:
+ sys.exit()
+if result == scribe.ResultCode.TRY_LATER:
+ print >> sys.stderr, "Try later"
+ sys.exit(84)
+sys.exit(result)
+
diff --git a/sca-cpp/trunk/components/log/scribed-central-conf b/sca-cpp/trunk/components/log/scribed-central-conf
new file mode 100755
index 0000000000..458cbdebca
--- /dev/null
+++ b/sca-cpp/trunk/components/log/scribed-central-conf
@@ -0,0 +1,66 @@
+#!/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.
+
+# Generate a Scribe central conf
+here=`readlink -f $0`; here=`dirname $here`
+root=`readlink -f $1`
+
+mkdir -p $root/scribe/conf
+mkdir -p $root/scribe/logs/central
+mkdir -p $root/scribe/logs/central-secondary
+
+cat >$root/scribe/conf/scribe-central.conf <<EOF
+# Scribe central configuration
+port=1463
+max_msg_per_second=2000000
+check_interval=3
+
+# Log store configuration
+<store>
+category=default
+type=buffer
+
+target_write_size=20480
+max_write_interval=1
+buffer_send_rate=2
+retry_interval=30
+retry_interval_range=10
+
+<primary>
+type=file
+fs_type=std
+file_path=$root/scribe/logs/central
+base_filename=central
+max_size=1000000
+add_newlines=1
+rotate_period=daily
+rotate_hour=0
+rotate_minute=10
+</primary>
+
+<secondary>
+type=file
+fs_type=std
+file_path=$root/scribe/logs/central-secondary
+base_filename=central
+max_size=3000000
+</secondary>
+
+</store>
+EOF
diff --git a/sca-cpp/trunk/components/log/scribed-central-start b/sca-cpp/trunk/components/log/scribed-central-start
new file mode 100755
index 0000000000..c2035037de
--- /dev/null
+++ b/sca-cpp/trunk/components/log/scribed-central-start
@@ -0,0 +1,27 @@
+#!/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.
+
+# Start central scribed
+here=`readlink -f $0`; here=`dirname $here`
+root=`readlink -f $1`
+
+scribe_prefix=`cat $here/scribe.prefix`
+thrift_prefix=`cat $here/thrift.prefix`
+export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${thrift_prefix}/lib:${thrift_prefix}/contrib/fb303/lib:${scribe_prefix}/lib
+$scribe_prefix/bin/scribed -c $root/scribe/conf/scribe-central.conf 1>$root/scribe/logs/central.log 2>&1 &
diff --git a/sca-cpp/trunk/components/log/scribed-central-stop b/sca-cpp/trunk/components/log/scribed-central-stop
new file mode 100755
index 0000000000..95a976813f
--- /dev/null
+++ b/sca-cpp/trunk/components/log/scribed-central-stop
@@ -0,0 +1,28 @@
+#!/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.
+
+# Stop central scribed
+here=`readlink -f $0`; here=`dirname $here`
+root=`readlink -f $1`
+
+scribe_prefix=`cat $here/scribe.prefix`
+thrift_prefix=`cat $here/thrift.prefix`
+scribed="$scribe_prefix/bin/scribed -c $root/scribe/conf/scribe-central.conf"
+
+kill `ps -ef | grep -v grep | grep "${scribed}" | awk '{ print $2 }'`
diff --git a/sca-cpp/trunk/components/log/scribed-client-conf b/sca-cpp/trunk/components/log/scribed-client-conf
new file mode 100755
index 0000000000..c813f21ced
--- /dev/null
+++ b/sca-cpp/trunk/components/log/scribed-client-conf
@@ -0,0 +1,60 @@
+#!/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.
+
+# Generate a Scribe client conf
+here=`readlink -f $0`; here=`dirname $here`
+root=`readlink -f $1`
+central=$2
+
+mkdir -p $root/scribe/conf
+mkdir -p $root/scribe/logs/client-secondary
+
+cat >$root/scribe/conf/scribe-client.conf <<EOF
+# Scribe client configuration
+port=1464
+max_msg_per_second=2000000
+check_interval=3
+
+# Forward all messages to central Scribe on port 1463
+# Save them locally as well
+<store>
+category=default
+type=buffer
+
+target_write_size=20480
+max_write_interval=1
+buffer_send_rate=1
+retry_interval=30
+retry_interval_range=10
+
+<primary>
+type=network
+remote_host=$2
+remote_port=1463
+</primary>
+
+<secondary>
+type=file
+fs_type=std
+file_path=$root/scribe/logs/client-secondary
+base_filename=client
+max_size=3000000
+</secondary>
+</store>
+EOF
diff --git a/sca-cpp/trunk/components/log/scribed-client-start b/sca-cpp/trunk/components/log/scribed-client-start
new file mode 100755
index 0000000000..ed8636d7f2
--- /dev/null
+++ b/sca-cpp/trunk/components/log/scribed-client-start
@@ -0,0 +1,27 @@
+#!/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.
+
+# Start client scribed
+here=`readlink -f $0`; here=`dirname $here`
+root=`readlink -f $1`
+
+scribe_prefix=`cat $here/scribe.prefix`
+thrift_prefix=`cat $here/thrift.prefix`
+export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${thrift_prefix}/lib:${thrift_prefix}/contrib/fb303/lib:${scribe_prefix}/lib
+$scribe_prefix/bin/scribed -c $root/scribe/conf/scribe-client.conf 1>$root/scribe/logs/client.log 2>&1 &
diff --git a/sca-cpp/trunk/components/log/scribed-client-stop b/sca-cpp/trunk/components/log/scribed-client-stop
new file mode 100755
index 0000000000..2e8959fbfc
--- /dev/null
+++ b/sca-cpp/trunk/components/log/scribed-client-stop
@@ -0,0 +1,28 @@
+#!/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.
+
+# Stop client scribed
+here=`readlink -f $0`; here=`dirname $here`
+root=`readlink -f $1`
+
+scribe_prefix=`cat $here/scribe.prefix`
+thrift_prefix=`cat $here/thrift.prefix`
+scribed="$scribe_prefix/bin/scribed -c $root/scribe/conf/scribe-client.conf"
+
+kill `ps -ef | grep -v grep | grep "${scribed}" | awk '{ print $2 }'`
diff --git a/sca-cpp/trunk/components/log/server-test b/sca-cpp/trunk/components/log/server-test
new file mode 100755
index 0000000000..9f14bcee8d
--- /dev/null
+++ b/sca-cpp/trunk/components/log/server-test
@@ -0,0 +1,53 @@
+#!/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.
+
+# Setup
+../../modules/http/httpd-conf tmp localhost 8090 ../../modules/http/htdocs
+../../modules/server/server-conf tmp
+../../modules/server/scheme-conf tmp
+cat >>tmp/conf/httpd.conf <<EOF
+SCAContribution `pwd`/
+SCAComposite log.composite
+EOF
+
+rm -rf tmp/scribe
+./scribed-central-conf tmp
+./scribed-client-conf tmp localhost
+./scribed-central-start tmp
+./scribed-client-start tmp
+sleep 1
+../../modules/http/httpd-start tmp
+sleep 2
+
+# Test
+./client-test 2>/dev/null
+rc=$?
+if [ "$rc" = "0" ]; then
+ sleep 4
+ grep "Apple" tmp/scribe/logs/central/default/* >/dev/null
+ rc=$?
+fi
+
+# Cleanup
+../../modules/http/httpd-stop tmp
+sleep 1
+./scribed-client-stop tmp
+./scribed-central-stop tmp
+sleep 1
+return $rc