From eeadfbfaba62300909f97c8a30c9899717ae3b06 Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Mon, 28 Sep 2015 15:38:44 -0700 Subject: [PATCH] removing files in the wrong place --- apple/external_commit_helper.cpp | 250 --------------------- apple/external_commit_helper.hpp | 92 -------- examples/ReactExample/package.json | 2 +- index_set.cpp | 92 -------- index_set.hpp | 62 ------ realm_delegate.hpp | 154 ------------- schema.cpp | 115 ---------- schema.hpp | 58 ----- transact_log_handler.cpp | 347 ----------------------------- transact_log_handler.hpp | 46 ---- 10 files changed, 1 insertion(+), 1217 deletions(-) delete mode 100644 apple/external_commit_helper.cpp delete mode 100644 apple/external_commit_helper.hpp delete mode 100644 index_set.cpp delete mode 100644 index_set.hpp delete mode 100644 realm_delegate.hpp delete mode 100644 schema.cpp delete mode 100644 schema.hpp delete mode 100644 transact_log_handler.cpp delete mode 100644 transact_log_handler.hpp diff --git a/apple/external_commit_helper.cpp b/apple/external_commit_helper.cpp deleted file mode 100644 index 1444281a..00000000 --- a/apple/external_commit_helper.cpp +++ /dev/null @@ -1,250 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2015 Realm Inc. -// -// 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 "external_commit_helper.hpp" - -#include "shared_realm.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace realm; - -namespace { -// Write a byte to a pipe to notify anyone waiting for data on the pipe -void notify_fd(int fd) -{ - while (true) { - char c = 0; - ssize_t ret = write(fd, &c, 1); - if (ret == 1) { - break; - } - - // If the pipe's buffer is full, we need to read some of the old data in - // it to make space. We don't just read in the code waiting for - // notifications so that we can notify multiple waiters with a single - // write. - assert(ret == -1 && errno == EAGAIN); - char buff[1024]; - read(fd, buff, sizeof buff); - } -} -} // anonymous namespace - -void ExternalCommitHelper::FdHolder::close() -{ - if (m_fd != -1) { - ::close(m_fd); - } - m_fd = -1; - -} - -// Inter-thread and inter-process notifications of changes are done using a -// named pipe in the filesystem next to the Realm file. Everyone who wants to be -// notified of commits waits for data to become available on the pipe, and anyone -// who commits a write transaction writes data to the pipe after releasing the -// write lock. Note that no one ever actually *reads* from the pipe: the data -// actually written is meaningless, and trying to read from a pipe from multiple -// processes at once is fraught with race conditions. - -// When a RLMRealm instance is created, we add a CFRunLoopSource to the current -// thread's runloop. On each cycle of the run loop, the run loop checks each of -// its sources for work to do, which in the case of CFRunLoopSource is just -// checking if CFRunLoopSourceSignal has been called since the last time it ran, -// and if so invokes the function pointer supplied when the source is created, -// which in our case just invokes `[realm handleExternalChange]`. - -// Listening for external changes is done using kqueue() on a background thread. -// kqueue() lets us efficiently wait until the amount of data which can be read -// from one or more file descriptors has changed, and tells us which of the file -// descriptors it was that changed. We use this to wait on both the shared named -// pipe, and a local anonymous pipe. When data is written to the named pipe, we -// signal the runloop source and wake up the target runloop, and when data is -// written to the anonymous pipe the background thread removes the runloop -// source from the runloop and and shuts down. -ExternalCommitHelper::ExternalCommitHelper(Realm* realm) -{ - add_realm(realm); - - m_kq = kqueue(); - if (m_kq == -1) { - throw std::system_error(errno, std::system_category()); - } - - auto path = realm->config().path + ".note"; - - // Create and open the named pipe - int ret = mkfifo(path.c_str(), 0600); - if (ret == -1) { - int err = errno; - if (err == ENOTSUP) { - // Filesystem doesn't support named pipes, so try putting it in tmp instead - // Hash collisions are okay here because they just result in doing - // extra work, as opposed to correctness problems - std::ostringstream ss; - ss << getenv("TMPDIR"); - ss << "realm_" << std::hash()(path) << ".note"; - path = ss.str(); - ret = mkfifo(path.c_str(), 0600); - err = errno; - } - // the fifo already existing isn't an error - if (ret == -1 && err != EEXIST) { - throw std::system_error(err, std::system_category()); - } - } - - m_notify_fd = open(path.c_str(), O_RDWR); - if (m_notify_fd == -1) { - throw std::system_error(errno, std::system_category()); - } - - // Make writing to the pipe return -1 when the pipe's buffer is full - // rather than blocking until there's space available - ret = fcntl(m_notify_fd, F_SETFL, O_NONBLOCK); - if (ret == -1) { - throw std::system_error(errno, std::system_category()); - } - - // Create the anonymous pipe - int pipeFd[2]; - ret = pipe(pipeFd); - if (ret == -1) { - throw std::system_error(errno, std::system_category()); - } - - m_shutdown_read_fd = pipeFd[0]; - m_shutdown_write_fd = pipeFd[1]; - - // Use the minimum allowed stack size, as we need very little in our listener - // https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html#//apple_ref/doc/uid/10000057i-CH15-SW7 - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setstacksize(&attr, 16 * 1024); - - auto fn = [](void *self) -> void * { - static_cast(self)->listen(); - return nullptr; - }; - ret = pthread_create(&m_thread, &attr, fn, this); - pthread_attr_destroy(&attr); - if (ret != 0) { - throw std::system_error(errno, std::system_category()); - } -} - -ExternalCommitHelper::~ExternalCommitHelper() -{ - REALM_ASSERT_DEBUG(m_realms.empty()); - notify_fd(m_shutdown_write_fd); - pthread_join(m_thread, nullptr); // Wait for the thread to exit -} - -void ExternalCommitHelper::add_realm(realm::Realm* realm) -{ - std::lock_guard lock(m_realms_mutex); - - // Create the runloop source - CFRunLoopSourceContext ctx{}; - ctx.info = realm; - ctx.perform = [](void* info) { - static_cast(info)->notify(); - }; - - CFRunLoopRef runloop = CFRunLoopGetCurrent(); - CFRetain(runloop); - CFRunLoopSourceRef signal = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &ctx); - CFRunLoopAddSource(runloop, signal, kCFRunLoopDefaultMode); - - m_realms.push_back({realm, runloop, signal}); -} - -void ExternalCommitHelper::remove_realm(realm::Realm* realm) -{ - std::lock_guard lock(m_realms_mutex); - for (auto it = m_realms.begin(); it != m_realms.end(); ++it) { - if (it->realm == realm) { - CFRunLoopSourceInvalidate(it->signal); - CFRelease(it->signal); - CFRelease(it->runloop); - m_realms.erase(it); - return; - } - } - REALM_TERMINATE("Realm not registered"); -} - -void ExternalCommitHelper::listen() -{ - pthread_setname_np("RLMRealm notification listener"); - - - // Set up the kqueue - // EVFILT_READ indicates that we care about data being available to read - // on the given file descriptor. - // EV_CLEAR makes it wait for the amount of data available to be read to - // change rather than just returning when there is any data to read. - struct kevent ke[2]; - EV_SET(&ke[0], m_notify_fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, 0); - EV_SET(&ke[1], m_shutdown_read_fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, 0); - int ret = kevent(m_kq, ke, 2, nullptr, 0, nullptr); - assert(ret == 0); - - while (true) { - struct kevent event; - // Wait for data to become on either fd - // Return code is number of bytes available or -1 on error - ret = kevent(m_kq, nullptr, 0, &event, 1, nullptr); - assert(ret >= 0); - if (ret == 0) { - // Spurious wakeup; just wait again - continue; - } - - // Check which file descriptor had activity: if it's the shutdown - // pipe, then someone called -stop; otherwise it's the named pipe - // and someone committed a write transaction - if (event.ident == (uint32_t)m_shutdown_read_fd) { - return; - } - assert(event.ident == (uint32_t)m_notify_fd); - - std::lock_guard lock(m_realms_mutex); - for (auto const& realm : m_realms) { - CFRunLoopSourceSignal(realm.signal); - // Signalling the source makes it run the next time the runloop gets - // to it, but doesn't make the runloop start if it's currently idle - // waiting for events - CFRunLoopWakeUp(realm.runloop); - } - } -} - -void ExternalCommitHelper::notify_others() -{ - notify_fd(m_notify_fd); -} - diff --git a/apple/external_commit_helper.hpp b/apple/external_commit_helper.hpp deleted file mode 100644 index acf0e1c4..00000000 --- a/apple/external_commit_helper.hpp +++ /dev/null @@ -1,92 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2015 Realm Inc. -// -// 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. -// -//////////////////////////////////////////////////////////////////////////// - -#ifndef REALM_EXTERNAL_COMMIT_HELPER_HPP -#define REALM_EXTERNAL_COMMIT_HELPER_HPP - -#include -#include -#include - -namespace realm { -class Realm; - -class ExternalCommitHelper { -public: - ExternalCommitHelper(Realm* realm); - ~ExternalCommitHelper(); - - void notify_others(); - void add_realm(Realm* realm); - void remove_realm(Realm* realm); - -private: - // A RAII holder for a file descriptor which automatically closes the wrapped - // fd when it's deallocated - class FdHolder { - public: - FdHolder() = default; - ~FdHolder() { close(); } - operator int() const { return m_fd; } - - FdHolder& operator=(int newFd) { - close(); - m_fd = newFd; - return *this; - } - - private: - int m_fd = -1; - void close(); - - FdHolder& operator=(FdHolder const&) = delete; - FdHolder(FdHolder const&) = delete; - }; - - struct PerRealmInfo { - Realm* realm; - CFRunLoopRef runloop; - CFRunLoopSourceRef signal; - }; - - void listen(); - - // Currently registered realms and the signal for delivering notifications - // to them - std::vector m_realms; - - // Mutex which guards m_realms - std::mutex m_realms_mutex; - - // The listener thread - pthread_t m_thread; - - // Read-write file descriptor for the named pipe which is waited on for - // changes and written to when a commit is made - FdHolder m_notify_fd; - // File descriptor for the kqueue - FdHolder m_kq; - // The two ends of an anonymous pipe used to notify the kqueue() thread that - // it should be shut down. - FdHolder m_shutdown_read_fd; - FdHolder m_shutdown_write_fd; -}; - -} // namespace realm - -#endif /* REALM_EXTERNAL_COMMIT_HELPER_HPP */ diff --git a/examples/ReactExample/package.json b/examples/ReactExample/package.json index bd64cc8b..1705934a 100644 --- a/examples/ReactExample/package.json +++ b/examples/ReactExample/package.json @@ -6,6 +6,6 @@ "start": "node_modules/react-native/packager/packager.sh" }, "dependencies": { - "react-native": "0.11.0" + "react-native": "0.11.4" } } diff --git a/index_set.cpp b/index_set.cpp deleted file mode 100644 index b7e4961c..00000000 --- a/index_set.cpp +++ /dev/null @@ -1,92 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2015 Realm Inc. -// -// 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 "index_set.hpp" - -using namespace realm; - -IndexSet::iterator IndexSet::find(size_t index) -{ - for (auto it = m_ranges.begin(), end = m_ranges.end(); it != end; ++it) { - if (it->second > index) - return it; - } - return m_ranges.end(); -} - -void IndexSet::add(size_t index) -{ - do_add(find(index), index); -} - -void IndexSet::do_add(iterator it, size_t index) -{ - bool more_before = it != m_ranges.begin(), valid = it != m_ranges.end(); - if (valid && it->first <= index && it->second > index) { - // index is already in set - } - else if (more_before && (it - 1)->second == index) { - // index is immediately after an existing range - ++(it - 1)->second; - } - else if (more_before && valid && (it - 1)->second == it->first) { - // index joins two existing ranges - (it - 1)->second = it->second; - m_ranges.erase(it); - } - else if (valid && it->first == index + 1) { - // index is immediately before an existing range - --it->first; - } - else { - // index is not next to an existing range - m_ranges.insert(it, {index, index + 1}); - } -} - -void IndexSet::set(size_t len) -{ - m_ranges.clear(); - if (len) { - m_ranges.push_back({0, len}); - } -} - -void IndexSet::insert_at(size_t index) -{ - auto pos = find(index); - if (pos != m_ranges.end()) { - if (pos->first >= index) - ++pos->first; - ++pos->second; - for (auto it = pos + 1; it != m_ranges.end(); ++it) { - ++it->first; - ++it->second; - } - } - do_add(pos, index); -} - -void IndexSet::add_shifted(size_t index) -{ - auto it = m_ranges.begin(); - for (auto end = m_ranges.end(); it != end && it->first <= index; ++it) { - index += it->second - it->first; - } - do_add(it, index); -} diff --git a/index_set.hpp b/index_set.hpp deleted file mode 100644 index 7a229177..00000000 --- a/index_set.hpp +++ /dev/null @@ -1,62 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2015 Realm Inc. -// -// 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. -// -//////////////////////////////////////////////////////////////////////////// - -#ifndef REALM_INDEX_SET_HPP -#define REALM_INDEX_SET_HPP - -#include - -namespace realm { -class IndexSet { -public: - using value_type = std::pair; - using iterator = std::vector::iterator; - using const_iterator = std::vector::const_iterator; - - const_iterator begin() const { return m_ranges.begin(); } - const_iterator end() const { return m_ranges.end(); } - bool empty() const { return m_ranges.empty(); } - size_t size() const { return m_ranges.size(); } - - // Add an index to the set, doing nothing if it's already present - void add(size_t index); - - // Remove all indexes from the set and then add a single range starting from - // zero with the given length - void set(size_t len); - - // Insert an index at the given position, shifting existing indexes at or - // after that point back by one - void insert_at(size_t index); - - // Add an index which has had all of the ranges in the set before it removed - void add_shifted(size_t index); - -private: - std::vector m_ranges; - - // Find the range which contains the index, or the first one after it if - // none do - iterator find(size_t index); - // Insert the index before the given position, combining existing ranges as - // applicable - void do_add(iterator pos, size_t index); -}; -} // namespace realm - -#endif // REALM_INDEX_SET_HPP diff --git a/realm_delegate.hpp b/realm_delegate.hpp deleted file mode 100644 index 0d9e9dfe..00000000 --- a/realm_delegate.hpp +++ /dev/null @@ -1,154 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2015 Realm Inc. -// -// 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. -// -//////////////////////////////////////////////////////////////////////////// - -#ifndef REALM_DELEGATE_HPP -#define REALM_DELEGATE_HPP - -#include "index_set.hpp" - -#include -#include - -namespace realm { -// RealmDelegate is the extension point for adding binding-specific behavior to -// a SharedRealm. It can be used to store additonal data associated with the -// Realm which is needed by the binding, and there are several methods which -// can be overridden to receive notifications of state changes within the Realm. -// -// A simple delegate implementation which lets the user register functions to be -// called on refresh could look like the following: -// -// class DelegateImplementation : public RealmDelegate { -// public: -// // A token returned from add_notification that can be used to remove the -// // notification later -// struct token : private std::list>::iterator { -// token(std::list>::iterator it) : std::list>::iterator(it) { } -// friend class DelegateImplementation; -// }; -// -// token add_notification(std::function func) -// { -// m_registered_notifications.push_back(std::move(func)); -// return token(std::prev(m_registered_notifications.end())); -// } -// -// void remove_notification(token entry) -// { -// m_registered_notifications.erase(entry); -// } -// -// // Override the did_change method to call each registered notification -// void did_change(std::vector const&, std::vector const&) override -// { -// // Loop oddly so that unregistering a notification from within the -// // registered function works -// for (auto it = m_registered_notifications.begin(); it != m_registered_notifications.end(); ) { -// (*it++)(); -// } -// } -// -// private: -// std::list> m_registered_notifications; -// }; -class RealmDelegate { -public: - virtual ~RealmDelegate() = default; - - // Called by the Realm when a write transaction is committed to the file by - // a different Realm instance (possibly in a different process) - virtual void changes_available() { } - - struct ObserverState; - - // Override this function if you want to recieve detailed information about - // external changes to a specific set of objects. - // This is called before each operation which may advance the read - // transaction to include - // ObserverStates for each row for which detailed change information is - // desired. - virtual std::vector get_observed_rows() { return {}; } - - // Called immediately before the read transaction is advanced if detailed - // change information was requested (by returning a non-empty array from - // get_observed_rows()). - // The observers vector is the vector returned by get_observed_row(), - // updated with change information. The invalidated vector is a list of the - // `info` fields of observed rows which will be deleted. - virtual void will_change(std::vector const& observers, - std::vector const& invalidated); - - // Called immediately after the read transaction version is advanced. Unlike - // will_change(), this is called even if detailed change information was not - // requested or if the Realm is not actually in a read transactuib, although - // both vectors will be empty in that case. - virtual void did_change(std::vector const& observers, - std::vector const& invalidated); - - // Change information for a single field of a row - struct ColumnInfo { - // Did this column change? - bool changed = false; - // For LinkList columns, what kind of change occurred? - // Always None for other column types - enum class Kind { - None, // No change - Set, // The entries at `indices` were assigned to - Insert, // New values were inserted at each of the indices given - Remove, // Values were removed at each of the indices given - SetAll // The entire LinkList has been replaced with a new set of values - } kind = Kind::None; - // The indices where things happened for Set, Insert and Remove - // Not used for None and SetAll - IndexSet indices; - }; - - // Information about an observed row in a table - // - // Each object which needs detailed change information should have an - // ObserverState entry in the vector returned from get_observed_rows(), with - // the initial table and row indexes set (and optionally the info field). - // The Realm parses the transaction log, and populates the `changes` vector - // in each ObserverState with information about what changes were made. - struct ObserverState { - // Initial table and row which is observed - // May be updated by row insertions and removals - size_t table_ndx; - size_t row_ndx; - - // Opaque userdata for the delegate's use - void* info; - - // Populated with information about which columns were changed - // May be shorter than the actual number of columns if the later columns - // are not modified - std::vector changes; - - // Simple lexographic ordering - friend bool operator<(ObserverState const& lft, ObserverState const& rgt) - { - return std::tie(lft.table_ndx, lft.row_ndx) < std::tie(rgt.table_ndx, rgt.row_ndx); - } - }; -}; - -inline void RealmDelegate::will_change(std::vector const&, std::vector const&) { } -inline void RealmDelegate::did_change(std::vector const&, std::vector const&) { } -} // namespace realm - -#endif /* REALM_DELEGATE_HPP */ diff --git a/schema.cpp b/schema.cpp deleted file mode 100644 index fe9b4de0..00000000 --- a/schema.cpp +++ /dev/null @@ -1,115 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2015 Realm Inc. -// -// 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 "schema.hpp" - -#include "object_schema.hpp" -#include "object_store.hpp" -#include "property.hpp" - -using namespace realm; - -static bool compare_by_name(ObjectSchema const& lft, ObjectSchema const& rgt) { - return lft.name < rgt.name; -} - -Schema::Schema(base types) : base(std::move(types)) { - std::sort(begin(), end(), compare_by_name); -} - -Schema::iterator Schema::find(std::string const& name) -{ - ObjectSchema cmp; - cmp.name = name; - return find(cmp); -} - -Schema::const_iterator Schema::find(std::string const& name) const -{ - return const_cast(this)->find(name); -} - -Schema::iterator Schema::find(ObjectSchema const& object) noexcept -{ - auto it = std::lower_bound(begin(), end(), object, compare_by_name); - if (it != end() && it->name != object.name) { - it = end(); - } - return it; -} - -Schema::const_iterator Schema::find(ObjectSchema const& object) const noexcept -{ - return const_cast(this)->find(object); -} - -ObjectSchema& Schema::operator[] (std::string const& name) -{ - auto iter = find(name); - if (iter == end()) { - throw std::runtime_error("Object type '" + name + "' not present in schema."); - } - return *iter; -} - -void Schema::validate() const -{ - std::vector exceptions; - for (auto const& object : *this) { - const Property *primary = nullptr; - for (auto const& prop : object.properties) { - // check object_type existence - if (!prop.object_type.empty() && find(prop.object_type) == end()) { - exceptions.emplace_back(MissingObjectTypeException(object.name, prop)); - } - - // check nullablity - if (prop.is_nullable) { -#if REALM_NULL_STRINGS == 1 - if (prop.type == PropertyTypeArray || prop.type == PropertyTypeAny) { -#else - if (prop.type != PropertyTypeObject) { -#endif - exceptions.emplace_back(InvalidNullabilityException(object.name, prop)); - } - } - else if (prop.type == PropertyTypeObject) { - exceptions.emplace_back(InvalidNullabilityException(object.name, prop)); - } - - // check primary keys - if (prop.is_primary) { - if (primary) { - exceptions.emplace_back(DuplicatePrimaryKeysException(object.name)); - } - primary = ∝ - } - - // check indexable - if (prop.is_indexed) { - if (prop.type != PropertyTypeString && prop.type != PropertyTypeInt) { - exceptions.emplace_back(PropertyTypeNotIndexableException(object.name, prop)); - } - } - } - } - - if (exceptions.size()) { - throw SchemaValidationException(exceptions); - } -} diff --git a/schema.hpp b/schema.hpp deleted file mode 100644 index 1e44b74c..00000000 --- a/schema.hpp +++ /dev/null @@ -1,58 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2015 Realm Inc. -// -// 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. -// -//////////////////////////////////////////////////////////////////////////// - -#ifndef REALM_SCHEMA_HPP -#define REALM_SCHEMA_HPP - -#include - -namespace realm { -class ObjectSchema; - -class Schema : private std::vector { -private: - using base = std::vector; -public: - // Create a schema from a vector of ObjectSchema - Schema(base types); - - // find an ObjectSchema by name - iterator find(std::string const& name); - const_iterator find(std::string const& name) const; - - // find an ObjectSchema with the same name as the passed in one - iterator find(ObjectSchema const& object) noexcept; - const_iterator find(ObjectSchema const& object) const noexcept; - - // get and ObjectSchema by name, throws if not present in the Schema - ObjectSchema& operator[] (std::string const& name); - - // Verify that this schema is internally consistent (i.e. all properties are - // valid, links link to types that actually exist, etc.) - void validate() const; - - using base::iterator; - using base::const_iterator; - using base::begin; - using base::end; - using base::empty; - using base::size; -}; -} - -#endif /* defined(REALM_SCHEMA_HPP) */ \ No newline at end of file diff --git a/transact_log_handler.cpp b/transact_log_handler.cpp deleted file mode 100644 index 3f833b19..00000000 --- a/transact_log_handler.cpp +++ /dev/null @@ -1,347 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2015 Realm Inc. -// -// 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 "transact_log_handler.hpp" - -#include "realm_delegate.hpp" - -#include -#include -#include - -using namespace realm; - -namespace { -class TransactLogHandler { - using ColumnInfo = RealmDelegate::ColumnInfo; - using ObserverState = RealmDelegate::ObserverState; - - // Observed table rows which need change information - std::vector m_observers; - // Userdata pointers for rows which have been deleted - std::vector invalidated; - // Delegate to send change information to - RealmDelegate* m_delegate; - - // Index of currently selected table - size_t m_current_table = 0; - // Change information for the currently selected LinkList, if any - ColumnInfo* m_active_linklist = nullptr; - - // Get the change info for the given column, creating it if needed - static ColumnInfo& get_change(ObserverState& state, size_t i) - { - if (state.changes.size() <= i) { - state.changes.resize(std::max(state.changes.size() * 2, i + 1)); - } - return state.changes[i]; - } - - // Loop over the columns which were changed in an observer state - template - static void for_each(ObserverState& state, Func&& f) - { - for (size_t i = 0; i < state.changes.size(); ++i) { - auto const& change = state.changes[i]; - if (change.changed) { - f(i, change); - } - } - } - - // Mark the given row/col as needing notifications sent - bool mark_dirty(size_t row_ndx, size_t col_ndx) - { - auto it = lower_bound(begin(m_observers), end(m_observers), ObserverState{m_current_table, row_ndx, nullptr}); - if (it != end(m_observers) && it->table_ndx == m_current_table && it->row_ndx == row_ndx) { - get_change(*it, col_ndx).changed = true; - } - return true; - } - - // Remove the given observer from the list of observed objects and add it - // to the listed of invalidated objects - void invalidate(ObserverState *o) - { - invalidated.push_back(o->info); - m_observers.erase(m_observers.begin() + (o - &m_observers[0])); - } - -public: - template - TransactLogHandler(RealmDelegate* delegate, SharedGroup& sg, Func&& func) - : m_delegate(delegate) - { - if (!delegate) { - func(); - return; - } - - m_observers = delegate->get_observed_rows(); - if (m_observers.empty()) { - auto old_version = sg.get_version_of_current_transaction(); - func(); - if (old_version != sg.get_version_of_current_transaction()) { - delegate->did_change({}, {}); - } - return; - } - - func(*this); - delegate->did_change(m_observers, invalidated); - } - - // Called at the end of the transaction log immediately before the version - // is advanced - void parse_complete() - { - m_delegate->will_change(m_observers, invalidated); - } - - // These would require having an observer before schema init - // Maybe do something here to throw an error when multiple processes have different schemas? - bool insert_group_level_table(size_t, size_t, StringData) { return false; } - bool erase_group_level_table(size_t, size_t) { return false; } - bool rename_group_level_table(size_t, StringData) { return false; } - bool insert_column(size_t, DataType, StringData, bool) { return false; } - bool insert_link_column(size_t, DataType, StringData, size_t, size_t) { return false; } - bool erase_column(size_t) { return false; } - bool erase_link_column(size_t, size_t, size_t) { return false; } - bool rename_column(size_t, StringData) { return false; } - bool add_search_index(size_t) { return false; } - bool remove_search_index(size_t) { return false; } - bool add_primary_key(size_t) { return false; } - bool remove_primary_key() { return false; } - bool set_link_type(size_t, LinkType) { return false; } - - bool select_table(size_t group_level_ndx, int, const size_t*) noexcept - { - m_current_table = group_level_ndx; - return true; - } - - bool insert_empty_rows(size_t, size_t, size_t, bool) - { - // rows are only inserted at the end, so no need to do anything - return true; - } - - bool erase_rows(size_t row_ndx, size_t, size_t last_row_ndx, bool unordered) - { - for (size_t i = 0; i < m_observers.size(); ++i) { - auto& o = m_observers[i]; - if (o.table_ndx == m_current_table) { - if (o.row_ndx == row_ndx) { - invalidate(&o); - --i; - } - else if (unordered && o.row_ndx == last_row_ndx) { - o.row_ndx = row_ndx; - } - else if (!unordered && o.row_ndx > row_ndx) { - o.row_ndx -= 1; - } - } - } - return true; - } - - bool clear_table() - { - for (size_t i = 0; i < m_observers.size(); ) { - auto& o = m_observers[i]; - if (o.table_ndx == m_current_table) { - invalidate(&o); - } - else { - ++i; - } - } - return true; - } - - bool select_link_list(size_t col, size_t row) - { - m_active_linklist = nullptr; - for (auto& o : m_observers) { - if (o.table_ndx == m_current_table && o.row_ndx == row) { - m_active_linklist = &get_change(o, col); - break; - } - } - return true; - } - - void append_link_list_change(ColumnInfo::Kind kind, size_t index) { - ColumnInfo *o = m_active_linklist; - if (!o || o->kind == ColumnInfo::Kind::SetAll) { - // Active LinkList isn't observed or already has multiple kinds of changes - return; - } - - if (o->kind == ColumnInfo::Kind::None) { - o->kind = kind; - o->changed = true; - o->indices.add(index); - } - else if (o->kind == kind) { - if (kind == ColumnInfo::Kind::Remove) { - o->indices.add_shifted(index); - } - else if (kind == ColumnInfo::Kind::Insert) { - o->indices.insert_at(index); - } - else { - o->indices.add(index); - } - } - else { - // Array KVO can only send a single kind of change at a time, so - // if there's multiple just give up and send "Set" - o->indices.set(0); - o->kind = ColumnInfo::Kind::SetAll; - } - } - - bool link_list_set(size_t index, size_t) - { - append_link_list_change(ColumnInfo::Kind::Set, index); - return true; - } - - bool link_list_insert(size_t index, size_t) - { - append_link_list_change(ColumnInfo::Kind::Insert, index); - return true; - } - - bool link_list_erase(size_t index) - { - append_link_list_change(ColumnInfo::Kind::Remove, index); - return true; - } - - bool link_list_nullify(size_t index) - { - append_link_list_change(ColumnInfo::Kind::Remove, index); - return true; - } - - bool link_list_swap(size_t index1, size_t index2) - { - append_link_list_change(ColumnInfo::Kind::Set, index1); - append_link_list_change(ColumnInfo::Kind::Set, index2); - return true; - } - - bool link_list_clear(size_t old_size) - { - ColumnInfo *o = m_active_linklist; - if (!o || o->kind == ColumnInfo::Kind::SetAll) { - return true; - } - - if (o->kind == ColumnInfo::Kind::Remove) - old_size += o->indices.size(); - else if (o->kind == ColumnInfo::Kind::Insert) - old_size -= o->indices.size(); - - o->indices.set(old_size); - - o->kind = ColumnInfo::Kind::Remove; - o->changed = true; - return true; - } - - bool link_list_move(size_t from, size_t to) - { - ColumnInfo *o = m_active_linklist; - if (!o || o->kind == ColumnInfo::Kind::SetAll) { - return true; - } - if (from > to) { - std::swap(from, to); - } - - if (o->kind == ColumnInfo::Kind::None) { - o->kind = ColumnInfo::Kind::Set; - o->changed = true; - } - if (o->kind == ColumnInfo::Kind::Set) { - for (size_t i = from; i <= to; ++i) - o->indices.add(i); - } - else { - o->indices.set(0); - o->kind = ColumnInfo::Kind::SetAll; - } - return true; - } - - // Things that just mark the field as modified - bool set_int(size_t col, size_t row, int_fast64_t) { return mark_dirty(row, col); } - bool set_bool(size_t col, size_t row, bool) { return mark_dirty(row, col); } - bool set_float(size_t col, size_t row, float) { return mark_dirty(row, col); } - bool set_double(size_t col, size_t row, double) { return mark_dirty(row, col); } - bool set_string(size_t col, size_t row, StringData) { return mark_dirty(row, col); } - bool set_binary(size_t col, size_t row, BinaryData) { return mark_dirty(row, col); } - bool set_date_time(size_t col, size_t row, DateTime) { return mark_dirty(row, col); } - bool set_table(size_t col, size_t row) { return mark_dirty(row, col); } - bool set_mixed(size_t col, size_t row, const Mixed&) { return mark_dirty(row, col); } - bool set_link(size_t col, size_t row, size_t) { return mark_dirty(row, col); } - bool set_null(size_t col, size_t row) { return mark_dirty(row, col); } - bool nullify_link(size_t col, size_t row) { return mark_dirty(row, col); } - - // Doesn't change any data - bool optimize_table() { return true; } - - // Used for subtables, which we currently don't support - bool select_descriptor(int, const size_t*) { return false; } -}; -} // anonymous namespace - -namespace realm { -namespace transaction { -void advance(SharedGroup& sg, ClientHistory& history, RealmDelegate* delegate) { - TransactLogHandler(delegate, sg, [&](auto&&... args) { - LangBindHelper::advance_read(sg, history, std::move(args)...); - }); -} - -void begin(SharedGroup& sg, ClientHistory& history, RealmDelegate* delegate) { - TransactLogHandler(delegate, sg, [&](auto&&... args) { - LangBindHelper::promote_to_write(sg, history, std::move(args)...); - }); -} - -void commit(SharedGroup& sg, ClientHistory&, RealmDelegate* delegate) { - LangBindHelper::commit_and_continue_as_read(sg); - - if (delegate) { - delegate->did_change({}, {}); - } -} - -void cancel(SharedGroup& sg, ClientHistory& history, RealmDelegate* delegate) { - TransactLogHandler(delegate, sg, [&](auto&&... args) { - LangBindHelper::rollback_and_continue_as_read(sg, history, std::move(args)...); - }); -} - -} // namespace transaction -} // namespace realm diff --git a/transact_log_handler.hpp b/transact_log_handler.hpp deleted file mode 100644 index 3a77848f..00000000 --- a/transact_log_handler.hpp +++ /dev/null @@ -1,46 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2015 Realm Inc. -// -// 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. -// -//////////////////////////////////////////////////////////////////////////// - -#ifndef REALM_TRANSACT_LOG_HANDLER_HPP -#define REALM_TRANSACT_LOG_HANDLER_HPP - -namespace realm { -class RealmDelegate; -class SharedGroup; -class ClientHistory; - -namespace transaction { -// Advance the read transaction version, with change notifications sent to delegate -// Must not be called from within a write transaction. -void advance(SharedGroup& sg, ClientHistory& history, RealmDelegate* delegate); - -// Begin a write transaction -// If the read transaction version is not up to date, will first advance to the -// most recent read transaction and sent notifications to delegate -void begin(SharedGroup& sg, ClientHistory& history, RealmDelegate* delegate); - -// Commit a write transaction -void commit(SharedGroup& sg, ClientHistory& history, RealmDelegate* delegate); - -// Cancel a write transaction and roll back all changes, with change notifications -// for reverting to the old values sent to delegate -void cancel(SharedGroup& sg, ClientHistory& history, RealmDelegate* delegate); -} // namespace transaction -} // namespace realm - -#endif /* REALM_TRANSACT_LOG_HANDLER_HPP */