mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
updated vm (breaking compatibility)
- updated vm - new actor scheduler - updated tonlib - updated DNS smartcontract
This commit is contained in:
parent
9e4816e7f6
commit
e27fb1e09c
100 changed files with 3692 additions and 1299 deletions
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -117,24 +117,28 @@ template <class T>
|
|||
class OneValue<T *> {
|
||||
public:
|
||||
bool set_value(T *value) {
|
||||
T *was = nullptr;
|
||||
T *was = Empty();
|
||||
return state_.compare_exchange_strong(was, value, std::memory_order_acq_rel);
|
||||
}
|
||||
bool get_value(T *&value) {
|
||||
value = state_.exchange(Taken(), std::memory_order_acq_rel);
|
||||
return value != nullptr;
|
||||
return value != Empty();
|
||||
}
|
||||
void reset() {
|
||||
state_ = nullptr;
|
||||
state_ = Empty();
|
||||
}
|
||||
OneValue() {
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic<T *> state_{nullptr};
|
||||
T *Taken() {
|
||||
static T xxx;
|
||||
return &xxx;
|
||||
std::atomic<T *> state_{Empty()};
|
||||
static T *Empty() {
|
||||
static int64 xxx;
|
||||
return reinterpret_cast<T *>(&xxx);
|
||||
}
|
||||
static T *Taken() {
|
||||
static int64 xxx;
|
||||
return reinterpret_cast<T *>(&xxx);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -14,63 +14,86 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/port/thread.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <algorithm>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
|
||||
namespace td {
|
||||
|
||||
class MpmcWaiter {
|
||||
class MpmcEagerWaiter {
|
||||
public:
|
||||
int wait(int yields, uint32 worker_id) {
|
||||
if (yields < RoundsTillSleepy) {
|
||||
struct Slot {
|
||||
private:
|
||||
friend class MpmcEagerWaiter;
|
||||
int yields;
|
||||
uint32 worker_id;
|
||||
};
|
||||
void init_slot(Slot &slot, uint32 worker_id) {
|
||||
slot.yields = 0;
|
||||
slot.worker_id = worker_id;
|
||||
}
|
||||
void wait(Slot &slot) {
|
||||
if (slot.yields < RoundsTillSleepy) {
|
||||
td::this_thread::yield();
|
||||
return yields + 1;
|
||||
} else if (yields == RoundsTillSleepy) {
|
||||
slot.yields++;
|
||||
return;
|
||||
} else if (slot.yields == RoundsTillSleepy) {
|
||||
auto state = state_.load(std::memory_order_relaxed);
|
||||
if (!State::has_worker(state)) {
|
||||
auto new_state = State::with_worker(state, worker_id);
|
||||
auto new_state = State::with_worker(state, slot.worker_id);
|
||||
if (state_.compare_exchange_strong(state, new_state, std::memory_order_acq_rel)) {
|
||||
td::this_thread::yield();
|
||||
return yields + 1;
|
||||
slot.yields++;
|
||||
return;
|
||||
}
|
||||
if (state == State::awake()) {
|
||||
return 0;
|
||||
slot.yields = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
td::this_thread::yield();
|
||||
return 0;
|
||||
} else if (yields < RoundsTillAsleep) {
|
||||
slot.yields = 0;
|
||||
return;
|
||||
} else if (slot.yields < RoundsTillAsleep) {
|
||||
auto state = state_.load(std::memory_order_acquire);
|
||||
if (State::still_sleepy(state, worker_id)) {
|
||||
if (State::still_sleepy(state, slot.worker_id)) {
|
||||
td::this_thread::yield();
|
||||
return yields + 1;
|
||||
slot.yields++;
|
||||
return;
|
||||
}
|
||||
return 0;
|
||||
slot.yields = 0;
|
||||
return;
|
||||
} else {
|
||||
auto state = state_.load(std::memory_order_acquire);
|
||||
if (State::still_sleepy(state, worker_id)) {
|
||||
if (State::still_sleepy(state, slot.worker_id)) {
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
if (state_.compare_exchange_strong(state, State::asleep(), std::memory_order_acq_rel)) {
|
||||
condition_variable_.wait(lock);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
slot.yields = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int stop_wait(int yields, uint32 worker_id) {
|
||||
if (yields > RoundsTillSleepy) {
|
||||
void stop_wait(Slot &slot) {
|
||||
if (slot.yields > RoundsTillSleepy) {
|
||||
notify_cold();
|
||||
}
|
||||
return 0;
|
||||
slot.yields = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
void close() {
|
||||
}
|
||||
|
||||
void notify() {
|
||||
|
@ -102,8 +125,8 @@ class MpmcWaiter {
|
|||
return (state >> 1) == (worker + 1);
|
||||
}
|
||||
};
|
||||
//enum { RoundsTillSleepy = 32, RoundsTillAsleep = 64 };
|
||||
enum { RoundsTillSleepy = 1, RoundsTillAsleep = 2 };
|
||||
enum { RoundsTillSleepy = 32, RoundsTillAsleep = 64 };
|
||||
// enum { RoundsTillSleepy = 1, RoundsTillAsleep = 2 };
|
||||
std::atomic<uint32> state_{State::awake()};
|
||||
std::mutex mutex_;
|
||||
std::condition_variable condition_variable_;
|
||||
|
@ -117,4 +140,208 @@ class MpmcWaiter {
|
|||
}
|
||||
};
|
||||
|
||||
class MpmcSleepyWaiter {
|
||||
public:
|
||||
struct Slot {
|
||||
private:
|
||||
friend class MpmcSleepyWaiter;
|
||||
|
||||
enum State { Search, Work, Sleep } state_{Work};
|
||||
|
||||
void park() {
|
||||
std::unique_lock<std::mutex> guard(mutex_);
|
||||
condition_variable_.wait(guard, [&] { return unpark_flag_; });
|
||||
unpark_flag_ = false;
|
||||
}
|
||||
|
||||
bool cancel_park() {
|
||||
auto res = unpark_flag_;
|
||||
unpark_flag_ = false;
|
||||
return res;
|
||||
}
|
||||
|
||||
void unpark() {
|
||||
//TODO: try unlock guard before notify_all
|
||||
std::unique_lock<std::mutex> guard(mutex_);
|
||||
unpark_flag_ = true;
|
||||
condition_variable_.notify_all();
|
||||
}
|
||||
|
||||
std::mutex mutex_;
|
||||
std::condition_variable condition_variable_;
|
||||
bool unpark_flag_{false}; // TODO: move out of lock
|
||||
int yield_cnt{0};
|
||||
int32 worker_id{0};
|
||||
char padding[128];
|
||||
};
|
||||
|
||||
// There are a lot of workers
|
||||
// Each has a slot
|
||||
//
|
||||
// States of a worker:
|
||||
// - searching for work | Search
|
||||
// - processing work | Work
|
||||
// - sleeping | Sleep
|
||||
//
|
||||
// When somebody adds a work it calls notify
|
||||
//
|
||||
// notify
|
||||
// if there are workers in search phase do nothing.
|
||||
// if all workers are awake do nothing
|
||||
// otherwise wake some random worker
|
||||
//
|
||||
// Initially all workers are in Search mode.
|
||||
//
|
||||
// When worker found nothing it may try to call wait.
|
||||
// This may put it in a Sleep for some time.
|
||||
// After wait return worker will be in Search state again.
|
||||
//
|
||||
// Suppose worker found a work and ready to process it.
|
||||
// Than it may call stop_wait. This will cause transition from
|
||||
// Search to Work state.
|
||||
//
|
||||
// Main invariant:
|
||||
// After notify is called there should be at least on worker in Search or Work state.
|
||||
// If possible - in Search state
|
||||
//
|
||||
|
||||
void init_slot(Slot &slot, int32 worker_id) {
|
||||
slot.state_ = Slot::State::Work;
|
||||
slot.unpark_flag_ = false;
|
||||
slot.worker_id = worker_id;
|
||||
VLOG(waiter) << "Init slot " << worker_id;
|
||||
}
|
||||
|
||||
int VERBOSITY_NAME(waiter) = VERBOSITY_NAME(DEBUG) + 10;
|
||||
void wait(Slot &slot) {
|
||||
if (slot.state_ == Slot::State::Work) {
|
||||
VLOG(waiter) << "Work -> Search";
|
||||
state_++;
|
||||
slot.state_ = Slot::State::Search;
|
||||
slot.yield_cnt = 0;
|
||||
return;
|
||||
}
|
||||
if (slot.state_ == Slot::Search) {
|
||||
if (slot.yield_cnt++ < 10 && false) {
|
||||
td::this_thread::yield();
|
||||
return;
|
||||
}
|
||||
|
||||
slot.state_ = Slot::State::Sleep;
|
||||
std::unique_lock<std::mutex> guard(sleepers_mutex_);
|
||||
auto state_view = StateView(state_.fetch_add((1 << PARKING_SHIFT) - 1));
|
||||
CHECK(state_view.searching_count != 0);
|
||||
bool should_search = state_view.searching_count == 1;
|
||||
if (closed_) {
|
||||
return;
|
||||
}
|
||||
sleepers_.push_back(&slot);
|
||||
LOG_CHECK(slot.unpark_flag_ == false) << slot.worker_id;
|
||||
VLOG(waiter) << "add to sleepers " << slot.worker_id;
|
||||
//guard.unlock();
|
||||
if (should_search) {
|
||||
VLOG(waiter) << "Search -> Search once then Sleep ";
|
||||
return;
|
||||
}
|
||||
VLOG(waiter) << "Search -> Sleep " << state_view.searching_count << " " << state_view.parked_count;
|
||||
}
|
||||
|
||||
CHECK(slot.state_ == Slot::State::Sleep);
|
||||
VLOG(waiter) << "Park " << slot.worker_id;
|
||||
slot.park();
|
||||
VLOG(waiter) << "Resume " << slot.worker_id;
|
||||
slot.state_ = Slot::State::Search;
|
||||
slot.yield_cnt = 0;
|
||||
}
|
||||
|
||||
void stop_wait(Slot &slot) {
|
||||
if (slot.state_ == Slot::State::Work) {
|
||||
return;
|
||||
}
|
||||
if (slot.state_ == Slot::State::Sleep) {
|
||||
VLOG(waiter) << "Search once then Sleep -> Work/Search " << slot.worker_id;
|
||||
slot.state_ = Slot::State::Work;
|
||||
std::unique_lock<std::mutex> guard(sleepers_mutex_);
|
||||
auto it = std::find(sleepers_.begin(), sleepers_.end(), &slot);
|
||||
if (it != sleepers_.end()) {
|
||||
sleepers_.erase(it);
|
||||
VLOG(waiter) << "remove from sleepers " << slot.worker_id;
|
||||
state_.fetch_sub((1 << PARKING_SHIFT) - 1);
|
||||
guard.unlock();
|
||||
} else {
|
||||
guard.unlock();
|
||||
VLOG(waiter) << "not in sleepers" << slot.worker_id;
|
||||
CHECK(slot.cancel_park());
|
||||
}
|
||||
}
|
||||
VLOG(waiter) << "Search once then Sleep -> Work " << slot.worker_id;
|
||||
slot.state_ = Slot::State::Search;
|
||||
auto state_view = StateView(state_.fetch_sub(1));
|
||||
CHECK(state_view.searching_count != 0);
|
||||
CHECK(state_view.searching_count < 1000);
|
||||
bool should_notify = state_view.searching_count == 1;
|
||||
if (should_notify) {
|
||||
VLOG(waiter) << "Notify others";
|
||||
notify();
|
||||
}
|
||||
VLOG(waiter) << "Search -> Work ";
|
||||
slot.state_ = Slot::State::Work;
|
||||
}
|
||||
|
||||
void notify() {
|
||||
auto view = StateView(state_.load());
|
||||
//LOG(ERROR) << view.parked_count;
|
||||
if (view.searching_count > 0 || view.parked_count == 0) {
|
||||
VLOG(waiter) << "Ingore notify: " << view.searching_count << " " << view.parked_count;
|
||||
return;
|
||||
}
|
||||
|
||||
VLOG(waiter) << "Notify: " << view.searching_count << " " << view.parked_count;
|
||||
std::unique_lock<std::mutex> guard(sleepers_mutex_);
|
||||
|
||||
view = StateView(state_.load());
|
||||
if (view.searching_count > 0) {
|
||||
VLOG(waiter) << "Skip notify: got searching";
|
||||
return;
|
||||
}
|
||||
|
||||
CHECK(view.parked_count == static_cast<int>(sleepers_.size()));
|
||||
if (sleepers_.empty()) {
|
||||
VLOG(waiter) << "Skip notify: no sleepers";
|
||||
return;
|
||||
}
|
||||
|
||||
auto sleeper = sleepers_.back();
|
||||
sleepers_.pop_back();
|
||||
state_.fetch_sub((1 << PARKING_SHIFT) - 1);
|
||||
VLOG(waiter) << "Unpark " << sleeper->worker_id;
|
||||
sleeper->unpark();
|
||||
}
|
||||
|
||||
void close() {
|
||||
StateView state(state_.load());
|
||||
LOG_CHECK(state.parked_count == 0) << state.parked_count;
|
||||
LOG_CHECK(state.searching_count == 0) << state.searching_count;
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr td::int32 PARKING_SHIFT = 16;
|
||||
struct StateView {
|
||||
td::int32 parked_count;
|
||||
td::int32 searching_count;
|
||||
explicit StateView(int32 x) {
|
||||
parked_count = x >> PARKING_SHIFT;
|
||||
searching_count = x & ((1 << PARKING_SHIFT) - 1);
|
||||
}
|
||||
};
|
||||
std::atomic<td::int32> state_{0};
|
||||
|
||||
std::mutex sleepers_mutex_;
|
||||
std::vector<Slot *> sleepers_;
|
||||
|
||||
bool closed_ = false;
|
||||
};
|
||||
|
||||
using MpmcWaiter = MpmcSleepyWaiter;
|
||||
|
||||
} // namespace td
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -49,9 +49,7 @@ class AtomicRefCnt {
|
|||
};
|
||||
|
||||
template <class DataT, class DeleterT>
|
||||
class SharedPtrRaw
|
||||
: public DeleterT
|
||||
, private MpscLinkQueueImpl::Node {
|
||||
class SharedPtrRaw : public DeleterT, private MpscLinkQueueImpl::Node {
|
||||
public:
|
||||
explicit SharedPtrRaw(DeleterT deleter) : DeleterT(std::move(deleter)), ref_cnt_{0}, option_magic_(Magic) {
|
||||
}
|
||||
|
@ -100,6 +98,7 @@ template <class T, class DeleterT = std::default_delete<T>>
|
|||
class SharedPtr {
|
||||
public:
|
||||
using Raw = detail::SharedPtrRaw<T, DeleterT>;
|
||||
struct acquire_t {};
|
||||
SharedPtr() = default;
|
||||
~SharedPtr() {
|
||||
if (!raw_) {
|
||||
|
@ -112,6 +111,8 @@ class SharedPtr {
|
|||
raw_->inc();
|
||||
}
|
||||
}
|
||||
SharedPtr(acquire_t, Raw *raw) : raw_(raw) {
|
||||
}
|
||||
SharedPtr(const SharedPtr &other) : SharedPtr(other.raw_) {
|
||||
}
|
||||
SharedPtr &operator=(const SharedPtr &other) {
|
||||
|
|
124
tdutils/td/utils/StealingQueue.h
Normal file
124
tdutils/td/utils/StealingQueue.h
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2019-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "td/utils/Status.h"
|
||||
#include "td/utils/Span.h"
|
||||
namespace td {
|
||||
template <class T, size_t N = 256 /*must be a power of two*/>
|
||||
class StealingQueue {
|
||||
public:
|
||||
// tries to put a value
|
||||
// returns if succeeded
|
||||
// only owner is alowed to to do this
|
||||
template <class F>
|
||||
void local_push(T value, F&& overflow_f) {
|
||||
while (true) {
|
||||
auto tail = tail_.load(std::memory_order_relaxed);
|
||||
auto head = head_.load(); //TODO: memory order
|
||||
|
||||
if (static_cast<size_t>(tail - head) < N) {
|
||||
buf_[tail & MASK].store(value, std::memory_order_relaxed);
|
||||
tail_.store(tail + 1, std::memory_order_release);
|
||||
return;
|
||||
}
|
||||
|
||||
// queue is full
|
||||
// TODO: batch insert into global queue?
|
||||
auto n = N / 2 + 1;
|
||||
auto new_head = head + n;
|
||||
if (!head_.compare_exchange_strong(head, new_head)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
overflow_f(buf_[(i + head) & MASK].load(std::memory_order_relaxed));
|
||||
}
|
||||
overflow_f(value);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// tries to pop a value
|
||||
// returns if succeeded
|
||||
// only owner is alowed to to do this
|
||||
bool local_pop(T& value) {
|
||||
auto tail = tail_.load(std::memory_order_relaxed);
|
||||
auto head = head_.load();
|
||||
|
||||
if (head == tail) {
|
||||
return false;
|
||||
}
|
||||
|
||||
value = buf_[head & MASK].load(std::memory_order_relaxed);
|
||||
return head_.compare_exchange_strong(head, head + 1);
|
||||
}
|
||||
|
||||
bool steal(T& value, StealingQueue<T, N>& other) {
|
||||
while (true) {
|
||||
auto tail = tail_.load(std::memory_order_relaxed);
|
||||
auto head = head_.load(); //TODO: memory order
|
||||
|
||||
auto other_head = other.head_.load();
|
||||
auto other_tail = other.tail_.load(std::memory_order_acquire);
|
||||
|
||||
if (other_tail < other_head) {
|
||||
continue;
|
||||
}
|
||||
size_t n = other_tail - other_head;
|
||||
if (n > N) {
|
||||
continue;
|
||||
}
|
||||
n -= n / 2;
|
||||
n = td::min(n, static_cast<size_t>(head + N - tail));
|
||||
if (n == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
buf_[(i + tail) & MASK].store(other.buf_[(i + other_head) & MASK].load(std::memory_order_relaxed),
|
||||
std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
if (!other.head_.compare_exchange_strong(other_head, other_head + n)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
n--;
|
||||
value = buf_[(tail + n) & MASK].load(std::memory_order_relaxed);
|
||||
tail_.store(tail + n, std::memory_order_release);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
StealingQueue() {
|
||||
for (auto& x : buf_) {
|
||||
x.store(T{}, std::memory_order_relaxed);
|
||||
}
|
||||
std::atomic_thread_fence(std::memory_order_seq_cst);
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic<td::int64> head_{0};
|
||||
std::atomic<td::int64> tail_{0};
|
||||
static constexpr size_t MASK{N - 1};
|
||||
std::array<std::atomic<T>, N> buf_;
|
||||
};
|
||||
}; // namespace td
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "TsFileLog.h"
|
||||
|
||||
|
@ -24,8 +24,10 @@ namespace td {
|
|||
namespace detail {
|
||||
class TsFileLog : public LogInterface {
|
||||
public:
|
||||
Status init(string path) {
|
||||
Status init(string path, td::int64 rotate_threshold, bool redirect_stderr) {
|
||||
path_ = std::move(path);
|
||||
rotate_threshold_ = rotate_threshold;
|
||||
redirect_stderr_ = redirect_stderr;
|
||||
for (int i = 0; i < (int)logs_.size(); i++) {
|
||||
logs_[i].id = i;
|
||||
}
|
||||
|
@ -54,6 +56,8 @@ class TsFileLog : public LogInterface {
|
|||
int id;
|
||||
};
|
||||
static constexpr int MAX_THREAD_ID = 128;
|
||||
td::int64 rotate_threshold_;
|
||||
bool redirect_stderr_;
|
||||
std::string path_;
|
||||
std::array<Info, MAX_THREAD_ID> logs_;
|
||||
|
||||
|
@ -70,7 +74,7 @@ class TsFileLog : public LogInterface {
|
|||
}
|
||||
|
||||
Status init_info(Info *info) {
|
||||
TRY_STATUS(info->log.init(get_path(info), std::numeric_limits<int64>::max(), info->id == 0));
|
||||
TRY_STATUS(info->log.init(get_path(info), std::numeric_limits<int64>::max(), info->id == 0 && redirect_stderr_));
|
||||
info->is_inited = true;
|
||||
return Status::OK();
|
||||
}
|
||||
|
@ -92,9 +96,9 @@ class TsFileLog : public LogInterface {
|
|||
};
|
||||
} // namespace detail
|
||||
|
||||
Result<td::unique_ptr<LogInterface>> TsFileLog::create(string path) {
|
||||
Result<td::unique_ptr<LogInterface>> TsFileLog::create(string path, td::int64 rotate_threshold, bool redirect_stderr) {
|
||||
auto res = td::make_unique<detail::TsFileLog>();
|
||||
TRY_STATUS(res->init(path));
|
||||
TRY_STATUS(res->init(path, rotate_threshold, redirect_stderr));
|
||||
return std::move(res);
|
||||
}
|
||||
} // namespace td
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -22,7 +22,10 @@
|
|||
|
||||
namespace td {
|
||||
class TsFileLog {
|
||||
static constexpr int64 DEFAULT_ROTATE_THRESHOLD = 10 * (1 << 20);
|
||||
|
||||
public:
|
||||
static Result<td::unique_ptr<LogInterface>> create(string path);
|
||||
static Result<td::unique_ptr<LogInterface>> create(string path, int64 rotate_threshold = DEFAULT_ROTATE_THRESHOLD,
|
||||
bool redirect_stderr = true);
|
||||
};
|
||||
} // namespace td
|
||||
|
|
|
@ -1,3 +1,21 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2019-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "rlimit.h"
|
||||
#if TD_LINUX || TD_ANDROID
|
||||
#include <unistd.h>
|
||||
|
|
|
@ -1,3 +1,21 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "td/utils/port/config.h"
|
||||
|
|
|
@ -1,3 +1,21 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "user.h"
|
||||
#if TD_LINUX
|
||||
#include <unistd.h>
|
||||
|
|
|
@ -1,3 +1,21 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "td/utils/port/config.h"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue