You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ac...@apache.org on 2006/12/01 06:11:53 UTC

svn commit: r481159 [10/12] - in /incubator/qpid/trunk/qpid/cpp: ./ build-aux/ gen/ lib/ lib/broker/ lib/client/ lib/common/ lib/common/framing/ lib/common/sys/ lib/common/sys/apr/ lib/common/sys/posix/ m4/ src/ src/qpid/ src/qpid/apr/ src/qpid/broker/...

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/Socket.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/Socket.h
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/Thread.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/Thread.h?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/Thread.h (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/Thread.h Thu Nov 30 21:11:45 2006
@@ -0,0 +1,142 @@
+#ifndef _sys_Thread_h
+#define _sys_Thread_h
+
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <sys/Runnable.h>
+
+#ifdef USE_APR
+#  include <apr_thread_proc.h>
+#  include <apr_portable.h>
+#  include <apr/APRPool.h>
+#  include <apr/APRBase.h>
+#else
+#  include <posix/check.h>
+#  include <pthread.h>
+#endif
+
+namespace qpid {
+namespace sys {
+
+class Thread
+{
+  public:
+    inline static Thread current();
+    inline static void yield();
+
+    inline Thread();
+    inline explicit Thread(qpid::sys::Runnable*);
+    inline explicit Thread(qpid::sys::Runnable&);
+    
+    inline void join();
+
+    inline long id();
+        
+  private:
+#ifdef USE_APR
+    static void* APR_THREAD_FUNC runRunnable(apr_thread_t* thread, void *data);
+    inline Thread(apr_thread_t* t);
+    apr_thread_t* thread;
+#else
+    static void* runRunnable(void* runnable);
+    inline Thread(pthread_t);
+    pthread_t thread;
+#endif    
+};
+
+
+Thread::Thread() : thread(0) {}
+
+// APR ================================================================
+#ifdef USE_APR
+
+Thread::Thread(Runnable* runnable) {
+    CHECK_APR_SUCCESS(
+        apr_thread_create(&thread, 0, runRunnable, runnable, APRPool::get()));
+}
+
+Thread::Thread(Runnable& runnable) {
+    CHECK_APR_SUCCESS(
+        apr_thread_create(&thread, 0, runRunnable, &runnable, APRPool::get()));
+}
+
+void Thread::join(){
+    apr_status_t status;
+    if (thread != 0) 
+        CHECK_APR_SUCCESS(apr_thread_join(&status, thread));
+}
+
+long Thread::id() {
+    return long(thread);
+}
+
+Thread::Thread(apr_thread_t* t) : thread(t) {}
+
+Thread Thread::current(){
+    apr_thread_t* thr;
+    apr_os_thread_t osthr = apr_os_thread_current();
+    CHECK_APR_SUCCESS(apr_os_thread_put(&thr, &osthr, APRPool::get()));
+    return Thread(thr);
+}
+
+void Thread::yield() 
+{
+    apr_thread_yield();
+}
+
+
+// POSIX ================================================================
+#else
+
+Thread::Thread(Runnable* runnable) {
+    QPID_POSIX_THROW_IF(pthread_create(&thread, NULL, runRunnable, runnable));
+}
+
+Thread::Thread(Runnable& runnable) {
+    QPID_POSIX_THROW_IF(pthread_create(&thread, NULL, runRunnable, &runnable));
+}
+
+void Thread::join(){
+    QPID_POSIX_THROW_IF(pthread_join(thread, 0));
+}
+
+long Thread::id() {
+    return long(thread);
+}
+
+Thread::Thread(pthread_t thr) : thread(thr) {}
+
+Thread Thread::current() {
+    return Thread(pthread_self());
+}
+
+void Thread::yield() 
+{
+    QPID_POSIX_THROW_IF(pthread_yield());
+}
+
+
+#endif
+
+}}
+
+#endif  /*!_sys_Thread_h*/

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/Thread.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/Thread.h
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/Time.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/Time.cpp?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/Time.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/Time.cpp Thu Nov 30 21:11:45 2006
@@ -0,0 +1,60 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include "Time.h"
+
+namespace qpid {
+namespace sys {
+
+// APR ================================================================
+#if USE_APR
+
+Time now() { return apr_time_now() * TIME_USEC; }
+
+// POSIX================================================================
+#else 
+
+Time now() {
+    struct timespec ts;
+    clock_gettime(CLOCK_REALTIME, &ts);
+    return toTime(ts);
+}
+
+struct timespec toTimespec(const Time& t) {
+    struct timespec ts;
+    toTimespec(ts, t);
+    return ts;
+}
+
+struct timespec& toTimespec(struct timespec& ts, const Time& t) {
+    ts.tv_sec  = t / TIME_SEC;
+    ts.tv_nsec = t % TIME_SEC;
+    return  ts;
+}
+
+Time toTime(const struct timespec& ts) {
+    return ts.tv_sec*TIME_SEC + ts.tv_nsec;
+}
+
+
+#endif
+}}
+

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/Time.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/Time.cpp
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/Time.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/Time.h?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/Time.h (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/Time.h Thu Nov 30 21:11:45 2006
@@ -0,0 +1,58 @@
+#ifndef _sys_Time_h
+#define _sys_Time_h
+
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <stdint.h>
+
+#ifdef USE_APR
+#  include <apr_time.h>
+#else
+#  include <time.h>
+#endif
+
+namespace qpid {
+namespace sys {
+
+/** Time in nanoseconds */
+typedef int64_t Time;
+
+Time now();
+
+/** Nanoseconds per second. */
+const Time TIME_SEC  = 1000*1000*1000;
+/** Nanoseconds per millisecond */
+const Time TIME_MSEC = 1000*1000;
+/** Nanoseconds per microseconds. */
+const Time TIME_USEC = 1000;
+/** Nanoseconds per nanosecond. */
+const Time TIME_NSEC = 1;
+
+#ifndef USE_APR
+struct timespec toTimespec(const Time& t);
+struct timespec& toTimespec(struct timespec& ts, const Time& t);
+Time toTime(const struct timespec& ts);
+#endif
+
+}}
+
+#endif  /*!_sys_Time_h*/

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/Time.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/Time.h
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/TimeoutHandler.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/TimeoutHandler.h?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/TimeoutHandler.h (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/TimeoutHandler.h Thu Nov 30 21:11:45 2006
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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.
+ *
+ */
+#ifndef _TimeoutHandler_
+#define _TimeoutHandler_
+
+namespace qpid {
+namespace sys {
+
+    class TimeoutHandler
+    {
+    public:
+	virtual void idleOut() = 0;
+	virtual void idleIn() = 0;
+	virtual ~TimeoutHandler(){}
+    };
+
+}
+}
+
+
+#endif

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/TimeoutHandler.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/TimeoutHandler.h
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRAcceptor.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRAcceptor.cpp?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRAcceptor.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRAcceptor.cpp Thu Nov 30 21:11:45 2006
@@ -0,0 +1,110 @@
+/*
+ *
+ * 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.
+ *
+ */
+#include <sys/Acceptor.h>
+#include <sys/SessionHandlerFactory.h>
+#include "LFProcessor.h"
+#include "LFSessionContext.h"
+#include "APRBase.h"
+#include "APRPool.h"
+
+namespace qpid {
+namespace sys {
+
+class APRAcceptor : public Acceptor
+{
+  public:
+    APRAcceptor(int16_t port, int backlog, int threads, bool trace);
+    virtual int16_t getPort() const;
+    virtual void run(qpid::sys::SessionHandlerFactory* factory);
+    virtual void shutdown();
+
+  private:
+    int16_t port;
+    bool trace;
+    LFProcessor processor;
+    apr_socket_t* socket;
+    volatile bool running;
+};
+
+// Define generic Acceptor::create() to return APRAcceptor.
+Acceptor::shared_ptr Acceptor::create(int16_t port, int backlog, int threads, bool trace)
+{
+    return Acceptor::shared_ptr(new APRAcceptor(port, backlog, threads, trace));
+}
+// Must define Acceptor virtual dtor.
+Acceptor::~Acceptor() {}
+
+    APRAcceptor::APRAcceptor(int16_t port_, int backlog, int threads, bool trace_) :
+    port(port_),
+    trace(trace_),
+    processor(APRPool::get(), threads, 1000, 5000000)
+{
+    apr_sockaddr_t* address;
+    CHECK_APR_SUCCESS(apr_sockaddr_info_get(&address, APR_ANYADDR, APR_UNSPEC, port, APR_IPV4_ADDR_OK, APRPool::get()));
+    CHECK_APR_SUCCESS(apr_socket_create(&socket, APR_INET, SOCK_STREAM, APR_PROTO_TCP, APRPool::get()));
+    CHECK_APR_SUCCESS(apr_socket_opt_set(socket, APR_SO_REUSEADDR, 1));
+    CHECK_APR_SUCCESS(apr_socket_bind(socket, address));
+    CHECK_APR_SUCCESS(apr_socket_listen(socket, backlog));
+}
+
+int16_t APRAcceptor::getPort() const {
+    apr_sockaddr_t* address;
+    CHECK_APR_SUCCESS(apr_socket_addr_get(&address, APR_LOCAL, socket));
+    return address->port;
+}
+
+void APRAcceptor::run(SessionHandlerFactory* factory) {
+    running = true;
+    processor.start();
+    std::cout << "Listening on port " << getPort() << "..." << std::endl;
+    while(running){
+        apr_socket_t* client;
+        apr_status_t status = apr_socket_accept(&client, socket, APRPool::get());
+        if(status == APR_SUCCESS){
+            //make this socket non-blocking:
+            CHECK_APR_SUCCESS(apr_socket_timeout_set(client, 0));
+            CHECK_APR_SUCCESS(apr_socket_opt_set(client, APR_SO_NONBLOCK, 1));
+            CHECK_APR_SUCCESS(apr_socket_opt_set(client, APR_TCP_NODELAY, 1));
+            CHECK_APR_SUCCESS(apr_socket_opt_set(client, APR_SO_SNDBUF, 32768));
+            CHECK_APR_SUCCESS(apr_socket_opt_set(client, APR_SO_RCVBUF, 32768));
+            LFSessionContext* session = new LFSessionContext(APRPool::get(), client, &processor, trace);
+            session->init(factory->create(session));
+        }else{
+            running = false;
+            if(status != APR_EINTR){
+                std::cout << "ERROR: " << get_desc(status) << std::endl;
+            }
+        }
+    }
+    shutdown();
+}
+
+void APRAcceptor::shutdown() {
+    // TODO aconway 2006-10-12: Cleanup, this is not thread safe.
+    if (running) {
+        running = false;
+        processor.stop();
+        CHECK_APR_SUCCESS(apr_socket_close(socket));
+    }
+}
+
+
+}}

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRAcceptor.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRAcceptor.cpp
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRBase.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRBase.cpp?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRBase.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRBase.cpp Thu Nov 30 21:11:45 2006
@@ -0,0 +1,100 @@
+/*
+ *
+ * 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.
+ *
+ */
+#include <iostream>
+#include <QpidError.h>
+#include "APRBase.h"
+
+using namespace qpid::sys;
+
+APRBase* APRBase::instance = 0;
+
+APRBase* APRBase::getInstance(){
+    if(instance == 0){
+	instance = new APRBase();
+    }
+    return instance;
+}
+
+
+APRBase::APRBase() : count(0){
+    apr_initialize();
+    CHECK_APR_SUCCESS(apr_pool_create(&pool, 0));
+    CHECK_APR_SUCCESS(apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_NESTED, pool));
+}
+
+APRBase::~APRBase(){
+    CHECK_APR_SUCCESS(apr_thread_mutex_destroy(mutex));
+    apr_pool_destroy(pool);
+    apr_terminate();  
+}
+
+bool APRBase::_increment(){
+    bool deleted(false);
+    CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex));
+    if(this == instance){
+	count++;
+    }else{
+	deleted = true;
+    }
+    CHECK_APR_SUCCESS(apr_thread_mutex_unlock(mutex));
+    return !deleted;
+}
+
+void APRBase::_decrement(){
+    APRBase* copy = 0;
+    CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex));
+    if(--count == 0){
+	copy = instance;
+	instance = 0;
+    }
+    CHECK_APR_SUCCESS(apr_thread_mutex_unlock(mutex));
+    if(copy != 0){
+	delete copy;
+    }
+}
+
+void APRBase::increment(){
+    int count = 0;
+    while(count++ < 2 && !getInstance()->_increment()){
+        std::cout << "WARNING: APR initialization triggered concurrently with termination." << std::endl;
+    }
+}
+
+void APRBase::decrement(){
+    getInstance()->_decrement();
+}
+
+void qpid::sys::check(apr_status_t status, const std::string& file, const int line){
+    if (status != APR_SUCCESS){
+        const int size = 50;
+        char tmp[size];
+        std::string msg(apr_strerror(status, tmp, size));
+        throw QpidError(APR_ERROR + ((int) status), msg,
+                        qpid::SrcLine(file, line));
+    }
+}
+
+std::string qpid::sys::get_desc(apr_status_t status){
+    const int size = 50;
+    char tmp[size];
+    return std::string(apr_strerror(status, tmp, size));
+}
+

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRBase.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRBase.cpp
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRBase.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRBase.h?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRBase.h (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRBase.h Thu Nov 30 21:11:45 2006
@@ -0,0 +1,66 @@
+/*
+ *
+ * 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.
+ *
+ */
+#ifndef _APRBase_
+#define _APRBase_
+
+#include <string>
+#include <apr_thread_mutex.h>
+#include <apr_errno.h>
+
+namespace qpid {
+namespace sys {
+
+    /**
+     * Use of APR libraries necessitates explicit init and terminate
+     * calls. Any class using APR libs should obtain the reference to
+     * this singleton and increment on construction, decrement on
+     * destruction. This class can then correctly initialise apr
+     * before the first use and terminate after the last use.
+     */
+    class APRBase{
+	static APRBase* instance;
+	apr_pool_t* pool;
+	apr_thread_mutex_t* mutex;
+	int count;
+
+	APRBase();
+	~APRBase();
+	static APRBase* getInstance();
+	bool _increment();
+	void _decrement();
+    public:
+	static void increment();
+	static void decrement();
+    };
+
+    //this is also a convenient place for a helper function for error checking:
+    void check(apr_status_t status, const std::string& file, const int line);
+    std::string get_desc(apr_status_t status);
+
+#define CHECK_APR_SUCCESS(A) qpid::sys::check(A, __FILE__, __LINE__); 
+
+}
+}
+
+
+
+
+#endif

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRBase.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRBase.h
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRPool.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRPool.cpp?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRPool.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRPool.cpp Thu Nov 30 21:11:45 2006
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include "APRPool.h"
+#include "APRBase.h"
+#include <boost/pool/detail/singleton.hpp>
+
+using namespace qpid::sys;
+
+APRPool::APRPool(){
+    APRBase::increment();
+    CHECK_APR_SUCCESS(apr_pool_create(&pool, NULL));
+}
+
+APRPool::~APRPool(){
+    apr_pool_destroy(pool);
+    APRBase::decrement();
+}
+
+apr_pool_t* APRPool::get() {
+    return boost::details::pool::singleton_default<APRPool>::instance().pool;
+}
+

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRPool.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRPool.cpp
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRPool.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRPool.h?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRPool.h (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRPool.h Thu Nov 30 21:11:45 2006
@@ -0,0 +1,50 @@
+#ifndef _APRPool_
+#define _APRPool_
+
+/*
+ *
+ * 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.
+ *
+ */
+#include <boost/noncopyable.hpp>
+#include <apr_pools.h>
+
+namespace qpid {
+namespace sys {
+/**
+ * Singleton APR memory pool.
+ */
+class APRPool : private boost::noncopyable {
+  public:
+    APRPool();
+    ~APRPool();
+
+    /** Get singleton instance */
+    static apr_pool_t* get();
+
+  private:
+    apr_pool_t* pool;
+};
+
+}}
+
+
+
+
+
+#endif  /*!_APRPool_*/

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRPool.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRPool.h
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRSocket.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRSocket.cpp?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRSocket.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRSocket.cpp Thu Nov 30 21:11:45 2006
@@ -0,0 +1,78 @@
+/*
+ *
+ * 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.
+ *
+ */
+#include "APRBase.h"
+#include "APRSocket.h"
+#include <assert.h>
+#include <iostream>
+
+using namespace qpid::sys;
+using namespace qpid::framing;
+
+APRSocket::APRSocket(apr_socket_t* _socket) : socket(_socket), closed(false){
+
+}
+
+void APRSocket::read(qpid::framing::Buffer& buffer){
+    apr_size_t bytes;
+    bytes = buffer.available();
+    apr_status_t s = apr_socket_recv(socket, buffer.start(), &bytes);
+    buffer.move(bytes);
+    if(APR_STATUS_IS_TIMEUP(s)){
+        //timed out
+    }else if(APR_STATUS_IS_EOF(s)){
+        close();
+    }
+}
+
+void APRSocket::write(qpid::framing::Buffer& buffer){
+    apr_size_t bytes;
+    do{
+        bytes = buffer.available();
+        apr_socket_send(socket, buffer.start(), &bytes);
+        buffer.move(bytes);    
+    }while(bytes > 0);
+}
+
+void APRSocket::close(){
+    if(!closed){
+        std::cout << "Closing socket " << socket << "@" << this << std::endl;
+        CHECK_APR_SUCCESS(apr_socket_close(socket));
+        closed = true;
+    }
+}
+
+bool APRSocket::isOpen(){
+    return !closed;
+}
+
+u_int8_t APRSocket::read(){
+    char data[1];
+    apr_size_t bytes = 1;
+    apr_status_t s = apr_socket_recv(socket, data, &bytes);
+    if(APR_STATUS_IS_EOF(s) || bytes == 0){
+        return 0;
+    }else{
+        return *data;
+    }
+}
+
+APRSocket::~APRSocket(){
+}

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRSocket.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRSocket.cpp
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRSocket.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRSocket.h?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRSocket.h (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRSocket.h Thu Nov 30 21:11:45 2006
@@ -0,0 +1,48 @@
+/*
+ *
+ * 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.
+ *
+ */
+#ifndef _APRSocket_
+#define _APRSocket_
+
+#include <apr_network_io.h>
+#include <Buffer.h>
+
+namespace qpid {
+namespace sys {
+
+    class APRSocket
+    {
+	apr_socket_t* const socket;
+        volatile bool closed;
+    public:
+	APRSocket(apr_socket_t* socket);
+        void read(qpid::framing::Buffer& b);
+        void write(qpid::framing::Buffer& b);
+        void close();
+        bool isOpen();
+        u_int8_t read();
+	~APRSocket();
+    };
+
+}
+}
+
+
+#endif

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRSocket.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/APRSocket.h
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFProcessor.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFProcessor.cpp?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFProcessor.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFProcessor.cpp Thu Nov 30 21:11:45 2006
@@ -0,0 +1,179 @@
+/*
+ *
+ * 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.
+ *
+ */
+#include <sstream>
+#include <QpidError.h>
+#include "LFProcessor.h"
+#include "APRBase.h"
+#include "LFSessionContext.h"
+
+using namespace qpid::sys;
+using qpid::QpidError;
+
+// TODO aconway 2006-10-12: stopped is read outside locks.
+//
+
+LFProcessor::LFProcessor(apr_pool_t* pool, int _workers, int _size, int _timeout) :
+    size(_size),
+    timeout(_timeout), 
+    signalledCount(0),
+    current(0),
+    count(0),
+    workerCount(_workers),
+    hasLeader(false),
+    workers(new Thread[_workers]),
+    stopped(false)
+{
+
+    CHECK_APR_SUCCESS(apr_pollset_create(&pollset, size, pool, APR_POLLSET_THREADSAFE));
+}
+
+
+LFProcessor::~LFProcessor(){
+    if (!stopped) stop();
+    delete[] workers;
+    CHECK_APR_SUCCESS(apr_pollset_destroy(pollset));
+}
+
+void LFProcessor::start(){
+    for(int i = 0; i < workerCount; i++){
+        workers[i] = Thread(this);
+    }
+}
+
+void LFProcessor::add(const apr_pollfd_t* const fd){
+    CHECK_APR_SUCCESS(apr_pollset_add(pollset, fd));
+    Monitor::ScopedLock l(countLock);
+    sessions.push_back(reinterpret_cast<LFSessionContext*>(fd->client_data));
+    count++;
+}
+
+void LFProcessor::remove(const apr_pollfd_t* const fd){
+    CHECK_APR_SUCCESS(apr_pollset_remove(pollset, fd));
+    Monitor::ScopedLock l(countLock);
+    sessions.erase(find(sessions.begin(), sessions.end(), reinterpret_cast<LFSessionContext*>(fd->client_data)));
+    count--;
+}
+
+void LFProcessor::reactivate(const apr_pollfd_t* const fd){
+    CHECK_APR_SUCCESS(apr_pollset_add(pollset, fd));
+}
+
+void LFProcessor::deactivate(const apr_pollfd_t* const fd){
+    CHECK_APR_SUCCESS(apr_pollset_remove(pollset, fd));
+}
+
+void LFProcessor::update(const apr_pollfd_t* const fd){
+    CHECK_APR_SUCCESS(apr_pollset_remove(pollset, fd));
+    CHECK_APR_SUCCESS(apr_pollset_add(pollset, fd));
+}
+
+bool LFProcessor::full(){
+    Mutex::ScopedLock locker(countLock);
+    return count == size; 
+}
+
+bool LFProcessor::empty(){
+    Mutex::ScopedLock locker(countLock);
+    return count == 0; 
+}
+
+void LFProcessor::poll() {
+    apr_status_t status = APR_EGENERAL;
+    do{
+        current = 0;
+        if(!stopped){
+            status = apr_pollset_poll(pollset, timeout, &signalledCount, &signalledFDs);
+        }
+    }while(status != APR_SUCCESS && !stopped);
+}
+
+void LFProcessor::run(){
+    try{
+        while(!stopped){
+            const apr_pollfd_t* event = 0;
+            LFSessionContext* session = 0;
+            {
+                Monitor::ScopedLock l(leadLock);
+                waitToLead();
+                event = getNextEvent();
+                if(!event) return;
+                session = reinterpret_cast<LFSessionContext*>(
+                    event->client_data);
+                session->startProcessing();
+                relinquishLead();
+            }
+
+            //process event:
+            if(event->rtnevents & APR_POLLIN) session->read();
+            if(event->rtnevents & APR_POLLOUT) session->write();
+
+            if(session->isClosed()){
+                session->handleClose();
+                Monitor::ScopedLock l(countLock);
+                sessions.erase(find(sessions.begin(),sessions.end(), session));
+                count--;
+            }else{
+                session->stopProcessing();
+            }
+        }
+    }catch(std::exception e){
+	std::cout << e.what() << std::endl;
+    }
+}
+
+void LFProcessor::waitToLead(){
+    while(hasLeader && !stopped) leadLock.wait();
+    hasLeader = !stopped;
+}
+
+void LFProcessor::relinquishLead(){
+    hasLeader = false;
+    leadLock.notify();
+}
+
+const apr_pollfd_t* LFProcessor::getNextEvent(){
+    while(true){
+        if(stopped){
+            return 0;
+        }else if(current < signalledCount){
+            //use result of previous poll if one is available
+            return signalledFDs + (current++);
+        }else{
+            //else poll to get new events
+            poll();
+        }
+    }
+}
+
+void LFProcessor::stop(){
+    stopped = true;
+    {
+        Monitor::ScopedLock l(leadLock);
+        leadLock.notifyAll();
+    }
+    for(int i = 0; i < workerCount; i++){
+        workers[i].join();
+    }
+    for(iterator i = sessions.begin(); i < sessions.end(); i++){
+        (*i)->shutdown();
+    }
+}
+

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFProcessor.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFProcessor.cpp
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFProcessor.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFProcessor.h?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFProcessor.h (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFProcessor.h Thu Nov 30 21:11:45 2006
@@ -0,0 +1,121 @@
+/*
+ *
+ * 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.
+ *
+ */
+#ifndef _LFProcessor_
+#define _LFProcessor_
+
+#include <apr_poll.h>
+#include <iostream>
+#include <vector>
+#include <sys/Monitor.h>
+#include <sys/Runnable.h>
+#include <sys/Thread.h>
+
+namespace qpid {
+namespace sys {
+
+    class LFSessionContext;
+
+    /**
+     * This class processes a poll set using the leaders-followers
+     * pattern for thread synchronization: the leader will poll and on
+     * the poll returning, it will remove a session, promote a
+     * follower to leadership, then process the session.
+     */
+    class LFProcessor : private virtual qpid::sys::Runnable
+    {
+        typedef std::vector<LFSessionContext*>::iterator iterator;
+        
+        const int size;
+        const apr_interval_time_t timeout;
+        apr_pollset_t* pollset;
+        int signalledCount;
+        int current;
+        const apr_pollfd_t* signalledFDs;
+        int count;
+        const int workerCount;
+        bool hasLeader;
+        qpid::sys::Thread* workers;
+        qpid::sys::Monitor leadLock;
+        qpid::sys::Mutex countLock;
+        std::vector<LFSessionContext*> sessions;
+        volatile bool stopped;
+
+        const apr_pollfd_t* getNextEvent();
+        void waitToLead();
+        void relinquishLead();
+        void poll();        
+        virtual void run();        
+
+    public:
+        LFProcessor(apr_pool_t* pool, int workers, int size, int timeout);
+        /**
+         * Add the fd to the poll set. Relies on the client_data being
+         * an instance of LFSessionContext.
+         */
+        void add(const apr_pollfd_t* const fd);
+        /**
+         * Remove the fd from the poll set.
+         */
+        void remove(const apr_pollfd_t* const fd);
+        /**
+         * Signal that the fd passed in, already part of the pollset,
+         * has had its flags altered.
+         */
+        void update(const apr_pollfd_t* const fd);
+        /**
+         * Add an fd back to the poll set after deactivation.
+         */
+        void reactivate(const apr_pollfd_t* const fd);
+        /**
+         * Temporarily remove the fd from the poll set. Called when processing
+         * is about to begin.
+         */
+        void deactivate(const apr_pollfd_t* const fd);
+        /**
+         * Indicates whether the capacity of this processor has been
+         * reached (or whether it can still handle further fd's).
+         */
+        bool full();
+        /**
+         * Indicates whether there are any fd's registered.
+         */
+        bool empty();
+        /**
+         * Stop processing.
+         */
+        void stop();
+        /**
+         * Start processing.
+         */
+        void start();
+        /**
+         * Is processing stopped?
+         */
+        bool isStopped();
+        
+	~LFProcessor();
+    };
+
+}
+}
+
+
+#endif

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFProcessor.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFProcessor.h
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFSessionContext.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFSessionContext.cpp?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFSessionContext.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFSessionContext.cpp Thu Nov 30 21:11:45 2006
@@ -0,0 +1,173 @@
+/*
+ *
+ * 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.
+ *
+ */
+#include "LFSessionContext.h"
+#include "APRBase.h"
+#include <QpidError.h>
+#include <assert.h>
+
+using namespace qpid::sys;
+using namespace qpid::sys;
+using namespace qpid::framing;
+
+LFSessionContext::LFSessionContext(apr_pool_t* _pool, apr_socket_t* _socket, 
+                                   LFProcessor* const _processor,
+                                   bool _debug) :
+    debug(_debug),
+    socket(_socket),
+    initiated(false),
+    in(65536),
+    out(65536),
+    processor(_processor),
+    processing(false),
+    closing(false)
+{
+    
+    fd.p = _pool;
+    fd.desc_type = APR_POLL_SOCKET;
+    fd.reqevents = APR_POLLIN;
+    fd.client_data = this;
+    fd.desc.s = _socket;
+
+    out.flip();
+}
+
+LFSessionContext::~LFSessionContext(){
+
+}
+
+void LFSessionContext::read(){
+    socket.read(in);
+    in.flip();
+    if(initiated){
+        AMQFrame frame;
+        while(frame.decode(in)){
+            if(debug) log("RECV", &frame);
+            handler->received(&frame);
+        }
+    }else{
+        ProtocolInitiation protocolInit;
+        if(protocolInit.decode(in)){
+            handler->initiated(&protocolInit);
+            initiated = true;
+            if(debug) std::cout << "INIT [" << &socket << "]" << std::endl;
+        }
+    }
+    in.compact();
+}
+
+void LFSessionContext::write(){
+    bool done = isClosed();
+    while(!done){
+        if(out.available() > 0){
+            socket.write(out);
+            if(out.available() > 0){
+
+                //incomplete write, leave flags to receive notification of readiness to write
+                done = true;//finished processing for now, but write is still in progress
+            }
+        }else{
+            //do we have any frames to write?
+            Mutex::ScopedLock l(writeLock);
+            if(!framesToWrite.empty()){
+                out.clear();
+                bool encoded(false);
+                AMQFrame* frame = framesToWrite.front();
+                while(frame && out.available() >= frame->size()){
+                    encoded = true;
+                    frame->encode(out);
+                    if(debug) log("SENT", frame);
+                    delete frame;
+                    framesToWrite.pop();
+                    frame = framesToWrite.empty() ? 0 : framesToWrite.front();
+                }
+                if(!encoded) THROW_QPID_ERROR(FRAMING_ERROR, "Could not write frame, too large for buffer.");
+                out.flip();
+            }else{
+                //reset flags, don't care about writability anymore
+                fd.reqevents = APR_POLLIN;
+                done = true;
+
+                if(closing){
+                    socket.close();
+                }
+            }
+        }
+    }
+}
+
+void LFSessionContext::send(AMQFrame* frame){
+    Mutex::ScopedLock l(writeLock);
+    if(!closing){
+        framesToWrite.push(frame);
+        if(!(fd.reqevents & APR_POLLOUT)){
+            fd.reqevents |= APR_POLLOUT;
+            if(!processing){
+                processor->update(&fd);
+            }
+        }
+    }
+}
+
+void LFSessionContext::startProcessing(){
+    Mutex::ScopedLock l(writeLock);
+    processing = true;
+    processor->deactivate(&fd);
+}
+
+void LFSessionContext::stopProcessing(){
+    Mutex::ScopedLock l(writeLock);
+    processor->reactivate(&fd);
+    processing = false;
+}
+
+void LFSessionContext::close(){
+    closing = true;
+    Mutex::ScopedLock l(writeLock);
+    if(!processing){
+        //allow pending frames to be written to socket
+        fd.reqevents = APR_POLLOUT;
+        processor->update(&fd);
+    }
+}
+
+void LFSessionContext::handleClose(){
+    handler->closed();
+    std::cout << "Session closed [" << &socket << "]" << std::endl;
+    delete handler;
+    delete this;
+}
+
+void LFSessionContext::shutdown(){
+    socket.close();
+    handleClose();
+}
+
+void LFSessionContext::init(SessionHandler* _handler){
+    handler = _handler;
+    processor->add(&fd);
+}
+
+void LFSessionContext::log(const std::string& desc, AMQFrame* const frame){
+    Mutex::ScopedLock l(logLock);
+    std::cout << desc << " [" << &socket << "]: " << *frame << std::endl;
+}
+
+Mutex LFSessionContext::logLock;

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFSessionContext.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFSessionContext.cpp
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFSessionContext.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFSessionContext.h?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFSessionContext.h (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFSessionContext.h Thu Nov 30 21:11:45 2006
@@ -0,0 +1,90 @@
+/*
+ *
+ * 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.
+ *
+ */
+#ifndef _LFSessionContext_
+#define _LFSessionContext_
+
+#include <queue>
+
+#include <apr_network_io.h>
+#include <apr_poll.h>
+#include <apr_time.h>
+
+#include <AMQFrame.h>
+#include <Buffer.h>
+#include <sys/Monitor.h>
+#include <sys/SessionContext.h>
+#include <sys/SessionHandler.h>
+
+#include "APRSocket.h"
+#include "LFProcessor.h"
+
+namespace qpid {
+namespace sys {
+
+
+class LFSessionContext : public virtual qpid::sys::SessionContext
+{
+    const bool debug;
+    APRSocket socket;
+    bool initiated;
+        
+    qpid::framing::Buffer in;
+    qpid::framing::Buffer out;
+        
+    qpid::sys::SessionHandler* handler;
+    LFProcessor* const processor;
+
+    apr_pollfd_t fd;
+
+    std::queue<qpid::framing::AMQFrame*> framesToWrite;
+    qpid::sys::Mutex writeLock;
+        
+    bool processing;
+    bool closing;
+
+    static qpid::sys::Mutex logLock;
+    void log(const std::string& desc,
+             qpid::framing::AMQFrame* const frame);
+        
+
+  public:
+    LFSessionContext(apr_pool_t* pool, apr_socket_t* socket, 
+                     LFProcessor* const processor, 
+                     bool debug = false);
+    virtual ~LFSessionContext();
+    virtual void send(qpid::framing::AMQFrame* frame);
+    virtual void close();        
+    void read();
+    void write();
+    void init(qpid::sys::SessionHandler* handler);
+    void startProcessing();
+    void stopProcessing();
+    void handleClose();        
+    void shutdown();        
+    inline apr_pollfd_t* const getFd(){ return &fd; }
+    inline bool isClosed(){ return !socket.isOpen(); }
+};
+
+}
+}
+
+
+#endif

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFSessionContext.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/LFSessionContext.h
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/Socket.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/Socket.cpp?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/Socket.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/Socket.cpp Thu Nov 30 21:11:45 2006
@@ -0,0 +1,83 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+
+#include <sys/Socket.h>
+#include <apr/APRBase.h>
+#include <apr/APRPool.h>
+
+
+using namespace qpid::sys;
+
+Socket Socket::createTcp() {
+    Socket s;
+    CHECK_APR_SUCCESS(
+        apr_socket_create(
+            &s.socket, APR_INET, SOCK_STREAM, APR_PROTO_TCP,
+            APRPool::get()));
+    return s;
+}
+
+Socket::Socket(apr_socket_t* s) {
+    socket = s;
+}
+
+void Socket::setTimeout(Time interval) {
+    apr_socket_timeout_set(socket, interval/TIME_USEC);
+}
+
+void Socket::connect(const std::string& host, int port) {
+    apr_sockaddr_t* address;
+    CHECK_APR_SUCCESS(
+        apr_sockaddr_info_get(
+            &address, host.c_str(), APR_UNSPEC, port, APR_IPV4_ADDR_OK,
+            APRPool::get()));
+    CHECK_APR_SUCCESS(apr_socket_connect(socket, address));
+}
+
+void Socket::close() {
+    if (socket == 0) return;
+    CHECK_APR_SUCCESS(apr_socket_close(socket));
+    socket = 0;
+}
+
+ssize_t Socket::send(const void* data, size_t size)
+{
+    apr_size_t sent = size;
+    apr_status_t status =
+        apr_socket_send(socket, reinterpret_cast<const char*>(data), &sent);
+    if (APR_STATUS_IS_TIMEUP(status)) return SOCKET_TIMEOUT;
+    if (APR_STATUS_IS_EOF(status)) return SOCKET_EOF;
+    CHECK_APR_SUCCESS(status);
+    return sent;
+}
+
+ssize_t Socket::recv(void* data, size_t size)
+{
+    apr_size_t received = size;
+    apr_status_t status =
+        apr_socket_recv(socket, reinterpret_cast<char*>(data), &received);
+    if (APR_STATUS_IS_TIMEUP(status)) return SOCKET_TIMEOUT;
+    CHECK_APR_SUCCESS(status);
+     return received;
+}
+
+

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/Socket.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/Socket.cpp
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/Thread.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/Thread.cpp?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/Thread.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/Thread.cpp Thu Nov 30 21:11:45 2006
@@ -0,0 +1,33 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <sys/Thread.h>
+
+using namespace qpid::sys;
+using qpid::sys::Runnable;
+
+void* APR_THREAD_FUNC Thread::runRunnable(apr_thread_t* thread, void *data) {
+    reinterpret_cast<Runnable*>(data)->run();
+    CHECK_APR_SUCCESS(apr_thread_exit(thread, APR_SUCCESS));
+    return NULL;
+} 
+
+

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/Thread.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/apr/Thread.cpp
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannel.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannel.cpp?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannel.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannel.cpp Thu Nov 30 21:11:45 2006
@@ -0,0 +1,325 @@
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * 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.
+ *
+ */
+
+#include <mqueue.h>
+#include <string.h>
+#include <iostream>
+
+#include <sys/errno.h>
+#include <sys/socket.h>
+#include <sys/epoll.h>
+
+#include <typeinfo>
+#include <iostream>
+#include <queue>
+
+#include <boost/ptr_container/ptr_map.hpp>
+#include <boost/current_function.hpp>
+
+#include <QpidError.h>
+#include <sys/Monitor.h>
+
+#include "check.h"
+#include "EventChannel.h"
+
+using namespace std;
+
+
+// Convenience template to zero out a struct.
+template <class S> struct ZeroStruct : public S {
+    ZeroStruct() { memset(this, 0, sizeof(*this)); }
+};
+    
+namespace qpid {
+namespace sys {
+
+
+/**
+ * EventHandler wraps an epoll file descriptor. Acts as private
+ * interface between EventChannel and subclasses.
+ *
+ * Also implements Event interface for events that are not associated
+ * with a file descriptor and are passed via the message queue.
+ */ 
+class EventHandler : public Event, private Monitor
+{
+  public:
+    EventHandler(int epollSize = 256);
+    ~EventHandler();
+
+    int getEpollFd() { return epollFd; }
+    void epollAdd(int fd, uint32_t epollEvents, Event* event);
+    void epollMod(int fd, uint32_t epollEvents, Event* event);
+    void epollDel(int fd);
+
+    void mqPut(Event* event);
+    Event* mqGet();
+    
+  protected:
+    // Should never be called, only complete.
+    void prepare(EventHandler&) { assert(0); }
+    Event* complete(EventHandler& eh);
+    
+  private:
+    int epollFd;
+    std::string mqName;
+    int mqFd;
+    std::queue<Event*> mqEvents;
+};
+
+EventHandler::EventHandler(int epollSize)
+{
+    epollFd = epoll_create(epollSize);
+    if (epollFd < 0) throw QPID_POSIX_ERROR(errno);
+
+    // Create a POSIX message queue for non-fd events.
+    // We write one byte and never read it is always ready for read
+    // when we add it to epoll.
+    // 
+    ZeroStruct<struct mq_attr> attr;
+    attr.mq_maxmsg = 1;
+    attr.mq_msgsize = 1;
+    do {
+        char tmpnam[L_tmpnam];
+        tmpnam_r(tmpnam);
+        mqName = tmpnam + 4; // Skip "tmp/"
+        mqFd = mq_open(
+            mqName.c_str(), O_CREAT|O_EXCL|O_RDWR|O_NONBLOCK, S_IRWXU, &attr);
+        if (mqFd < 0) throw QPID_POSIX_ERROR(errno);
+    } while (mqFd == EEXIST);  // Name already taken, try again.
+
+    static char zero = '\0';
+    mq_send(mqFd, &zero, 1, 0);
+    epollAdd(mqFd, 0, this);
+}
+
+EventHandler::~EventHandler() {
+    mq_close(mqFd);
+    mq_unlink(mqName.c_str());
+}
+
+void EventHandler::mqPut(Event* event) {
+    ScopedLock l(*this);
+    assert(event != 0);
+    mqEvents.push(event);
+    epollMod(mqFd, EPOLLIN|EPOLLONESHOT, this);
+}
+
+Event* EventHandler::mqGet() {
+    ScopedLock l(*this);
+    if (mqEvents.empty()) 
+        return 0;
+    Event* event = mqEvents.front();
+    mqEvents.pop();
+    if(!mqEvents.empty())
+        epollMod(mqFd, EPOLLIN|EPOLLONESHOT, this);
+    return event;
+}
+
+void EventHandler::epollAdd(int fd, uint32_t epollEvents, Event* event)
+{
+    ZeroStruct<struct epoll_event> ee;
+    ee.data.ptr = event;
+    ee.events = epollEvents;
+    if (epoll_ctl(epollFd, EPOLL_CTL_ADD, fd, &ee) < 0) 
+        throw QPID_POSIX_ERROR(errno);
+}
+
+void EventHandler::epollMod(int fd, uint32_t epollEvents, Event* event)
+{
+    ZeroStruct<struct epoll_event> ee;
+    ee.data.ptr = event;
+    ee.events = epollEvents;
+    if (epoll_ctl(epollFd, EPOLL_CTL_MOD, fd, &ee) < 0) 
+        throw QPID_POSIX_ERROR(errno);
+}
+
+void EventHandler::epollDel(int fd) {
+    if (epoll_ctl(epollFd, EPOLL_CTL_DEL, fd, 0) < 0)
+        throw QPID_POSIX_ERROR(errno);
+}
+
+Event* EventHandler::complete(EventHandler& eh)
+{
+    assert(&eh == this);
+    Event* event =  mqGet();
+    return event==0 ? 0 : event->complete(eh);
+}
+    
+// ================================================================
+// EventChannel
+
+EventChannel::shared_ptr EventChannel::create() {
+    return shared_ptr(new EventChannel());
+}
+
+EventChannel::EventChannel() : handler(new EventHandler()) {}
+
+EventChannel::~EventChannel() {}
+
+void EventChannel::postEvent(Event& e) 
+{
+    e.prepare(*handler);
+}
+
+Event* EventChannel::getEvent()
+{
+    static const int infiniteTimeout = -1; 
+    ZeroStruct<struct epoll_event> epollEvent;
+
+    // Loop until we can complete the event. Some events may re-post
+    // themselves and return 0 from complete, e.g. partial reads. // 
+    Event* event = 0;
+    while (event == 0) {
+        int eventCount = epoll_wait(handler->getEpollFd(),
+                                    &epollEvent, 1, infiniteTimeout);
+        if (eventCount < 0) {
+            if (errno != EINTR) {
+                // TODO aconway 2006-11-28: Proper handling/logging of errors.
+                cerr << BOOST_CURRENT_FUNCTION << " ignoring error "
+                     << PosixError::getMessage(errno) << endl;
+                assert(0);
+            }
+        }
+        else if (eventCount == 1) {
+            event = reinterpret_cast<Event*>(epollEvent.data.ptr);
+            assert(event != 0);
+            try {
+                event = event->complete(*handler);
+            }
+            catch (const Exception& e) {
+                if (event)
+                    event->setError(e);
+            }
+            catch (const std::exception& e) {
+                if (event)
+                    event->setError(e);
+            }
+        }
+    }
+    return event;
+}
+
+Event::~Event() {}
+    
+void Event::prepare(EventHandler& handler)
+{
+    handler.mqPut(this);
+}
+
+bool Event::hasError() const {
+    return error;
+}
+
+void Event::throwIfError() throw (Exception) {
+    if (hasError())
+        error.throwSelf();
+}
+
+Event* Event::complete(EventHandler&)
+{
+    return this;
+}
+
+void Event::dispatch()
+{
+    try {
+        if (!callback.empty())
+            callback();
+    } catch (const std::exception&) {
+        throw;
+    } catch (...) {
+        throw QPID_ERROR(INTERNAL_ERROR, "Unknown exception.");
+    }
+}
+
+void Event::setError(const ExceptionHolder& e) {
+    error = e;
+}
+
+void ReadEvent::prepare(EventHandler& handler)
+{
+    handler.epollAdd(descriptor, EPOLLIN | EPOLLONESHOT, this);
+}
+
+ssize_t ReadEvent::doRead() {
+    ssize_t n = ::read(descriptor, static_cast<char*>(buffer) + received,
+                       size - received);
+    if (n > 0) received += n;
+    return n;
+}
+
+Event* ReadEvent::complete(EventHandler& handler)
+{
+    // Read as much as possible without blocking.
+    ssize_t n = doRead();
+    while (n > 0 && received < size) doRead();
+
+    if (received == size) {
+        handler.epollDel(descriptor);
+        received = 0;           // Reset for re-use.
+        return this;
+    }
+    else if (n <0 && (errno == EAGAIN)) {
+        // Keep polling for more.
+        handler.epollMod(descriptor, EPOLLIN | EPOLLONESHOT, this);
+        return 0;
+    }
+    else {
+        // Unexpected EOF or error. Throw ENODATA for EOF.
+        handler.epollDel(descriptor);
+        received = 0;           // Reset for re-use.
+        throw QPID_POSIX_ERROR((n < 0) ? errno : ENODATA);
+    }
+}
+
+void WriteEvent::prepare(EventHandler& handler)
+{
+    handler.epollAdd(descriptor, EPOLLOUT | EPOLLONESHOT, this);
+}
+
+Event* WriteEvent::complete(EventHandler& handler)
+{
+    ssize_t n = write(descriptor, static_cast<const char*>(buffer) + written,
+                      size - written);
+    if (n < 0) throw QPID_POSIX_ERROR(errno);
+    written += n;
+    if(written < size) {
+        // Keep polling.
+        handler.epollMod(descriptor, EPOLLOUT | EPOLLONESHOT, this);
+        return 0;
+    }
+    written = 0;                // Reset for re-use.
+    handler.epollDel(descriptor);
+    return this;
+}
+
+void AcceptEvent::prepare(EventHandler& handler)
+{
+    handler.epollAdd(descriptor, EPOLLIN | EPOLLONESHOT, this);
+}
+
+Event* AcceptEvent::complete(EventHandler& handler)
+{
+    handler.epollDel(descriptor);
+    accepted = ::accept(descriptor, 0, 0);
+    if (accepted < 0) throw QPID_POSIX_ERROR(errno);
+    return this;
+}
+
+}}

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannel.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannel.cpp
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannel.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannel.h?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannel.h (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannel.h Thu Nov 30 21:11:45 2006
@@ -0,0 +1,176 @@
+#ifndef _sys_EventChannel_h
+#define _sys_EventChannel_h
+
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * 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.
+ *
+ */
+
+#include <SharedObject.h>
+#include <ExceptionHolder.h>
+#include <boost/function.hpp>
+#include <memory>
+
+namespace qpid {
+namespace sys {
+
+class Event;
+class EventHandler;
+class EventChannel;
+
+/**
+ * Base class for all Events.
+ */
+class Event
+{
+  public:
+    /** Type for callback when event is dispatched */
+    typedef boost::function0<void> Callback;
+
+    /**
+     * Create an event with optional callback.
+     * Instances of Event are sent directly through the channel.
+     * Derived classes define additional waiting behaviour.
+     *@param cb A callback functor that is invoked when dispatch() is called.
+     */
+    Event(Callback cb = 0) : callback(cb) {}
+
+    virtual ~Event();
+
+    /** Call the callback provided to the constructor, if any. */
+    void dispatch();
+
+    /** True if there was an error processing this event */
+    bool hasError() const;
+
+    /** If hasError() throw the corresponding exception. */
+    void throwIfError() throw(Exception);
+
+  protected:
+    virtual void prepare(EventHandler&);
+    virtual Event* complete(EventHandler&);
+    void setError(const ExceptionHolder& e);
+
+    Callback callback;
+    ExceptionHolder error;
+
+  friend class EventChannel;
+  friend class EventHandler;
+};
+
+template <class BufT>
+class IOEvent : public Event {
+  public:
+    void getDescriptor() const { return descriptor; }
+    size_t getSize() const { return size; }
+    BufT getBuffer() const { return buffer; }
+  
+  protected:
+    IOEvent(int fd, Callback cb, size_t sz, BufT buf) :
+        Event(cb), descriptor(fd), buffer(buf), size(sz) {}
+
+    int descriptor;
+    BufT buffer;
+    size_t size;
+};
+
+/** Asynchronous read event */
+class ReadEvent : public IOEvent<void*>
+{
+  public:
+    explicit ReadEvent(int fd=-1, void* buf=0, size_t sz=0, Callback cb=0) :
+        IOEvent<void*>(fd, cb, sz, buf), received(0) {}
+
+  private:
+    void prepare(EventHandler&);
+    Event* complete(EventHandler&);
+    ssize_t doRead();
+
+    size_t received;
+};
+
+/** Asynchronous write event */
+class WriteEvent : public IOEvent<const void*>
+{
+  public:
+    explicit WriteEvent(int fd=-1, const void* buf=0, size_t sz=0,
+                        Callback cb=0) :
+        IOEvent<const void*>(fd, cb, sz, buf), written(0) {}
+
+  protected:
+    void prepare(EventHandler&);
+    Event* complete(EventHandler&);
+
+  private:
+    ssize_t doWrite();
+    size_t written;
+};
+
+/** Asynchronous socket accept event */
+class AcceptEvent : public Event
+{
+  public:
+    /** Accept a connection on fd. */
+    explicit AcceptEvent(int fd=-1, Callback cb=0) :
+        Event(cb), descriptor(fd), accepted(0) {}
+
+    /** Get descriptor for server socket */
+    int getAcceptedDesscriptor() const { return accepted; }
+
+  private:
+    void prepare(EventHandler&);
+    Event* complete(EventHandler&);
+
+    int descriptor;
+    int accepted;
+};
+
+
+class QueueSet;
+
+/**
+ * Channel to post and wait for events.
+ */
+class EventChannel : public qpid::SharedObject<EventChannel>
+{
+  public:
+    static shared_ptr create();
+    
+    ~EventChannel();
+    
+    /** Post an event to the channel. */
+    void postEvent(Event& event);
+
+    /** Post an event to the channel. Must not be 0. */
+    void postEvent(Event* event) { postEvent(*event); }
+        
+    /**
+     * Wait for the next complete event.
+     *@return Pointer to event. Will never return 0.
+     */
+    Event* getEvent();
+
+  private:
+    EventChannel();
+    boost::shared_ptr<EventHandler> handler;
+};
+
+
+}}
+
+
+
+#endif  /*!_sys_EventChannel_h*/

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannel.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannel.h
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannelThreads.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannelThreads.cpp?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannelThreads.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannelThreads.cpp Thu Nov 30 21:11:45 2006
@@ -0,0 +1,119 @@
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * 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.
+ *
+ */
+
+#include "EventChannelThreads.h"
+#include <sys/Runnable.h>
+#include <iostream>
+using namespace std;
+#include <boost/bind.hpp>
+
+namespace qpid {
+namespace sys {
+
+EventChannelThreads::shared_ptr EventChannelThreads::create(
+    EventChannel::shared_ptr ec)
+{
+    return EventChannelThreads::shared_ptr(new EventChannelThreads(ec));
+}
+
+EventChannelThreads::EventChannelThreads(EventChannel::shared_ptr ec) :
+    channel(ec), nWaiting(0), state(RUNNING)
+{
+    // TODO aconway 2006-11-15: Estimate initial threads based on CPUs.
+    addThread();
+}
+
+EventChannelThreads::~EventChannelThreads() {
+    shutdown();
+    join();
+}
+
+void EventChannelThreads::shutdown() 
+{
+    ScopedLock lock(*this);
+    if (state != RUNNING)       // Already shutting down.
+        return;
+    for (size_t i = 0; i < workers.size(); ++i) {
+        channel->postEvent(terminate);
+    }
+    state = TERMINATE_SENT;
+    notify();                // Wake up one join() thread.
+}
+
+void EventChannelThreads::join() 
+{
+    {
+        ScopedLock lock(*this);
+        while (state == RUNNING)    // Wait for shutdown to start.
+            wait();
+        if (state == SHUTDOWN)      // Shutdown is complete
+            return;
+        if (state == JOINING) {
+            // Someone else is doing the join.
+            while (state != SHUTDOWN)
+                wait();
+            return;
+        }
+        // I'm the  joining thread
+        assert(state == TERMINATE_SENT); 
+        state = JOINING; 
+    } // Drop the lock.
+
+    for (size_t i = 0; i < workers.size(); ++i) {
+        assert(state == JOINING); // Only this thread can change JOINING.
+        workers[i].join();
+    }
+    state = SHUTDOWN;
+    notifyAll();                // Notify other join() threaeds.
+}
+
+void EventChannelThreads::addThread() {
+    ScopedLock l(*this);
+    workers.push_back(Thread(*this));
+}
+
+void EventChannelThreads::run()
+{
+    // Start life waiting. Decrement on exit.
+    AtomicCount::ScopedIncrement inc(nWaiting);
+    try {
+        while (true) {
+            Event* e = channel->getEvent(); 
+            assert(e != 0);
+            if (e == &terminate) {
+                return;
+            }
+            AtomicCount::ScopedDecrement dec(nWaiting);
+            // I'm no longer waiting, make sure someone is.
+            if (dec == 0)
+                addThread();
+            e->dispatch();
+        }
+    }
+    catch (const std::exception& e) {
+        // TODO aconway 2006-11-15: need better logging across the board.
+        std::cerr << "EventChannelThreads::run() caught: " << e.what()
+                  << std::endl;
+    }
+    catch (...) {
+        std::cerr << "EventChannelThreads::run() caught unknown exception."
+                  << std::endl;
+    }
+}
+
+}}

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannelThreads.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannelThreads.cpp
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannelThreads.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannelThreads.h?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannelThreads.h (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannelThreads.h Thu Nov 30 21:11:45 2006
@@ -0,0 +1,92 @@
+#ifndef _posix_EventChannelThreads_h
+#define _sys_EventChannelThreads_h
+
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * 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.
+ *
+ */
+#include <vector>
+
+#include <Exception.h>
+#include <sys/Time.h>
+#include <sys/Monitor.h>
+#include <sys/Thread.h>
+#include <sys/AtomicCount.h>
+#include "EventChannel.h"
+
+namespace qpid {
+namespace sys {
+
+/**
+   Dynamic thread pool serving an EventChannel.
+
+   Threads run a loop { e = getEvent(); e->dispatch(); }
+   The size of the thread pool is automatically adjusted to optimal size.
+*/
+class EventChannelThreads :
+        public qpid::SharedObject<EventChannelThreads>,
+        public sys::Monitor, private sys::Runnable
+{
+  public:
+    /** Create the thread pool and start initial threads. */
+    static EventChannelThreads::shared_ptr create(
+        EventChannel::shared_ptr channel
+    );
+
+    ~EventChannelThreads();
+
+    /** Post event to the underlying channel */
+    void postEvent(Event& event) { channel->postEvent(event); }
+
+    /** Post event to the underlying channel Must not be 0. */
+    void postEvent(Event* event) { channel->postEvent(event); }
+
+    /**
+     * Terminate all threads.
+     *
+     * Returns immediately, use join() to wait till all threads are
+     * shut down. 
+     */
+    void shutdown();
+    
+    /** Wait for all threads to terminate. */
+    void join();
+
+  private:
+    typedef std::vector<sys::Thread> Threads;
+    typedef enum {
+        RUNNING, TERMINATE_SENT, JOINING, SHUTDOWN
+    } State;
+
+    EventChannelThreads(EventChannel::shared_ptr underlyingChannel);
+    void addThread();
+
+    void run();
+    bool keepRunning();
+    void adjustThreads();
+
+    EventChannel::shared_ptr channel;
+    Threads workers;
+    sys::AtomicCount nWaiting;
+    State state;
+    Event terminate;
+};
+
+
+}}
+
+
+#endif  /*!_sys_EventChannelThreads_h*/

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannelThreads.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/EventChannelThreads.h
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/PosixAcceptor.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/PosixAcceptor.cpp?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/PosixAcceptor.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/PosixAcceptor.cpp Thu Nov 30 21:11:45 2006
@@ -0,0 +1,48 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <sys/Acceptor.h>
+#include <Exception.h>
+
+namespace qpid {
+namespace sys {
+
+namespace {
+void fail() { throw qpid::Exception("PosixAcceptor not implemented"); }
+}
+
+class PosixAcceptor : public Acceptor {
+  public:
+    virtual int16_t getPort() const { fail(); return 0; }
+    virtual void run(qpid::sys::SessionHandlerFactory* ) { fail(); }
+    virtual void shutdown() { fail(); }
+};
+
+// Define generic Acceptor::create() to return APRAcceptor.
+    Acceptor::shared_ptr Acceptor::create(int16_t , int, int, bool)
+{
+    return Acceptor::shared_ptr(new PosixAcceptor());
+}
+
+// Must define Acceptor virtual dtor.
+Acceptor::~Acceptor() {}
+
+}}

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/PosixAcceptor.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/PosixAcceptor.cpp
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/Socket.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/Socket.cpp?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/Socket.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/Socket.cpp Thu Nov 30 21:11:45 2006
@@ -0,0 +1,118 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <boost/format.hpp>
+
+#include <QpidError.h>
+#include <posix/check.h>
+#include <sys/Socket.h>
+
+using namespace qpid::sys;
+
+Socket Socket::createTcp() 
+{
+    int s = ::socket (PF_INET, SOCK_STREAM, 0);
+    if (s < 0) throw QPID_POSIX_ERROR(errno);
+    return s;
+}
+
+Socket::Socket(int descriptor) : socket(descriptor) {}
+
+void Socket::setTimeout(Time interval)
+{
+    struct timeval tv;
+    tv.tv_sec = interval/TIME_SEC;
+    tv.tv_usec = (interval%TIME_SEC)/TIME_USEC;
+    setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
+    setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+}
+
+void Socket::connect(const std::string& host, int port)
+{
+    struct sockaddr_in name;
+    name.sin_family = AF_INET;
+    name.sin_port = htons(port);
+    struct hostent* hp = gethostbyname ( host.c_str() );
+    if (hp == 0) throw QPID_POSIX_ERROR(errno);
+    memcpy(&name.sin_addr.s_addr, hp->h_addr_list[0], hp->h_length);
+    if (::connect(socket, (struct sockaddr*)(&name), sizeof(name)) < 0)
+        throw QPID_POSIX_ERROR(errno);
+}
+
+void
+Socket::close()
+{
+    if (socket == 0) return;
+    if (::close(socket) < 0) throw QPID_POSIX_ERROR(errno);
+    socket = 0;
+}
+
+ssize_t
+Socket::send(const void* data, size_t size)
+{
+    ssize_t sent = ::send(socket, data, size, 0);
+    if (sent < 0) {
+        if (errno == ECONNRESET) return SOCKET_EOF;
+        if (errno == ETIMEDOUT) return SOCKET_TIMEOUT;
+        throw QPID_POSIX_ERROR(errno);
+    }
+    return sent;
+}
+
+ssize_t
+Socket::recv(void* data, size_t size)
+{
+    ssize_t received = ::recv(socket, data, size, 0);
+    if (received < 0) {
+        if (errno == ETIMEDOUT) return SOCKET_TIMEOUT;
+        throw QPID_POSIX_ERROR(errno);
+    }
+    return received;
+}
+
+int Socket::listen(int port, int backlog) 
+{
+    struct sockaddr_in name;
+    name.sin_family = AF_INET;
+    name.sin_port = htons(port);
+    name.sin_addr.s_addr = 0;
+    if (::bind(socket, (struct sockaddr*)&name, sizeof(name)) < 0)
+        throw QPID_POSIX_ERROR(errno);
+    if (::listen(socket, backlog) < 0)
+        throw QPID_POSIX_ERROR(errno);
+    
+    socklen_t namelen = sizeof(name);
+    if (::getsockname(socket, (struct sockaddr*)&name, &namelen) < 0)
+        throw QPID_POSIX_ERROR(errno);
+
+    return ntohs(name.sin_port);
+}
+
+
+int Socket::fd() 
+{
+    return socket;
+}

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/Socket.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/Socket.cpp
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/Thread.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/Thread.cpp?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/Thread.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/Thread.cpp Thu Nov 30 21:11:45 2006
@@ -0,0 +1,28 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <sys/Thread.h>
+
+void* qpid::sys::Thread::runRunnable(void* p)
+{
+    static_cast<Runnable*>(p)->run();
+    return 0;
+}

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/Thread.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/Thread.cpp
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/check.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/check.cpp?view=auto&rev=481159
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/check.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/check.cpp Thu Nov 30 21:11:45 2006
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <cerrno>
+#include "check.h" 
+
+namespace qpid {
+namespace sys {
+
+std::string
+PosixError::getMessage(int errNo)
+{
+    char buf[512];
+    return std::string(strerror_r(errNo, buf, sizeof(buf)));
+}
+
+PosixError::PosixError(int errNo, const qpid::SrcLine& loc) throw()
+    : qpid::QpidError(INTERNAL_ERROR + errNo, getMessage(errNo), loc)
+{ }
+    
+}}

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/check.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/qpid/trunk/qpid/cpp/lib/common/sys/posix/check.cpp
------------------------------------------------------------------------------
    svn:keywords = Rev Date