diff options
| author | Kim van der Riet <kpvdr@apache.org> | 2012-05-04 15:39:19 +0000 |
|---|---|---|
| committer | Kim van der Riet <kpvdr@apache.org> | 2012-05-04 15:39:19 +0000 |
| commit | 633c33f224f3196f3f9bd80bd2e418d8143fea06 (patch) | |
| tree | 1391da89470593209466df68c0b40b89c14963b1 /cpp/src/qpid/sys | |
| parent | c73f9286ebff93a6c8dbc29cf05e258c4b55c976 (diff) | |
| download | qpid-python-633c33f224f3196f3f9bd80bd2e418d8143fea06.tar.gz | |
QPID-3858: Updated branch - merged from trunk r.1333987
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/asyncstore@1334037 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src/qpid/sys')
| -rw-r--r-- | cpp/src/qpid/sys/MemStat.h (renamed from cpp/src/qpid/sys/apr/Time.cpp) | 24 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/Probes.h | 65 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/apr/APRBase.cpp | 89 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/apr/APRBase.h | 74 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/apr/APRPool.cpp | 41 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/apr/APRPool.h | 50 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/apr/Condition.h | 84 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/apr/Mutex.h | 124 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/apr/Shlib.cpp | 49 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/apr/Socket.cpp | 114 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/apr/Thread.cpp | 34 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/apr/Thread.h | 106 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/posix/AsynchIO.cpp | 38 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/posix/PollableCondition.cpp | 5 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/ssl/SslIo.cpp | 7 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/windows/AsynchIO.cpp | 100 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/windows/PollableCondition.cpp | 5 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/windows/Socket.cpp | 10 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/windows/SslAsynchIO.cpp | 8 |
19 files changed, 194 insertions, 833 deletions
diff --git a/cpp/src/qpid/sys/apr/Time.cpp b/cpp/src/qpid/sys/MemStat.h index 34e740b144..d855786cd5 100644 --- a/cpp/src/qpid/sys/apr/Time.cpp +++ b/cpp/src/qpid/sys/MemStat.h @@ -7,9 +7,9 @@ * 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 @@ -18,19 +18,21 @@ * under the License. * */ +#ifndef sys_MemStat +#define sys_MemStat -#include "qpid/sys/Time.h" - -#include <apr_time.h> +#include "qpid/CommonImportExport.h" +#include "qmf/org/apache/qpid/broker/Memory.h" namespace qpid { namespace sys { - -AbsTime AbsTime::now() { - AbsTime time_now; - time_now.time_ns = apr_time_now() * TIME_USEC; - return time_now; -} + + class QPID_COMMON_CLASS_EXTERN MemStat { + public: + QPID_COMMON_EXTERN static void loadMemInfo(qmf::org::apache::qpid::broker::Memory* object); + }; }} +#endif + diff --git a/cpp/src/qpid/sys/Probes.h b/cpp/src/qpid/sys/Probes.h new file mode 100644 index 0000000000..d30181c357 --- /dev/null +++ b/cpp/src/qpid/sys/Probes.h @@ -0,0 +1,65 @@ +#ifndef _sys_Probes +#define _sys_Probes +/* + * + * 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 "config.h" + +#ifdef HAVE_SYS_SDT_H +#include <sys/sdt.h> +#endif + +// Pragmatically it seems that Linux and Solaris versions of sdt.h which support +// user static probes define up to DTRACE_PROBE8, but FreeBSD 8 which doesn't +// support usdt only defines up to DTRACE_PROBE4 - FreeBSD 9 which does support usdt +// defines up to DTRACE_PROBE5. + +#ifdef DTRACE_PROBE5 +// Versions for Linux Systemtap/Solaris/FreeBSD 9 +#define QPID_PROBE(probe) DTRACE_PROBE(qpid, probe) +#define QPID_PROBE1(probe, p1) DTRACE_PROBE1(qpid, probe, p1) +#define QPID_PROBE2(probe, p1, p2) DTRACE_PROBE2(qpid, probe, p1, p2) +#define QPID_PROBE3(probe, p1, p2, p3) DTRACE_PROBE3(qpid, probe, p1, p2, p3) +#define QPID_PROBE4(probe, p1, p2, p3, p4) DTRACE_PROBE4(qpid, probe, p1, p2, p3, p4) +#define QPID_PROBE5(probe, p1, p2, p3, p4, p5) DTRACE_PROBE5(qpid, probe, p1, p2, p3, p4, p5) +#else +// FreeBSD 8 +#define QPID_PROBE(probe) +#define QPID_PROBE1(probe, p1) +#define QPID_PROBE2(probe, p1, p2) +#define QPID_PROBE3(probe, p1, p2, p3) +#define QPID_PROBE4(probe, p1, p2, p3, p4) +#define QPID_PROBE5(probe, p1, p2, p3, p4, p5) +#endif + +#ifdef DTRACE_PROBE8 +// Versions for Linux Systemtap +#define QPID_PROBE6(probe, p1, p2, p3, p4, p5, p6) DTRACE_PROBE6(qpid, probe, p1, p2, p3, p4, p5, p6) +#define QPID_PROBE7(probe, p1, p2, p3, p4, p5, p6, p7) DTRACE_PROBE7(qpid, probe, p1, p2, p3, p4, p5, p6, p7) +#define QPID_PROBE8(probe, p1, p2, p3, p4, p5, p6, p7, p8) DTRACE_PROBE8(qpid, probe, p1, p2, p3, p4, p5, p6, p7, p8) +#else +// Versions for Solaris/FreeBSD +#define QPID_PROBE6(probe, p1, p2, p3, p4, p5, p6) +#define QPID_PROBE7(probe, p1, p2, p3, p4, p5, p6, p7) +#define QPID_PROBE8(probe, p1, p2, p3, p4, p5, p6, p7, p8) +#endif + +#endif // _sys_Probes diff --git a/cpp/src/qpid/sys/apr/APRBase.cpp b/cpp/src/qpid/sys/apr/APRBase.cpp deleted file mode 100644 index 8bdba66bdc..0000000000 --- a/cpp/src/qpid/sys/apr/APRBase.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * - * 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 "qpid/log/Statement.h" -#include "qpid/sys/apr/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()) - QPID_LOG(warning, "APR initialization triggered concurrently with termination."); -} - -void APRBase::decrement(){ - getInstance()->_decrement(); -} - -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)); -} - diff --git a/cpp/src/qpid/sys/apr/APRBase.h b/cpp/src/qpid/sys/apr/APRBase.h deleted file mode 100644 index 7b5644a129..0000000000 --- a/cpp/src/qpid/sys/apr/APRBase.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * - * 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 char* file, const int line); - std::string get_desc(apr_status_t status); - -#define CHECK_APR_SUCCESS(A) qpid::sys::check(A, __FILE__, __LINE__); - -} -} - -// Inlined as it is called *a lot* -void inline qpid::sys::check(apr_status_t status, const char* file, const int line){ - if (status != APR_SUCCESS){ - char tmp[256]; - throw Exception(QPID_MSG(apr_strerror(status, tmp, size))) - } -} - - - - -#endif diff --git a/cpp/src/qpid/sys/apr/APRPool.cpp b/cpp/src/qpid/sys/apr/APRPool.cpp deleted file mode 100644 index e221bfc2f1..0000000000 --- a/cpp/src/qpid/sys/apr/APRPool.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * 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 "qpid/sys/apr/APRPool.h" -#include "qpid/sys/apr/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; -} - diff --git a/cpp/src/qpid/sys/apr/APRPool.h b/cpp/src/qpid/sys/apr/APRPool.h deleted file mode 100644 index da7661fcfa..0000000000 --- a/cpp/src/qpid/sys/apr/APRPool.h +++ /dev/null @@ -1,50 +0,0 @@ -#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_*/ diff --git a/cpp/src/qpid/sys/apr/Condition.h b/cpp/src/qpid/sys/apr/Condition.h deleted file mode 100644 index 66d465ca75..0000000000 --- a/cpp/src/qpid/sys/apr/Condition.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef _sys_apr_Condition_h -#define _sys_apr_Condition_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 "qpid/sys/apr/APRPool.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Time.h" - -#include <sys/errno.h> -#include <boost/noncopyable.hpp> -#include <apr_thread_cond.h> - -namespace qpid { -namespace sys { - -/** - * A condition variable for thread synchronization. - */ -class Condition -{ - public: - inline Condition(); - inline ~Condition(); - inline void wait(Mutex&); - inline bool wait(Mutex&, const AbsTime& absoluteTime); - inline void notify(); - inline void notifyAll(); - - private: - apr_thread_cond_t* condition; -}; - - -Condition::Condition() { - CHECK_APR_SUCCESS(apr_thread_cond_create(&condition, APRPool::get())); -} - -Condition::~Condition() { - CHECK_APR_SUCCESS(apr_thread_cond_destroy(condition)); -} - -void Condition::wait(Mutex& mutex) { - CHECK_APR_SUCCESS(apr_thread_cond_wait(condition, mutex.mutex)); -} - -bool Condition::wait(Mutex& mutex, const AbsTime& absoluteTime){ - // APR uses microseconds. - apr_status_t status = - apr_thread_cond_timedwait( - condition, mutex.mutex, Duration(now(), absoluteTime)/TIME_USEC); - if(status != APR_TIMEUP) CHECK_APR_SUCCESS(status); - return status == 0; -} - -void Condition::notify(){ - CHECK_APR_SUCCESS(apr_thread_cond_signal(condition)); -} - -void Condition::notifyAll(){ - CHECK_APR_SUCCESS(apr_thread_cond_broadcast(condition)); -} - -}} -#endif /*!_sys_apr_Condition_h*/ diff --git a/cpp/src/qpid/sys/apr/Mutex.h b/cpp/src/qpid/sys/apr/Mutex.h deleted file mode 100644 index cb75f5b339..0000000000 --- a/cpp/src/qpid/sys/apr/Mutex.h +++ /dev/null @@ -1,124 +0,0 @@ -#ifndef _sys_apr_Mutex_h -#define _sys_apr_Mutex_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 "qpid/sys/apr/APRBase.h" -#include "qpid/sys/apr/APRPool.h" - -#include <boost/noncopyable.hpp> -#include <apr_thread_mutex.h> - -namespace qpid { -namespace sys { - -class Condition; - -/** - * Mutex lock. - */ -class Mutex : private boost::noncopyable { - public: - typedef ScopedLock<Mutex> ScopedLock; - typedef ScopedUnlock<Mutex> ScopedUnlock; - - inline Mutex(); - inline ~Mutex(); - inline void lock(); - inline void unlock(); - inline bool trylock(); - - protected: - apr_thread_mutex_t* mutex; - friend class Condition; -}; - -Mutex::Mutex() { - CHECK_APR_SUCCESS(apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_NESTED, APRPool::get())); -} - -Mutex::~Mutex(){ - CHECK_APR_SUCCESS(apr_thread_mutex_destroy(mutex)); -} - -void Mutex::lock() { - CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex)); -} -void Mutex::unlock() { - CHECK_APR_SUCCESS(apr_thread_mutex_unlock(mutex)); -} - -bool Mutex::trylock() { - return apr_thread_mutex_trylock(mutex) == 0; -} - - -/** - * RW lock. - */ -class RWlock : private boost::noncopyable { - friend class Condition; - -public: - typedef ScopedRlock<RWlock> ScopedRlock; - typedef ScopedWlock<RWlock> ScopedWlock; - - inline RWlock(); - inline ~RWlock(); - inline void wlock(); // will write-lock - inline void rlock(); // will read-lock - inline void unlock(); - inline bool trywlock(); // will write-try - inline bool tryrlock(); // will read-try - - protected: - apr_thread_mutex_t* mutex; -}; - -RWlock::RWlock() { - CHECK_APR_SUCCESS(apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_NESTED, APRPool::get())); -} - -RWlock::~RWlock(){ - CHECK_APR_SUCCESS(apr_thread_mutex_destroy(mutex)); -} - -void RWlock::wlock() { - CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex)); -} - -void RWlock::rlock() { - CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex)); -} - -void RWlock::unlock() { - CHECK_APR_SUCCESS(apr_thread_mutex_unlock(mutex)); -} - -bool RWlock::trywlock() { - return apr_thread_mutex_trylock(mutex) == 0; -} - -bool RWlock::tryrlock() { - return apr_thread_mutex_trylock(mutex) == 0; -} - - -}} -#endif /*!_sys_apr_Mutex_h*/ diff --git a/cpp/src/qpid/sys/apr/Shlib.cpp b/cpp/src/qpid/sys/apr/Shlib.cpp deleted file mode 100644 index b7ee13a03b..0000000000 --- a/cpp/src/qpid/sys/apr/Shlib.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 "qpid/sys/Shlib.h" -#include "qpid/sys/apr/APRBase.h" -#include "qpid/sys/apr/APRPool.h" -#include <apr_dso.h> - -namespace qpid { -namespace sys { - -void Shlib::load(const char* libname) { - apr_dso_handle_t* aprHandle; - CHECK_APR_SUCCESS( - apr_dso_load(&aprHandle, libname, APRPool::get())); - handle=aprHandle; -} - -void Shlib::unload() { - CHECK_APR_SUCCESS( - apr_dso_unload(static_cast<apr_dso_handle_t*>(handle))); -} - -void* Shlib::getSymbol(const char* name) { - apr_dso_handle_sym_t symbol; - CHECK_APR_SUCCESS(apr_dso_sym(&symbol, - static_cast<apr_dso_handle_t*>(handle), - name)); - return (void*) symbol; -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/apr/Socket.cpp b/cpp/src/qpid/sys/apr/Socket.cpp deleted file mode 100644 index d9024d11c1..0000000000 --- a/cpp/src/qpid/sys/apr/Socket.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * - * 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 "qpid/sys/Socket.h" - -#include "qpid/sys/apr/APRBase.h" -#include "qpid/sys/apr/APRPool.h" - -#include <apr_network_io.h> - -namespace qpid { -namespace sys { - -class SocketPrivate { -public: - SocketPrivate(apr_socket_t* s = 0) : - socket(s) - {} - - apr_socket_t* socket; -}; - -Socket::Socket() : - impl(new SocketPrivate) -{ - createTcp(); -} - -Socket::Socket(SocketPrivate* sp) : - impl(sp) -{} - -Socket::~Socket() { - delete impl; -} - -void Socket::createTcp() const { - apr_socket_t*& socket = impl->socket; - apr_socket_t* s; - CHECK_APR_SUCCESS( - apr_socket_create( - &s, APR_INET, SOCK_STREAM, APR_PROTO_TCP, - APRPool::get())); - socket = s; -} - -void Socket::setTimeout(const Duration& interval) const { - apr_socket_t*& socket = impl->socket; - apr_socket_timeout_set(socket, interval/TIME_USEC); -} - -void Socket::connect(const std::string& host, int port) const { - apr_socket_t*& socket = impl->socket; - 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() const { - apr_socket_t*& socket = impl->socket; - if (socket == 0) return; - CHECK_APR_SUCCESS(apr_socket_close(socket)); - socket = 0; -} - -ssize_t Socket::send(const void* data, size_t size) const -{ - apr_socket_t*& socket = impl->socket; - 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) const -{ - apr_socket_t*& socket = impl->socket; - 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; - if (APR_STATUS_IS_EOF(status)) - return SOCKET_EOF; - CHECK_APR_SUCCESS(status); - return received; -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/apr/Thread.cpp b/cpp/src/qpid/sys/apr/Thread.cpp deleted file mode 100644 index b52d0e6ace..0000000000 --- a/cpp/src/qpid/sys/apr/Thread.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * - * 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 "qpid/sys/apr/Thread.h" -#include "qpid/sys/Runnable.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; -} - - diff --git a/cpp/src/qpid/sys/apr/Thread.h b/cpp/src/qpid/sys/apr/Thread.h deleted file mode 100644 index 6cc63db5c9..0000000000 --- a/cpp/src/qpid/sys/apr/Thread.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef _sys_apr_Thread_h -#define _sys_apr_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 "qpid/sys/apr/APRPool.h" -#include "qpid/sys/apr/APRBase.h" - -#include <apr_thread_proc.h> -#include <apr_portable.h> - -namespace qpid { -namespace sys { - -class Runnable; - -class Thread -{ - public: - inline static Thread current(); - - /** ID of current thread for logging. - * Workaround for broken Thread::current() in APR - */ - inline static long logId(); - - 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: - static void* APR_THREAD_FUNC runRunnable(apr_thread_t* thread, void *data); - inline Thread(apr_thread_t* t); - apr_thread_t* thread; -}; - -Thread::Thread() : thread(0) {} - -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); -} - -/** ID of current thread for logging. - * Workaround for broken Thread::current() in APR - */ -long Thread::logId() { - return static_cast<long>(apr_os_thread_current()); -} - -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(); -} - -}} -#endif /*!_sys_apr_Thread_h*/ diff --git a/cpp/src/qpid/sys/posix/AsynchIO.cpp b/cpp/src/qpid/sys/posix/AsynchIO.cpp index a1c161b596..01ff8b6bfa 100644 --- a/cpp/src/qpid/sys/posix/AsynchIO.cpp +++ b/cpp/src/qpid/sys/posix/AsynchIO.cpp @@ -23,6 +23,7 @@ #include "qpid/sys/Socket.h" #include "qpid/sys/SocketAddress.h" #include "qpid/sys/Poller.h" +#include "qpid/sys/Probes.h" #include "qpid/sys/DispatchHandle.h" #include "qpid/sys/Time.h" #include "qpid/log/Statement.h" @@ -40,7 +41,9 @@ #include <boost/bind.hpp> #include <boost/lexical_cast.hpp> -using namespace qpid::sys; +namespace qpid { +namespace sys { +namespace posix { namespace { @@ -70,10 +73,6 @@ __thread int64_t threadMaxIoTimeNs = 2 * 1000000; // start at 2ms /* * Asynch Acceptor */ -namespace qpid { -namespace sys { -namespace posix { - class AsynchAcceptor : public qpid::sys::AsynchAcceptor { public: AsynchAcceptor(const Socket& s, AsynchAcceptor::Callback callback); @@ -423,9 +422,12 @@ AsynchIO::BufferBase* AsynchIO::getQueuedBuffer() { void AsynchIO::readable(DispatchHandle& h) { if (readingStopped) { // We have been flow controlled. + QPID_PROBE1(asynchio_read_flowcontrolled, &h); return; } AbsTime readStartTime = AbsTime::now(); + size_t total = 0; + int readCalls = 0; do { // (Try to) get a buffer if (!bufferQueue.empty()) { @@ -436,23 +438,29 @@ void AsynchIO::readable(DispatchHandle& h) { errno = 0; int readCount = buff->byteCount-buff->dataCount; int rc = socket.read(buff->bytes + buff->dataCount, readCount); + int64_t duration = Duration(readStartTime, AbsTime::now()); + ++readCalls; if (rc > 0) { buff->dataCount += rc; threadReadTotal += rc; + total += rc; readCallback(*this, buff); if (readingStopped) { // We have been flow controlled. + QPID_PROBE4(asynchio_read_finished_flowcontrolled, &h, duration, total, readCalls); break; } if (rc != readCount) { // If we didn't fill the read buffer then time to stop reading + QPID_PROBE4(asynchio_read_finished_done, &h, duration, total, readCalls); break; } // Stop reading if we've overrun our timeslot - if (Duration(readStartTime, AbsTime::now()) > threadMaxIoTimeNs) { + if ( duration > threadMaxIoTimeNs) { + QPID_PROBE4(asynchio_read_finished_maxtime, &h, duration, total, readCalls); break; } @@ -461,6 +469,7 @@ void AsynchIO::readable(DispatchHandle& h) { bufferQueue.push_front(buff); assert(buff); + QPID_PROBE5(asynchio_read_finished_error, &h, duration, total, readCalls, errno); // Eof or other side has gone away if (rc == 0 || errno == ECONNRESET) { eofCallback(*this); @@ -486,6 +495,7 @@ void AsynchIO::readable(DispatchHandle& h) { // If we still have no buffers we can't do anything more if (bufferQueue.empty()) { h.unwatchRead(); + QPID_PROBE4(asynchio_read_finished_nobuffers, &h, Duration(readStartTime, AbsTime::now()), total, readCalls); break; } @@ -501,6 +511,8 @@ void AsynchIO::readable(DispatchHandle& h) { */ void AsynchIO::writeable(DispatchHandle& h) { AbsTime writeStartTime = AbsTime::now(); + size_t total = 0; + int writeCalls = 0; do { // See if we've got something to write if (!writeQueue.empty()) { @@ -510,14 +522,18 @@ void AsynchIO::writeable(DispatchHandle& h) { errno = 0; assert(buff->dataStart+buff->dataCount <= buff->byteCount); int rc = socket.write(buff->bytes+buff->dataStart, buff->dataCount); + int64_t duration = Duration(writeStartTime, AbsTime::now()); + ++writeCalls; if (rc >= 0) { threadWriteTotal += rc; + total += rc; // If we didn't write full buffer put rest back if (rc != buff->dataCount) { buff->dataStart += rc; buff->dataCount -= rc; writeQueue.push_back(buff); + QPID_PROBE4(asynchio_write_finished_done, &h, duration, total, writeCalls); break; } @@ -525,12 +541,15 @@ void AsynchIO::writeable(DispatchHandle& h) { queueReadBuffer(buff); // Stop writing if we've overrun our timeslot - if (Duration(writeStartTime, AbsTime::now()) > threadMaxIoTimeNs) { + if (duration > threadMaxIoTimeNs) { + QPID_PROBE4(asynchio_write_finished_maxtime, &h, duration, total, writeCalls); break; } } else { // Put buffer back writeQueue.push_back(buff); + QPID_PROBE5(asynchio_write_finished_error, &h, duration, total, writeCalls, errno); + if (errno == ECONNRESET || errno == EPIPE) { // Just stop watching for write here - we'll get a // disconnect callback soon enough @@ -548,9 +567,13 @@ void AsynchIO::writeable(DispatchHandle& h) { } } } else { + int64_t duration = Duration(writeStartTime, AbsTime::now()); + (void) duration; // force duration to be used if no probes are compiled + // If we're waiting to close the socket then can do it now as there is nothing to write if (queuedClose) { close(h); + QPID_PROBE4(asynchio_write_finished_closed, &h, duration, total, writeCalls); break; } // Fd is writable, but nothing to write @@ -567,6 +590,7 @@ void AsynchIO::writeable(DispatchHandle& h) { // desired rewatchWrite so we correct that here if (writePending) h.rewatchWrite(); + QPID_PROBE4(asynchio_write_finished_nodata, &h, duration, total, writeCalls); break; } } diff --git a/cpp/src/qpid/sys/posix/PollableCondition.cpp b/cpp/src/qpid/sys/posix/PollableCondition.cpp index b22a615a54..abff8a5be8 100644 --- a/cpp/src/qpid/sys/posix/PollableCondition.cpp +++ b/cpp/src/qpid/sys/posix/PollableCondition.cpp @@ -1,6 +1,3 @@ -#ifndef QPID_SYS_LINUX_POLLABLECONDITION_CPP -#define QPID_SYS_LINUX_POLLABLECONDITION_CPP - /* * * Licensed to the Apache Software Foundation (ASF) under one @@ -120,5 +117,3 @@ void PollableCondition::set() { impl->set(); } void PollableCondition::clear() { impl->clear(); } }} // namespace qpid::sys - -#endif /*!QPID_SYS_LINUX_POLLABLECONDITION_CPP*/ diff --git a/cpp/src/qpid/sys/ssl/SslIo.cpp b/cpp/src/qpid/sys/ssl/SslIo.cpp index 73f15617dc..2a7cf16923 100644 --- a/cpp/src/qpid/sys/ssl/SslIo.cpp +++ b/cpp/src/qpid/sys/ssl/SslIo.cpp @@ -37,8 +37,9 @@ #include <boost/bind.hpp> -using namespace qpid::sys; -using namespace qpid::sys::ssl; +namespace qpid { +namespace sys { +namespace ssl { namespace { @@ -448,3 +449,5 @@ SecuritySettings SslIO::getSecuritySettings() { settings.authid = socket.getClientAuthId(); return settings; } + +}}} diff --git a/cpp/src/qpid/sys/windows/AsynchIO.cpp b/cpp/src/qpid/sys/windows/AsynchIO.cpp index 30378d4c5f..ae53414e52 100644 --- a/cpp/src/qpid/sys/windows/AsynchIO.cpp +++ b/cpp/src/qpid/sys/windows/AsynchIO.cpp @@ -291,6 +291,8 @@ private: volatile LONG opsInProgress; // Is there a write in progress? volatile bool writeInProgress; + // Or a read? + volatile bool readInProgress; // Deletion requested, but there are callbacks in progress. volatile bool queuedDelete; // Socket close requested, but there are operations in progress. @@ -344,6 +346,11 @@ private: * Called when there's a completion to process. */ void completion(AsynchIoResult *result); + + /** + * Helper function to facilitate the close operation + */ + void cancelRead(); }; // This is used to encapsulate pure callbacks into a handle @@ -372,6 +379,7 @@ AsynchIO::AsynchIO(const Socket& s, socket(s), opsInProgress(0), writeInProgress(false), + readInProgress(false), queuedDelete(false), queuedClose(false), working(false) { @@ -389,21 +397,24 @@ AsynchIO::~AsynchIO() { } void AsynchIO::queueForDeletion() { - queuedDelete = true; - if (opsInProgress > 0) { - QPID_LOG(info, "Delete AsynchIO queued; ops in progress"); - // AsynchIOHandler calls this then deletes itself; don't do any more - // callbacks. - readCallback = 0; - eofCallback = 0; - disCallback = 0; - closedCallback = 0; - emptyCallback = 0; - idleCallback = 0; - } - else { - delete this; + { + ScopedLock<Mutex> l(completionLock); + assert(!queuedDelete); + queuedDelete = true; + if (working || opsInProgress > 0) { + QPID_LOG(info, "Delete AsynchIO queued; ops in progress"); + // AsynchIOHandler calls this then deletes itself; don't do any more + // callbacks. + readCallback = 0; + eofCallback = 0; + disCallback = 0; + closedCallback = 0; + emptyCallback = 0; + idleCallback = 0; + return; + } } + delete this; } void AsynchIO::start(Poller::shared_ptr poller0) { @@ -451,9 +462,14 @@ void AsynchIO::notifyPendingWrite() { } void AsynchIO::queueWriteClose() { - queuedClose = true; - if (!writeInProgress) - notifyPendingWrite(); + { + ScopedLock<Mutex> l(completionLock); + queuedClose = true; + if (working || writeInProgress) + // no need to summon an IO thread + return; + } + notifyPendingWrite(); } bool AsynchIO::writeQueueEmpty() { @@ -466,7 +482,7 @@ bool AsynchIO::writeQueueEmpty() { * called when the read is complete and data is available. */ void AsynchIO::startReading() { - if (queuedDelete) + if (queuedDelete || queuedClose) return; // (Try to) get a buffer; look on the front since there may be an @@ -489,6 +505,7 @@ void AsynchIO::startReading() { readCount); DWORD bytesReceived = 0, flags = 0; InterlockedIncrement(&opsInProgress); + readInProgress = true; int status = WSARecv(toSocketHandle(socket), const_cast<LPWSABUF>(result->getWSABUF()), 1, &bytesReceived, @@ -616,17 +633,19 @@ void AsynchIO::close(void) { void AsynchIO::readComplete(AsynchReadResult *result) { int status = result->getStatus(); size_t bytes = result->getTransferred(); + readInProgress = false; if (status == 0 && bytes > 0) { - bool restartRead = true; // May not if receiver doesn't want more if (readCallback) readCallback(*this, result->getBuff()); - if (restartRead) - startReading(); + startReading(); } else { // No data read, so put the buffer back. It may be partially filled, // so "unread" it back to the front of the queue. unread(result->getBuff()); + if (queuedClose) { + return; // Expected from cancelRead() + } notifyEof(); if (status != 0) { @@ -682,6 +701,8 @@ void AsynchIO::writeComplete(AsynchWriteResult *result) { } void AsynchIO::completion(AsynchIoResult *result) { + bool closing = false; + bool deleting = false; { ScopedLock<Mutex> l(completionLock); if (working) { @@ -713,6 +734,8 @@ void AsynchIO::completion(AsynchIoResult *result) { delete result; result = 0; InterlockedDecrement(&opsInProgress); + if (queuedClose && opsInProgress == 1 && readInProgress) + cancelRead(); } // Lock is held again. if (completionQueue.empty()) @@ -721,17 +744,40 @@ void AsynchIO::completion(AsynchIoResult *result) { completionQueue.pop(); } working = false; + if (opsInProgress == 0) { + closing = queuedClose; + deleting = queuedDelete; + } } // Lock released; ok to close if ops are done and close requested. // Layer above will call back to queueForDeletion() if it hasn't // already been done. If it already has, go ahead and delete. - if (opsInProgress == 0) { - if (queuedClose) - // close() may cause a delete; don't trust 'this' on return - close(); - else if (queuedDelete) - delete this; + if (deleting) + delete this; + else if (closing) + // close() may cause a delete; don't trust 'this' on return + close(); +} + +/* + * NOTE - this method must be called in the same context as other completions, + * so that the resulting readComplete, and final AsynchIO::close() is serialized + * after this method returns. + */ +void AsynchIO::cancelRead() { + if (queuedDelete) + return; // socket already deleted + else { + ScopedLock<Mutex> l(completionLock);; + if (!completionQueue.empty()) + return; // process it; come back later if necessary } + // Cancel outstanding read and force to completion. Otherwise, on a faulty + // physical link, the pending read can remain uncompleted indefinitely. + // Draining the pending read will result in the official close (and + // notifyClosed). CancelIoEX() is the natural choice, but not available in + // XP, so we make do with closesocket(). + socket.close(); } } // namespace windows diff --git a/cpp/src/qpid/sys/windows/PollableCondition.cpp b/cpp/src/qpid/sys/windows/PollableCondition.cpp index 6a1d9045b4..bb637be0a6 100644 --- a/cpp/src/qpid/sys/windows/PollableCondition.cpp +++ b/cpp/src/qpid/sys/windows/PollableCondition.cpp @@ -1,6 +1,3 @@ -#ifndef QPID_SYS_WINDOWS_POLLABLECONDITION_CPP -#define QPID_SYS_WINDOWS_POLLABLECONDITION_CPP - /* * * Licensed to the Apache Software Foundation (ASF) under one @@ -110,5 +107,3 @@ void PollableCondition::clear() { } }} // namespace qpid::sys - -#endif /*!QPID_SYS_WINDOWS_POLLABLECONDITION_CPP*/ diff --git a/cpp/src/qpid/sys/windows/Socket.cpp b/cpp/src/qpid/sys/windows/Socket.cpp index 1fa4768329..b085f67539 100644 --- a/cpp/src/qpid/sys/windows/Socket.cpp +++ b/cpp/src/qpid/sys/windows/Socket.cpp @@ -32,6 +32,9 @@ #include <winsock2.h> +namespace qpid { +namespace sys { + // Need to initialize WinSock. Ideally, this would be a singleton or embedded // in some one-time initialization function. I tried boost singleton and could // not get it to compile (and others located in google had the same problem). @@ -76,13 +79,6 @@ protected: static WinSockSetup setup; -} /* namespace */ - -namespace qpid { -namespace sys { - -namespace { - std::string getName(SOCKET fd, bool local) { ::sockaddr_storage name_s; // big enough for any socket address diff --git a/cpp/src/qpid/sys/windows/SslAsynchIO.cpp b/cpp/src/qpid/sys/windows/SslAsynchIO.cpp index 11a3389e45..25cc94b290 100644 --- a/cpp/src/qpid/sys/windows/SslAsynchIO.cpp +++ b/cpp/src/qpid/sys/windows/SslAsynchIO.cpp @@ -38,6 +38,10 @@ #include <queue> #include <boost/bind.hpp> +namespace qpid { +namespace sys { +namespace windows { + namespace { /* @@ -66,10 +70,6 @@ namespace { }; } -namespace qpid { -namespace sys { -namespace windows { - SslAsynchIO::SslAsynchIO(const qpid::sys::Socket& s, CredHandle hCred, ReadCallback rCb, |
