. 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:
parent
d40007667c
commit
3512a86b44
@ -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,
|
||||
|
@ -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 *
|
||||
|
@ -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
259
lib/syslib/ds.c
Normal 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;
|
||||
}
|
||||
|
@ -310,3 +310,4 @@ cp_grant_id_t gid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
Loading…
x
Reference in New Issue
Block a user