next up previous contents
Next: 2.4.5.1 Navigation C++ source Up: 2.4 System resources Previous: 2.4.4 Freezing resources

   
2.4.5 Architecture awareness support

Each resource will be wrapped with a Navigator and an Inspector. This way, the OS built on top of the kernel will be able to transparently navigate through its components and later on ask about resource attributes (e.g. bandwidth, persistence, etc.),

The class hierarchies of Navigators and Inspectors mimic that of Resource, thus we omit them by now.

Every resource will include two methods, get_navigator and get_inspector, to provide a pointer to its specific navigator and inspector. Both of them will be friends of the object considered and will be able to access its state in order to support their services.

<Other public methods of off_Resource. >+= (<-U) [<-D]
// Returns the navigator for the resource.
virtual off_Navigator *get_navigator(void) const { return NULL; }
// Returns the inspector for the resource.
virtual off_Inspector *get_inspector(void) const { return NULL; }

By enquiring the navigator, references to other system resources may be obtained and get_navigator or get_inspector may be used again.

The scheme works as shown in the example of the figure [*]:

1.
The user has a reference to a memory bank.
2.
Using get_navigator, a reference to its navigator is obtained. This navigator implements the Navigator interface.
3.
Browsing with the navigator, a page frame is located \item Its method get_inspector is used to obtain a reference to an object implementing the Inspector interface. A common protocol can be used now to find out about the page frame persistence, size, etc.

Of course, both get_navigator and get_inspector are exported to system users.

<Other public methods of off_uResource. >+= (<-U) [<-D]
off_Navigator *get_navigator(const off_Rights &r ) const;
off_Inspector *get_inspector(const off_Rights &r ) const;

Resources now depend on the Navigator class.

<Off resource dependencies. >+= (<-U) [<-D]
#include <klib/nav.h>

However, navigators and inspectors use the resource class. To circumvent the circular reference we will use this dependency

<Off resource navigator dependencies. >= (U->) [D->]
class off_Resource;     // to break circular dependency. 

after declaring Navigator and Inspector classes, we will import resource definitions.

<Off resource navigator late dependencies. >= (U->)
#include <klib/Resource.h>

A Navigator provides methods to select and lookup components.

  
Figure 2.5: Architecture awareness support: Navigators and Inspectors.

<Off resource navigator. >= (U->)
// A resource navigator
//
class off_Navigator {
public: 
   // Returns a reference to the resource being navigated
   virtual off_Resource *get_current(void)=0;

   // Advances the iteration and returns the next element.
   virtual off_Resource *get_next(void)=0;
   // Resets the iteration so that get_next will return the 1st element.
   virtual void reset(void)=0;

   // Select a component by name or id.
   virtual off_Resource *operator[](const char *name)=0;
   virtual off_Resource *operator[](const off_id_t &id)=0;
}; 

Defines off_Navigator (links are to index).

An Inspector has two main methods to lookup attributes either by name or by index. Attribute indexes will vary from 0 to some arbitrary value. The first invalid attribute is guaranteed to have a NULL name and type.

To avoid usage of void *, users are requested to specify the expected type of an attribute. As it is unrealistic to force users to know in advance which attributes can be present, a method nameof is provided to obtain the name of a given attribute, and a method kindof is provided to obtain its type.

<Off resource inspector. >= (U->)
// A resource inspector
//
class off_Inspector {
private:
   <Other private members of off_Inspector. >
protected:
   <Other protected methods of off_Inspector. >
public:
   <Other public methods of off_Inspector. >
   // Returns  the name of an attribute at [idx]
   virtual const char *nameof(natural_t idx) const; 
   // Returns the type of an attribute
   virtual off_attr_kind_t kindof(natural_t idx) const;
   // Returns the # of attributes.
   virtual natural_t length(void) const;

   // Look up a boolean attribute by name or by index
   virtual boolean_t get_bool_attr(const char *name)     const;
   virtual boolean_t get_bool_attr(natural_t idx)  const;

   // Look up a natural attribute by name or by index
   virtual natural_t get_nat_attr(const char *name)      const;
   virtual natural_t get_nat_attr(natural_t idx)   const;

   // Look up a string attribute by name or by index
   virtual char *get_str_attr(const char *name)          const;
   virtual char *get_str_attr(natural_t idx)       const;

   // Look up an id attribute by name or by index
   virtual off_id_t get_id_attr(const char *name)  const;
   virtual off_id_t get_id_attr(natural_t idx) const;

  
};

Defines off_Inspector (links are to index).

<Off resource navigator dependencies. >+= (U->) [<-D->]
#include <flux/types.h>         // for boolean_t natural_t et al.
#include <klib/ids.h>           // for off_id_t

The default implementation is to ignore the arguments and return a silly value, so that such function could be ignored: not every resource has attributes of every type. Thus, only nameof, kindof and one of the for previous pairs of methods must be provided by any subclass.

The valid attribute types are

<Off attribute type ids. >= (U->)
// Kinds of attribute.
enum  { OFF_NULL_ATTR,// Not an attribute.
        OFF_BOOL_ATTR,// boolean_t
        OFF_NAT_ATTR, // natural_t
        OFF_STR_ATTR, // char * (null terminated).
        OFF_ID_ATTR   // off_id_t
};
typedef int off_attr_kind_t;

Defines off_attr_kind_t, OFF_BOOL_ATTR, OFF_ID_ATTR, OFF_NAT_ATTR, OFF_STR_ATTR (links are to index).

Finally, any resource should have at least these attributes defined

<Off attributes. >= (U->)
// attributes that should be defined by every system resource.
//
enum { OFF_ATTR_NAME,      // Name of this resource   (string)
       OFF_ATTR_CLASS,     // Class for this resource (string)
       OFF_ATTR_DOM,       // Resource domain  (id)
       OFF_ATTR_ID,        // Resource id (or container id when offset is 0) 
       OFF_ATTR_URL,       // URL for the resource literate source code
                           //  (string)
       <Other Off resource attributes. >
  };

Defines OFF_ATTR_CLASS, OFF_ATTR_DOM, OFF_ATTR_ID, OFF_ATTR_NAME, OFF_ATTR_NULL, OFF_ATTR_OFFSET, OFF_ATTR_URL (links are to index).

Besides, those resources representing system servers or system services which are independent entities should at least support this two attributes, so that an automatic configuration engine could be used.

<Other Off resource attributes. >= (<-U)
OFF_ATTR_PROVIDES,              // Resource provided  (string w/o blanks).
OFF_ATTR_REQUIRES               // Resources required (string)

The first one is an identifier used to name the resource being provided. Each resource provider may depend on other resources to provide its service. The second attribute is a string containing the identifiers (names) of the resources required (separated by blanks).

Navigators are implemented almost by hand by subclasses of Navigators, but inspectors are very similar one to another and most of their implementation is contained in Inspector.

An inspector keeps an array of attributes indexed by attribute id and a pointer to the resource being inspected.

<Other private members of off_Inspector. >= (U->)
off_Resource *i_res;            // Resource being inspected
const off_attr_t *i_attr;       // Attribute list.
const natural_t  i_nattrs;      // # of attributes.

Attributes must be any of these defined below.

<Off attribute data type. >= (U->)
union off_attr_val_t {
  boolean_t (off_Resource::*b)(void);
  natural_t (off_Resource::*n)(void);
  char     *(off_Resource::*s)(void);
  off_id_t  (off_Resource::*i)(void);
  off_attr_val_t(boolean_t (off_Resource::*ab)(void)) : b(ab) {};
  off_attr_val_t(natural_t (off_Resource::*an)(void)) : n(an) {};
  off_attr_val_t(char *(off_Resource::*as)(void)) : s(as) {};
  off_attr_val_t(off_id_t (off_Resource::*ai)(void)) : i(ai) {};
}; 
struct off_attr_t {
  off_attr_kind_t a_kind;       // kind of attribute.
  char           *a_name;       // Attribute name.
  off_attr_val_t  a_val;        // Ptr. to function giving attribute's value.
};
Defines off_attr_t (links are to index).

The inspector constructor only needs to receive the attribute array and a pointer to the object being inspected.

<Other public methods of off_Inspector. >= (U->)
off_Inspector(off_Resource *r, const off_attr_t *attrs,natural_t nattrs):
  i_res(r),i_attr(attrs), i_nattrs(nattrs) 
{}

Once the array is set, inspector methods are straightforward to implement.

<off_Inspector::nameof implementation. >= (U->)
const char *off_Inspector::nameof(natural_t idx) const
{
   
  return (idx >= i_nattrs) ? (char*)NULL : i_attr[idx].a_name;
}

<off_Inspector::kindof implementation. >= (U->)
off_attr_kind_t off_Inspector::kindof(natural_t idx) const
{
  return (idx >= i_nattrs) ? OFF_NULL_ATTR : i_attr[idx].a_kind;

}

<off_Inspector::length implementation. >= (U->)
natural_t off_Inspector::length(void) const
{
  return i_nattrs;
}

<off_Inspector::get_bool_attr implementation. >= (U->)
boolean_t off_Inspector::get_bool_attr(natural_t idx) const
{
  if (idx <= i_nattrs && kindof(idx)==OFF_BOOL_ATTR)
    return (i_res->*i_attr[idx].a_val.b)();
  else
    return FALSE;
}

<off_Inspector::get_nat_attr implementation. >= (U->)
natural_t off_Inspector::get_nat_attr(natural_t idx) const
{
  if (idx <= i_nattrs && kindof(idx)==OFF_NAT_ATTR)
    return (i_res->*i_attr[idx].a_val.n)();
  else
    return 0;
}

<off_Inspector::get_str_attr implementation. >= (U->)
char *off_Inspector::get_str_attr(natural_t idx) const
{
  if (idx <= i_nattrs && kindof(idx)==OFF_STR_ATTR)
    return (i_res->*i_attr[idx].a_val.s)();
  else
    return NULL;
}

<off_Inspector::get_id_attr implementation. >= (U->)
off_id_t off_Inspector::get_id_attr(natural_t idx) const
{
  if (idx <= i_nattrs && kindof(idx)==OFF_ID_ATTR)
    return (i_res->*i_attr[idx].a_val.i)();
  else
    return OFF_ID_NULL;
}

To implement the version of these methods shown above taking a name as an argument we rely on this protected method:

<Other protected methods of off_Inspector. >= (U->)
natural_t lookup_by_name(const char *name) const ;

<off_Inspector::lookup_by_name implementation. >= (U->)
natural_t off_Inspector::lookup_by_name(const char *name) const 
{
  natural_t idx;
  assert(name);
  for ( idx=0; idx < i_nattrs && strcmp(nameof(idx),name) ; idx++)
    ;
  return idx;
}

<Accessors by name of off_Inspector implementation. >= (U->)
boolean_t off_Inspector::get_bool_attr(const char *name) const
{
  assert(name);
  return get_bool_attr(lookup_by_name(name));
}
natural_t off_Inspector::get_nat_attr(const char *name)      const
{
  assert(name);
  return get_nat_attr(lookup_by_name(name));
}
char *off_Inspector::get_str_attr(const char *name)          const
{
  assert(name);
  return get_str_attr(lookup_by_name(name));
}
off_id_t off_Inspector::get_id_attr(const char *name)  const
{
  assert(name);
  return get_id_attr(lookup_by_name(name));
}

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

\subsubsection{Navigators and inspectors for plain users}

Navigators and inspectors are provided off-the-shelf for plain users. Just a few more arguments to ensure protection are used.

<Off resource navigator for users. >= (U->)
// A resource navigator for users.
//
class off_uNavigator {
public: 
   // Returns a reference to the resource being navigated
   off_uResource *get_current(const off_Rights &r);

   // Returns the first element.
   off_uResource *get_first(const off_Rights &r);
   // Advances the iteration and returns the next element.
   off_uResource *get_next(const off_Rights &r);

   // Selects a component by name.
   off_uResource *fetch(char *name,const off_Rights &r);
   // Selectors by id (off_uResource *fetch(id,rights)) are defined by
   // subclasses.
}; 

Defines off_uNavigator (links are to index).

<Off resource navigator dependencies. >+= (U->) [<-D]
#include <klib/prot.h>
class off_uResource;     // to break circular dependency. 

<Off resource inspector for users. >= (U->)
// A resource inspector for users.
//
class off_uInspector {
public:
   // Returns  the name of an attribute at [idx]
   virtual const char *nameof( natural_t idx, const off_Rights &r) const; 
   // Returns the type of an attribute
   virtual off_attr_kind_t kindof(natural_t idx, 
                                  const off_Rights &r) const;
   // Returns the # of attributes.
   virtual natural_t length(const off_Rights &r) const;

   // Look up a boolean attribute by name or by index
   virtual boolean_t get_bool_attr(const char *name, 
                                   const off_Rights &r) const;
   virtual boolean_t get_bool_attr(natural_t idx, 
                                   const off_Rights &r)  const;

   // Look up a natural attribute by name or by index
   virtual natural_t get_nat_attr(const char *name, const off_Rights &r) const;
   virtual natural_t get_nat_attr(natural_t idx, 
                                  const off_Rights &r) const;

   // Look up a string attribute by name or by index
   virtual char *get_str_attr(const char *name, const off_Rights &r) const;
   virtual char *get_str_attr(natural_t idx, const off_Rights &r) const;

   // Look up an id attribute by name or by index
   virtual off_id_t get_id_attr(const char *name, const off_Rights &r)  const;
   virtual off_id_t get_id_attr(natural_t idx, 
                                const off_Rights &r) const;

  
};

Defines off_uInspector (links are to index).

To avoid new protection operations, execution (OFF_OP_X) in resource containers will be considered to mean ``navigation'' (as happens on directories in the unix file system). Inspection will require read access.



 
next up previous contents
Next: 2.4.5.1 Navigation C++ source Up: 2.4 System resources Previous: 2.4.4 Freezing resources
Francisco J. Ballesteros
1998-05-25