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);
 | 
						|
}
 | 
						|
 |