. DS understands publishing and subscribing where keys are in string

form. Subscriptions are regular expressions.
 . different types are stored per key; currently u32 and/or string.
   the same key can be referenced (publish, subscribe, check) as any type.
 . notify()s are sent when subscriptions are triggered (publishing or
   updating of matching keys); optionally, a subscribe flag sends
   updates for all matching keys at subscription time, instead of only
   after updates after subscribing
 . all interfacing to ds is in /usr/src/lib/syslib/ds.c.
 . subscribe is ds_subscribe
   publish functions are ds_publish_<type>
   retrieve functions are ds_retrieve_<type> (one-time retrieval of a value)
   check functions are ds_check_<type> (check for updated key caller
      subscribes to not yet checked for, or ESRCH for none)
 . ramdisk driver updated with new ds interface
This commit is contained in:
Ben Gras 2006-07-13 14:50:23 +00:00
parent d40007667c
commit 3512a86b44
11 changed files with 642 additions and 91 deletions

View File

@ -17,10 +17,14 @@
#include "../drivers.h"
#include "../libdriver/driver.h"
#include <sys/ioc_memory.h>
#include <minix/ds.h>
#include "../../kernel/const.h"
#include "../../kernel/config.h"
#include "../../kernel/type.h"
#define MY_DS_NAME_BASE "dev:memory:ramdisk_base"
#define MY_DS_NAME_SIZE "dev:memory:ramdisk_size"
#include <sys/vm.h>
#include "assert.h"
@ -291,8 +295,8 @@ message *m_ptr;
PRIVATE void m_init()
{
/* Initialize this task. All minor devices are initialized one by one. */
phys_bytes ramdev_size;
phys_bytes ramdev_base;
u32_t ramdev_size;
u32_t ramdev_base;
message m;
int i, s;
@ -319,10 +323,8 @@ PRIVATE void m_init()
}
/* See if there are already RAM disk details at the Data Store server. */
m.DS_KEY = MEMORY_MAJOR;
if (OK == (s = _taskcall(DS_PROC_NR, DS_RETRIEVE, &m))) {
ramdev_size = m.DS_VAL_L1;
ramdev_base = m.DS_VAL_L2;
if(ds_retrieve_u32(MY_DS_NAME_BASE, &ramdev_base) == OK &&
ds_retrieve_u32(MY_DS_NAME_SIZE, &ramdev_size) == OK) {
printf("MEM retrieved size %u and base %u from DS, status %d\n",
ramdev_size, ramdev_base, s);
if (OK != (s=sys_segctl(&m_seg[RAM_DEV], (u16_t *) &s,
@ -423,15 +425,14 @@ int safe;
/* Store the values we got in the data store so we can retrieve
* them later on, in the unfortunate event of a crash.
*/
m.DS_KEY = MEMORY_MAJOR;
m.DS_VAL_L1 = ramdev_size;
m.DS_VAL_L2 = ramdev_base;
if (OK != (s = _taskcall(DS_PROC_NR, DS_PUBLISH, &m))) {
if(ds_publish_u32(MY_DS_NAME_BASE, ramdev_base) != OK ||
ds_publish_u32(MY_DS_NAME_SIZE, ramdev_size) != OK) {
panic("MEM","Couldn't store RAM disk details at DS.",s);
}
#if DEBUG
printf("MEM stored size %u and base %u at DS, status %d\n",
ramdev_size, ramdev_base, s);
printf("MEM stored size %u and base %u at DS, names %s and %s\n",
ramdev_size, ramdev_base, MY_DS_NAME_BASE, MY_DS_NAME_SIZE);
#endif
if (OK != (s=sys_segctl(&m_seg[RAM_DEV], (u16_t *) &s,

View File

@ -65,6 +65,7 @@
# define NEW_KSIG NOTIFY_FROM(HARDWARE) /* new kernel signal */
# define FKEY_PRESSED NOTIFY_FROM(TTY_PROC_NR)/* function key press */
# define DEV_PING NOTIFY_FROM(RS_PROC_NR) /* driver liveness ping */
# define DS_UPDATE NOTIFY_FROM(DS_PROC_NR) /* subscription update */
/* Shorthands for message parameters passed with notifications. */
#define NOTIFY_SOURCE m_source
@ -548,14 +549,18 @@
#define DS_RQ_BASE 0x800
#define DS_PUBLISH (DS_RQ_BASE + 0) /* publish information */
#define DS_RETRIEVE (DS_RQ_BASE + 1) /* retrieve information */
#define DS_SUBSCRIBE (DS_RQ_BASE + 2) /* subscribe to information */
#define DS_SUBSCRIBE (DS_RQ_BASE + 1) /* subscribe to information */
#define DS_RETRIEVE (DS_RQ_BASE + 2) /* retrieve information by name */
#define DS_CHECK (DS_RQ_BASE + 3) /* retrieve updated information */
# define DS_KEY m2_i1 /* key for the information */
/* DS field names: DS_SUBSCRIBE, DS_PUBLISH, DS_RETRIEVE */
# define DS_KEY_GRANT m2_p1 /* key for the information */
# define DS_KEY_LEN m2_i1 /* length of key incl. '\0' */
# define DS_FLAGS m2_i2 /* flags provided by caller */
# define DS_AUTH m2_p1 /* authorization of caller */
# define DS_VAL_L1 m2_l1 /* first long data value */
# define DS_VAL_L2 m2_l2 /* second long data value */
/* DS_PUBLISH, DS_RETRIEVE */
# define DS_VAL m2_l1 /* data (u32, char *, etc.) */
# define DS_VAL_LEN m2_l2 /* data length */
/*===========================================================================*
* Miscellaneous messages used by TTY *

View File

@ -63,6 +63,7 @@ libsys_FILES=" \
sys_voutb.c \
sys_voutl.c \
sys_voutw.c \
taskcall.c"
taskcall.c \
ds.c"
TYPE=both

259
lib/syslib/ds.c Normal file
View File

@ -0,0 +1,259 @@
#include <minix/ds.h>
#include <string.h>
#include "syslib.h"
int
ds_subscribe(ds_name_regexp, type, flags)
char *ds_name_regexp;
int type;
int flags;
{
int r;
message m;
cp_grant_id_t g;
size_t len;
len = strlen(ds_name_regexp)+1;
g = cpf_grant_direct(DS_PROC_NR,
(vir_bytes) ds_name_regexp, len, CPF_READ);
if(!GRANT_VALID(g))
return -1;
flags &= DS_INITIAL;
m.DS_KEY_GRANT = (char *) g;
m.DS_KEY_LEN = len;
m.DS_FLAGS = flags | (type & DS_TYPE_MASK);
r = _taskcall(DS_PROC_NR, DS_SUBSCRIBE, &m);
cpf_revoke(g);
return r;
}
int ds_publish_u32(ds_name, value)
char *ds_name;
u32_t value;
{
int r;
message m;
cp_grant_id_t g;
size_t len;
len = strlen(ds_name)+1;
g = cpf_grant_direct(DS_PROC_NR,
(vir_bytes) ds_name, len, CPF_READ);
if(!GRANT_VALID(g))
return -1;
m.DS_KEY_GRANT = (char *) g;
m.DS_KEY_LEN = len;
m.DS_FLAGS = DS_TYPE_U32;
m.DS_VAL = value;
m.DS_VAL_LEN = sizeof(value);
r = _taskcall(DS_PROC_NR, DS_PUBLISH, &m);
cpf_revoke(g);
return r;
}
int ds_publish_str(ds_name, value)
char *ds_name;
char *value;
{
int r;
message m;
cp_grant_id_t g_key, g_str;
size_t len_key, len_str;
/* Grant for key. */
len_key = strlen(ds_name)+1;
g_key = cpf_grant_direct(DS_PROC_NR,
(vir_bytes) ds_name, len_key, CPF_READ);
if(!GRANT_VALID(g_key))
return -1;
/* Grant for value. */
len_str = strlen(value)+1;
g_str = cpf_grant_direct(DS_PROC_NR,
(vir_bytes) value, len_str, CPF_READ);
if(!GRANT_VALID(g_str)) {
cpf_revoke(g_key);
return -1;
}
m.DS_KEY_GRANT = (char *) g_key;
m.DS_KEY_LEN = len_key;
m.DS_FLAGS = DS_TYPE_STR;
m.DS_VAL = g_str;
m.DS_VAL_LEN = len_str;
r = _taskcall(DS_PROC_NR, DS_PUBLISH, &m);
cpf_revoke(g_key);
cpf_revoke(g_str);
return r;
}
int ds_retrieve_u32(ds_name, value)
char *ds_name;
u32_t *value;
{
int r;
message m;
cp_grant_id_t g_key;
size_t len_key;
/* Grant for key. */
len_key = strlen(ds_name)+1;
g_key = cpf_grant_direct(DS_PROC_NR,
(vir_bytes) ds_name, len_key, CPF_READ);
if(!GRANT_VALID(g_key))
return -1;
/* Do request. */
m.DS_KEY_GRANT = (char *) g_key;
m.DS_KEY_LEN = len_key;
m.DS_FLAGS = DS_TYPE_U32;
r = _taskcall(DS_PROC_NR, DS_RETRIEVE, &m);
cpf_revoke(g_key);
/* Assign u32 value. */
*value = m.DS_VAL;
return r;
}
int ds_retrieve_str(ds_name, value, len_str)
char *ds_name;
char *value;
size_t len_str;
{
int r;
message m;
cp_grant_id_t g_key, g_str;
size_t len_key;
/* Grant for key. */
len_key = strlen(ds_name)+1;
g_key = cpf_grant_direct(DS_PROC_NR,
(vir_bytes) ds_name, len_key, CPF_READ);
if(!GRANT_VALID(g_key))
return -1;
/* Grant for value. */
g_str = cpf_grant_direct(DS_PROC_NR,
(vir_bytes) value, len_str, CPF_WRITE);
if(!GRANT_VALID(g_str)) {
cpf_revoke(g_key);
return -1;
}
/* Do request. */
m.DS_KEY_GRANT = (char *) g_key;
m.DS_KEY_LEN = len_key;
m.DS_FLAGS = DS_TYPE_STR;
m.DS_VAL = g_str;
m.DS_VAL_LEN = len_str;
r = _taskcall(DS_PROC_NR, DS_RETRIEVE, &m);
cpf_revoke(g_key);
cpf_revoke(g_str);
return r;
}
int ds_check_str(ds_key, len_key, value, len_str)
char *ds_key;
size_t len_key;
char *value;
size_t len_str;
{
int r;
message m;
cp_grant_id_t g_key, g_str;
if(len_key < 1 || len_str < 1) return -1;
/* Grant for key. */
g_key = cpf_grant_direct(DS_PROC_NR,
(vir_bytes) ds_key, len_key, CPF_WRITE);
if(!GRANT_VALID(g_key))
return -1;
/* Grant for value. */
g_str = cpf_grant_direct(DS_PROC_NR,
(vir_bytes) value, len_str, CPF_WRITE);
if(!GRANT_VALID(g_str)) {
cpf_revoke(g_key);
return -1;
}
/* Do request. */
m.DS_KEY_GRANT = (char *) g_key;
m.DS_KEY_LEN = len_key;
m.DS_FLAGS = DS_TYPE_STR;
m.DS_VAL = g_str;
m.DS_VAL_LEN = len_str;
r = _taskcall(DS_PROC_NR, DS_CHECK, &m);
cpf_revoke(g_key);
cpf_revoke(g_str);
ds_key[len_key-1] = '\0';
value[len_str-1] = '\0';
return r;
}
int ds_check_u32(ds_key, len_key, value)
char *ds_key;
size_t len_key;
u32_t *value;
{
int r;
message m;
cp_grant_id_t g_key;
if(len_key < 1) return -1;
/* Grant for key. */
g_key = cpf_grant_direct(DS_PROC_NR,
(vir_bytes) ds_key, len_key, CPF_WRITE);
if(!GRANT_VALID(g_key))
return -1;
/* Do request. */
m.DS_KEY_GRANT = (char *) g_key;
m.DS_KEY_LEN = len_key;
m.DS_FLAGS = DS_TYPE_U32;
r = _taskcall(DS_PROC_NR, DS_CHECK, &m);
cpf_revoke(g_key);
ds_key[len_key-1] = '\0';
/* Assign u32 value. */
*value = m.DS_VAL;
return r;
}

View File

@ -310,3 +310,4 @@ cp_grant_id_t gid;
return 0;
}

View File

@ -59,6 +59,9 @@ PUBLIC int main(int argc, char **argv)
case DS_SUBSCRIBE:
result = do_subscribe(&m);
break;
case DS_CHECK:
result = do_check(&m);
break;
case GETSYSINFO:
result = do_getsysinfo(&m);
break;
@ -91,6 +94,9 @@ PRIVATE void init_server(int argc, char **argv)
sigact.sa_flags = 0; /* default behaviour */
if (sigaction(SIGTERM, &sigact, NULL) < 0)
report("DS","warning, sigaction() failed", errno);
/* Initialize DS. */
ds_init();
}
/*===========================================================================*

View File

@ -7,4 +7,6 @@ _PROTOTYPE(int main, (int argc, char **argv));
_PROTOTYPE(int do_publish, (message *m_ptr));
_PROTOTYPE(int do_retrieve, (message *m_ptr));
_PROTOTYPE(int do_subscribe, (message *m_ptr));
_PROTOTYPE(int do_check, (message *m_ptr));
_PROTOTYPE(int do_getsysinfo, (message *m_ptr));
_PROTOTYPE(void ds_init, (void));

View File

@ -4,40 +4,66 @@
/* Allocate space for the data store. */
PRIVATE struct data_store ds_store[NR_DS_KEYS];
PRIVATE struct subscription ds_subs[NR_DS_SUBS];
PRIVATE int nr_in_use;
PRIVATE _PROTOTYPE(int find_key, (int key, struct data_store **dsp));
PRIVATE _PROTOTYPE(int set_owner, (struct data_store *dsp, void *auth_ptr));
PRIVATE _PROTOTYPE(int is_authorized, (struct data_store *dsp, void *auth_ptr));
PRIVATE _PROTOTYPE(int find_key, (char *key, struct data_store **dsp, int t));
PRIVATE _PROTOTYPE(int set_owner, (struct data_store *dsp, int auth));
PRIVATE _PROTOTYPE(int is_authorized, (struct data_store *dsp, int auth));
PRIVATE _PROTOTYPE(void check_subscribers, (struct data_store *dsp));
PRIVATE int set_owner(dsp, ap)
struct data_store *dsp; /* data store structure */
void *ap; /* authorization pointer */
/*===========================================================================*
* ds_init *
*===========================================================================*/
PUBLIC void ds_init(void)
{
int i;
/* Reset data store: data and subscriptions. */
for(i = 0; i < NR_DS_KEYS; i++) {
int b;
ds_store[i].ds_flags = 0;
for(b = 0; b < BITMAP_CHUNKS(NR_DS_SUBS); b++) {
ds_store[i].ds_old_subs[b] = 0;
}
}
for(i = 0; i < NR_DS_SUBS; i++)
ds_subs[i].sub_flags = 0;
return;
}
PRIVATE int set_owner(dsp, auth)
struct data_store *dsp; /* data store structure */
int auth;
{
/* Authorize the caller. */
return(TRUE);
}
PRIVATE int is_authorized(dsp, ap)
struct data_store *dsp; /* data store structure */
void *ap; /* authorization pointer */
int ap; /* authorization value */
{
/* Authorize the caller. */
return(TRUE);
}
PRIVATE int find_key(key, dsp)
int key; /* key to look up */
PRIVATE int find_key(key_name, dsp, type)
char *key_name; /* key to look up */
struct data_store **dsp; /* store pointer here */
int type; /* type info */
{
register int i;
*dsp = NULL;
for (i=0; i<NR_DS_KEYS; i++) {
if ((ds_store[i].ds_flags & DS_IN_USE) && ds_store[i].ds_key == key) {
if ((ds_store[i].ds_flags & DS_IN_USE) /* valid slot? */
&& ((ds_store[i].ds_flags & type) == type) /* right type? */
&& !strcmp(ds_store[i].ds_key, key_name)) { /* matching name? */
*dsp = &ds_store[i];
return(TRUE); /* report success */
}
@ -50,27 +76,45 @@ PUBLIC int do_publish(m_ptr)
message *m_ptr; /* request message */
{
struct data_store *dsp;
char key_name[DS_MAX_KEYLEN];
int r, type;
/* Store (key,value)-pair. First see if key already exists. If so,
* check if the caller is allowed to overwrite the value. Otherwise
* find a new slot and store the new value.
*/
if (find_key(m_ptr->DS_KEY, &dsp)) { /* look up key */
if (! is_authorized(dsp,m_ptr->DS_AUTH)) { /* check if owner */
return(EPERM);
}
}
else { /* find a new slot */
if (m_ptr->DS_KEY_LEN > DS_MAX_KEYLEN || m_ptr->DS_KEY_LEN < 2) {
printf("DS: bogus key length (%d) from %d\n", m_ptr->DS_KEY_LEN,
m_ptr->m_source);
return EINVAL;
}
/* Check type info. */
type = m_ptr->DS_FLAGS & DS_TYPE_MASK;
if(type != DS_TYPE_U32 && type != DS_TYPE_STR) {
printf("DS: bogus type code %lx from %d\n", type, m_ptr->m_source);
return EINVAL;
}
/* Copy name from caller. */
if ((r=sys_safecopyfrom(m_ptr->m_source,
(cp_grant_id_t) m_ptr->DS_KEY_GRANT, 0,
(vir_bytes) key_name, m_ptr->DS_KEY_LEN, D)) != OK) {
printf("DS: publish: copy failed from %d: %d\n", m_ptr->m_source, r);
return r;
}
/* Make sure name is 0-terminated. */
key_name[DS_MAX_KEYLEN-1] = '\0';
/* See if it already exists. */
if (!find_key(key_name, &dsp, type)) { /* look up key */
if (nr_in_use >= NR_DS_KEYS) {
return(EAGAIN); /* store is full */
} else {
dsp = &ds_store[nr_in_use]; /* new slot found */
dsp->ds_key = m_ptr->DS_KEY;
if (! set_owner(dsp,m_ptr->DS_AUTH)) { /* associate owner */
return(EINVAL);
}
dsp->ds_nr_subs = 0; /* nr of subscribers */
dsp->ds_flags = DS_IN_USE; /* initialize slot */
strcpy(dsp->ds_key, key_name);
dsp->ds_flags = DS_IN_USE | m_ptr->DS_FLAGS; /* initialize slot */
nr_in_use ++;
}
}
@ -78,59 +122,245 @@ message *m_ptr; /* request message */
/* At this point we have a data store pointer and know the caller is
* authorize to write to it. Set all fields as requested.
*/
dsp->ds_val_l1 = m_ptr->DS_VAL_L1; /* store all data */
dsp->ds_val_l2 = m_ptr->DS_VAL_L2;
switch(type) {
case DS_TYPE_U32:
dsp->ds_val.ds_val_u32 = (u32_t) m_ptr->DS_VAL; /* store data */
break;
case DS_TYPE_STR:
/* store string data: check size, then do copy */
if(m_ptr->DS_VAL_LEN < 1 || m_ptr->DS_VAL_LEN > DS_MAX_VALLEN) {
printf("DS: publish: bogus len from %d: %d\n",
m_ptr->m_source, m_ptr->DS_VAL_LEN);
return EINVAL;
}
/* If the data is public. Check if there are any subscribers to this key.
* If so, notify all subscribers so that they can retrieve the data, if
* they're still interested.
*/
if ((dsp->ds_flags & DS_PUBLIC) && dsp->ds_nr_subs > 0) {
/* Subscriptions are not yet implemented. */
if((r=sys_safecopyfrom(m_ptr->m_source, m_ptr->DS_VAL, 0,
(vir_bytes) dsp->ds_val.ds_val_str,
m_ptr->DS_VAL_LEN, D)) != OK) {
printf("DS: publish: str copy failed from %d: %d\n",
m_ptr->m_source, r);
return r;
}
break;
default:
panic(__FILE__, "Impossible type.", type);
break;
}
/* If anyone has a matching subscription, update them. */
check_subscribers(dsp);
return(OK);
}
/*===========================================================================*
* do_retrieve *
*===========================================================================*/
PUBLIC int do_retrieve(m_ptr)
message *m_ptr; /* request message */
{
struct data_store *dsp;
char key_name[DS_MAX_KEYLEN];
int r, type;
size_t len;
if (m_ptr->DS_KEY_LEN > DS_MAX_KEYLEN || m_ptr->DS_KEY_LEN < 1) {
printf("DS: bogus key length (%d) from %d\n", m_ptr->DS_KEY_LEN,
m_ptr->m_source);
return EINVAL;
}
/* Copy name from caller. */
if ((r=sys_safecopyfrom(m_ptr->m_source,
(cp_grant_id_t) m_ptr->DS_KEY_GRANT, 0,
(vir_bytes) key_name, m_ptr->DS_KEY_LEN, D)) != OK) {
printf("DS: retrieve: copy failed from %d: %d\n", m_ptr->m_source, r);
return r;
}
/* Make sure name is 0-terminated. */
key_name[DS_MAX_KEYLEN-1] = '\0';
/* Retrieve data. Look up the key in the data store. Return an error if it
* is not found. If this data is private, only the owner may retrieve it.
*/
if (find_key(m_ptr->DS_KEY, &dsp)) { /* look up key */
/* If the data is not public, the caller must be authorized. */
if (! dsp->ds_flags & DS_PUBLIC) { /* check if private */
if (! is_authorized(dsp,m_ptr->DS_AUTH)) { /* authorize call */
return(EPERM); /* not allowed */
}
}
type = m_ptr->DS_FLAGS & DS_TYPE_MASK;
if (find_key(key_name, &dsp, type)) { /* look up key */
/* Data is public or the caller is authorized to retrieve it. */
printf("DS retrieves data: key %d (found %d), l1 %u, l2 %u\n",
m_ptr->DS_KEY, dsp->ds_key, dsp->ds_val_l1, dsp->ds_val_l2);
m_ptr->DS_VAL_L1 = dsp->ds_val_l1; /* return value */
m_ptr->DS_VAL_L2 = dsp->ds_val_l2; /* return value */
switch(type) {
case DS_TYPE_U32:
m_ptr->DS_VAL = dsp->ds_val.ds_val_u32; /* return value */
break;
case DS_TYPE_STR:
len = strlen(dsp->ds_val.ds_val_str) + 1;
if(len > m_ptr->DS_VAL_LEN)
len = m_ptr->DS_VAL_LEN;
if ((r=sys_safecopyto(m_ptr->m_source, m_ptr->DS_VAL,
0, (vir_bytes) dsp->ds_val.ds_val_str,len, D)) != OK) {
printf("DS: retrieve: copy failed to %d: %d\n",
m_ptr->m_source, r);
return r;
}
break;
default:
panic(__FILE__, "retrieve: impossible type.", type);
/* not reached. */
break;
}
return(OK); /* report success */
}
return(ESRCH); /* key not found */
}
/*===========================================================================*
* do_check *
*===========================================================================*/
PUBLIC int do_check(m_ptr)
message *m_ptr; /* request message */
{
/* This routine goes through all subscriptions for a client,
* and checks all data items if it has been flagged (i.e.,
* created or updated) matching that subscription. Return
* a message and copy the key and value for every one.
*/
struct data_store *dsp;
int r, s, d, type = m_ptr->DS_FLAGS & DS_TYPE_MASK;
if(!type) return EINVAL;
for(s = 0; s < NR_DS_SUBS; s++) {
int len;
if(!(ds_subs[s].sub_flags & DS_IN_USE))
continue;
if(m_ptr->m_source != ds_subs[s].sub_owner)
continue;
for(d = 0; d < NR_DS_KEYS; d++) {
/* No match if this is no value, it's
* not flagged, or the type is wrong.
*/
if(!(ds_store[d].ds_flags & DS_IN_USE))
continue;
if(!GET_BIT(ds_store[d].ds_old_subs, s))
continue;
if(type != (ds_store[d].ds_flags & DS_TYPE_MASK))
continue;
/* We have a match. Unflag it for this
* subscription.
*/
UNSET_BIT(ds_store[d].ds_old_subs, s);
len = strlen(ds_store[d].ds_key)+1;
if(len > m_ptr->DS_KEY_LEN)
len = m_ptr->DS_KEY_LEN;
/* Copy the key into client. */
if ((r=sys_safecopyto(m_ptr->m_source,
(cp_grant_id_t) m_ptr->DS_KEY_GRANT, 0,
(vir_bytes) ds_store[d].ds_key,
len, D)) != OK)
return r;
/* Now copy the value. */
switch(type) {
case DS_TYPE_STR:
len = strlen(ds_store[d].
ds_val.ds_val_str)+1;
if(len > m_ptr->DS_VAL_LEN)
len = m_ptr->DS_VAL_LEN;
if ((r=sys_safecopyto(m_ptr->m_source,
m_ptr->DS_VAL, 0,
(vir_bytes) ds_store[d].
ds_val.ds_val_str,
len, D)) != OK)
return r;
break;
case DS_TYPE_U32:
m_ptr->DS_VAL =
ds_store[d].ds_val.ds_val_u32;
break;
default:
panic(__FILE__,
"Check impossible type.",
type);
}
return OK;
}
}
return(ESRCH); /* key not found */
}
PUBLIC int do_subscribe(m_ptr)
message *m_ptr; /* request message */
{
/* Subscribe to a key of interest. Only existing and public keys can be
* subscribed to. All updates to the key will cause a notification message
char regex[DS_MAX_KEYLEN+3];
int s, type, e, d, n = 0;
char errbuf[80];
/* Subscribe to a key of interest.
* All updates to the key will cause a notification message
* to be sent to the subscribed. On success, directly return a copy of the
* data for the given key.
*/
return(ENOSYS);
if(m_ptr->DS_KEY_LEN < 2 || m_ptr->DS_KEY_LEN > DS_MAX_KEYLEN)
return EINVAL;
/* Copy name from caller. Anchor the subscription with "^regexp$" so
* substrings don't match. The caller probably will not expect this,
* and the usual case is for a complete match.
*/
regex[0] = '^';
if ((s=sys_safecopyfrom(m_ptr->m_source,
(cp_grant_id_t) m_ptr->DS_KEY_GRANT, 0,
(vir_bytes) regex + 1, m_ptr->DS_KEY_LEN, D)) != OK) {
printf("DS: retrieve: copy failed from %d: %d\n", m_ptr->m_source, s);
return s;
}
regex[DS_MAX_KEYLEN-1] = '\0';
strcat(regex, "$");
/* Find subscription slot. */
for(s = 0; s < NR_DS_SUBS; s++)
if(!(ds_subs[s].sub_flags & DS_IN_USE))
break;
if(s >= NR_DS_SUBS) {
printf("DS: no space for subscription by %d.\n", m_ptr->m_source);
return ENOSPC;
}
/* Compile regular expression. */
if((e=regcomp(&ds_subs[s].sub_regex, regex, REG_EXTENDED)) != 0) {
regerror(e, &ds_subs[s].sub_regex, errbuf, sizeof(errbuf));
printf("DS: subscribe: regerror: %s\n", errbuf);
return EINVAL;
}
type = (m_ptr->DS_FLAGS & DS_TYPE_MASK);
ds_subs[s].sub_flags = DS_IN_USE | type;
ds_subs[s].sub_owner = m_ptr->m_source;
/* Caller requested an instant initial list? */
if(m_ptr->DS_FLAGS & DS_INITIAL) {
for(d = 0; d < NR_DS_KEYS; d++) {
if(!(ds_store[d].ds_flags & DS_IN_USE))
continue;
if(regexec(&ds_subs[s].sub_regex, ds_store[d].ds_key,
0, NULL, 0) == 0) {
SET_BIT(ds_store[d].ds_old_subs, s);
n = 1;
}
}
/* Any matches? */
if(n) notify(ds_subs[s].sub_owner);
}
return OK;
}
@ -156,8 +386,34 @@ message *m_ptr;
dst_proc = m_ptr->m_source;
dst_addr = (vir_bytes) m_ptr->m1_p1;
if (OK != (s=sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len)))
if (OK != (s=sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len))) {
printf("DS: copy failed: %d\n", s);
return(s);
}
return(OK);
}
/*===========================================================================*
* check_subscribers *
*===========================================================================*/
PRIVATE void
check_subscribers(struct data_store *dsp)
{
/* Send subscribers whose subscriptions match this (new
* or updated) data item a notify(), and flag the subscriptions
* as updated.
*/
int i;
for(i = 0; i < NR_DS_SUBS; i++) {
if(ds_subs[i].sub_flags & DS_IN_USE) {
if(regexec(&ds_subs[i].sub_regex, dsp->ds_key,
0, NULL, 0) == 0) {
SET_BIT(dsp->ds_old_subs, i);
notify(ds_subs[i].sub_owner);
} else {
UNSET_BIT(dsp->ds_old_subs, i);
}
}
}
}

View File

@ -1,19 +1,33 @@
/* Type definitions for the Data Store Server. */
struct data_store {
int ds_flags; /* flags for this store */
int ds_key; /* key to lookup information */
long ds_val_l1; /* data associated with key */
long ds_val_l2; /* data associated with key */
long ds_auth; /* secret given by owner of data */
int ds_nr_subs; /* number of subscribers for key */
};
/* Flag values. */
#define DS_IN_USE 0x01
#define DS_PUBLIC 0x02
#include <sys/types.h>
#include <minix/sys_config.h>
#include <minix/ds.h>
#include <minix/bitmap.h>
#include <regex.h>
/* Constants for the Data Store Server. */
#define NR_DS_KEYS 64 /* reserve space for so many items */
#define NR_DS_KEYS 64 /* reserve space for so many items */
#define NR_DS_SUBS (4*_NR_SYS_PROCS) /* .. and so many subscriptions */
/* Types. */
struct data_store {
int ds_flags; /* flags for this store, includes type info */
char ds_key[DS_MAX_KEYLEN]; /* key to lookup information */
union {
u32_t ds_val_u32; /* u32 data (DS_TYPE_U32) */
char ds_val_str[DS_MAX_VALLEN]; /* string data (DS_TYPE_STR) */
} ds_val;
/* out of date subscribers. */
bitchunk_t ds_old_subs[BITMAP_CHUNKS(NR_DS_SUBS)];
};
struct subscription {
int sub_flags; /* flags for this subscription */
regex_t sub_regex; /* regular expression agains keys */
endpoint_t sub_owner; /* who is subscribed */
};

View File

@ -12,7 +12,7 @@
/* Define hooks for the debugging dumps. This table maps function keys
* onto a specific dump and provides a description for it.
*/
#define NHOOKS 19
#define NHOOKS 18
struct hook_entry {
int key;

View File

@ -20,26 +20,32 @@ FORWARD _PROTOTYPE( char *s_flags_str, (int flags) );
PUBLIC void data_store_dmp()
{
struct data_store *dsp;
int i,j, n=0;
int i,j, n=0, s;
static int prev_i=0;
printf("Data Store (DS) contents dump\n");
getsysinfo(DS_PROC_NR, SI_DATA_STORE, store);
if((s=getsysinfo(DS_PROC_NR, SI_DATA_STORE, store)) != OK) {
printf("Couldn't talk to DS: %d.\n", s);
return;
}
printf("-slot- -key- -flags- -val_l1- -val_l2-\n");
printf("slot key type value\n");
for (i=prev_i; i<NR_DS_KEYS; i++) {
dsp = &store[i];
if (! dsp->ds_flags & DS_IN_USE) continue;
if (++n > 22) break;
printf("%3d %8d %s [%8d] [%8d] \n",
i, dsp->ds_key,
s_flags_str(dsp->ds_flags),
dsp->ds_val_l1,
dsp->ds_val_l2
);
printf("%3d %-20s ",
i, dsp->ds_key);
if(dsp->ds_flags & DS_TYPE_U32) {
printf("u32 %lu\n", dsp->ds_val.ds_val_u32);
} else if(dsp->ds_flags & DS_TYPE_STR) {
printf("str \"%s\"\n", dsp->ds_val.ds_val_str);
} else {
printf("Bogus type\n");
}
}
if (i >= NR_DS_KEYS) i = 0;
else printf("--more--\r");