Files
scylladb/disk-error-handler.hh
Benoît Canet 3b1d3d977d exceptions: Shutdown communications on non file I/O errors
Apply the same treatment to non file filesystem I/O errors.

Signed-off-by: Benoît Canet <benoit@scylladb.com>
Message-Id: <1458154098-9977-2-git-send-email-benoit@scylladb.com>
2016-03-17 15:02:54 +02:00

101 lines
3.3 KiB
C++

/*
* Copyright 2016 ScyllaDB
**/
/* This file is part of Scylla.
*
* Scylla is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Scylla is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Scylla. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <boost/signals2.hpp>
#include <boost/signals2/dummy_mutex.hpp>
#include <type_traits>
#include "utils/exceptions.hh"
#include <core/future.hh>
namespace bs2 = boost::signals2;
using disk_error_signal_type = bs2::signal_type<void (), bs2::keywords::mutex_type<bs2::dummy_mutex>>::type;
extern thread_local disk_error_signal_type commit_error;
extern thread_local disk_error_signal_type sstable_read_error;
extern thread_local disk_error_signal_type sstable_write_error;
extern thread_local disk_error_signal_type general_disk_error;
template<typename Func, typename... Args>
std::enable_if_t<!is_future<std::result_of_t<Func(Args&&...)>>::value,
std::result_of_t<Func(Args&&...)>>
do_io_check(disk_error_signal_type& signal, Func&& func, Args&&... args) {
try {
// calling function
return func(std::forward<Args>(args)...);
} catch (std::system_error& e) {
if (is_system_error_errno(EIO)) {
signal();
throw storage_io_error(e);
}
throw;
}
}
template<typename Func, typename... Args,
typename RetType = typename std::enable_if<is_future<std::result_of_t<Func(Args&&...)>>::value>::type>
auto do_io_check(disk_error_signal_type& signal, Func&& func, Args&&... args) {
try {
// calling function
auto fut = func(std::forward<Args>(args)...);
return fut.handle_exception([&signal] (auto ep) {
try {
std::rethrow_exception(ep);
} catch (std::system_error& sys_err) {
if (is_system_error_errno(EIO)) {
signal();
throw storage_io_error(sys_err);
}
}
return futurize<std::result_of_t<Func(Args&&...)>>::make_exception_future(ep);
});
} catch (std::system_error& e) {
if (is_system_error_errno(EIO)) {
signal();
throw storage_io_error(e);
}
throw;
}
}
template<typename Func, typename... Args>
auto commit_io_check(Func&& func, Args&&... args) {
return do_io_check(commit_error, func, std::forward<Args>(args)...);
}
template<typename Func, typename... Args>
auto sstable_read_io_check(Func&& func, Args&&... args) {
return do_io_check(sstable_read_error, func, std::forward<Args>(args)...);
}
template<typename Func, typename... Args>
auto sstable_write_io_check(Func&& func, Args&&... args) {
return do_io_check(sstable_write_error, func, std::forward<Args>(args)...);
}
template<typename Func, typename... Args>
auto io_check(Func&& func, Args&&... args) {
return do_io_check(general_disk_error, func, std::forward<Args>(args)...);
}