1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-01-11 05:17:41 +03:00
one/include/ZoneServer.h
2017-04-25 17:15:31 +02:00

395 lines
9.1 KiB
C++

/* -------------------------------------------------------------------------- */
/* 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 <queue>
#include <set>
#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++;
}
/**
* Increase the term for this server
*/
void inc_term()
{
term++;
}
/**
* Increase the term for this server
*/
void inc_applied()
{
applied++;
}
void set_commit(unsigned int _c)
{
commit = _c;
}
/**
* 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<VectorAttribute *> 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<ZoneServer *>(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<ZoneServer *>(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<ZoneServer *>(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_*/