Skip to content

Commit

Permalink
Unify remaining std::error_codes into Status/ErrorCodes in sync client (
Browse files Browse the repository at this point in the history
  • Loading branch information
jbreams authored Aug 11, 2023
1 parent a80ab11 commit 1bd0a8d
Show file tree
Hide file tree
Showing 35 changed files with 390 additions and 620 deletions.
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@

### Breaking changes
* The `WebSocketObserver` interface in the sync `SocketProvider` API now takes a `WebSocketError` enum/`std::string_view` for the `websocket_closed_handler()` instead of a `Status`. Implementers of platform networking should make sure all their error handling is expressed in terms of the WebSocketError enum. ([PR #6859](https://github.com/realm/realm-core/pull/6859))
* `Status` no longer holds a `std::error_code` for `SystemError`'s ([PR #6869](https://github.com/realm/realm-core/pull/6869))
* C API no longer has a special type for sync error codes. Instead sync errors codes are converted to `realm_error_t` ([PR #6869](https://github.com/realm/realm-core/pull/6869))
* WebSocket specific error codes are no longer in the ErrorCodes enum or C API. ([PR #6869](https://github.com/realm/realm-core/pull/6869))
* `ProtocolError` is no longer a `std::error_code` enum and is no longer directly exposed by the sync error API ([PR #6869](https://github.com/realm/realm-core/pull/6869))
* The ClientError enum/`std::error_code` in the sync client has been removed in favor of a simplified error set using Status/ErrorCodes ([PR #6846](https://github.com/realm/realm-core/pull/6846)).
* SyncError now contains a Status to hold the error information from the sync client instead of a `std::error_code`/`std::string` ([PR #6824](https://github.com/realm/realm-core/pull/6824)).

### Compatibility
* Fileformat: Generates files with format v23. Reads and automatically upgrade from fileformat v5.
Expand All @@ -18,8 +24,6 @@

### Internals
* Timestamp objects can now only be created from a system clock timepoint. ([#6112](https://github.com/realm/realm-core/issues/6112))
* SyncError now contains a Status to hold the error information from the sync client instead of a `std::error_code`/`std::string` ([PR #6824](https://github.com/realm/realm-core/pull/6824)).
* The ClientError enum/`std::error_code` in the sync client has been removed in favor of a simplified error set using Status/ErrorCodes ([PR #6846](https://github.com/realm/realm-core/pull/6846)).

----------------------------------------------

Expand Down
46 changes: 7 additions & 39 deletions src/realm.h
Original file line number Diff line number Diff line change
Expand Up @@ -3334,26 +3334,6 @@ typedef enum realm_sync_progress_direction {
RLM_SYNC_PROGRESS_DIRECTION_DOWNLOAD,
} realm_sync_progress_direction_e;

/**
* Possible error categories realm_sync_error_code_t can fall in.
*/
typedef enum realm_sync_error_category {
RLM_SYNC_ERROR_CATEGORY_CLIENT,
RLM_SYNC_ERROR_CATEGORY_CONNECTION,
RLM_SYNC_ERROR_CATEGORY_SESSION,
RLM_SYNC_ERROR_CATEGORY_WEBSOCKET,

/**
* System error - POSIX errno, Win32 HRESULT, etc.
*/
RLM_SYNC_ERROR_CATEGORY_SYSTEM,

/**
* Unknown source of error.
*/
RLM_SYNC_ERROR_CATEGORY_UNKNOWN,
} realm_sync_error_category_e;

typedef enum realm_sync_error_action {
RLM_SYNC_ERROR_ACTION_NO_ACTION,
RLM_SYNC_ERROR_ACTION_PROTOCOL_VIOLATION,
Expand All @@ -3370,17 +3350,6 @@ typedef enum realm_sync_error_action {
typedef struct realm_sync_session realm_sync_session_t;
typedef struct realm_async_open_task realm_async_open_task_t;

// This type should never be returned from a function.
// It's only meant as an asynchronous callback argument.
// Pointers to this struct and its pointer members are only valid inside the scope
// of the callback they were passed to.
typedef struct realm_sync_error_code {
realm_sync_error_category_e category;
int value;
const char* message;
const char* category_name;
} realm_sync_error_code_t;

typedef struct realm_sync_error_user_info {
const char* key;
const char* value;
Expand All @@ -3397,8 +3366,7 @@ typedef struct realm_sync_error_compensating_write_info {
// Pointers to this struct and its pointer members are only valid inside the scope
// of the callback they were passed to.
typedef struct realm_sync_error {
realm_sync_error_code_t error_code;
const char* detailed_message;
realm_error_t status;
const char* c_original_file_path_key;
const char* c_recovery_file_path_key;
bool is_fatal;
Expand All @@ -3422,7 +3390,7 @@ typedef struct realm_sync_error {
*
* @param error Null, if the operation completed successfully.
*/
typedef void (*realm_sync_wait_for_completion_func_t)(realm_userdata_t userdata, realm_sync_error_code_t* error);
typedef void (*realm_sync_wait_for_completion_func_t)(realm_userdata_t userdata, realm_error_t* error);
typedef void (*realm_sync_connection_state_changed_func_t)(realm_userdata_t userdata,
realm_sync_connection_state_e old_state,
realm_sync_connection_state_e new_state);
Expand Down Expand Up @@ -3864,13 +3832,13 @@ RLM_API void realm_sync_session_wait_for_upload_completion(realm_sync_session_t*
/**
* Wrapper for SyncSession::OnlyForTesting::handle_error. This routine should be used only for testing.
* @param session ptr to a valid sync session
* @param error_code error code to simulate
* @param category category of the error to simulate
* @param error_message string representing the error
* @param error_code realm_errno_e representing the error to simulate
* @param error_str error message to be included with Status
* @param is_fatal boolean to signal if the error is fatal or not
*/
RLM_API void realm_sync_session_handle_error_for_testing(const realm_sync_session_t* session, int error_code,
int category, const char* error_message, bool is_fatal);
RLM_API void realm_sync_session_handle_error_for_testing(const realm_sync_session_t* session,
realm_errno_e error_code, const char* error_str,
bool is_fatal);

/**
* In case of exception thrown in user code callbacks, this api will allow the sdk to store the user code exception
Expand Down
8 changes: 0 additions & 8 deletions src/realm/error_codes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,11 +225,6 @@ ErrorCategory ErrorCodes::error_categories(Error code)
.set(ErrorCategory::app_error)
.set(ErrorCategory::service_error);

case WebSocketResolveFailedError:
case WebSocketConnectionClosedClientError:
case WebSocketConnectionClosedServerError:
return ErrorCategory().set(ErrorCategory::runtime_error).set(ErrorCategory::websocket_error);

case UnknownError:
break;
}
Expand Down Expand Up @@ -400,9 +395,6 @@ static const MapElem string_to_error_code[] = {
{"ValueAlreadyExists", ErrorCodes::ValueAlreadyExists},
{"ValueDuplicateName", ErrorCodes::ValueDuplicateName},
{"ValueNotFound", ErrorCodes::ValueNotFound},
{"WebSocketConnectionClosedClientError", ErrorCodes::WebSocketConnectionClosedClientError},
{"WebSocketConnectionClosedServerError", ErrorCodes::WebSocketConnectionClosedServerError},
{"WebSocketResolveFailedError", ErrorCodes::WebSocketResolveFailedError},
{"WrongSyncType", ErrorCodes::WrongSyncType},
{"WrongThread", ErrorCodes::WrongThread},
{"WrongTransactionState", ErrorCodes::WrongTransactionState},
Expand Down
4 changes: 0 additions & 4 deletions src/realm/error_codes.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,6 @@ typedef enum realm_errno {
RLM_ERR_INVALID_SERVER_RESPONSE = 4354,
RLM_ERR_APP_SERVER_ERROR = 4355,

RLM_ERR_WEBSOCKET_RESOLVE_FAILED_ERROR = 4400,
RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_CLIENT_ERROR = 4401,
RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_SERVER_ERROR = 4402,

RLM_ERR_CALLBACK = 1000000, /**< A user-provided callback failed. */
RLM_ERR_UNKNOWN = 2000000 /* Should not be used in code */
} realm_errno_e;
Expand Down
4 changes: 0 additions & 4 deletions src/realm/error_codes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,10 +246,6 @@ class ErrorCodes {
InvalidServerResponse = RLM_ERR_INVALID_SERVER_RESPONSE,
AppServerError = RLM_ERR_APP_SERVER_ERROR,

WebSocketResolveFailedError = RLM_ERR_WEBSOCKET_RESOLVE_FAILED_ERROR,
WebSocketConnectionClosedClientError = RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_CLIENT_ERROR,
WebSocketConnectionClosedServerError = RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_SERVER_ERROR,

CallbackFailed = RLM_ERR_CALLBACK,
UnknownError = RLM_ERR_UNKNOWN,
};
Expand Down
13 changes: 2 additions & 11 deletions src/realm/exceptions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,20 +367,11 @@ struct SystemError : RuntimeError {

~SystemError() noexcept override;

std::error_code get_system_error() const
{
return to_status().get_std_error_code();
}

const std::error_category& get_category() const
{
return get_system_error().category();
}

private:
static Status make_status(std::error_code err, std::string_view msg, bool msg_is_prefix)
{
return Status(err, msg_is_prefix ? util::format("%1: %2 (%3)", msg, err.message(), err.value()) : msg);
return Status(ErrorCodes::SystemError,
msg_is_prefix ? util::format("%1: %2 (%3)", msg, err.message(), err.value()) : msg);
}
};

Expand Down
30 changes: 8 additions & 22 deletions src/realm/impl/simulated_failure.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <cstdint>
#include <system_error>

#include <realm/exceptions.hpp>
#include <realm/util/features.h>

#ifdef REALM_DEBUG
Expand All @@ -31,7 +32,7 @@
namespace realm {
namespace _impl {

class SimulatedFailure : public std::system_error {
class SimulatedFailure : public RuntimeError {
public:
enum FailureType {
generic,
Expand Down Expand Up @@ -64,11 +65,6 @@ class SimulatedFailure : public std::system_error {
/// not defined, this function always return false.
static bool check_trigger(FailureType) noexcept;

/// The specified error code is set to `make_error_code(failure_type)` if
/// check_trigger() returns true. Otherwise it is set to
/// `std::error_code()`. Returns a copy of the updated error code.
static std::error_code trigger(FailureType failure_type, std::error_code&) noexcept;

/// Throws SimulatedFailure if check_trigger() returns true. The exception
/// will be constructed with an error code equal to
/// `make_error_code(failure_type)`.
Expand All @@ -90,7 +86,7 @@ class SimulatedFailure : public std::system_error {
/// when turning this off.
static void set_thread_local(bool);

SimulatedFailure(std::error_code);
SimulatedFailure(FailureType);

private:
#ifdef REALM_ENABLE_SIMULATED_FAILURE
Expand Down Expand Up @@ -132,7 +128,8 @@ std::error_code make_error_code(SimulatedFailure::FailureType) noexcept;

namespace std {

template<> struct is_error_code_enum<realm::_impl::SimulatedFailure::FailureType> {
template <>
struct is_error_code_enum<realm::_impl::SimulatedFailure::FailureType> {
static const bool value = true;
};

Expand Down Expand Up @@ -184,21 +181,10 @@ inline bool SimulatedFailure::check_trigger(FailureType failure_type) noexcept
#endif
}

inline std::error_code SimulatedFailure::trigger(FailureType failure_type, std::error_code& ec) noexcept
{
if (check_trigger(failure_type)) {
ec = make_error_code(failure_type);
}
else {
ec = std::error_code();
}
return ec;
}

inline void SimulatedFailure::trigger(FailureType failure_type)
{
if (check_trigger(failure_type))
throw SimulatedFailure(make_error_code(failure_type));
throw SimulatedFailure(failure_type);
}

inline constexpr bool SimulatedFailure::is_enabled()
Expand All @@ -219,8 +205,8 @@ inline void SimulatedFailure::set_thread_local(bool tl)
#endif
}

inline SimulatedFailure::SimulatedFailure(std::error_code ec)
: std::system_error(ec)
inline SimulatedFailure::SimulatedFailure(FailureType)
: RuntimeError(Status{ErrorCodes::RuntimeError, "SimulatedFailure"})
{
}

Expand Down
4 changes: 2 additions & 2 deletions src/realm/object-store/audit.mm
Original file line number Diff line number Diff line change
Expand Up @@ -783,8 +783,8 @@ bool write_event(Timestamp timestamp, StringData activity, StringData event_type
std::string path = session->path();
session->close();
m_open_paths.erase(path);
if (status.get_std_error_code()) {
m_logger->error("Events: Upload on '%1' failed with error '%2'.", path, status.reason());
if (!status.is_ok()) {
m_logger->error("Events: Upload on '%1' failed with error '%2'.", path, status);
if (m_error_handler) {
m_error_handler(SyncError(std::move(status), false));
}
Expand Down
10 changes: 8 additions & 2 deletions src/realm/object-store/c_api/conversion.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -485,8 +485,14 @@ static inline realm_version_id_t to_capi(const VersionID& v)
return version_id;
}

realm_sync_error_code_t to_capi(const Status& status, std::string& message);
void sync_error_to_error_code(const realm_sync_error_code_t& sync_error_code, std::error_code* error_code_out);
static inline realm_error_t to_capi(const Status& s)
{
realm_error_t err;
err.error = static_cast<realm_errno_e>(s.code());
err.categories = static_cast<realm_error_category_e>(ErrorCodes::error_categories(s.code()).value());
err.message = s.reason().c_str();
return err;
}

} // namespace realm::c_api

Expand Down
Loading

0 comments on commit 1bd0a8d

Please sign in to comment.