4 /* Allocate space for the data store. */
5 static struct data_store ds_store
[NR_DS_KEYS
];
6 static struct subscription ds_subs
[NR_DS_SUBS
];
8 /*===========================================================================*
10 *===========================================================================*/
11 static struct data_store
*alloc_data_slot(void)
13 /* Allocate a new data slot. */
16 for (i
= 0; i
< NR_DS_KEYS
; i
++) {
17 if (!(ds_store
[i
].flags
& DSF_IN_USE
))
24 /*===========================================================================*
26 *===========================================================================*/
27 static struct subscription
*alloc_sub_slot(void)
29 /* Allocate a new subscription slot. */
32 for (i
= 0; i
< NR_DS_SUBS
; i
++) {
33 if (!(ds_subs
[i
].flags
& DSF_IN_USE
))
40 /*===========================================================================*
42 *===========================================================================*/
43 static struct data_store
*lookup_entry(const char *key_name
, int type
)
45 /* Lookup an existing entry by key and type. */
48 for (i
= 0; i
< NR_DS_KEYS
; i
++) {
49 if ((ds_store
[i
].flags
& DSF_IN_USE
) /* used */
50 && (ds_store
[i
].flags
& type
) /* same type*/
51 && !strcmp(ds_store
[i
].key
, key_name
)) /* same key*/
58 /*===========================================================================*
59 * lookup_label_entry *
60 *===========================================================================*/
61 static struct data_store
*lookup_label_entry(unsigned num
)
63 /* Lookup an existing label entry by num. */
66 for (i
= 0; i
< NR_DS_KEYS
; i
++) {
67 if ((ds_store
[i
].flags
& DSF_IN_USE
)
68 && (ds_store
[i
].flags
& DSF_TYPE_LABEL
)
69 && (ds_store
[i
].u
.u32
== num
))
76 /*===========================================================================*
78 *===========================================================================*/
79 static struct subscription
*lookup_sub(const char *owner
)
81 /* Lookup an existing subscription given its owner. */
84 for (i
= 0; i
< NR_DS_SUBS
; i
++) {
85 if ((ds_subs
[i
].flags
& DSF_IN_USE
) /* used */
86 && !strcmp(ds_subs
[i
].owner
, owner
)) /* same key*/
93 /*===========================================================================*
95 *===========================================================================*/
96 static char *ds_getprocname(endpoint_t e
)
98 /* Get a process name given its endpoint. */
99 struct data_store
*dsp
;
101 static char *first_proc_name
= "ds";
102 endpoint_t first_proc_ep
= DS_PROC_NR
;
104 if(e
== first_proc_ep
)
105 return first_proc_name
;
107 if((dsp
= lookup_label_entry(e
)) != NULL
)
113 /*===========================================================================*
115 *===========================================================================*/
116 static endpoint_t
ds_getprocep(const char *s
)
118 /* Get a process endpoint given its name. */
119 struct data_store
*dsp
;
121 if((dsp
= lookup_entry(s
, DSF_TYPE_LABEL
)) != NULL
)
123 panic("ds_getprocep: process endpoint not found");
126 /*===========================================================================*
128 *===========================================================================*/
129 static int check_auth(const struct data_store
*p
, endpoint_t ep
, int perm
)
131 /* Check authorization for a given type of permission. */
134 if(!(p
->flags
& perm
))
137 source
= ds_getprocname(ep
);
138 return source
&& !strcmp(p
->owner
, source
);
141 /*===========================================================================*
143 *===========================================================================*/
144 static int get_key_name(const message
*m_ptr
, char *key_name
)
146 /* Get key name given an input message. */
149 if (m_ptr
->m_ds_req
.key_len
> DS_MAX_KEYLEN
|| m_ptr
->m_ds_req
.key_len
< 2) {
150 printf("DS: bogus key length (%d) from %d\n", m_ptr
->m_ds_req
.key_len
,
155 /* Copy name from caller. */
156 r
= sys_safecopyfrom(m_ptr
->m_source
,
157 (cp_grant_id_t
) m_ptr
->m_ds_req
.key_grant
, 0,
158 (vir_bytes
) key_name
, m_ptr
->m_ds_req
.key_len
);
160 printf("DS: publish: copy failed from %d: %d\n", m_ptr
->m_source
, r
);
164 key_name
[DS_MAX_KEYLEN
-1] = '\0';
169 /*===========================================================================*
171 *===========================================================================*/
172 static int check_sub_match(const struct subscription
*subp
,
173 struct data_store
*dsp
, endpoint_t ep
)
175 /* Check if an entry matches a subscription. Return 1 in case of match. */
176 return (check_auth(dsp
, ep
, DSF_PRIV_SUBSCRIBE
)
177 && regexec(&subp
->regex
, dsp
->key
, 0, NULL
, 0) == 0)
181 /*===========================================================================*
182 * update_subscribers *
183 *===========================================================================*/
184 static void update_subscribers(struct data_store
*dsp
, int set
)
186 /* If set = 1, set bit in the sub bitmap of any subscription matching the given
187 * entry, otherwise clear it. In both cases, notify the subscriber.
190 int nr
= dsp
- ds_store
;
193 for(i
= 0; i
< NR_DS_SUBS
; i
++) {
194 if(!(ds_subs
[i
].flags
& DSF_IN_USE
))
196 if(!(ds_subs
[i
].flags
& dsp
->flags
& DSF_MASK_TYPE
))
199 ep
= ds_getprocep(ds_subs
[i
].owner
);
200 if(!check_sub_match(&ds_subs
[i
], dsp
, ep
))
204 SET_BIT(ds_subs
[i
].old_subs
, nr
);
206 UNSET_BIT(ds_subs
[i
].old_subs
, nr
);
212 /*===========================================================================*
214 *===========================================================================*/
215 static int map_service(const struct rprocpub
*rpub
)
217 /* Map a new service by registering its label. */
218 struct data_store
*dsp
;
220 /* Allocate a new data slot. */
221 if((dsp
= alloc_data_slot()) == NULL
) {
225 /* Set attributes. */
226 strcpy(dsp
->key
, rpub
->label
);
227 dsp
->u
.u32
= (u32_t
) rpub
->endpoint
;
228 strcpy(dsp
->owner
, "rs");
229 dsp
->flags
= DSF_IN_USE
| DSF_TYPE_LABEL
;
231 /* Update subscribers having a matching subscription. */
232 update_subscribers(dsp
, 1);
237 /*===========================================================================*
238 * sef_cb_init_fresh *
239 *===========================================================================*/
240 int sef_cb_init_fresh(int UNUSED(type
), sef_init_info_t
*info
)
242 /* Initialize the data store server. */
244 struct rprocpub rprocpub
[NR_BOOT_PROCS
];
246 /* Reset data store: data and subscriptions. */
247 for(i
= 0; i
< NR_DS_KEYS
; i
++) {
248 ds_store
[i
].flags
= 0;
250 for(i
= 0; i
< NR_DS_SUBS
; i
++) {
251 ds_subs
[i
].flags
= 0;
254 /* Map all the services in the boot image. */
255 if((r
= sys_safecopyfrom(RS_PROC_NR
, info
->rproctab_gid
, 0,
256 (vir_bytes
) rprocpub
, sizeof(rprocpub
))) != OK
) {
257 panic("sys_safecopyfrom failed: %d", r
);
259 for(i
=0;i
< NR_BOOT_PROCS
;i
++) {
260 if(rprocpub
[i
].in_use
) {
261 if((r
= map_service(&rprocpub
[i
])) != OK
) {
262 panic("unable to map service: %d", r
);
270 /*===========================================================================*
272 *===========================================================================*/
273 int do_publish(message
*m_ptr
)
275 struct data_store
*dsp
;
276 char key_name
[DS_MAX_KEYLEN
];
278 int flags
= m_ptr
->m_ds_req
.flags
;
282 /* Lookup the source. */
283 source
= ds_getprocname(m_ptr
->m_source
);
287 /* Only RS can publish labels. */
288 if((flags
& DSF_TYPE_LABEL
) && m_ptr
->m_source
!= RS_PROC_NR
)
292 if((r
= get_key_name(m_ptr
, key_name
)) != OK
)
295 /* Lookup the entry. */
296 dsp
= lookup_entry(key_name
, flags
& DSF_MASK_TYPE
);
297 /* If type is LABEL, also try to lookup the entry by num. */
298 if((flags
& DSF_TYPE_LABEL
) && (dsp
== NULL
))
299 dsp
= lookup_label_entry(m_ptr
->m_ds_req
.val_in
.ep
);
302 /* The entry doesn't exist, allocate a new data slot. */
303 if((dsp
= alloc_data_slot()) == NULL
)
305 } else if (flags
& DSF_OVERWRITE
) {
307 if(!check_auth(dsp
, m_ptr
->m_source
, DSF_PRIV_OVERWRITE
))
310 /* Don't overwrite and return error. */
315 switch(flags
& DSF_MASK_TYPE
) {
317 dsp
->u
.u32
= m_ptr
->m_ds_req
.val_in
.u32
;
320 dsp
->u
.u32
= m_ptr
->m_ds_req
.val_in
.ep
;
324 length
= m_ptr
->m_ds_req
.val_len
;
325 /* Allocate a new data buffer if necessary. */
326 if(!(dsp
->flags
& DSF_IN_USE
)) {
327 if((dsp
->u
.mem
.data
= malloc(length
)) == NULL
)
329 dsp
->u
.mem
.reallen
= length
;
330 } else if(length
> dsp
->u
.mem
.reallen
) {
331 free(dsp
->u
.mem
.data
);
332 if((dsp
->u
.mem
.data
= malloc(length
)) == NULL
)
334 dsp
->u
.mem
.reallen
= length
;
337 /* Copy the memory range. */
338 r
= sys_safecopyfrom(m_ptr
->m_source
, m_ptr
->m_ds_req
.val_in
.grant
,
339 0, (vir_bytes
) dsp
->u
.mem
.data
, length
);
341 printf("DS: publish: memory map/copy failed from %d: %d\n",
343 free(dsp
->u
.mem
.data
);
346 dsp
->u
.mem
.length
= length
;
347 if(flags
& DSF_TYPE_STR
) {
348 ((char*)dsp
->u
.mem
.data
)[length
-1] = '\0';
355 /* Set attributes. */
356 strcpy(dsp
->key
, key_name
);
357 strcpy(dsp
->owner
, source
);
358 dsp
->flags
= DSF_IN_USE
| (flags
& DSF_MASK_INTERNAL
);
360 /* Update subscribers having a matching subscription. */
361 update_subscribers(dsp
, 1);
366 /*===========================================================================*
368 *===========================================================================*/
369 int do_retrieve(message
*m_ptr
)
371 struct data_store
*dsp
;
372 char key_name
[DS_MAX_KEYLEN
];
373 int flags
= m_ptr
->m_ds_req
.flags
;
374 int type
= flags
& DSF_MASK_TYPE
;
379 if((r
= get_key_name(m_ptr
, key_name
)) != OK
)
382 /* Lookup the entry. */
383 if((dsp
= lookup_entry(key_name
, type
)) == NULL
)
385 if(!check_auth(dsp
, m_ptr
->m_source
, DSF_PRIV_RETRIEVE
))
388 /* Copy the requested data. */
391 m_ptr
->m_ds_reply
.val_out
.u32
= dsp
->u
.u32
;
394 m_ptr
->m_ds_reply
.val_out
.ep
= dsp
->u
.u32
;
398 length
= MIN(m_ptr
->m_ds_req
.val_len
, dsp
->u
.mem
.length
);
399 r
= sys_safecopyto(m_ptr
->m_source
, m_ptr
->m_ds_req
.val_in
.grant
, 0,
400 (vir_bytes
) dsp
->u
.mem
.data
, length
);
402 printf("DS: retrieve: copy failed to %d: %d\n",
406 m_ptr
->m_ds_reply
.val_len
= length
;
415 /*===========================================================================*
416 * do_retrieve_label *
417 *===========================================================================*/
418 int do_retrieve_label(const message
*m_ptr
)
420 struct data_store
*dsp
;
423 /* Lookup the label entry. */
424 if((dsp
= lookup_label_entry(m_ptr
->m_ds_req
.val_in
.ep
)) == NULL
)
427 /* Copy the key name. */
428 r
= sys_safecopyto(m_ptr
->m_source
,
429 (cp_grant_id_t
) m_ptr
->m_ds_req
.key_grant
, (vir_bytes
) 0,
430 (vir_bytes
) dsp
->key
, strlen(dsp
->key
) + 1);
432 printf("DS: copy failed from %d: %d\n", m_ptr
->m_source
, r
);
439 /*===========================================================================*
441 *===========================================================================*/
442 int do_subscribe(message
*m_ptr
)
444 char regex
[DS_MAX_KEYLEN
+2];
445 struct subscription
*subp
;
451 /* Find the owner. */
452 owner
= ds_getprocname(m_ptr
->m_source
);
456 /* See if the owner already has an existing subscription. */
457 if((subp
= lookup_sub(owner
)) == NULL
) {
458 /* The subscription doesn't exist, allocate a new one. */
459 if((subp
= alloc_sub_slot()) == NULL
)
461 } else if(!(m_ptr
->m_ds_req
.flags
& DSF_OVERWRITE
)) {
462 /* The subscription exists but we can't overwrite, return error. */
466 /* Copy key name from the caller. Anchor the subscription with "^regexp$" so
467 * substrings don't match. The caller will probably not expect this,
468 * and the usual case is for a complete match.
471 if((r
= get_key_name(m_ptr
, regex
+1)) != OK
)
475 /* Compile regular expression. */
476 if((e
=regcomp(&subp
->regex
, regex
, REG_EXTENDED
)) != 0) {
477 regerror(e
, &subp
->regex
, errbuf
, sizeof(errbuf
));
478 printf("DS: subscribe: regerror: %s\n", errbuf
);
482 /* If type_set = 0, then subscribe all types. */
483 type_set
= m_ptr
->m_ds_req
.flags
& DSF_MASK_TYPE
;
485 type_set
= DSF_MASK_TYPE
;
487 subp
->flags
= DSF_IN_USE
| type_set
;
488 strcpy(subp
->owner
, owner
);
489 for(b
= 0; b
< BITMAP_CHUNKS(NR_DS_KEYS
); b
++)
490 subp
->old_subs
[b
] = 0;
492 /* See if caller requested an instant initial list. */
493 if(m_ptr
->m_ds_req
.flags
& DSF_INITIAL
) {
494 int i
, match_found
= FALSE
;
495 for(i
= 0; i
< NR_DS_KEYS
; i
++) {
496 if(!(ds_store
[i
].flags
& DSF_IN_USE
))
498 if(!(ds_store
[i
].flags
& type_set
))
500 if(!check_sub_match(subp
, &ds_store
[i
], m_ptr
->m_source
))
503 SET_BIT(subp
->old_subs
, i
);
507 /* Notify in case of match. */
509 ipc_notify(m_ptr
->m_source
);
515 /*===========================================================================*
517 *===========================================================================*/
518 int do_check(message
*m_ptr
)
520 struct subscription
*subp
;
522 endpoint_t entry_owner_e
;
525 /* Find the subscription owner. */
526 owner
= ds_getprocname(m_ptr
->m_source
);
530 /* Lookup the owner's subscription. */
531 if((subp
= lookup_sub(owner
)) == NULL
)
534 /* Look for an updated entry the subscriber is interested in. */
535 for(i
= 0; i
< NR_DS_KEYS
; i
++) {
536 if(GET_BIT(subp
->old_subs
, i
))
542 /* Copy the key name. */
543 r
= sys_safecopyto(m_ptr
->m_source
,
544 (cp_grant_id_t
) m_ptr
->m_ds_req
.key_grant
, (vir_bytes
) 0,
545 (vir_bytes
) ds_store
[i
].key
, strlen(ds_store
[i
].key
) + 1);
547 printf("DS: check: copy failed from %d: %d\n", m_ptr
->m_source
, r
);
551 /* Copy the type and the owner of the original entry. */
552 entry_owner_e
= ds_getprocep(ds_store
[i
].owner
);
553 m_ptr
->m_ds_req
.flags
= ds_store
[i
].flags
& DSF_MASK_TYPE
;
554 m_ptr
->m_ds_req
.owner
= entry_owner_e
;
556 /* Mark the entry as no longer updated for the subscriber. */
557 UNSET_BIT(subp
->old_subs
, i
);
562 /*===========================================================================*
564 *===========================================================================*/
565 int do_delete(message
*m_ptr
)
567 struct data_store
*dsp
;
568 char key_name
[DS_MAX_KEYLEN
];
571 int type
= m_ptr
->m_ds_req
.flags
& DSF_MASK_TYPE
;
574 /* Lookup the source. */
575 source
= ds_getprocname(m_ptr
->m_source
);
580 if((r
= get_key_name(m_ptr
, key_name
)) != OK
)
583 /* Lookup the entry. */
584 if((dsp
= lookup_entry(key_name
, type
)) == NULL
)
587 /* Only the owner can delete. */
588 if(strcmp(dsp
->owner
, source
))
597 /* Clean up subscriptions. */
598 for (i
= 0; i
< NR_DS_SUBS
; i
++) {
599 if ((ds_subs
[i
].flags
& DSF_IN_USE
)
600 && !strcmp(ds_subs
[i
].owner
, label
)) {
601 ds_subs
[i
].flags
= 0;
605 /* Clean up data entries. */
606 for (i
= 0; i
< NR_DS_KEYS
; i
++) {
607 if ((ds_store
[i
].flags
& DSF_IN_USE
)
608 && !strcmp(ds_store
[i
].owner
, label
)) {
609 update_subscribers(&ds_store
[i
], 0);
611 ds_store
[i
].flags
= 0;
617 free(dsp
->u
.mem
.data
);
623 /* Update subscribers having a matching subscription. */
624 update_subscribers(dsp
, 0);
626 /* Clear the entry. */
632 /*===========================================================================*
634 *===========================================================================*/
635 int do_getsysinfo(const message
*m_ptr
)
641 switch(m_ptr
->m_lsys_getsysinfo
.what
) {
643 src_addr
= (vir_bytes
)ds_store
;
644 length
= sizeof(struct data_store
) * NR_DS_KEYS
;
650 if (length
!= m_ptr
->m_lsys_getsysinfo
.size
)
653 if (OK
!= (s
=sys_datacopy(SELF
, src_addr
,
654 m_ptr
->m_source
, m_ptr
->m_lsys_getsysinfo
.where
, length
))) {
655 printf("DS: copy failed: %d\n", s
);