0523 core: import NSS cache bond runtime base
This commit is contained in:
@@ -144,6 +144,7 @@ add_library(nwcore SHARED
|
||||
library/os/config.c
|
||||
nss/cache/control.c
|
||||
nss/cache/asyncio.c
|
||||
nss/cache/bond.c
|
||||
library/fsm/fsmnw.c
|
||||
library/latch/intlatch.c
|
||||
library/latch/latch.c
|
||||
|
||||
362
src/core/nss/cache/bond.c
vendored
Normal file
362
src/core/nss/cache/bond.c
vendored
Normal file
@@ -0,0 +1,362 @@
|
||||
/****************************************************************************
|
||||
|
|
||||
| (C) Copyright 1985, 1991, 1993, 1996 Novell, Inc.
|
||||
| All Rights Reserved.
|
||||
|
|
||||
| This program is free software; you can redistribute it and/or
|
||||
| modify it under the terms of version 2 of the GNU General Public
|
||||
| License as published by the Free Software Foundation.
|
||||
|
|
||||
| This program 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 General Public License for more details.
|
||||
|
|
||||
| You should have received a copy of the GNU General Public License
|
||||
| along with this program; if not, contact Novell, Inc.
|
||||
|
|
||||
| To contact Novell about this file by physical or electronic mail,
|
||||
| you may find current contact information at www.novell.com
|
||||
|
|
||||
|***************************************************************************
|
||||
|
|
||||
| NetWare Advance File Services (NSS) module
|
||||
|
|
||||
|---------------------------------------------------------------------------
|
||||
|
|
||||
| $Author: vandana $
|
||||
| $Date: 2005-08-10 01:03:51 +0530 (Wed, 10 Aug 2005) $
|
||||
|
|
||||
| $RCSfile$
|
||||
| $Revision: 1177 $
|
||||
|
|
||||
|---------------------------------------------------------------------------
|
||||
| This module is used to:
|
||||
+-------------------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <internal/nCache.h>
|
||||
#include <internal/pssConfig.h>
|
||||
|
||||
ControlStore_s BondControl; /* Structure for Controlling allocation and
|
||||
* tracking of bond strucutures.
|
||||
*/
|
||||
|
||||
STATUS BOND_Startup (void)
|
||||
{
|
||||
STATUS status;
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
status = CONTROL_Startup( &BondControl, Config.cache.numBonds,
|
||||
sizeof(Bond_s), NULL);
|
||||
return status;
|
||||
}
|
||||
|
||||
void BOND_Shutdown (void)
|
||||
{
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
CONTROL_Shutdown( &BondControl);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Agent 'toSignal' is dependent on 'toFlush' occuring(written) first. So
|
||||
* a good way to remember the relationships recorded by this function is
|
||||
* that AGENT
|
||||
* 'toFlush' will occur 1st.
|
||||
* 'toSignal' will occur 2nd.
|
||||
*
|
||||
* Agent 'toSignal' gets placed on the signal list of agent 'toFlush'. I.E.
|
||||
* when 'toFlush' occurs then 'toSignal' Agent gets signaled.
|
||||
*
|
||||
* Agent 'toFlush' gets placed on the flush list of the agent 'toSignal'. I.E.
|
||||
* if agent 'toSignal' needs to be flushed, "toSignal's" flush list is used
|
||||
* to find and then tell 'toFlush' that it should flush.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
void LB_bind (Agent_s *toSignal, Agent_s *toFlush)
|
||||
{
|
||||
Bond_s *bond;
|
||||
|
||||
ENTER(TBOND, bind);
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
|
||||
bond = GET_BOND();
|
||||
|
||||
zASSERT(bond != NULL);
|
||||
|
||||
SETUP_BOND(bond, toSignal, toFlush);
|
||||
|
||||
RTN_VOID();
|
||||
}
|
||||
|
||||
|
||||
///**************************************************************************
|
||||
// *
|
||||
// ***************************************************************************/
|
||||
//void initBind (Bond_s *bond, Agent_s *toSignal, Agent_s *toFlush)
|
||||
//{
|
||||
// zASSERT(bond != NULL);
|
||||
//
|
||||
// bond->toSignal = toSignal;
|
||||
// bond->toFlush = toFlush;
|
||||
// STK_PUSH(toFlush->signalList, bond, signalLink);
|
||||
// DQ_ENQ( &toSignal->flushList, bond, flushLink);
|
||||
//}
|
||||
|
||||
/**************************************************************************
|
||||
* Release the BOND and put it back on the AVAIL list
|
||||
***************************************************************************/
|
||||
void freeBond (Bond_s *bond)
|
||||
{
|
||||
ENTER(TBOND, freeBond);
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
zASSERT(!QMEMBER( &bond->signalLink));
|
||||
zASSERT(!QMEMBER( &bond->flushLink));
|
||||
// zASSERT((bond->toFlush == NULL) || DQ_EMPTY( &bond->toFlush->flushList));
|
||||
// zASSERT((bond->toFlush == NULL) || (bond->toFlush->numLeft == 0));
|
||||
|
||||
CONTROL_FREE(bond);
|
||||
RTN_VOID();
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
***************************************************************************/
|
||||
void initAgent (
|
||||
Agent_s *agent,
|
||||
AgentSignalFunc_t signal,
|
||||
char *name)
|
||||
{
|
||||
static int instance = 0;
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
zASSERT(agent != NULL);
|
||||
|
||||
++instance;
|
||||
FSMLITE_INIT( &agent->fsm, name, instance);
|
||||
INIT_LATCH( &agent->latch);
|
||||
INIT_ONESHOT(agent->timer);
|
||||
STK_INIT(agent->signalList);
|
||||
DQ_INIT( &agent->flushList);
|
||||
agent->signal = (signal) ? signal : defaultSignal;
|
||||
agent->numLeft = 0;
|
||||
agent->state = 0;
|
||||
agent->status = zOK;
|
||||
agent->bondFreedSignal = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* This is called when a signal handler finishes writing the requested
|
||||
* item. This propogates the signals back up through the bond that the
|
||||
* request has completed.
|
||||
***************************************************************************/
|
||||
void LB_defaultSignal(Agent_s *agent)
|
||||
{
|
||||
Bond_s *next;
|
||||
Agent_s *toSignal;
|
||||
|
||||
ENTER(TBOND, defaultSignal);
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
zASSERT(agent->state & AGENT_FLUSHING);
|
||||
// I'm removing the NO_BONDS assert, because if the agent is a beast then,
|
||||
// it is possible that we are doing a cacheFlushMyCacheBufs (which will be
|
||||
// followed by a defaultFlush), and new bonds are being put on the beast.
|
||||
// The defaultFlush that will happen after will take care of the new
|
||||
// bonds. We could get around this whole thing by X_LATCHING the beast
|
||||
// while in cacheFlushMyCacheBufs. But at this point we do not want to
|
||||
// take the risk of making that change. Vandana - 11/21/00
|
||||
// zASSERT(NO_BONDS(agent));
|
||||
ASSERT_SLATCH(&agent->latch);
|
||||
|
||||
STK_POP(agent->signalList, next, Bond_s, signalLink);
|
||||
while (next != NULL)
|
||||
{
|
||||
toSignal = next->toSignal;
|
||||
if (QMEMBER( &next->flushLink))
|
||||
{
|
||||
DQ_RMV(next, flushLink);
|
||||
}
|
||||
else
|
||||
{
|
||||
zASSERT(toSignal->numLeft != 0);
|
||||
--toSignal->numLeft;
|
||||
}
|
||||
if ((toSignal->state & AGENT_FLUSHING)
|
||||
&& (toSignal->state & AGENT_AWAIT_SIGNALS)
|
||||
&& (NO_BONDS(toSignal)))
|
||||
{
|
||||
toSignal->state &= ~AGENT_AWAIT_SIGNALS;
|
||||
toSignal->signal(toSignal);
|
||||
}
|
||||
if (toSignal->bondFreedSignal != NULL)
|
||||
{
|
||||
toSignal->bondFreedSignal(toSignal);
|
||||
}
|
||||
freeBond(next);
|
||||
STK_POP(agent->signalList, next, Bond_s, signalLink);
|
||||
}
|
||||
agent->state &= ~AGENT_FLUSHING;
|
||||
UNS_LATCH( &agent->latch);
|
||||
RTN_VOID();
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* This is called to continue the default flush request.
|
||||
***************************************************************************/
|
||||
void LB_continueFlush (FsmLite_s *fsm)
|
||||
{
|
||||
Agent_s *agent = STRUCT(fsm, Agent_s, fsm);
|
||||
Agent_s *toFlush;
|
||||
Bond_s *next;
|
||||
|
||||
ENTER(TBOND, continueFlush);
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
if (NO_BONDS(agent))
|
||||
{
|
||||
agent->signal(agent);
|
||||
}
|
||||
else
|
||||
{
|
||||
agent->state |= AGENT_AWAIT_SIGNALS;
|
||||
DQ_DEQ( &agent->flushList, next, Bond_s, flushLink);
|
||||
while (next != NULL)
|
||||
{
|
||||
toFlush = next->toFlush;
|
||||
++agent->numLeft;
|
||||
defaultFlush(toFlush);
|
||||
DQ_DEQ( &agent->flushList, next, Bond_s, flushLink);
|
||||
}
|
||||
}
|
||||
RTN_VOID();
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* This routine is called when you want to write anything to the disk.
|
||||
* It handles buffers, beasts, volumes, etc. This is an asyncrounous
|
||||
* request and will return when all the appropriate items are queued.
|
||||
* This propogates all of the flush request appropriatly through any
|
||||
* dependent bonds.
|
||||
***************************************************************************/
|
||||
void LB_defaultFlush (Agent_s *agent)
|
||||
{
|
||||
ENTER(TBOND, defaultFlush);
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
CANCEL_ALARM(agent->timer);
|
||||
|
||||
if (!(agent->state & AGENT_FLUSHING))
|
||||
{
|
||||
agent->state |= AGENT_FLUSHING;
|
||||
/* We aquire this latch so that we can wait for this operation
|
||||
* to complete. See defaultFlushWait
|
||||
*/
|
||||
FSM_S_LATCH( &agent->latch, &agent->fsm, LB_continueFlush);
|
||||
}
|
||||
RTN_VOID();
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* This will flush and then wait for it to finish.
|
||||
***************************************************************************/
|
||||
void LB_defaultFlushWait (Agent_s *agent)
|
||||
{
|
||||
ENTER(TBOND, defaultFlushWait);
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
defaultFlush(agent);
|
||||
X_BARRIER( &agent->latch);
|
||||
RTN_VOID();
|
||||
}
|
||||
|
||||
/*
|
||||
* Lazy flush sets up the agent to signal up the dependancy when
|
||||
* all of its dependancies have been flushed but it doesn't force
|
||||
* them.
|
||||
*/
|
||||
void LB_lazyFlush (Agent_s *agent)
|
||||
{
|
||||
if (NO_BONDS(agent))
|
||||
{ /*
|
||||
* We don't need to wait for anything else to finish, so
|
||||
* clean ourself up.
|
||||
*/
|
||||
defaultFlush(agent);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_NOLATCH( &agent->latch);
|
||||
agent->state |= (AGENT_FLUSHING | AGENT_AWAIT_SIGNALS);
|
||||
S_FORCE( &agent->latch);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if NSS_DEBUG IS_ENABLED && 0
|
||||
/*=========================================================================
|
||||
*=========================================================================
|
||||
* DEBUG CODE
|
||||
*=========================================================================
|
||||
*=========================================================================*/
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
***************************************************************************/
|
||||
void prDepth (NINT depth)
|
||||
{
|
||||
NINT i;
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
for (i = 0; i < depth; ++i)
|
||||
{
|
||||
printf(MSGNot(" "));
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
***************************************************************************/
|
||||
void prSignals (Agent_s *agent, NINT depth)
|
||||
{
|
||||
Bond_s *next;
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
prDepth(depth++);
|
||||
printf(MSGNot("signals=%s[%d]\n"), agent->fsm.type, agent->numLeft);
|
||||
STK_FOREACH(agent->signalList, next, Bond_s, signalLink)
|
||||
{
|
||||
prSignals(next->toSignal, depth);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
***************************************************************************/
|
||||
void prFlushes (Agent_s *agent, NINT depth)
|
||||
{
|
||||
Bond_s *next;
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
prDepth(depth++);
|
||||
printf(MSGNot("flushes=%s[%d]\n"), agent->fsm.type, agent->numLeft);
|
||||
DQ_FOREACH( &agent->flushList, next, Bond_s, flushLink)
|
||||
{
|
||||
prFlushes(next->toFlush, depth);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
***************************************************************************/
|
||||
void prBondControl (Agent_s *agent)
|
||||
{
|
||||
Bond_s *next;
|
||||
ASSERT_MPKNSS_LOCK();
|
||||
printf(MSGNot("agent=%s[%d]\n"), agent->fsm.type, agent->numLeft);
|
||||
STK_FOREACH(agent->signalList, next, Bond_s, signalLink)
|
||||
{
|
||||
printf(MSGNot("\tsignal=%s\n"), next->toSignal->fsm.type);
|
||||
}
|
||||
DQ_FOREACH( &agent->flushList, next, Bond_s, flushLink)
|
||||
{
|
||||
printf(MSGNot("\tflush=%s\n"), next->toFlush->fsm.type);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -28,6 +28,7 @@ if(MARS_NWE_BUILD_NWFS_TESTS)
|
||||
add_subdirectory(core/alarm)
|
||||
add_subdirectory(core/control)
|
||||
add_subdirectory(core/asyncio)
|
||||
add_subdirectory(core/bond)
|
||||
add_subdirectory(core/config)
|
||||
add_subdirectory(core/parse)
|
||||
add_subdirectory(core/fsm)
|
||||
|
||||
@@ -14,6 +14,7 @@ add_subdirectory(worktodo)
|
||||
add_subdirectory(alarm)
|
||||
add_subdirectory(control)
|
||||
add_subdirectory(asyncio)
|
||||
add_subdirectory(bond)
|
||||
add_subdirectory(config)
|
||||
add_subdirectory(parse)
|
||||
add_subdirectory(fsm)
|
||||
|
||||
3
tests/core/bond/CMakeLists.txt
Normal file
3
tests/core/bond/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
add_executable(test_nwcore_bond test_nwcore_bond.c)
|
||||
target_link_libraries(test_nwcore_bond PRIVATE mars_nwe::core)
|
||||
add_test(NAME nwcore.bond COMMAND test_nwcore_bond)
|
||||
54
tests/core/bond/test_nwcore_bond.c
Normal file
54
tests/core/bond/test_nwcore_bond.c
Normal file
@@ -0,0 +1,54 @@
|
||||
#include <include/xCache.h>
|
||||
#include <include/pssmpk.h>
|
||||
#include <internal/pssConfig.h>
|
||||
#include <internal/nCache.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define CHECK(expr) do { \
|
||||
if (!(expr)) { \
|
||||
fprintf(stderr, "CHECK failed: %s:%d: %s\n", __FILE__, __LINE__, #expr); \
|
||||
return 1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
extern void fsmWorkToDo(void);
|
||||
|
||||
static int signal_count;
|
||||
|
||||
static void test_signal(Agent_s *agent)
|
||||
{
|
||||
++signal_count;
|
||||
LB_defaultSignal(agent);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Agent_s to_signal;
|
||||
Agent_s to_flush;
|
||||
|
||||
configStartup();
|
||||
|
||||
MPKNSS_LOCK();
|
||||
CHECK(BOND_Startup() == zOK);
|
||||
|
||||
initAgent(&to_signal, test_signal, "to_signal");
|
||||
initAgent(&to_flush, NULL, "to_flush");
|
||||
|
||||
CHECK(NO_BONDS(&to_signal));
|
||||
CHECK(NO_SIGNALS(&to_flush));
|
||||
|
||||
LB_bind(&to_signal, &to_flush);
|
||||
CHECK(!NO_BONDS(&to_signal));
|
||||
CHECK(!NO_SIGNALS(&to_flush));
|
||||
|
||||
LB_defaultFlush(&to_signal);
|
||||
fsmWorkToDo();
|
||||
CHECK(NO_BONDS(&to_signal));
|
||||
CHECK(NO_SIGNALS(&to_flush));
|
||||
CHECK(signal_count == 1);
|
||||
|
||||
BOND_Shutdown();
|
||||
MPKNSS_UNLOCK();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user