next up previous contents
Next: 3.2 System booting Up: 3.1 The node interface Previous: 3.1 The node interface

3.1.1 The node navigator

The node navigator gives access to every resource container in the local node.

<Off node navigator. >= (U->)
// A node navigator.
//
class off_NodeNav : public off_Navigator {
private:
  off_Node &n_nd;
  <Other private members of off_NodeNav. >
public:
  // Creates a node navigator. 
  off_NodeNav(off_Node &nd);

  // Returns a reference to the resource being navigated
  virtual off_Resource *get_current(void); 
  
  // Advances the iteration and returns the next element.
  virtual off_CompResource *get_next(void);
  // Resets the iteration so that get_next will return the 1st element.
  virtual void reset(void);
  
  // Selects a component by name.
  virtual off_CompResource *operator[](const char *name);
  virtual off_CompResource *operator[](const off_id_t &id);

  

};

Defines off_NodeNav (links are to index).

<Off node navigator dependencies. >= (U->) [D->]
#include <assert.h>             // for assert
#include <klib/ids.h>           // for off_id_t et al.
#include <klib/CompResource.h>  // for off_CompResource.
#include <klib/nav.h>           // for off_Navigator.
class off_Node;                 // to break circular dependency.

<Off node navigator late dependencies. >= (U->)
#include <node/Node.h>          // for off_Node.

The node navigator is generated dynamically every time it is needed using a simple constructor.

<off_NodeNav::off_NodeNav implementation. >= (U->)
// Creates a node navigator. 
off_NodeNav::off_NodeNav(off_Node &nd) : 
    n_nd(nd),
    <Initialize other aggregate members of off_NodeNav. >
{
  assert(nd.valid());
}

Now we can implement this method:

<Other public methods of off_Node. >+= (<-U) [<-D->]
off_Navigator *get_navigator(void)  { return new off_NodeNav(*this); }

<Off node dependencies. >+= (U->) [<-D->]
#include <klib/nav.h>           // for off_Navigator
#include <node/ndnav.h>         // for off_NodeNav

Besides, this other one is fairly trivial too.

<off_NodeNav::get_current implementation. >= (U->)
// Returns a reference to the resource being navigated
off_Resource *off_NodeNav::get_current(void)
{
  return &n_nd;
}

The key methods are reset and get_next. They use some members to keep the iteration state.

<Other private members of off_NodeNav. >= (<-U)
enum  { 
  N_MBANK=0, 
  N_IOBANK, 
  N_PROC, 
  //  N_DMA, 
  N_SHTL, 
  // N_PRTL, 
  // N_DMM, 
  N_EXHAUST
};
natural_t n_resource;           // resource kind being navigated inside n_nd.
natural_t n_pos;                // resource nb.

boolean_t valid(void) const { 
  return n_resource <= N_EXHAUST;    // It's always >=N_MBANK
} 

<Initialize other aggregate members of off_NodeNav. >= (<-U)
  n_resource(N_MBANK), n_pos(0)

The initial state is recovered by reset.

<off_NodeNav::reset implementation. >= (U->)
// Resets the iteration so that get_next will return the 1st element.
void off_NodeNav::reset(void)
{
  n_resource=N_MBANK;
  n_pos=0;
}

Iteration is advanced by get_next. It advances the iterator using the node navigation methods.

<off_NodeNav::get_next implementation. >= (U->)
// Advances the iteration and returns the next element.
off_CompResource *off_NodeNav::get_next(void)
{
  off_CompResource *res=NULL;
  assert(valid());
  switch(n_resource){
  case N_MBANK:
    if (n_pos==n_nd.get_num_mbanks()){
      n_pos=0; n_resource++;
      res= get_next();
    }
    else {
      res=&n_nd.get_mbank(n_pos++);
      break;
    }
  case N_IOBANK:
    if (n_pos==n_nd.get_num_iobanks()){
      n_pos=0; n_resource++;
      res= get_next();
    }
    else 
      res=&n_nd.get_iobank(n_pos++);
    break;
  case N_PROC:
    if (n_pos==n_nd.get_num_procs()){
      n_pos=0; n_resource++;
      res= get_next();
    }
    else 
      res=&n_nd.get_proc(n_pos++);
    break;
#if 0               // XXX fix this
  case N_DMA:
    if (n_pos==n_nd.get_num_dmas()){
      n_pos=0; n_resource++;
      res= get_next();
    }
    else 
      res=&n_nd.get_dma(n_pos++);
    break;
#endif // 0
  case N_SHTL:
    res=&n_nd.get_shtl();
    n_resource++;
    break;
#if 0
  case N_PRTL:
    res=&n_nd.get_prtl();
    n_resource++;
    break;
  case N_DMM:
    res=&n_nd.get_dmm();
    n_resource++;
    break;
#endif // 0
  case N_EXHAUST:
    break;
  default:
    panic("node nagivator: invalid resource id.");
  }
  return res;
}

<Off node navigator implementation dependencies. >= (U->)
#include <flux/debug.h>         // for otsan et al.

The last couple of iteration methods are implemented with those shown above.

<off_NodeNav::operator[]  implementation. >= (U->) [D->]
// Selects a component by name.
off_CompResource *off_NodeNav::operator[](const char *name)
{
  off_CompResource *res;
  assert(name && valid()); 
  reset();
  while ( (res=get_next()) && strcmp(res->nameof(),name) )
    ;
  return res;
}

<off_NodeNav::operator[]  implementation. >+= (U->) [<-D]
// Selects a component by name.
off_CompResource *off_NodeNav::operator[](const off_id_t &id)
{
  off_CompResource *res;
  assert(valid()); 
  reset();
  while ( (res=get_next()) && res->get_id() != id )
    ;
  return res;
}

\subsection{The node inspector}

The node inspector's attribute array looks like this:

<Off nd inspector attribute array initializer. >= (U->)
{ { OFF_STR_ATTR , "name",     &off_Node::nameof },
 { OFF_STR_ATTR,  "class",    &off_Node::kindof },
 { OFF_ID_ATTR,   "dom",      &off_Node::get_domain },
 { OFF_ID_ATTR,   "id",       &off_Node::get_id },
 { OFF_STR_ATTR,  "url",      &off_Node::get_url },
 { OFF_STR_ATTR,  "provides", &off_Node::nameof },
 { OFF_STR_ATTR,  NULL,       NULL    },    // no requeriments. 
 // Node specific attributes.
 { OFF_STR_ATTR,  "arch",     &off_Node::get_arch  }, // Architecture
 { OFF_STR_ATTR,  "owner",    &off_Node::get_owner }, // Owner's email
 { OFF_STR_ATTR,  "kvers",    &off_Node::get_kvers }, // Kernel version
 { OFF_NULL_ATTR, NULL,       NULL } } // End of attribute list. 

<Off node inspector attribute array length. >= (U->)
const int OFF_NINSP_NATTR=10;   // not counting final NULL attr.

We already knew many node attributes, only accessors for new node attributes must now be implemented.

<Other private members of off_Node. >= (<-U) [D->]
char *n_owner;                  // Node owner.
char *n_url;                    // Source code url

<Other public methods of off_Node. >+= (<-U) [<-D->]
  // Get the node URL architecture and kernel version.
  const char *get_url(void)  {  return n_url; }
  const char *get_arch(void) const { return off_Version::arch; }
  const char *get_kvers(void) const { return off_Version::version; }
  const char *get_owner(void) const { return n_owner; }

<Off node dependencies. >+= (U->) [<-D->]
#include <klib/Version.h>       // for off_Version

The owner's email and source URL are initialized at boot time, when boot time options are processed. Initially they are set to null values.

<Initialize other private members of off_Node. >+= (<-U) [<-D->]
n_owner=n_url=NULL;

Given this attribute list, the node inspector is defined as follows

<Off node inspector. >= (U->)
// A node inspector.
//
class off_NodeInsp : public off_Inspector {
private:
  static off_attr_t n_attrs[OFF_NINSP_NATTR+1]; // for final NULL attr.
public:
  // Creates a node inspector. 
  off_NodeInsp(off_Node *nd); 

};

Defines off_NodeInsp (links are to index).

<Off node navigator dependencies. >+= (U->) [<-D]
#include <assert.h>             // for assert

Where the attribute array is shared.

<Off node inspector static members. >= (U->)
// inspector attributes for node.
off_attr_t off_NodeInsp::n_attrs[OFF_NINSP_NATTR+1] =
               <Off nd inspector attribute array initializer. > 
;

Every time get_inspector is called, a new inspector is created. The user should delete it whenever it is no longer needed.

<Other public methods of off_Node. >+= (<-U) [<-D->]
off_Inspector *get_inspector(void)  { 
 return new off_NodeInsp(this);
}

The constructor is very simple.

<off_NodeInsp::off_NodeInsp implementation. >= (U->)
// Creates a node inspector. 
off_NodeInsp::off_NodeInsp(off_Node *nd) : 
  off_Inspector(nd, n_attrs, OFF_NINSP_NATTR)
{
  assert(nd && nd->valid()); 
}

\subsection{Node navigation \cpp{} source files}

The navigation code for nodes is kept in node/ndnav.h and node/ndnav.C.

<ndnav.h*>=
<Read the literate code instead warning. >
#ifndef __OFF_NODE_NAV_H
#define __OFF_NODE_NAV_H 1

<Off node navigator dependencies. >

<Off node inspector attribute array length. >
#ifdef __KERNEL__
<Off node navigator. >
<Off node inspector. >
#endif // __KERNEL__

<Off node navigator late dependencies. >

#endif // __OFF_NODE_NAV_H

<ndnav.C*>=
<Read the literate code instead warning. >

#include <node/ndnav.h>         // Exported interface.
<Off node navigator implementation dependencies. >

<Off node inspector static members. >

<off_NodeNav::off_NodeNav implementation. >
<off_NodeInsp::off_NodeInsp implementation. >
<off_NodeNav::get_current implementation. >
<off_NodeNav::reset implementation. >
<off_NodeNav::get_next implementation. >
<off_NodeNav::operator[]  implementation. >

\section{Nodes for plain users}

The wrapper for node services export almost everything as can be seen.

<Off node for users. >= (U->)
// A Node for system users.
//
ENTRY class off_uNode : public off_uResource{
public:

#if 0               // XXX fix this
  off_prtl_id_t get_auth(const off_Rights &r) const;
  off_prtl_id_t get_xdt(const off_Rights &r)  const;
  err_t      set_auth(const off_prtl_id_t p, const off_Rights &r);
  err_t      set_xdt(const off_prtl_id_t  p, const off_Rights &r);
  void       halt( const char *msg );
  void       reboot( const off_Rights &r );
  err_t      suspend( const off_Rights &r );

  // Returns the number of specific containers found at this node
  natural_t get_num_mbanks(const off_Rights &r) const ;
  // Returns a pointer to a local memory bank. 
  off_MBank   &get_mbank( natural_t id = 0, const off_Rights &r);
  // Return the number of specific containers found at this node
  // Get a pointer to a hardware resource container
  natural_t get_num_iobanks(const off_Rights &r) const;
  off_IOBank  &get_iobank( natural_t id=0, const off_Rights &r);
  natural_t get_num_dmas(const off_Rights &r)               const ;
  off_DMA     &get_dma( natural_t id=0, const off_Rights &r);
  natural_t get_num_procs(const off_Rights &r)  const;

  off_Processor &get_proc( natural_t id=0, const off_Rights &r);
  off_ShtlSrv &get_shtl( const off_Rights &r);
  off_PrtlSrv &get_prtl( const off_Rights &r);
  off_DMM     &get_dmm( const off_Rights &r);

  <Other public methods of off_uNode. >
#endif  
};

Defines off_uNode (links are to index).

\section{Node \cpp{} source files}

Main node definitions are found in node/Node.h. The implementation is kept in node/Node.C.

<Node.h*>=
<Read the literate code instead warning. >

#ifndef __OFF_NODE_H
#define __OFF_NODE_H 1

<Off node dependencies. >

#ifdef __KERNEL__
<Off node. >
<Off node exported variables. >
#else  // __KERNEL__
<Off node for users. >
#endif // __KERNEL__

#endif // __OFF_NODE_H

<Node.C*>=
<Read the literate code instead warning. >
#define __OFF_NODE_C
#include <node/Node.h>      // Exported interface.
<Off node implementation dependencies. >

<Off node global variables. >

<off_Node::halt implementation. >
<off_Node::reboot implementation. >
<off_Node::suspend implementation. >

<Implementation of other methods of off_Node. >


next up previous contents
Next: 3.2 System booting Up: 3.1 The node interface Previous: 3.1 The node interface
Francisco J. Ballesteros
1998-05-25