//////////////////////////////////////////////////////////////////////////////// /// DISCLAIMER /// /// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany /// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany /// /// 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. /// /// Copyright holder is ArangoDB GmbH, Cologne, Germany /// /// @author Jan Steemann //////////////////////////////////////////////////////////////////////////////// #ifndef ARANGOD_CLUSTER_HEARTBEAT_THREAD_H #define ARANGOD_CLUSTER_HEARTBEAT_THREAD_H 1 #include "Basics/Thread.h" #include "Basics/ConditionVariable.h" #include "Basics/Mutex.h" #include "Cluster/AgencyComm.h" #include "Logger/Logger.h" struct TRI_server_t; struct TRI_vocbase_t; namespace arangodb { class AgencyCallbackRegistry; class HeartbeatThread : public Thread { HeartbeatThread(HeartbeatThread const&) = delete; HeartbeatThread& operator=(HeartbeatThread const&) = delete; public: HeartbeatThread(TRI_server_t*, AgencyCallbackRegistry*, uint64_t, uint64_t); ~HeartbeatThread(); public: ////////////////////////////////////////////////////////////////////////////// /// @brief initializes the heartbeat ////////////////////////////////////////////////////////////////////////////// bool init(); ////////////////////////////////////////////////////////////////////////////// /// @brief whether or not the thread is ready ////////////////////////////////////////////////////////////////////////////// bool isReady() const { return _ready.load(); } ////////////////////////////////////////////////////////////////////////////// /// @brief set the thread status to ready ////////////////////////////////////////////////////////////////////////////// void setReady() { _ready.store(true); } ////////////////////////////////////////////////////////////////////////////// /// @brief decrement the counter for a dispatched job, the argument is true /// if the job was finished successfully and false otherwise ////////////////////////////////////////////////////////////////////////////// void removeDispatchedJob(bool success); ////////////////////////////////////////////////////////////////////////////// /// @brief whether or not the thread has run at least once. /// this is used on the coordinator only ////////////////////////////////////////////////////////////////////////////// static bool hasRunOnce() { return (HasRunOnce == 1); } protected: ////////////////////////////////////////////////////////////////////////////// /// @brief heartbeat main loop ////////////////////////////////////////////////////////////////////////////// void run() override; private: ////////////////////////////////////////////////////////////////////////////// /// @brief heartbeat main loop, coordinator version ////////////////////////////////////////////////////////////////////////////// void runCoordinator(); ////////////////////////////////////////////////////////////////////////////// /// @brief heartbeat main loop, dbserver version ////////////////////////////////////////////////////////////////////////////// void runDBServer(); ////////////////////////////////////////////////////////////////////////////// /// @brief handles a plan change, coordinator case ////////////////////////////////////////////////////////////////////////////// bool handlePlanChangeCoordinator(uint64_t); ////////////////////////////////////////////////////////////////////////////// /// @brief handles a plan change, DBServer case ////////////////////////////////////////////////////////////////////////////// bool handlePlanChangeDBServer(uint64_t); ////////////////////////////////////////////////////////////////////////////// /// @brief handles a state change ////////////////////////////////////////////////////////////////////////////// bool handleStateChange(AgencyCommResult&, uint64_t&); ////////////////////////////////////////////////////////////////////////////// /// @brief fetch the last value of Sync/Commands/my-id from the agency ////////////////////////////////////////////////////////////////////////////// uint64_t getLastCommandIndex(); ////////////////////////////////////////////////////////////////////////////// /// @brief sends the current server's state to the agency ////////////////////////////////////////////////////////////////////////////// bool sendState(); ////////////////////////////////////////////////////////////////////////////// /// @brief fetch users for a database (run on coordinator only) ////////////////////////////////////////////////////////////////////////////// bool fetchUsers(TRI_vocbase_t*); private: ////////////////////////////////////////////////////////////////////////////// /// @brief server ////////////////////////////////////////////////////////////////////////////// TRI_server_t* _server; ////////////////////////////////////////////////////////////////////////////// /// @brief AgencyCallbackRegistry ////////////////////////////////////////////////////////////////////////////// AgencyCallbackRegistry* _agencyCallbackRegistry; ////////////////////////////////////////////////////////////////////////////// /// @brief status lock ////////////////////////////////////////////////////////////////////////////// arangodb::Mutex _statusLock; ////////////////////////////////////////////////////////////////////////////// /// @brief AgencyComm instance ////////////////////////////////////////////////////////////////////////////// AgencyComm _agency; ////////////////////////////////////////////////////////////////////////////// /// @brief condition variable for heartbeat ////////////////////////////////////////////////////////////////////////////// arangodb::basics::ConditionVariable _condition; uint64_t _dispatchedPlanVersion; ////////////////////////////////////////////////////////////////////////////// /// @brief users for these databases will be re-fetched the next time the /// heartbeat thread runs ////////////////////////////////////////////////////////////////////////////// std::unordered_set _refetchUsers; ////////////////////////////////////////////////////////////////////////////// /// @brief this server's id ////////////////////////////////////////////////////////////////////////////// std::string const _myId; ////////////////////////////////////////////////////////////////////////////// /// @brief heartbeat interval ////////////////////////////////////////////////////////////////////////////// uint64_t _interval; ////////////////////////////////////////////////////////////////////////////// /// @brief number of fails in a row before a warning is issued ////////////////////////////////////////////////////////////////////////////// uint64_t _maxFailsBeforeWarning; ////////////////////////////////////////////////////////////////////////////// /// @brief current number of fails in a row ////////////////////////////////////////////////////////////////////////////// uint64_t _numFails; ////////////////////////////////////////////////////////////////////////////// /// @brief current number of dispatched (pending) jobs ////////////////////////////////////////////////////////////////////////////// int64_t _numDispatchedJobs; ////////////////////////////////////////////////////////////////////////////// /// @brief flag, if last dispatched job was successfull ////////////////////////////////////////////////////////////////////////////// bool _lastDispatchedJobResult; ////////////////////////////////////////////////////////////////////////////// /// @brief version of Plan that triggered the last dispatched job ////////////////////////////////////////////////////////////////////////////// uint64_t _versionThatTriggeredLastJob; ////////////////////////////////////////////////////////////////////////////// /// @brief whether or not the thread is ready ////////////////////////////////////////////////////////////////////////////// std::atomic _ready; ////////////////////////////////////////////////////////////////////////////// /// @brief whether or not the heartbeat thread has run at least once /// this is used on the coordinator only ////////////////////////////////////////////////////////////////////////////// static volatile sig_atomic_t HasRunOnce; }; } #endif