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
:
get_navigator, a reference to its navigator is
obtained. This navigator implements the Navigator interface.
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.
<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;
};
Definesoff_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;
};
Definesoff_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;
Definesoff_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. >
};
DefinesOFF_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.
};
Definesoff_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.
};
Definesoff_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;
};
Definesoff_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.