New upstream version 8.1.0
This commit is contained in:
184
client_module/source/common/nodes/TargetStateStore.c
Normal file
184
client_module/source/common/nodes/TargetStateStore.c
Normal file
@@ -0,0 +1,184 @@
|
||||
#include "TargetStateStore.h"
|
||||
|
||||
BEEGFS_RBTREE_FUNCTIONS(static, _TargetStateStore, struct TargetStateStore, states,
|
||||
uint16_t,
|
||||
struct TargetStateInfo, targetID, _node,
|
||||
BEEGFS_RB_KEYCMP_LT_INTEGRAL)
|
||||
|
||||
void TargetStateStore_init(TargetStateStore* this)
|
||||
{
|
||||
RWLock_init(&this->rwlock);
|
||||
this->states = RB_ROOT;
|
||||
}
|
||||
|
||||
TargetStateStore* TargetStateStore_construct(void)
|
||||
{
|
||||
TargetStateStore* this = (TargetStateStore*)os_kmalloc(sizeof(*this) );
|
||||
|
||||
if (likely(this) )
|
||||
TargetStateStore_init(this);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
void TargetStateStore_uninit(TargetStateStore* this)
|
||||
{
|
||||
BEEGFS_KFREE_RBTREE(&this->states, struct TargetStateInfo, _node);
|
||||
}
|
||||
|
||||
void TargetStateStore_destruct(TargetStateStore* this)
|
||||
{
|
||||
TargetStateStore_uninit(this);
|
||||
|
||||
kfree(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically update target states and buddy groups together. This is important to avoid races
|
||||
* during a switch (e.g. where an outside viewer could see an offline primary).
|
||||
*
|
||||
* Of course, this implies that states and groups also have to be read atomically together via
|
||||
* getStatesAndGroupsAsLists() through GetStatesAndBuddyGroupsMsg.
|
||||
*/
|
||||
void TargetStateStore_syncStatesAndGroupsFromLists(TargetStateStore* this, Config* config,
|
||||
MirrorBuddyGroupMapper* buddyGroups, struct list_head* states, struct list_head* groups)
|
||||
{
|
||||
RWLock_writeLock(&this->rwlock); // L O C K targetStates
|
||||
RWLock_writeLock(&buddyGroups->rwlock); // L O C K buddyGroups
|
||||
|
||||
__TargetStateStore_syncStatesUnlocked(this, states);
|
||||
|
||||
__MirrorBuddyGroupMapper_syncGroupsUnlocked(buddyGroups, config, groups);
|
||||
|
||||
RWLock_writeUnlock(&buddyGroups->rwlock); // U N L O C K buddyGroups
|
||||
RWLock_writeUnlock(&this->rwlock); // U N L O C K targetStates
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: Caller must hold writelock.
|
||||
*/
|
||||
void __TargetStateStore_syncStatesUnlocked(TargetStateStore* this, struct list_head* states)
|
||||
{
|
||||
struct TargetStateMapping* state;
|
||||
|
||||
// clear existing map
|
||||
BEEGFS_KFREE_RBTREE(&this->states, struct TargetStateInfo, _node);
|
||||
|
||||
list_for_each_entry(state, states, _list)
|
||||
{
|
||||
CombinedTargetState currentState = { state->reachabilityState, state->consistencyState };
|
||||
|
||||
TargetStateInfo* stateInfo = kmalloc(sizeof(TargetStateInfo), GFP_NOFS | __GFP_NOFAIL);
|
||||
|
||||
stateInfo->targetID = state->targetID;
|
||||
stateInfo->state = currentState;
|
||||
|
||||
kfree(_TargetStateStore_insertOrReplace(this, stateInfo));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return pointer to static string (so don't free it)
|
||||
*/
|
||||
const char* TargetStateStore_reachabilityStateToStr(TargetReachabilityState state)
|
||||
{
|
||||
switch(state)
|
||||
{
|
||||
case TargetReachabilityState_ONLINE:
|
||||
return "Online";
|
||||
|
||||
case TargetReachabilityState_POFFLINE:
|
||||
return "Probably-offline";
|
||||
|
||||
case TargetReachabilityState_OFFLINE:
|
||||
return "Offline";
|
||||
|
||||
default:
|
||||
return "<invalid_value>";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return pointer to static string (so don't free it)
|
||||
*/
|
||||
const char* TargetStateStore_consistencyStateToStr(TargetConsistencyState state)
|
||||
{
|
||||
switch(state)
|
||||
{
|
||||
case TargetConsistencyState_GOOD:
|
||||
return "Good";
|
||||
|
||||
case TargetConsistencyState_NEEDS_RESYNC:
|
||||
return "Needs-resync";
|
||||
|
||||
case TargetConsistencyState_BAD:
|
||||
return "Bad";
|
||||
|
||||
default:
|
||||
return "<invalid_value>";
|
||||
}
|
||||
}
|
||||
|
||||
void TargetStateStore_getStatesAsLists(TargetStateStore* this, UInt16List* outTargetIDs,
|
||||
UInt8List* outReachabilityStates, UInt8List* outConsistencyStates)
|
||||
{
|
||||
struct TargetStateInfo* stateInfo;
|
||||
RWLock_readLock(&this->rwlock); // L O C K
|
||||
|
||||
BEEGFS_RBTREE_FOR_EACH_ENTRY(stateInfo, &this->states, _node)
|
||||
{
|
||||
UInt16List_append(outTargetIDs, stateInfo->targetID);
|
||||
UInt8List_append(outReachabilityStates, stateInfo->state.reachabilityState);
|
||||
UInt8List_append(outConsistencyStates, stateInfo->state.consistencyState);
|
||||
}
|
||||
|
||||
RWLock_readUnlock(&this->rwlock); // U N L O C K
|
||||
}
|
||||
|
||||
bool TargetStateStore_setAllStates(TargetStateStore* this, TargetReachabilityState state)
|
||||
{
|
||||
bool res = false;
|
||||
struct TargetStateInfo* stateInfo;
|
||||
|
||||
RWLock_writeLock(&this->rwlock); // L O C K
|
||||
|
||||
BEEGFS_RBTREE_FOR_EACH_ENTRY(stateInfo, &this->states, _node)
|
||||
{
|
||||
if (stateInfo->state.reachabilityState != state)
|
||||
{
|
||||
res = true;
|
||||
stateInfo->state.reachabilityState = state;
|
||||
}
|
||||
}
|
||||
|
||||
RWLock_writeUnlock(&this->rwlock); // U N L O C K
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool TargetStateStore_getState(TargetStateStore* this, uint16_t targetID,
|
||||
CombinedTargetState* state)
|
||||
{
|
||||
TargetStateInfo* stateInfo;
|
||||
bool res;
|
||||
|
||||
RWLock_readLock(&this->rwlock); // L O C K
|
||||
|
||||
stateInfo = _TargetStateStore_find(this, targetID);
|
||||
|
||||
if(likely(stateInfo) )
|
||||
{
|
||||
*state = stateInfo->state;
|
||||
res = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
state->reachabilityState = TargetReachabilityState_OFFLINE;
|
||||
state->consistencyState = TargetConsistencyState_GOOD;
|
||||
res = false;
|
||||
}
|
||||
|
||||
RWLock_readUnlock(&this->rwlock); // U N L O C K
|
||||
|
||||
return res;
|
||||
}
|
||||
Reference in New Issue
Block a user