164 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			164 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* Implementation of the Data Store. */
 | |
| 
 | |
| #include "inc.h"
 | |
| 
 | |
| /* Allocate space for the data store. */
 | |
| PRIVATE struct data_store ds_store[NR_DS_KEYS];
 | |
| 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 int set_owner(dsp, ap)
 | |
| struct data_store *dsp;				/* data store structure */
 | |
| void *ap;					/* authorization pointer */
 | |
| {
 | |
|   /* Authorize the caller. */
 | |
|   return(TRUE);
 | |
| }
 | |
| 
 | |
| 
 | |
| PRIVATE int is_authorized(dsp, ap)
 | |
| struct data_store *dsp;				/* data store structure */
 | |
| void *ap;					/* authorization pointer */
 | |
| {
 | |
|   /* Authorize the caller. */
 | |
|   return(TRUE);
 | |
| }
 | |
| 
 | |
| 
 | |
| PRIVATE int find_key(key, dsp)
 | |
| int key;					/* key to look up */
 | |
| struct data_store **dsp;			/* store pointer here */
 | |
| {
 | |
|   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) {
 | |
| 	  *dsp = &ds_store[i];
 | |
|           return(TRUE);				/* report success */
 | |
|       }
 | |
|   }
 | |
|   return(FALSE);				/* report not found */
 | |
| }
 | |
| 
 | |
| 
 | |
| PUBLIC int do_publish(m_ptr)
 | |
| message *m_ptr;					/* request message */
 | |
| {
 | |
|   struct data_store *dsp;
 | |
| 
 | |
|   /* 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 (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 */
 | |
| 	  nr_in_use ++;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /* 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;	
 | |
| 
 | |
|   /* 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. */
 | |
|   }
 | |
| 
 | |
|   return(OK);
 | |
| }
 | |
| 
 | |
| 
 | |
| PUBLIC int do_retrieve(m_ptr)
 | |
| message *m_ptr;					/* request message */
 | |
| {
 | |
|   struct data_store *dsp;
 | |
| 
 | |
|   /* 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 */
 | |
|           }
 | |
|       }
 | |
| 
 | |
|       /* 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 */
 | |
|       return(OK);					/* report success */
 | |
|   }
 | |
|   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
 | |
|    * to be sent to the subscribed. On success, directly return a copy of the
 | |
|    * data for the given key. 
 | |
|    */
 | |
|   return(ENOSYS);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				do_getsysinfo				     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int do_getsysinfo(m_ptr)
 | |
| message *m_ptr;
 | |
| {
 | |
|   vir_bytes src_addr, dst_addr;
 | |
|   int dst_proc;
 | |
|   size_t len;
 | |
|   int s;
 | |
| 
 | |
|   switch(m_ptr->m1_i1) {
 | |
|   case SI_DATA_STORE:
 | |
|   	src_addr = (vir_bytes) ds_store;
 | |
|   	len = sizeof(struct data_store) * NR_DS_KEYS;
 | |
|   	break; 
 | |
|   default:
 | |
|   	return(EINVAL);
 | |
|   }
 | |
| 
 | |
|   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)))
 | |
|   	return(s);
 | |
|   return(OK);
 | |
| }
 | |
| 
 | 
