#include#include /* * API's to handle forwarding of a key prefix * to a particular registry implementation (regImpl) */ boolean_t registry_forward( regCred a, const char* prefix, regImpl* implementation); boolean_t registry_notify( regCred a, const char* key, regNotifyClient func); regRawInfo registry_rawinfo( regCred a, const char* key); /* Supporting declarations */ typedef struct regImpl { ushort flags; void (*init)( struct regImpl*, regCred a ); void (*load)( struct regImpl*, regCred a, const char* password ); boolean_t (*commit)( struct regImpl*, regCred a, const char* password ); const char* (*get)( struct regImpl*, regCred a, const char* key, char* valuebuff, int buffleng ); boolean_t (*set)( struct regImpl*, regCred a, const char* key, const char* value ); boolean_t (*delete)( struct regImpl*, regCred a, const char* key ); const char* (*walkinit)( struct regImpl*, regCred a, const char*prefix, regWalkType t ); const char* (*walknext)( struct regImpl*, regCred a, const char* cookie, char* keybuff, int buffleng ); void (*walkend)( struct regImpl*, regCred a, const char* cookie ); boolean_t (*forward)( struct regImpl*, regCred a, const char* prefix, struct regImpl* forwardto ); regRawInfo (*rawinfo)( struct regImpl*, regCred a, const char* key ); boolean_t (*notify)( struct regImpl*, regCred a, const char* prefix, regNotifyClient f ); boolean_t (*validate)( struct regImpl*, regCred a, regOpType o, const char *key, const char *val, errors_t** errs ); boolean_t (*commitx)( struct regImpl*, regTransaction* t, const char* password, errors_t** errs ); const char* prefix; int lock[NHOSTS]; regCookieList cookies[NHOSTS]; void* private[NHOSTS]; } regImpl; typedef struct regRawInfo { ushort type; union regRawValueUnion { long *l; int *i; int4 *i4; double *d; } u; } regRawInfo; typedef boolean_t (*regNotifyClient)(regCred a, const char* key, const char* value);
To use registry_forward, you need to create an instance of the regImpl structure, and fill it with pointers to functions that implement some subset of the registry functions. (The one value you don't have to explicitly provide is prefix, which is set by the registry infrastructure.) An example is the best explanation, so here is code that implements read-only access to two of the global variables in the kernel - sk_tics and sk_busy_tics.
static boolean_t
stats_registry_get(regCred a, regImpl* impl, const char* key, char* valbuff, int leng)
{
char buff[16]; /* enough for an int4 */
int4 val;
/* This would be table-driven if there were lots of variables. */
if ( strcmp(key,"sk_tics") == 0 )
val = sk_tics;
else if ( strcmp(key,"sk_busy_tics") == 0 )
val = sk_busy_tics;
else {
errno = ENOENT;
return B_FALSE;
}
sprintf(buff,"%d",val);
/*
* registry_returnbuff is a utility function for helping to
* copy the result
* into valbuff.
*/
return registry_returnbuff(buff,valbuff,leng);
}
regImpl regStatsImpl = {
0, /* flags */
0, /* init */
0, /* load */
0, /* commit */
stats_registry_get,
0, /* set */
0, /* delete */
0, /* walkinit */
0, /* walknext */
0, /* walkend */
0, /* forward */
0, /* rawinfo */
0, /* notify */
0, /* prefix */
{ 0,0 } /* lock */
{ NULL,NULL } /* cookies */
0 /* private */
};
registry_forward("stats.",®StatsImpl);
After this line was executed, those variables would be accessible through the registry with the names "stats.sk_tics" and "stats.sk_busy_tics".
The flags value in the regImpl structure contains bit flags that indicate what type of "walks" are supported by the walkinit/walknext/walkend functions (if any) of the registry implementation. If the flags value is WALK_ALL, you are saying that your registry implementation (i.e. walkinit function) supports a WALK_ALL walking type, which should return all the keys in your part of the namespace. If the flags value contains the WALK_DEFAULTPERSISTENCE bit, you are saying that your registry implementation wants to make use of the default registry persistence (i.e. the /etc/registry file), and that a walk of type WALK_DEFAULTPERSISTENCE will return the keys that you want to save in that file. For further discussion of this, see the functional spec of the registry transaction APIs in the design depot (at http://web.netapp.com/engineering/design-depot/appliance-mgmt/registry_trans/fs.html ).
The private value in the regImpl structure can be used for any purpose, by a particular registry implementation. Note that it is an array, containing private values for each host. Note that each function in the regImpl structure has, as its first argument, a pointer to a regImpl this argument will be a pointer to the regImpl that triggered the function's invocation. This pointer can then be used to access the private element, which would then typically point to some larger data structure containing information that controls the operation of that registry implementation. This mechanism allows a single set of registry implementation functions to be shared by different forwarding prefixes. For example, to extend the example above, there could be two instances of regImpl (say, regStats1Impl and regStats2Impl ) which both contained a pointer to stats_registry_get as the value of their get function, but which contained pointers to different private values. You could then set up forwarding to two different prefixes:
The delete method, if implemented in a regImpl structure, should return B_FALSE if the item does not already exist.
An example is again the best explanation, so here is a function that adds raw access to the two global variables used in the previous example, and the value of regStatsImpl that would include it.
static regRawInfo
stats_registry_rawinfo(regImpl* impl, const char* name)
{
regRawInfo v;
v.type = 0; /* Not used, in this example */
/*
* This would be table-driven if there were lots of variables.
*/
if ( strcmp(key,"sk_tics") == 0 )
v.u.i4 = &sk_tics;
else if ( strcmp(key,"sk_busy_tics") == 0 )
v.u.i4 = &sk_busy_tics;
else
v.u = NULL;
return v;
}
regImpl regStatsImpl = {
0, /* flags */
0, /* init */
0, /* load */
0, /* commit */
stats_registry_get,
0, /* set */
0, /* delete */
0, /* walkinit */
0, /* walknext */
0, /* walkend */
0, /* forward */
stats_registry_rawinfo,
0, /* notify */
0, /* prefix */
{ 0,0 } /* lock */
{ NULL,NULL } /* cookies */
{0,0} /* private */
};
regRawinfo raw;
raw = registry_rawinfo("raw.sk_tics");
/*
* raw.u.i4 is now the pointer value you can use.
*/
dbg_printf("registry test: raw value is %d0,*(raw.u.i4));