/* -------------------------------------------------------------------------- */ /* Copyright 2002-2016, OpenNebula Project, OpenNebula Systems */ /* */ /* 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 ZONE_SERVER_H_ #define ZONE_SERVER_H_ #include #include #include "ExtendedAttribute.h" class LogDBManager; /** * The VirtualMachine DISK attribute */ class ZoneServer : public ExtendedAttribute { public: enum State { OFFLINE = 0, CANDIDATE = 1, FOLLOWER = 2, LEADER = 3 }; ZoneServer(VectorAttribute *va, int id):ExtendedAttribute(va, id), state(FOLLOWER), dbm(0){}; virtual ~ZoneServer(){}; /** * Initialized server metadata: * - NAME * - ENDPOINT * @param error string if any * @return -1 if server data could not be initialized, 0 on success */ int init(string& error) { if ( vector_value("NAME").empty() ) { error = "Missing NAME in SERVER"; return -1; } if ( vector_value("ENDPOINT").empty() ) { error = "Missing ENDPOINT in SERVER"; return -1; } return 0; } //-------------------------------------------------------------------------- // Server attributes //-------------------------------------------------------------------------- /** * @return the ID of the server */ int get_id() const { return ExtendedAttribute::get_id(); } int get_term() const { return term; } /** * @return highest log known to be commited */ int get_commit() const { return commit; } /** * @return highest log applied to DB */ int get_applied() const { return applied; } /** * @return next log to send to this server */ int get_next() const { return next; } /** * @return highest log replicated in this server */ int get_match() const { return match; } /** * Initialized follower data * @param last log index */ void init_follower(unsigned int last) { next = last + 1; match = 0; } /** * @return true if the server is offline */ bool is_offline() { return state == OFFLINE; } /** * @return true if the server is the leader of the zone */ bool is_leader() { return state == LEADER; } /** * Decrease the next log entry to send to this follower */ void dec_next() { next--; } /** * Increase the next log entry to send to this follower */ void inc_next() { next++; } /** * Set the the index of the highest log entry on this follower */ void set_match(unsigned int _match) { match = _match; } /** * Set the state for this follower */ void set_state(State s) { state = s; } //-------------------------------------------------------------------------- // LogDBManager interface //-------------------------------------------------------------------------- /** * Start the LogDB manager and associated replica threads for followers * @param 0 on success */ int logdbm_start(); /** * Stop the LogDB manager and threads * @param 0 on success */ void logdbm_stop(); /** * Start replica threads for new servers in zone */ void logdbm_addserver(); /** * Start replication of a new log entry on followers */ void logdbm_replicate(); private: State state; /** * Current term */ unsigned int term; //-------------------------------------------------------------------------- // Volatile log index variables // - commit, highest log known to be commited // - applied, highest log applied to DB // //---------------------------- LEADER VARIABLES ---------------------------- // // - next, next log to send to this server // - match, highest log replicated in this server // ------------------------------------------------------------------------- unsigned int commit; unsigned int applied; unsigned int next; unsigned int match; /** * Replication Manager for this server (only started in self) */ LogDBManager * dbm; }; /** * Set of Zone servers */ class ZoneServers : public ExtendedAttributeSet { public: /* ---------------------------------------------------------------------- */ /* Constructor and Initialization functions */ /* ---------------------------------------------------------------------- */ /** * Creates the ZoneServers set from a zone template with SERVER=[...] * attributes * @param tmpl template with SERVER */ ZoneServers(Template * tmpl):ExtendedAttributeSet(false), next_id(-1) { std::vector vas; tmpl->get(SERVER_NAME, vas); init_attribute_map(SERVER_ID_NAME, vas); for ( zone_iterator it = begin() ; it != end() ; ++it ) { string error; int i = (*it)->get_id(); if ( i > next_id ) { next_id = i; } (*it)->init(error); } next_id += 1; }; /** * Creates an empty zone server set */ ZoneServers():ExtendedAttributeSet(false){}; virtual ~ZoneServers(){}; /* ---------------------------------------------------------------------- */ /* Iterators */ /* ---------------------------------------------------------------------- */ class ZoneIterator : public AttributeIterator { public: ZoneIterator():AttributeIterator(){}; ZoneIterator(const AttributeIterator& dit):AttributeIterator(dit){}; virtual ~ZoneIterator(){}; ZoneServer * operator*() const { return static_cast(map_it->second); } }; ZoneIterator begin() { ZoneIterator it(ExtendedAttributeSet::begin()); return it; } ZoneIterator end() { ZoneIterator it(ExtendedAttributeSet::end()); return it; } typedef class ZoneIterator zone_iterator; /* ---------------------------------------------------------------------- */ /* ZoneServer interface */ /* ---------------------------------------------------------------------- */ /** * Returns the SERVER attribute for a zone server * @param disk_id of the DISK * @return pointer to the attribute ir null if not found */ ZoneServer * get_server(int id) const { return static_cast(get_attribute(id)); } int add_server(VectorAttribute * va, string& error) { ZoneServer * server = new ZoneServer(va, next_id); if ( server->init(error) != 0 ) { delete server; return -1; } va->replace(SERVER_ID_NAME, next_id); add_attribute(server, next_id); next_id += 1; return 0; }; ZoneServer * delete_server(int id) { return static_cast(delete_attribute(id)); }; /** * @return servers in zone */ unsigned int size() { return ExtendedAttributeSet::size(); } protected: ExtendedAttribute * attribute_factory(VectorAttribute * va, int id) const { return new ZoneServer(va, id); }; private: friend class Zone; static const char * SERVER_NAME; //"SERVER" static const char * SERVER_ID_NAME; //"ID" int next_id; }; #endif /*ZONE_SERVER_H_*/