IGNITE-1443: Implemented ContinuousQuery for C++ This closes #1343
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/598b464f Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/598b464f Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/598b464f Branch: refs/heads/master Commit: 598b464f81d2e74dc0df62011e08f3a76a674db6 Parents: 700529a Author: Igor Sapego <[email protected]> Authored: Tue Dec 20 19:38:41 2016 +0300 Committer: Pavel Tupitsyn <[email protected]> Committed: Tue Dec 20 19:38:41 2016 +0300 ---------------------------------------------------------------------- .gitignore | 1 + .../include/ignite/binary/binary_raw_reader.h | 21 + .../ignite/impl/binary/binary_reader_impl.h | 9 +- .../src/impl/binary/binary_reader_impl.cpp | 17 + .../platforms/cpp/common/include/Makefile.am | 5 +- .../common/include/ignite/common/concurrent.h | 90 ++- .../include/ignite/common/reference_impl.h | 286 +++++++++ .../cpp/common/include/ignite/reference.h | 564 +++++++++++++++++ .../cpp/common/project/vs/common.vcxproj | 2 + .../common/project/vs/common.vcxproj.filters | 6 + modules/platforms/cpp/core-test/Makefile.am | 7 +- .../core-test/config/cache-query-continuous.xml | 87 +++ .../cpp/core-test/project/vs/core-test.vcxproj | 10 +- .../project/vs/core-test.vcxproj.filters | 6 + .../cpp/core-test/src/cache_query_test.cpp | 76 +-- .../cpp/core-test/src/continuous_query_test.cpp | 611 +++++++++++++++++++ .../cpp/core-test/src/handle_registry_test.cpp | 18 +- .../cpp/core-test/src/reference_test.cpp | 412 +++++++++++++ modules/platforms/cpp/core/Makefile.am | 1 + .../cpp/core/include/ignite/cache/cache.h | 104 +++- .../cpp/core/include/ignite/cache/cache_entry.h | 40 +- .../ignite/cache/event/cache_entry_event.h | 139 +++++ .../cache/event/cache_entry_event_listener.h | 71 +++ .../cache/query/continuous/continuous_query.h | 239 ++++++++ .../query/continuous/continuous_query_handle.h | 133 ++++ .../core/include/ignite/impl/cache/cache_impl.h | 116 +++- .../continuous/continuous_query_handle_impl.h | 101 +++ .../query/continuous/continuous_query_impl.h | 351 +++++++++++ .../core/include/ignite/impl/handle_registry.h | 62 +- .../include/ignite/impl/ignite_environment.h | 34 +- modules/platforms/cpp/core/namespaces.dox | 74 ++- .../platforms/cpp/core/project/vs/core.vcxproj | 7 + .../cpp/core/project/vs/core.vcxproj.filters | 30 + .../cpp/core/src/impl/cache/cache_impl.cpp | 31 + .../continuous/continuous_query_handle_impl.cpp | 96 +++ .../cpp/core/src/impl/handle_registry.cpp | 102 ++-- .../cpp/core/src/impl/ignite_environment.cpp | 98 ++- modules/platforms/cpp/examples/Makefile.am | 1 + modules/platforms/cpp/examples/configure.ac | 1 + .../continuous-query-example/Makefile.am | 58 ++ .../config/continuous-query-example.xml | 52 ++ .../project/vs/continuous-query-example.vcxproj | 110 ++++ .../vs/continuous-query-example.vcxproj.filters | 35 ++ .../src/continuous_query_example.cpp | 142 +++++ .../examples/include/ignite/examples/person.h | 2 +- .../cpp/examples/project/vs/ignite-examples.sln | 6 + .../platforms/cpp/jni/include/ignite/jni/java.h | 2 +- modules/platforms/cpp/jni/src/java.cpp | 4 +- .../cpp/odbc-test/project/vs/odbc-test.vcxproj | 4 +- modules/platforms/cpp/project/vs/ignite.slnrel | 3 + .../platforms/cpp/project/vs/ignite_x86.slnrel | 3 + 51 files changed, 4216 insertions(+), 264 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/.gitignore ---------------------------------------------------------------------- diff --git a/.gitignore b/.gitignore index b534eb7..db6128e 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ git-patch-prop-local.sh *.opensdf *.db *.opendb +.vs ipch/ [Oo]bj/ [Bb]in http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_reader.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_reader.h b/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_reader.h index 72aab55..d15848b 100644 --- a/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_reader.h +++ b/modules/platforms/cpp/binary/include/ignite/binary/binary_raw_reader.h @@ -398,6 +398,27 @@ namespace ignite { return impl->ReadObject<T>(); } + + /** + * Try read object. + * Reads value, stores it to res and returns true if the value is + * not null. Otherwise just returns false. + * + * @param res Read value is placed here if non-null. + * @return True if the non-null value has been read and false + * otherwise. + */ + template<typename T> + bool TryReadObject(T& res) + { + if (impl->SkipIfNull()) + return false; + + res = impl->ReadObject<T>(); + + return true; + } + private: /** Implementation delegate. */ ignite::impl::binary::BinaryReaderImpl* impl; http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h index 8c4b464..cd32203 100644 --- a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h +++ b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h @@ -723,6 +723,13 @@ namespace ignite bool HasNextElement(int32_t id) const; /** + * Skip next value if it is the null. + * + * @return True if the null value has been detected and skipped. + */ + bool SkipIfNull(); + + /** * Read element. * * @param id Session ID. @@ -763,7 +770,7 @@ namespace ignite *key = ReadTopObject<K>(); *val = ReadTopObject<V>(); } - + /** * Read object. * http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp b/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp index fb75ba5..c128df6 100644 --- a/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp +++ b/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp @@ -663,6 +663,23 @@ namespace ignite return elemId == id && elemRead < elemCnt; } + bool BinaryReaderImpl::SkipIfNull() + { + CheckRawMode(true); + CheckSingleMode(true); + + InteropStreamPositionGuard<InteropInputStream> positionGuard(*stream); + + int8_t hdr = stream->ReadInt8(); + + if (hdr != IGNITE_HDR_NULL) + return false; + + positionGuard.Release(); + + return true; + } + void BinaryReaderImpl::SetRawMode() { CheckRawMode(false); http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/common/include/Makefile.am ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/common/include/Makefile.am b/modules/platforms/cpp/common/include/Makefile.am index 2e53608..a5073f6 100644 --- a/modules/platforms/cpp/common/include/Makefile.am +++ b/modules/platforms/cpp/common/include/Makefile.am @@ -23,14 +23,15 @@ nobase_include_HEADERS = \ ignite/common/concurrent.h \ ignite/common/decimal.h \ ignite/common/default_allocator.h \ + ignite/common/reference_impl.h \ ignite/common/dynamic_size_array.h \ ignite/common/fixed_size_array.h \ ignite/common/utils.h \ ignite/date.h \ ignite/guid.h \ ignite/ignite_error.h \ - ignite/timestamp.h - ignite/timestamp.h + ignite/timestamp.h \ + ignite/reference.h uninstall-hook: if [ -d ${includedir}/ignite ]; then find ${includedir}/ignite -type d -empty -delete; fi http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/common/include/ignite/common/concurrent.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/common/include/ignite/common/concurrent.h b/modules/platforms/cpp/common/include/ignite/common/concurrent.h index 35c2209..ff0e54a 100644 --- a/modules/platforms/cpp/common/include/ignite/common/concurrent.h +++ b/modules/platforms/cpp/common/include/ignite/common/concurrent.h @@ -19,6 +19,7 @@ #define _IGNITE_COMMON_CONCURRENT #include <cassert> +#include <utility> #include "ignite/common/concurrent_os.h" @@ -121,10 +122,15 @@ namespace ignite public: friend class EnableSharedFromThis<T>; + template<typename T2> + friend class SharedPointer; + /** * Constructor. */ - SharedPointer() : impl(0) + SharedPointer() : + ptr(0), + impl(0) { // No-op. } @@ -133,17 +139,17 @@ namespace ignite * Constructor. * * @param ptr Raw pointer. + * @param deleter Delete function. */ - explicit SharedPointer(T* ptr) + SharedPointer(T* ptr, void(*deleter)(T*) = &SharedPointerDefaultDeleter<T>) : + ptr(ptr), + impl(0) { if (ptr) { - void(*deleter)(T*) = (void(*)(T*)) &SharedPointerDefaultDeleter<T>; impl = new SharedPointerImpl(ptr, reinterpret_cast<SharedPointerImpl::DeleterType>(deleter)); ImplEnableShared(ptr, impl); } - else - impl = 0; } /** @@ -152,15 +158,16 @@ namespace ignite * @param ptr Raw pointer. * @param deleter Delete function. */ - SharedPointer(T* ptr, void(*deleter)(T*)) + template<typename T2> + SharedPointer(T2* ptr, void(*deleter)(T2*) = &SharedPointerDefaultDeleter<T2>) : + ptr(ptr), + impl(0) { if (ptr) { impl = new SharedPointerImpl(ptr, reinterpret_cast<SharedPointerImpl::DeleterType>(deleter)); ImplEnableShared(ptr, impl); } - else - impl = 0; } /** @@ -169,6 +176,21 @@ namespace ignite * @param other Instance to copy. */ SharedPointer(const SharedPointer& other) : + ptr(other.ptr), + impl(other.impl) + { + if (impl) + impl->Increment(); + } + + /** + * Copy constructor. + * + * @param other Instance to copy. + */ + template<typename T2> + SharedPointer(const SharedPointer<T2>& other) : + ptr(other.ptr), impl(other.impl) { if (impl) @@ -186,26 +208,43 @@ namespace ignite { SharedPointer tmp(other); - std::swap(impl, tmp.impl); + Swap(tmp); } return *this; } /** + * Assignment operator. + * + * @param other Other instance. + */ + template<typename T2> + SharedPointer& operator=(const SharedPointer<T2>& other) + { + SharedPointer<T> tmp(other); + + Swap(tmp); + + return *this; + } + + /** * Destructor. */ ~SharedPointer() { if (impl && impl->Decrement()) { - T* ptr = Get(); + void* ptr0 = impl->Pointer(); - void(*deleter)(T*) = reinterpret_cast<void(*)(T*)>(impl->Deleter()); + void(*deleter)(void*) = impl->Deleter(); - deleter(ptr); + deleter(ptr0); delete impl; + + ptr = 0; } } @@ -216,7 +255,7 @@ namespace ignite */ T* Get() { - return impl ? static_cast<T*>(impl->Pointer()) : 0; + return ptr; } /** @@ -226,7 +265,7 @@ namespace ignite */ const T* Get() const { - return impl ? static_cast<T*>(impl->Pointer()) : 0; + return ptr; } /** @@ -245,7 +284,30 @@ namespace ignite return impl != 0; } + /** + * Swap pointer content with another instance. + * + * @param other Other instance. + */ + void Swap(SharedPointer& other) + { + if (this != &other) + { + T* ptrTmp = ptr; + SharedPointerImpl* implTmp = impl; + + ptr = other.ptr; + impl = other.impl; + + other.ptr = ptrTmp; + other.impl = implTmp; + } + } + private: + /* Pointer. */ + T* ptr; + /** Implementation. */ SharedPointerImpl* impl; }; http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/common/include/ignite/common/reference_impl.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/common/include/ignite/common/reference_impl.h b/modules/platforms/cpp/common/include/ignite/common/reference_impl.h new file mode 100644 index 0000000..e38da8c --- /dev/null +++ b/modules/platforms/cpp/common/include/ignite/common/reference_impl.h @@ -0,0 +1,286 @@ +/* + * 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. + */ + +/** + * @file + * Declares ignite::ReferenceImplBase class and its implementations. + */ + +#ifndef _IGNITE_COMMON_REFERENCE_IMPL +#define _IGNITE_COMMON_REFERENCE_IMPL + +#include <utility> + +#include <ignite/common/common.h> + +namespace ignite +{ + namespace common + { + // Any number is good as long as it is not null. + enum { POINTER_CAST_MAGIC_NUMBER = 80000 }; + + /** + * Interface for constant Reference implementation class template. + */ + class ConstReferenceImplBase + { + public: + /** + * Destructor. + */ + virtual ~ConstReferenceImplBase() + { + // No-op. + } + + /** + * Get the constant pointer. + * + * @return Constant pointer to underlying value. + */ + virtual const void* Get() const = 0; + }; + + /** + * Interface for Reference implementation class template. + */ + class ReferenceImplBase : public ConstReferenceImplBase + { + public: + /** + * Destructor. + */ + virtual ~ReferenceImplBase() + { + // No-op. + } + + virtual const void* Get() const = 0; + + /** + * Get the pointer. + * + * @return Pointer to underlying value. + */ + virtual void* Get() = 0; + }; + + /** + * Reference class implementation for smart pointers. + * + * Note, this class does not implement any smart pointer functionality + * itself, instead it wraps one of the existing wide-spread smart + * pointer implementations and provides unified interface for them. + */ + template<typename P> + class ReferenceSmartPointer : public ReferenceImplBase + { + public: + /** + * Destructor. + */ + virtual ~ReferenceSmartPointer() + { + // No-op. + } + + /** + * Default constructor. + */ + ReferenceSmartPointer() : + ptr() + { + // No-op. + } + + virtual const void* Get() const + { + return reinterpret_cast<const void*>(&(*ptr)); + } + + virtual void* Get() + { + return reinterpret_cast<void*>(&(*ptr)); + } + + /** + * Swap underlying smart pointer. + * + * @param other Another instance. + */ + void Swap(P& other) + { + using std::swap; + + swap(ptr, other); + } + + private: + /** Underlying pointer. */ + P ptr; + }; + + /** + * Reference implementation for the owning raw pointer. + */ + template<typename T> + class ReferenceOwningRawPointer : public ReferenceImplBase + { + public: + /** + * Destructor. + */ + virtual ~ReferenceOwningRawPointer() + { + delete ptr; + } + + /** + * Default constructor. + */ + ReferenceOwningRawPointer() : + ptr(0) + { + // No-op. + } + + /** + * Pointer constructor. + * + * @param ptr Pointer to take ownership over. + */ + ReferenceOwningRawPointer(T* ptr) : + ptr(ptr) + { + // No-op. + } + + virtual const void* Get() const + { + return reinterpret_cast<const void*>(ptr); + } + + virtual void* Get() + { + return reinterpret_cast<void*>(ptr); + } + + private: + /** Underlying pointer. */ + T* ptr; + }; + + /** + * Reference implementation for the raw pointer. + */ + template<typename T> + class ReferenceNonOwningRawPointer : public ReferenceImplBase + { + public: + /** + * Destructor. + */ + virtual ~ReferenceNonOwningRawPointer() + { + // No-op. + } + + /** + * Default constructor. + */ + ReferenceNonOwningRawPointer() : + ptr(0) + { + // No-op. + } + + /** + * Pointer constructor. + * + * @param ptr Pointer. + */ + ReferenceNonOwningRawPointer(T* ptr) : + ptr(ptr) + { + // No-op. + } + + virtual const void* Get() const + { + return reinterpret_cast<const void*>(ptr); + } + + virtual void* Get() + { + return reinterpret_cast<void*>(ptr); + } + + private: + /** Underlying pointer. */ + T* ptr; + }; + + /** + * Constant reference implementation for the raw pointer. + */ + template<typename T> + class ConstReferenceNonOwningRawPointer : public ConstReferenceImplBase + { + public: + /** + * Destructor. + */ + virtual ~ConstReferenceNonOwningRawPointer() + { + // No-op. + } + + /** + * Default constructor. + */ + ConstReferenceNonOwningRawPointer() : + ptr(0) + { + // No-op. + } + + /** + * Pointer constructor. + * + * @param ptr Pointer. + */ + ConstReferenceNonOwningRawPointer(const T* ptr) : + ptr(ptr) + { + // No-op. + } + + virtual const void* Get() const + { + return reinterpret_cast<const void*>(ptr); + } + + private: + /** Underlying pointer. */ + const T* ptr; + }; + + } +} + +#endif //_IGNITE_COMMON_REFERENCE_IMPL \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/common/include/ignite/reference.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/common/include/ignite/reference.h b/modules/platforms/cpp/common/include/ignite/reference.h new file mode 100644 index 0000000..b026ad7 --- /dev/null +++ b/modules/platforms/cpp/common/include/ignite/reference.h @@ -0,0 +1,564 @@ +/* + * 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. + */ + +/** + * @file + * Declares ignite::Reference class. + */ + +#ifndef _IGNITE_COMMON_REFERENCE +#define _IGNITE_COMMON_REFERENCE + +#include <cstddef> + +#include <ignite/common/common.h> +#include <ignite/common/concurrent.h> +#include <ignite/common/reference_impl.h> + +namespace ignite +{ + template<typename T> + class Reference; + + /** + * Constant Reference class. + * + * Abstraction on any reference-type object, from simple raw pointers and + * references to standard library smart pointers. Provides only constant + * access to the underlying data. + * + * There are no requirements for the template type T. + */ + template<typename T> + class ConstReference + { + template<typename> + friend class ConstReference; + + template<typename> + friend class Reference; + + public: + /** + * Default constructor. + */ + ConstReference() : + ptr(), + offset(0) + { + // No-op. + } + + /** + * Constructor. + * + * @param ptr ConstReference class implementation. + * @param offset Pointer offset. + */ + explicit ConstReference(common::ConstReferenceImplBase* ptr, ptrdiff_t offset = 0) : + ptr(ptr), + offset(offset) + { + // No-op. + } + + /** + * Copy constructor. + * + * @param other Another instance. + */ + ConstReference(const ConstReference& other) : + ptr(other.ptr), + offset(other.offset) + { + // No-op. + } + + /** + * Copy constructor. + * + * Constant reference of type T2 should be static-castable to constant + * reference of type T. + * + * @param other Another instance. + */ + template<typename T2> + ConstReference(const ConstReference<T2>& other) : + ptr(other.ptr), + offset(other.offset) + { + T2* p0 = reinterpret_cast<T2*>(common::POINTER_CAST_MAGIC_NUMBER); + T* p1 = static_cast<T*>(p0); + + ptrdiff_t diff = reinterpret_cast<ptrdiff_t>(p1) - reinterpret_cast<ptrdiff_t>(p0); + offset += diff; + } + + /** + * Assignment operator. + * + * @param other Another instance. + */ + ConstReference& operator=(const ConstReference& other) + { + ptr = other.ptr; + offset = other.offset; + + return *this; + } + + /** + * Assignment operator. + * + * Constant reference of type T2 should be static-castable to constant + * reference of type T. + * + * @param other Another instance. + */ + template<typename T2> + ConstReference& operator=(const ConstReference<T2>& other) + { + ptr = other.ptr; + offset = other.offset; + + T2* p0 = reinterpret_cast<T2*>(common::POINTER_CAST_MAGIC_NUMBER); + T* p1 = static_cast<T*>(p0); + + ptrdiff_t diff = reinterpret_cast<ptrdiff_t>(p1) - reinterpret_cast<ptrdiff_t>(p0); + offset += diff; + + return *this; + } + + /** + * Destructor. + */ + ~ConstReference() + { + // No-op. + } + + /** + * Dereference the pointer. + * + * If the pointer is null then this operation causes undefined + * behaviour. + * + * @return Constant reference to underlying value. + */ + const T& Get() const + { + return *reinterpret_cast<const T*>(reinterpret_cast<ptrdiff_t>(ptr.Get()->Get()) + offset); + } + + /** + * Check if the pointer is null. + * + * @return True if the value is null. + */ + bool IsNull() const + { + const common::ConstReferenceImplBase* raw = ptr.Get(); + + return !raw || !raw->Get(); + } + + private: + /** Implementation. */ + common::concurrent::SharedPointer<common::ConstReferenceImplBase> ptr; + + /** Address offset. */ + ptrdiff_t offset; + }; + + /** + * Reference class. + * + * Abstraction on any reference-type object, from simple raw pointers and + * references to standard library smart pointers. + * + * There are no requirements for the template type T. + */ + template<typename T> + class Reference + { + template<typename> + friend class Reference; + public: + /** + * Default constructor. + */ + Reference() : + ptr(), + offset(0) + { + // No-op. + } + + /** + * Constructor. + * + * @param ptr Reference class implementation. + * @param offset Pointer offset. + */ + explicit Reference(common::ReferenceImplBase* ptr, ptrdiff_t offset = 0) : + ptr(ptr), + offset(offset) + { + // No-op. + } + + /** + * Copy constructor. + * + * @param other Another instance. + */ + Reference(const Reference& other) : + ptr(other.ptr), + offset(other.offset) + { + // No-op. + } + + /** + * Copy constructor. + * + * Reference of type T2 should be static-castable to reference of type T. + * + * @param other Another instance. + */ + template<typename T2> + Reference(const Reference<T2>& other) : + ptr(other.ptr), + offset(other.offset) + { + T2* p0 = reinterpret_cast<T2*>(common::POINTER_CAST_MAGIC_NUMBER); + T* p1 = static_cast<T*>(p0); + + ptrdiff_t diff = reinterpret_cast<ptrdiff_t>(p1) - reinterpret_cast<ptrdiff_t>(p0); + offset += diff; + } + + /** + * Assignment operator. + * + * @param other Another instance. + */ + Reference& operator=(const Reference& other) + { + ptr = other.ptr; + offset = other.offset; + + return *this; + } + + /** + * Assignment operator. + * + * Reference of type T2 should be static-castable to reference of type T. + * + * @param other Another instance. + */ + template<typename T2> + Reference& operator=(const Reference<T2>& other) + { + ptr = other.ptr; + offset = other.offset; + + T2* p0 = reinterpret_cast<T2*>(common::POINTER_CAST_MAGIC_NUMBER); + T* p1 = static_cast<T*>(p0); + + ptrdiff_t diff = reinterpret_cast<ptrdiff_t>(p1) - reinterpret_cast<ptrdiff_t>(p0); + offset += diff; + + return *this; + } + + /** + * Destructor. + */ + ~Reference() + { + // No-op. + } + + /** + * Const cast operator. + * + * Reference of type T2 should be static-castable to reference of type T. + * + * Casts this instance to constant reference. + */ + template<typename T2> + operator ConstReference<T2>() + { + ConstReference<T2> cr; + + cr.ptr = ptr; + cr.offset = offset; + + T2* p0 = reinterpret_cast<T2*>(common::POINTER_CAST_MAGIC_NUMBER); + const T* p1 = static_cast<T*>(p0); + + ptrdiff_t diff = reinterpret_cast<ptrdiff_t>(p1) - reinterpret_cast<ptrdiff_t>(p0); + cr.offset -= diff; + + return cr; + } + + /** + * Dereference the pointer. + * + * If the pointer is null then this operation causes undefined + * behaviour. + * + * @return Constant reference to underlying value. + */ + const T& Get() const + { + return *reinterpret_cast<const T*>(reinterpret_cast<ptrdiff_t>(ptr.Get()->Get()) + offset); + } + + /** + * Dereference the pointer. + * + * If the pointer is null then this operation causes undefined + * behaviour. + * + * @return Reference to underlying value. + */ + T& Get() + { + return *reinterpret_cast<T*>(reinterpret_cast<ptrdiff_t>(ptr.Get()->Get()) + offset); + } + + /** + * Check if the pointer is null. + * + * @return True if the value is null. + */ + bool IsNull() const + { + const common::ReferenceImplBase* raw = ptr.Get(); + + return !raw || !raw->Get(); + } + + private: + /** Implementation. */ + common::concurrent::SharedPointer<common::ReferenceImplBase> ptr; + + /** Address offset. */ + ptrdiff_t offset; + }; + + /** + * Make ignite::Reference instance out of smart pointer. + * + * Template type 'T' should be a smart pointer and provide pointer semantics: + * - There should be defined type 'T::element_type', showing underlying type. + * - Type 'T' should be dereferencible (should have operators + * T::element_type& operator*() and const T::element_type& operator*() const). + * - Operation std::swap should result in valid result if applied to two + * instances of that type. + * + * @param ptr Pointer. + * @return Implementation defined value. User should not explicitly use the + * returned value. + */ + template<typename T> + Reference<typename T::element_type> MakeReferenceFromSmartPointer(T ptr) + { + common::ReferenceSmartPointer<T>* impl = new common::ReferenceSmartPointer<T>(); + + Reference<typename T::element_type> res(impl); + + impl->Swap(ptr); + + return res; + } + + /** + * Make ignite::ConstReference instance out of smart pointer. + * + * Template type 'T' should be a smart pointer and provide pointer semantics: + * - There should be defined type 'T::element_type', showing underlying type. + * - Type 'T' should be dereferencible (should have operators + * T::element_type& operator*() and const T::element_type& operator*() const). + * - Operation std::swap should result in valid result if applied to two + * instances of that type. + * + * @param ptr Pointer. + * @return Implementation defined value. User should not explicitly use the + * returned value. + */ + template<typename T> + ConstReference<typename T::element_type> MakeConstReferenceFromSmartPointer(T ptr) + { + common::ReferenceSmartPointer<T>* impl = new common::ReferenceSmartPointer<T>(); + + ConstReference<typename T::element_type> res(impl); + + impl->Swap(ptr); + + return res; + } + + /** + * Copy object and wrap it to make ignite::Reference instance. + * + * Template type 'T' should be copy-constructible. + * + * @param val Instance. + * @return Implementation defined value. User should not explicitly use the + * returned value. + */ + template<typename T> + Reference<T> MakeReferenceFromCopy(const T& val) + { + common::ReferenceOwningRawPointer<T>* impl = new common::ReferenceOwningRawPointer<T>(new T(val)); + + return Reference<T>(impl); + } + + /** + * Copy object and wrap it to make ignite::ConstReference instance. + * + * Template type 'T' should be copy-constructible. + * + * @param val Instance. + * @return Implementation defined value. User should not explicitly use the + * returned value. + */ + template<typename T> + ConstReference<T> MakeConstReferenceFromCopy(const T& val) + { + common::ReferenceOwningRawPointer<T>* impl = new common::ReferenceOwningRawPointer<T>(new T(val)); + + return ConstReference<T>(impl); + } + + /** + * Make ignite::Reference instance out of pointer and pass its ownership. + * Passed object deleted by Ignite when no longer needed. + * + * There are no requirements for the template type T. + * + * @param val Instance. + * @return Implementation defined value. User should not explicitly use the + * returned value. + */ + template<typename T> + Reference<T> MakeReferenceFromOwningPointer(T* val) + { + common::ReferenceOwningRawPointer<T>* impl = new common::ReferenceOwningRawPointer<T>(val); + + return Reference<T>(impl); + } + + /** + * Make ignite::ConstReference instance out of pointer and pass its ownership. + * Passed object deleted by Ignite when no longer needed. + * + * There are no requirements for the template type T. + * + * @param val Instance. + * @return Implementation defined value. User should not explicitly use the + * returned value. + */ + template<typename T> + ConstReference<T> MakeConstReferenceFromOwningPointer(T* val) + { + common::ReferenceOwningRawPointer<T>* impl = new common::ReferenceOwningRawPointer<T>(val); + + return ConstReference<T>(impl); + } + + /** + * Make ignite::Reference instance out of reference. + * Ignite do not manage passed object and does not affect its lifetime. + * + * There are no requirements for the template type T. + * + * @param val Reference. + * @return Implementation defined value. User should not explicitly use the + * returned value. + */ + template<typename T> + Reference<T> MakeReference(T& val) + { + common::ReferenceNonOwningRawPointer<T>* impl = new common::ReferenceNonOwningRawPointer<T>(&val); + + return Reference<T>(impl); + } + + /** + * Make ignite::Reference instance out of pointer. + * Ignite do not manage passed object and does not affect its lifetime. + * + * There are no requirements for the template type T. + * + * @param val Reference. + * @return Implementation defined value. User should not explicitly use the + * returned value. + */ + template<typename T> + Reference<T> MakeReference(T* val) + { + common::ReferenceNonOwningRawPointer<T>* impl = new common::ReferenceNonOwningRawPointer<T>(val); + + return Reference<T>(impl); + } + + /** + * Make ignite::ConstReference instance out of constant reference. + * Ignite do not manage passed object and does not affect its lifetime. + * + * There are no requirements for the template type T. + * + * @param val Reference. + * @return Implementation defined value. User should not explicitly use the + * returned value. + */ + template<typename T> + ConstReference<T> MakeConstReference(const T& val) + { + common::ConstReferenceNonOwningRawPointer<T>* impl = new common::ConstReferenceNonOwningRawPointer<T>(&val); + + return ConstReference<T>(impl); + } + + /** + * Make ignite::ConstReference instance out of constant pointer. + * Ignite do not manage passed object and does not affect its lifetime. + * + * There are no requirements for the template type T. + * + * @param val Reference. + * @return Implementation defined value. User should not explicitly use the + * returned value. + */ + template<typename T> + ConstReference<T> MakeConstReference(const T* val) + { + common::ConstReferenceNonOwningRawPointer<T>* impl = new common::ConstReferenceNonOwningRawPointer<T>(val); + + return ConstReference<T>(impl); + } +} + +#endif //_IGNITE_COMMON_REFERENCE \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/common/project/vs/common.vcxproj ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/common/project/vs/common.vcxproj b/modules/platforms/cpp/common/project/vs/common.vcxproj index 149fa48..99fd551 100644 --- a/modules/platforms/cpp/common/project/vs/common.vcxproj +++ b/modules/platforms/cpp/common/project/vs/common.vcxproj @@ -171,10 +171,12 @@ <ClInclude Include="..\..\include\ignite\common\dynamic_size_array.h" /> <ClInclude Include="..\..\include\ignite\common\fixed_size_array.h" /> <ClInclude Include="..\..\include\ignite\common\bits.h" /> + <ClInclude Include="..\..\include\ignite\common\reference_impl.h" /> <ClInclude Include="..\..\include\ignite\common\utils.h" /> <ClInclude Include="..\..\include\ignite\date.h" /> <ClInclude Include="..\..\include\ignite\guid.h" /> <ClInclude Include="..\..\include\ignite\ignite_error.h" /> + <ClInclude Include="..\..\include\ignite\reference.h" /> <ClInclude Include="..\..\include\ignite\timestamp.h" /> <ClInclude Include="..\..\os\win\include\ignite\common\common.h" /> <ClInclude Include="..\..\os\win\include\ignite\common\concurrent_os.h" /> http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/common/project/vs/common.vcxproj.filters ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/common/project/vs/common.vcxproj.filters b/modules/platforms/cpp/common/project/vs/common.vcxproj.filters index ae17daf..d99722b 100644 --- a/modules/platforms/cpp/common/project/vs/common.vcxproj.filters +++ b/modules/platforms/cpp/common/project/vs/common.vcxproj.filters @@ -58,6 +58,12 @@ <ClInclude Include="..\..\include\ignite\common\decimal.h"> <Filter>Code\common</Filter> </ClInclude> + <ClInclude Include="..\..\include\ignite\common\reference_impl.h"> + <Filter>Code\common</Filter> + </ClInclude> + <ClInclude Include="..\..\include\ignite\reference.h"> + <Filter>Code</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="..\..\src\date.cpp"> http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/core-test/Makefile.am ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/Makefile.am b/modules/platforms/cpp/core-test/Makefile.am index 42680cd..3cf1d0e 100644 --- a/modules/platforms/cpp/core-test/Makefile.am +++ b/modules/platforms/cpp/core-test/Makefile.am @@ -43,15 +43,20 @@ AM_CXXFLAGS = \ ignite_tests_LDADD = \ @top_srcdir@/core/libignite.la \ - -lpthread + -lpthread \ + -lboost_thread \ + -lboost_system \ + -lboost_chrono ignite_tests_LDFLAGS = \ -static-libtool-libs ignite_tests_SOURCES = \ + src/reference_test.cpp \ src/bits_test.cpp \ src/cache_test.cpp \ src/cache_query_test.cpp \ + src/continuous_query_test.cpp \ src/concurrent_test.cpp \ src/ignition_test.cpp \ src/interop_memory_test.cpp \ http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/core-test/config/cache-query-continuous.xml ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/config/cache-query-continuous.xml b/modules/platforms/cpp/core-test/config/cache-query-continuous.xml new file mode 100644 index 0000000..1b940fd --- /dev/null +++ b/modules/platforms/cpp/core-test/config/cache-query-continuous.xml @@ -0,0 +1,87 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> + +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:util="http://www.springframework.org/schema/util" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/util + http://www.springframework.org/schema/util/spring-util.xsd"> + <bean id="grid.cfg" class="org.apache.ignite.configuration.IgniteConfiguration"> + <property name="localHost" value="127.0.0.1"/> + <property name="connectorConfiguration"><null/></property> + + <property name="cacheConfiguration"> + <list> + <bean class="org.apache.ignite.configuration.CacheConfiguration"> + <property name="name" value="transactional_no_backup"/> + <property name="cacheMode" value="PARTITIONED"/> + <property name="atomicityMode" value="TRANSACTIONAL"/> + <property name="writeSynchronizationMode" value="FULL_SYNC"/> + <property name="backups" value="0"/> + <property name="startSize" value="10"/> + <property name="queryEntities"> + <list> + <bean class="org.apache.ignite.cache.QueryEntity"> + <property name="keyType" value="java.lang.Integer"/> + <property name="valueType" value="TestEntry"/> + + <property name="fields"> + <map> + <entry key="value" value="java.lang.Integer"/> + </map> + </property> + + <property name="indexes"> + <list> + <bean class="org.apache.ignite.cache.QueryIndex"> + <property name="fields"> + <map> + <entry key="value" value="true"/> + </map> + </property> + <property name="indexType" value="FULLTEXT"/> + </bean> + </list> + </property> + </bean> + </list> + </property> + </bean> + </list> + </property> + + <property name="discoverySpi"> + <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi"> + <property name="ipFinder"> + <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder"> + <property name="addresses"> + <list> + <!-- In distributed environment, replace with actual host IP address. --> + <value>127.0.0.1:47500</value> + </list> + </property> + </bean> + </property> + <property name="socketTimeout" value="300" /> + </bean> + </property> + </bean> +</beans> http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj b/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj index 6f13719..a41d8f8 100644 --- a/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj +++ b/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj @@ -43,6 +43,7 @@ <ClCompile Include="..\..\src\decimal_test.cpp" /> <ClCompile Include="..\..\src\dynamic_size_array_test.cpp" /> <ClCompile Include="..\..\src\fixed_size_array_test.cpp" /> + <ClCompile Include="..\..\src\continuous_query_test.cpp" /> <ClCompile Include="..\..\src\ignite_error_test.cpp" /> <ClCompile Include="..\..\src\ignition_test.cpp" /> <ClCompile Include="..\..\src\handle_registry_test.cpp" /> @@ -54,6 +55,7 @@ <ClCompile Include="..\..\src\interop_memory_test.cpp" /> <ClCompile Include="..\..\src\interop_test.cpp" /> <ClCompile Include="..\..\src\bits_test.cpp" /> + <ClCompile Include="..\..\src\reference_test.cpp" /> <ClCompile Include="..\..\src\teamcity_boost.cpp" /> <ClCompile Include="..\..\src\teamcity_messages.cpp" /> <ClCompile Include="..\..\src\transactions_test.cpp" /> @@ -129,7 +131,7 @@ </ClCompile> <Link> <GenerateDebugInformation>true</GenerateDebugInformation> - <AdditionalDependencies>$(BOOST_HOME)\lib64-msvc-10.0\libboost_unit_test_framework-vc100-mt-gd-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalDependencies>$(BOOST_HOME)\lib64-msvc-10.0\libboost_unit_test_framework-vc100-mt-gd-1_58.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_thread-vc100-mt-gd-1_58.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_system-vc100-mt-gd-1_58.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_chrono-vc100-mt-gd-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies> <SubSystem>Console</SubSystem> </Link> </ItemDefinitionGroup> @@ -144,7 +146,7 @@ </ClCompile> <Link> <GenerateDebugInformation>true</GenerateDebugInformation> - <AdditionalDependencies>$(BOOST_HOME)\lib64-msvc-10.0\libboost_unit_test_framework-vc100-mt-gd-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalDependencies>$(BOOST_HOME)\lib32-msvc-10.0\libboost_unit_test_framework-vc100-mt-gd-1_58.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_thread-vc100-mt-gd-1_58.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_system-vc100-mt-gd-1_58.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_chrono-vc100-mt-gd-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> @@ -162,7 +164,7 @@ <GenerateDebugInformation>true</GenerateDebugInformation> <EnableCOMDATFolding>true</EnableCOMDATFolding> <OptimizeReferences>true</OptimizeReferences> - <AdditionalDependencies>$(BOOST_HOME)\lib64-msvc-10.0\libboost_unit_test_framework-vc100-mt-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalDependencies>$(BOOST_HOME)\lib64-msvc-10.0\libboost_unit_test_framework-vc100-mt-1_58.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_thread-vc100-mt-1_58.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_system-vc100-mt-1_58.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_chrono-vc100-mt-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> @@ -180,7 +182,7 @@ <GenerateDebugInformation>true</GenerateDebugInformation> <EnableCOMDATFolding>true</EnableCOMDATFolding> <OptimizeReferences>true</OptimizeReferences> - <AdditionalDependencies>$(BOOST_HOME)\lib64-msvc-10.0\libboost_unit_test_framework-vc100-mt-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalDependencies>$(BOOST_HOME)\lib32-msvc-10.0\libboost_unit_test_framework-vc100-mt-1_58.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_thread-vc100-mt-1_58.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_system-vc100-mt-1_58.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_chrono-vc100-mt-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies> </Link> </ItemDefinitionGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters b/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters index cf1aaca..a95e3a4 100644 --- a/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters +++ b/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters @@ -58,6 +58,12 @@ <ClCompile Include="..\..\src\interop_test.cpp"> <Filter>Code</Filter> </ClCompile> + <ClCompile Include="..\..\src\continuous_query_test.cpp"> + <Filter>Code</Filter> + </ClCompile> + <ClCompile Include="..\..\src\reference_test.cpp"> + <Filter>Code</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\include\teamcity_messages.h"> http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/core-test/src/cache_query_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/src/cache_query_test.cpp b/modules/platforms/cpp/core-test/src/cache_query_test.cpp index c1c26ac..928d29e 100644 --- a/modules/platforms/cpp/core-test/src/cache_query_test.cpp +++ b/modules/platforms/cpp/core-test/src/cache_query_test.cpp @@ -232,8 +232,6 @@ private: int32_t someVal; }; - - namespace ignite { namespace binary @@ -296,74 +294,6 @@ namespace ignite } } -///** -// * Test setup fixture. -// */ -//struct CacheQueryTestSuiteFixture -//{ -// Ignite StartNode(const char* name) -// { -// IgniteConfiguration cfg; -// -// cfg.jvmOpts.push_back("-Xdebug"); -// cfg.jvmOpts.push_back("-Xnoagent"); -// cfg.jvmOpts.push_back("-Djava.compiler=NONE"); -// cfg.jvmOpts.push_back("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"); -// cfg.jvmOpts.push_back("-XX:+HeapDumpOnOutOfMemoryError"); -// -//#ifdef IGNITE_TESTS_32 -// cfg.jvmInitMem = 256; -// cfg.jvmMaxMem = 768; -//#else -// cfg.jvmInitMem = 1024; -// cfg.jvmMaxMem = 4096; -//#endif -// -// cfg.springCfgPath.assign(getenv("IGNITE_NATIVE_TEST_CPP_CONFIG_PATH")).append("/cache-query.xml"); -// -// IgniteError err; -// -// Ignite grid0 = Ignition::Start(cfg, name, &err); -// -// if (err.GetCode() != IgniteError::IGNITE_SUCCESS) -// BOOST_ERROR(err.GetText()); -// -// return grid0; -// } -// -// -// /** -// * Constructor. -// */ -// CacheQueryTestSuiteFixture() : -// grid(StartNode("Node1")) -// { -// // No-op. -// } -// -// /** -// * Destructor. -// */ -// ~CacheQueryTestSuiteFixture() -// { -// Ignition::StopAll(true); -// } -// -// /** Person cache accessor. */ -// Cache<int, QueryPerson> GetPersonCache() -// { -// return grid.GetCache<int, QueryPerson>("QueryPerson"); -// } -// - ///** Relation cache accessor. */ - //Cache<int, QueryRelation> GetRelationCache() - //{ - // return grid.GetCache<int, QueryRelation>("QueryRelation"); - //} -// -// /** Node started during the test. */ -// Ignite grid; -//}; /** * Count number of records returned by cursor. @@ -677,7 +607,11 @@ struct CacheQueryTestSuiteFixture cfg.jvmMaxMem = 4096; #endif - cfg.springCfgPath.assign(getenv("IGNITE_NATIVE_TEST_CPP_CONFIG_PATH")).append("/cache-query.xml"); + const char* cfgPath = getenv("IGNITE_NATIVE_TEST_CPP_CONFIG_PATH"); + + BOOST_CHECK(cfgPath != 0); + + cfg.springCfgPath.assign(cfgPath).append("/cache-query.xml"); IgniteError err; http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/core-test/src/continuous_query_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/src/continuous_query_test.cpp b/modules/platforms/cpp/core-test/src/continuous_query_test.cpp new file mode 100644 index 0000000..e9d7e8a --- /dev/null +++ b/modules/platforms/cpp/core-test/src/continuous_query_test.cpp @@ -0,0 +1,611 @@ +/* + * 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 _MSC_VER + #define BOOST_TEST_DYN_LINK +#endif + +#include <deque> + +#include <boost/test/unit_test.hpp> +#include <boost/optional.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/condition_variable.hpp> + +#include "ignite/ignition.h" +#include "ignite/cache/cache.h" + +using namespace ignite; +using namespace ignite::cache; +using namespace ignite::cache::event; +using namespace ignite::cache::query; +using namespace ignite::cache::query::continuous; +using namespace boost::unit_test; + +/** + * Very simple concurrent queue implementation. + */ +template<typename T> +class ConcurrentQueue +{ +public: + /* + * Constructor. + */ + ConcurrentQueue() + { + // No-op. + } + + /* + * Push next element to queue. + * + * @param val Value to push. + */ + void Push(const T& val) + { + boost::unique_lock<boost::mutex> guard(mutex); + + queue.push_back(val); + + cv.notify_one(); + } + + /* + * Pull element from the queue with the specified timeout. + * + * @param val Value is placed there on success. + * @param timeout Timeout. + * @return True on success and false on timeout. + */ + template <typename Rep, typename Period> + bool Pull(T& val, const boost::chrono::duration<Rep, Period>& timeout) + { + boost::unique_lock<boost::mutex> guard(mutex); + + if (queue.empty()) + { + boost::cv_status res = cv.wait_for(guard, timeout); + + if (res == boost::cv_status::timeout) + return false; + } + + assert(!queue.empty()); + + val = queue.front(); + + queue.pop_front(); + + return true; + } + +private: + boost::mutex mutex; + + boost::condition_variable cv; + + std::deque<T> queue; +}; + +/* + * Test listener class. Stores events it has been notified about in concurrent + * queue so they can be checked later. + */ +template<typename K, typename V> +class Listener : public CacheEntryEventListener<K, V> +{ +public: + /* + * Default constructor. + */ + Listener() + { + // No-op. + } + + /** + * Event callback. + * + * @param evts Events. + * @param num Events number. + */ + virtual void OnEvent(const CacheEntryEvent<K, V>* evts, uint32_t num) + { + for (uint32_t i = 0; i < num; ++i) + eventQueue.Push(evts[i]); + } + + /* + * Check that next received event contains specific values. + * + * @param key Key. + * @param oldVal Old value. + * @param val Current value. + */ + void CheckNextEvent(const K& key, boost::optional<V> oldVal, boost::optional<V> val) + { + CacheEntryEvent<K, V> event; + bool success = eventQueue.Pull(event, boost::chrono::seconds(1)); + + BOOST_REQUIRE(success); + + BOOST_CHECK_EQUAL(event.GetKey(), key); + BOOST_CHECK_EQUAL(event.HasOldValue(), oldVal.is_initialized()); + BOOST_CHECK_EQUAL(event.HasValue(), val.is_initialized()); + + if (oldVal && event.HasOldValue()) + BOOST_CHECK_EQUAL(event.GetOldValue().value, oldVal->value); + + if (val && event.HasValue()) + BOOST_CHECK_EQUAL(event.GetValue().value, val->value); + } + + /* + * Check that there is no event for the specified ammount of time. + * + * @param timeout Timeout. + */ + template <typename Rep, typename Period> + void CheckNoEvent(const boost::chrono::duration<Rep, Period>& timeout) + { + CacheEntryEvent<K, V> event; + bool success = eventQueue.Pull(event, timeout); + + BOOST_REQUIRE(!success); + } + +private: + // Events queue. + ConcurrentQueue< CacheEntryEvent<K, V> > eventQueue; +}; + +/* + * Test entry. + */ +struct TestEntry +{ + /* + * Default constructor. + */ + TestEntry() : value(0) + { + // No-op. + } + + /* + * Constructor. + */ + TestEntry(int32_t val) : value(val) + { + // No-op. + } + + /* Value */ + int32_t value; +}; + +namespace ignite +{ + namespace binary + { + /** + * Binary type definition. + */ + IGNITE_BINARY_TYPE_START(TestEntry) + IGNITE_BINARY_GET_TYPE_ID_AS_HASH(TestEntry) + IGNITE_BINARY_GET_TYPE_NAME_AS_IS(TestEntry) + IGNITE_BINARY_GET_FIELD_ID_AS_HASH + IGNITE_BINARY_GET_HASH_CODE_ZERO(TestEntry) + IGNITE_BINARY_IS_NULL_FALSE(TestEntry) + IGNITE_BINARY_GET_NULL_DEFAULT_CTOR(TestEntry) + + void Write(BinaryWriter& writer, const TestEntry& obj) + { + writer.WriteInt32("value", obj.value); + } + + TestEntry Read(BinaryReader& reader) + { + TestEntry res; + res.value = reader.ReadInt32("value"); + + return res; + } + + IGNITE_BINARY_TYPE_END + } +} + +/* + * Test setup fixture. + */ +struct ContinuousQueryTestSuiteFixture +{ + Ignite grid; + + Cache<int, TestEntry> cache; + + /* + * Get configuration for nodes. + */ + IgniteConfiguration GetConfiguration() + { + IgniteConfiguration cfg; + + cfg.jvmOpts.push_back("-Xdebug"); + cfg.jvmOpts.push_back("-Xnoagent"); + cfg.jvmOpts.push_back("-Djava.compiler=NONE"); + cfg.jvmOpts.push_back("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"); + cfg.jvmOpts.push_back("-XX:+HeapDumpOnOutOfMemoryError"); + +#ifdef IGNITE_TESTS_32 + cfg.jvmInitMem = 256; + cfg.jvmMaxMem = 768; +#else + cfg.jvmInitMem = 1024; + cfg.jvmMaxMem = 4096; +#endif + + char* cfgPath = getenv("IGNITE_NATIVE_TEST_CPP_CONFIG_PATH"); + + cfg.springCfgPath = std::string(cfgPath).append("/").append("cache-query-continuous.xml"); + + return cfg; + } + + /* + * Constructor. + */ + ContinuousQueryTestSuiteFixture() : + grid(Ignition::Start(GetConfiguration(), "node-01")), + cache(grid.GetCache<int, TestEntry>("transactional_no_backup")) + { + // No-op. + } + + /* + * Destructor. + */ + ~ContinuousQueryTestSuiteFixture() + { + Ignition::StopAll(false); + + grid = Ignite(); + } +}; + +void CheckEvents(Cache<int, TestEntry>& cache, Listener<int, TestEntry>& lsnr) +{ + cache.Put(1, TestEntry(10)); + lsnr.CheckNextEvent(1, boost::none, TestEntry(10)); + + cache.Put(1, TestEntry(20)); + lsnr.CheckNextEvent(1, TestEntry(10), TestEntry(20)); + + cache.Put(2, TestEntry(20)); + lsnr.CheckNextEvent(2, boost::none, TestEntry(20)); + + cache.Remove(1); + lsnr.CheckNextEvent(1, TestEntry(20), boost::none); +} + +BOOST_FIXTURE_TEST_SUITE(ContinuousQueryTestSuite, ContinuousQueryTestSuiteFixture) + +BOOST_AUTO_TEST_CASE(TestBasic) +{ + Listener<int, TestEntry> lsnr; + + ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr)); + + ContinuousQueryHandle<int, TestEntry> handle = cache.QueryContinuous(qry); + + CheckEvents(cache, lsnr); +} + +BOOST_AUTO_TEST_CASE(TestInitialQueryScan) +{ + Listener<int, TestEntry> lsnr; + + ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr)); + + cache.Put(11, TestEntry(111)); + cache.Put(22, TestEntry(222)); + cache.Put(33, TestEntry(333)); + + ContinuousQueryHandle<int, TestEntry> handle = cache.QueryContinuous(qry, ScanQuery()); + + std::vector< CacheEntry<int, TestEntry> > vals; + + handle.GetInitialQueryCursor().GetAll(vals); + + BOOST_CHECK_THROW(handle.GetInitialQueryCursor(), IgniteError); + + BOOST_REQUIRE_EQUAL(vals.size(), 3); + + BOOST_CHECK_EQUAL(vals[0].GetKey(), 11); + BOOST_CHECK_EQUAL(vals[1].GetKey(), 22); + BOOST_CHECK_EQUAL(vals[2].GetKey(), 33); + + BOOST_CHECK_EQUAL(vals[0].GetValue().value, 111); + BOOST_CHECK_EQUAL(vals[1].GetValue().value, 222); + BOOST_CHECK_EQUAL(vals[2].GetValue().value, 333); + + CheckEvents(cache, lsnr); +} + +BOOST_AUTO_TEST_CASE(TestInitialQuerySql) +{ + Listener<int, TestEntry> lsnr; + + ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr)); + + cache.Put(11, TestEntry(111)); + cache.Put(22, TestEntry(222)); + cache.Put(33, TestEntry(333)); + + ContinuousQueryHandle<int, TestEntry> handle = cache.QueryContinuous(qry, SqlQuery("TestEntry", "value > 200")); + + std::vector< CacheEntry<int, TestEntry> > vals; + + handle.GetInitialQueryCursor().GetAll(vals); + + BOOST_CHECK_THROW(handle.GetInitialQueryCursor(), IgniteError); + + BOOST_REQUIRE_EQUAL(vals.size(), 2); + + BOOST_CHECK_EQUAL(vals[0].GetKey(), 22); + BOOST_CHECK_EQUAL(vals[1].GetKey(), 33); + + BOOST_CHECK_EQUAL(vals[0].GetValue().value, 222); + BOOST_CHECK_EQUAL(vals[1].GetValue().value, 333); + + CheckEvents(cache, lsnr); +} + +BOOST_AUTO_TEST_CASE(TestInitialQueryText) +{ + Listener<int, TestEntry> lsnr; + + ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr)); + + cache.Put(11, TestEntry(111)); + cache.Put(22, TestEntry(222)); + cache.Put(33, TestEntry(333)); + + ContinuousQueryHandle<int, TestEntry> handle = cache.QueryContinuous(qry, TextQuery("TestEntry", "222")); + + std::vector< CacheEntry<int, TestEntry> > vals; + + handle.GetInitialQueryCursor().GetAll(vals); + + BOOST_CHECK_THROW(handle.GetInitialQueryCursor(), IgniteError); + + BOOST_REQUIRE_EQUAL(vals.size(), 1); + + BOOST_CHECK_EQUAL(vals[0].GetKey(), 22); + + BOOST_CHECK_EQUAL(vals[0].GetValue().value, 222); + + CheckEvents(cache, lsnr); +} + +BOOST_AUTO_TEST_CASE(TestBasicNoExcept) +{ + Listener<int, TestEntry> lsnr; + + ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr)); + + IgniteError err; + + ContinuousQueryHandle<int, TestEntry> handle = cache.QueryContinuous(qry, err); + + BOOST_REQUIRE(err.GetCode() == IgniteError::IGNITE_SUCCESS); + + CheckEvents(cache, lsnr); +} + +BOOST_AUTO_TEST_CASE(TestInitialQueryScanNoExcept) +{ + Listener<int, TestEntry> lsnr; + + ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr)); + + cache.Put(11, TestEntry(111)); + cache.Put(22, TestEntry(222)); + cache.Put(33, TestEntry(333)); + + IgniteError err; + + ContinuousQueryHandle<int, TestEntry> handle = cache.QueryContinuous(qry, ScanQuery(), err); + + BOOST_REQUIRE(err.GetCode() == IgniteError::IGNITE_SUCCESS); + + std::vector< CacheEntry<int, TestEntry> > vals; + + handle.GetInitialQueryCursor().GetAll(vals); + + BOOST_CHECK_THROW(handle.GetInitialQueryCursor(), IgniteError); + + BOOST_REQUIRE_EQUAL(vals.size(), 3); + + BOOST_CHECK_EQUAL(vals[0].GetKey(), 11); + BOOST_CHECK_EQUAL(vals[1].GetKey(), 22); + BOOST_CHECK_EQUAL(vals[2].GetKey(), 33); + + BOOST_CHECK_EQUAL(vals[0].GetValue().value, 111); + BOOST_CHECK_EQUAL(vals[1].GetValue().value, 222); + BOOST_CHECK_EQUAL(vals[2].GetValue().value, 333); + + CheckEvents(cache, lsnr); +} + +BOOST_AUTO_TEST_CASE(TestInitialQuerySqlNoExcept) +{ + Listener<int, TestEntry> lsnr; + + ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr)); + + cache.Put(11, TestEntry(111)); + cache.Put(22, TestEntry(222)); + cache.Put(33, TestEntry(333)); + + IgniteError err; + + ContinuousQueryHandle<int, TestEntry> handle = cache.QueryContinuous(qry, SqlQuery("TestEntry", "value > 200"), err); + + BOOST_REQUIRE(err.GetCode() == IgniteError::IGNITE_SUCCESS); + + std::vector< CacheEntry<int, TestEntry> > vals; + + handle.GetInitialQueryCursor().GetAll(vals); + + BOOST_CHECK_THROW(handle.GetInitialQueryCursor(), IgniteError); + + BOOST_REQUIRE_EQUAL(vals.size(), 2); + + BOOST_CHECK_EQUAL(vals[0].GetKey(), 22); + BOOST_CHECK_EQUAL(vals[1].GetKey(), 33); + + BOOST_CHECK_EQUAL(vals[0].GetValue().value, 222); + BOOST_CHECK_EQUAL(vals[1].GetValue().value, 333); + + CheckEvents(cache, lsnr); +} + +BOOST_AUTO_TEST_CASE(TestInitialQueryTextNoExcept) +{ + Listener<int, TestEntry> lsnr; + + ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr)); + + cache.Put(11, TestEntry(111)); + cache.Put(22, TestEntry(222)); + cache.Put(33, TestEntry(333)); + + IgniteError err; + + ContinuousQueryHandle<int, TestEntry> handle = cache.QueryContinuous(qry, TextQuery("TestEntry", "222"), err); + + BOOST_REQUIRE(err.GetCode() == IgniteError::IGNITE_SUCCESS); + + std::vector< CacheEntry<int, TestEntry> > vals; + + handle.GetInitialQueryCursor().GetAll(vals); + + BOOST_CHECK_THROW(handle.GetInitialQueryCursor(), IgniteError); + + BOOST_REQUIRE_EQUAL(vals.size(), 1); + + BOOST_CHECK_EQUAL(vals[0].GetKey(), 22); + + BOOST_CHECK_EQUAL(vals[0].GetValue().value, 222); + + CheckEvents(cache, lsnr); +} + +BOOST_AUTO_TEST_CASE(TestExpiredQuery) +{ + Listener<int, TestEntry> lsnr; + ContinuousQueryHandle<int, TestEntry> handle; + + { + // Query scope. + ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr)); + + handle = cache.QueryContinuous(qry); + } + + // Query is destroyed here. + + CheckEvents(cache, lsnr); +} + +BOOST_AUTO_TEST_CASE(TestSetGetLocal) +{ + Listener<int, TestEntry> lsnr; + + ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr)); + + BOOST_CHECK(!qry.GetLocal()); + + qry.SetLocal(true); + + BOOST_CHECK(qry.GetLocal()); + + ContinuousQueryHandle<int, TestEntry> handle = cache.QueryContinuous(qry); + + BOOST_CHECK(qry.GetLocal()); + + CheckEvents(cache, lsnr); +} + +BOOST_AUTO_TEST_CASE(TestGetSetBufferSize) +{ + typedef ContinuousQuery<int, TestEntry> QueryType; + Listener<int, TestEntry> lsnr; + + ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr)); + + BOOST_CHECK_EQUAL(qry.GetBufferSize(), QueryType::DEFAULT_BUFFER_SIZE); + + qry.SetBufferSize(2 * QueryType::DEFAULT_BUFFER_SIZE); + + BOOST_CHECK_EQUAL(qry.GetBufferSize(), 2 * QueryType::DEFAULT_BUFFER_SIZE); + + ContinuousQueryHandle<int, TestEntry> handle = cache.QueryContinuous(qry); + + BOOST_CHECK_EQUAL(qry.GetBufferSize(), 2 * QueryType::DEFAULT_BUFFER_SIZE); + + CheckEvents(cache, lsnr); +} + +BOOST_AUTO_TEST_CASE(TestGetSetTimeInterval) +{ + typedef ContinuousQuery<int, TestEntry> QueryType; + Listener<int, TestEntry> lsnr; + + ContinuousQuery<int, TestEntry> qry(MakeReference(lsnr)); + + qry.SetBufferSize(10); + + BOOST_CHECK_EQUAL(qry.GetTimeInterval(), static_cast<int>(QueryType::DEFAULT_TIME_INTERVAL)); + + qry.SetTimeInterval(500); + + BOOST_CHECK_EQUAL(qry.GetTimeInterval(), 500); + + ContinuousQueryHandle<int, TestEntry> handle = cache.QueryContinuous(qry); + + BOOST_CHECK_EQUAL(qry.GetTimeInterval(), 500); + + CheckEvents(cache, lsnr); +} + +BOOST_AUTO_TEST_CASE(TestPublicPrivateConstantsConsistence) +{ + typedef ContinuousQuery<int, TestEntry> QueryType; + typedef impl::cache::query::continuous::ContinuousQueryImpl<int, TestEntry> QueryImplType; + + BOOST_CHECK_EQUAL(static_cast<int>(QueryImplType::DEFAULT_TIME_INTERVAL), + static_cast<int>(QueryType::DEFAULT_TIME_INTERVAL)); + + BOOST_CHECK_EQUAL(static_cast<int>(QueryImplType::DEFAULT_BUFFER_SIZE), + static_cast<int>(QueryType::DEFAULT_BUFFER_SIZE)); +} + +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/core-test/src/handle_registry_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/src/handle_registry_test.cpp b/modules/platforms/cpp/core-test/src/handle_registry_test.cpp index bc4a654..0956d9b 100644 --- a/modules/platforms/cpp/core-test/src/handle_registry_test.cpp +++ b/modules/platforms/cpp/core-test/src/handle_registry_test.cpp @@ -36,7 +36,7 @@ struct HandleRegistryTestProbe } }; -class HandleRegistryTestEntry : public HandleRegistryEntry +class HandleRegistryTestEntry { public: HandleRegistryTestEntry(HandleRegistryTestProbe* probe) : probe(probe) @@ -67,9 +67,9 @@ BOOST_AUTO_TEST_CASE(TestCritical) HandleRegistryTestEntry* entry1 = new HandleRegistryTestEntry(&probe1); HandleRegistryTestEntry* entry2 = new HandleRegistryTestEntry(&probe2); - int64_t hnd0 = reg.AllocateCritical(SharedPointer<HandleRegistryEntry>(entry0)); - int64_t hnd1 = reg.AllocateCritical(SharedPointer<HandleRegistryEntry>(entry1)); - int64_t hnd2 = reg.AllocateCritical(SharedPointer<HandleRegistryEntry>(entry2)); + int64_t hnd0 = reg.AllocateCritical(SharedPointer<HandleRegistryTestEntry>(entry0)); + int64_t hnd1 = reg.AllocateCritical(SharedPointer<HandleRegistryTestEntry>(entry1)); + int64_t hnd2 = reg.AllocateCritical(SharedPointer<HandleRegistryTestEntry>(entry2)); BOOST_REQUIRE(reg.Get(hnd0).Get() == entry0); BOOST_REQUIRE(!probe0.deleted); @@ -109,7 +109,7 @@ BOOST_AUTO_TEST_CASE(TestCritical) HandleRegistryTestProbe closedProbe; HandleRegistryTestEntry* closedEntry = new HandleRegistryTestEntry(&closedProbe); - int64_t closedHnd = closedReg.AllocateCritical(SharedPointer<HandleRegistryEntry>(closedEntry)); + int64_t closedHnd = closedReg.AllocateCritical(SharedPointer<HandleRegistryTestEntry>(closedEntry)); BOOST_REQUIRE(closedHnd == -1); BOOST_REQUIRE(closedProbe.deleted); } @@ -126,9 +126,9 @@ BOOST_AUTO_TEST_CASE(TestNonCritical) HandleRegistryTestEntry* entry1 = new HandleRegistryTestEntry(&probe1); HandleRegistryTestEntry* entry2 = new HandleRegistryTestEntry(&probe2); - int64_t hnd0 = reg.AllocateCritical(SharedPointer<HandleRegistryEntry>(entry0)); - int64_t hnd1 = reg.Allocate(SharedPointer<HandleRegistryEntry>(entry1)); - int64_t hnd2 = reg.Allocate(SharedPointer<HandleRegistryEntry>(entry2)); + int64_t hnd0 = reg.AllocateCritical(SharedPointer<HandleRegistryTestEntry>(entry0)); + int64_t hnd1 = reg.Allocate(SharedPointer<HandleRegistryTestEntry>(entry1)); + int64_t hnd2 = reg.Allocate(SharedPointer<HandleRegistryTestEntry>(entry2)); BOOST_REQUIRE(reg.Get(hnd0).Get() == entry0); BOOST_REQUIRE(!probe0.deleted); @@ -168,7 +168,7 @@ BOOST_AUTO_TEST_CASE(TestNonCritical) HandleRegistryTestProbe closedProbe; HandleRegistryTestEntry* closedEntry = new HandleRegistryTestEntry(&closedProbe); - int64_t closedHnd = closedReg.Allocate(SharedPointer<HandleRegistryEntry>(closedEntry)); + int64_t closedHnd = closedReg.Allocate(SharedPointer<HandleRegistryTestEntry>(closedEntry)); BOOST_REQUIRE(closedHnd == -1); BOOST_REQUIRE(closedProbe.deleted); } http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/core-test/src/reference_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/src/reference_test.cpp b/modules/platforms/cpp/core-test/src/reference_test.cpp new file mode 100644 index 0000000..f5c3e8d --- /dev/null +++ b/modules/platforms/cpp/core-test/src/reference_test.cpp @@ -0,0 +1,412 @@ +/* + * 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 _MSC_VER + #define BOOST_TEST_DYN_LINK +#endif + +#include <memory> + +#include <boost/test/unit_test.hpp> +#include <boost/smart_ptr.hpp> +#include <boost/interprocess/smart_ptr/unique_ptr.hpp> + +#include <ignite/reference.h> + +using namespace ignite; +using namespace boost::unit_test; + +class LivenessMarker +{ +public: + LivenessMarker(bool& flag) : + flag(flag) + { + flag = true; + } + + LivenessMarker(const LivenessMarker& other) : + flag(other.flag) + { + // No-op. + } + + LivenessMarker& operator=(const LivenessMarker& other) + { + flag = other.flag; + + return *this; + } + + ~LivenessMarker() + { + flag = false; + } + +private: + bool& flag; +}; + +class InstanceCounter +{ +public: + InstanceCounter(int& counter) : + counter(&counter) + { + ++(*this->counter); + } + + InstanceCounter(const InstanceCounter& other) : + counter(other.counter) + { + ++(*counter); + } + + InstanceCounter& operator=(const InstanceCounter& other) + { + counter = other.counter; + + ++(*counter); + + return *this; + } + + ~InstanceCounter() + { + --(*counter); + } + +private: + int* counter; +}; + + +void TestFunction(Reference<LivenessMarker> ptr) +{ + Reference<LivenessMarker> copy(ptr); + Reference<LivenessMarker> copy2(ptr); +} + +struct C1 +{ + int c1; +}; + +struct C2 +{ + int c2; +}; + +struct C3 : C1, C2 +{ + int c3; +}; + +void TestFunction1(Reference<C1> c1, int expected) +{ + BOOST_CHECK_EQUAL(c1.Get().c1, expected); +} + +void TestFunction2(Reference<C2> c2, int expected) +{ + BOOST_CHECK_EQUAL(c2.Get().c2, expected); +} + +void TestFunction3(Reference<C3> c3, int expected) +{ + BOOST_CHECK_EQUAL(c3.Get().c3, expected); +} + +void TestFunctionConst1(ConstReference<C1> c1, int expected) +{ + BOOST_CHECK_EQUAL(c1.Get().c1, expected); +} + +void TestFunctionConst2(ConstReference<C2> c2, int expected) +{ + BOOST_CHECK_EQUAL(c2.Get().c2, expected); +} + +void TestFunctionConst3(ConstReference<C3> c3, int expected) +{ + BOOST_CHECK_EQUAL(c3.Get().c3, expected); +} + +BOOST_AUTO_TEST_SUITE(ReferenceTestSuite) + +BOOST_AUTO_TEST_CASE(StdSharedPointerTestBefore) +{ + bool objAlive = false; + + std::shared_ptr<LivenessMarker> shared = std::make_shared<LivenessMarker>(objAlive); + + BOOST_CHECK(objAlive); + + { + Reference<LivenessMarker> smart = MakeReferenceFromSmartPointer(shared); + + BOOST_CHECK(objAlive); + + shared.reset(); + + BOOST_CHECK(objAlive); + } + + BOOST_CHECK(!objAlive); +} + +BOOST_AUTO_TEST_CASE(StdSharedPointerTestAfter) +{ + bool objAlive = false; + + std::shared_ptr<LivenessMarker> shared = std::make_shared<LivenessMarker>(objAlive); + + BOOST_CHECK(objAlive); + + { + Reference<LivenessMarker> smart = MakeReferenceFromSmartPointer(shared); + + BOOST_CHECK(objAlive); + } + + BOOST_CHECK(objAlive); + + shared.reset(); + + BOOST_CHECK(!objAlive); +} + +BOOST_AUTO_TEST_CASE(StdAutoPointerTest) +{ + bool objAlive = false; + + std::auto_ptr<LivenessMarker> autop(new LivenessMarker(objAlive)); + + BOOST_CHECK(objAlive); + + { + Reference<LivenessMarker> smart = MakeReferenceFromSmartPointer(autop); + + BOOST_CHECK(objAlive); + } + + BOOST_CHECK(!objAlive); +} + +BOOST_AUTO_TEST_CASE(StdUniquePointerTest) +{ + bool objAlive = false; + + std::unique_ptr<LivenessMarker> unique(new LivenessMarker(objAlive)); + + BOOST_CHECK(objAlive); + + { + Reference<LivenessMarker> smart = MakeReferenceFromSmartPointer(std::move(unique)); + + BOOST_CHECK(objAlive); + } + + BOOST_CHECK(!objAlive); +} + +BOOST_AUTO_TEST_CASE(BoostSharedPointerTestBefore) +{ + bool objAlive = false; + + boost::shared_ptr<LivenessMarker> shared = boost::make_shared<LivenessMarker>(objAlive); + + BOOST_CHECK(objAlive); + + { + Reference<LivenessMarker> smart = MakeReferenceFromSmartPointer(shared); + + BOOST_CHECK(objAlive); + + shared.reset(); + + BOOST_CHECK(objAlive); + } + + BOOST_CHECK(!objAlive); +} + +BOOST_AUTO_TEST_CASE(BoostSharedPointerTestAfter) +{ + bool objAlive = false; + + boost::shared_ptr<LivenessMarker> shared = boost::make_shared<LivenessMarker>(objAlive); + + BOOST_CHECK(objAlive); + + { + Reference<LivenessMarker> smart = MakeReferenceFromSmartPointer(shared); + + BOOST_CHECK(objAlive); + } + + BOOST_CHECK(objAlive); + + shared.reset(); + + BOOST_CHECK(!objAlive); +} + +BOOST_AUTO_TEST_CASE(PassingToFunction) +{ + bool objAlive = false; + + std::shared_ptr<LivenessMarker> stdShared = std::make_shared<LivenessMarker>(objAlive); + std::unique_ptr<LivenessMarker> stdUnique(new LivenessMarker(objAlive)); + std::auto_ptr<LivenessMarker> stdAuto(new LivenessMarker(objAlive)); + + boost::shared_ptr<LivenessMarker> boostShared = boost::make_shared<LivenessMarker>(objAlive); + + TestFunction(MakeReferenceFromSmartPointer(stdShared)); + TestFunction(MakeReferenceFromSmartPointer(std::move(stdUnique))); + TestFunction(MakeReferenceFromSmartPointer(stdAuto)); + + TestFunction(MakeReferenceFromSmartPointer(boostShared)); +} + +BOOST_AUTO_TEST_CASE(CopyTest) +{ + int instances = 0; + + { + InstanceCounter counter(instances); + + BOOST_CHECK_EQUAL(instances, 1); + + { + Reference<InstanceCounter> copy = MakeReferenceFromCopy(counter); + + BOOST_CHECK_EQUAL(instances, 2); + } + + BOOST_CHECK_EQUAL(instances, 1); + } + + BOOST_CHECK_EQUAL(instances, 0); +} + +BOOST_AUTO_TEST_CASE(OwningPointerTest) +{ + int instances = 0; + + { + InstanceCounter *counter = new InstanceCounter(instances); + + BOOST_CHECK_EQUAL(instances, 1); + + { + Reference<InstanceCounter> owned = MakeReferenceFromOwningPointer(counter); + + BOOST_CHECK_EQUAL(instances, 1); + } + + BOOST_CHECK_EQUAL(instances, 0); + } + + BOOST_CHECK_EQUAL(instances, 0); +} + +BOOST_AUTO_TEST_CASE(NonOwningPointerTest1) +{ + int instances = 0; + + { + InstanceCounter counter(instances); + + BOOST_CHECK_EQUAL(instances, 1); + + { + Reference<InstanceCounter> copy = MakeReference(counter); + + BOOST_CHECK_EQUAL(instances, 1); + } + + BOOST_CHECK_EQUAL(instances, 1); + } + + BOOST_CHECK_EQUAL(instances, 0); +} + +BOOST_AUTO_TEST_CASE(NonOwningPointerTest2) +{ + int instances = 0; + + InstanceCounter* counter = new InstanceCounter(instances); + + BOOST_CHECK_EQUAL(instances, 1); + + { + Reference<InstanceCounter> copy = MakeReference(*counter); + + BOOST_CHECK_EQUAL(instances, 1); + + delete counter; + + BOOST_CHECK_EQUAL(instances, 0); + } + + BOOST_CHECK_EQUAL(instances, 0); +} + +BOOST_AUTO_TEST_CASE(CastTest) +{ + C3 testVal; + + testVal.c1 = 1; + testVal.c2 = 2; + testVal.c3 = 3; + + TestFunction1(MakeReference(testVal), 1); + TestFunction2(MakeReference(testVal), 2); + TestFunction3(MakeReference(testVal), 3); + + TestFunction1(MakeReferenceFromCopy(testVal), 1); + TestFunction2(MakeReferenceFromCopy(testVal), 2); + TestFunction3(MakeReferenceFromCopy(testVal), 3); +} + +BOOST_AUTO_TEST_CASE(ConstTest) +{ + C3 testVal; + + testVal.c1 = 1; + testVal.c2 = 2; + testVal.c3 = 3; + + TestFunctionConst1(MakeConstReference(testVal), 1); + TestFunctionConst2(MakeConstReference(testVal), 2); + TestFunctionConst3(MakeConstReference(testVal), 3); + + TestFunctionConst1(MakeConstReferenceFromCopy(testVal), 1); + TestFunctionConst2(MakeConstReferenceFromCopy(testVal), 2); + TestFunctionConst3(MakeConstReferenceFromCopy(testVal), 3); + + TestFunctionConst1(MakeReference(testVal), 1); + TestFunctionConst2(MakeReference(testVal), 2); + TestFunctionConst3(MakeReference(testVal), 3); + + TestFunctionConst1(MakeReferenceFromCopy(testVal), 1); + TestFunctionConst2(MakeReferenceFromCopy(testVal), 2); + TestFunctionConst3(MakeReferenceFromCopy(testVal), 3); +} + +BOOST_AUTO_TEST_SUITE_END() http://git-wip-us.apache.org/repos/asf/ignite/blob/598b464f/modules/platforms/cpp/core/Makefile.am ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/Makefile.am b/modules/platforms/cpp/core/Makefile.am index 97523cf..758e68d 100644 --- a/modules/platforms/cpp/core/Makefile.am +++ b/modules/platforms/cpp/core/Makefile.am @@ -59,6 +59,7 @@ libignite_la_SOURCES = \ src/impl/ignite_environment.cpp \ src/impl/binary/binary_type_updater_impl.cpp \ src/impl/handle_registry.cpp \ + src/impl/cache/query/continuous/continuous_query_handle_impl.cpp \ src/impl/cache/query/query_impl.cpp \ src/impl/cache/cache_impl.cpp \ src/impl/cache/query/query_batch.cpp \
