0523 core: import NSS cache bond runtime base

This commit is contained in:
Mario Fetka
2026-06-14 09:13:02 +00:00
parent 77d4e1df7b
commit 8aeaf8b0fe
6 changed files with 422 additions and 0 deletions

View File

@@ -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
View 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

View File

@@ -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)

View File

@@ -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)

View 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)

View 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;
}