Пример #1
0
/*{
**  Name:	MOset - set value associated with an instance
**
**  Description:
**
**	Attempts to set the value associated with the instance.
**
**	If the call succeeds, it must also call the monitors for the
**	class with the MO_SET event, the instance id, and the new value.
**  Inputs:
**	 valid_perms
**		the roles currently in effect, to be and-ed with object
**		permissions to determine access rights.
**	 class
**		the class whose value should be altered.
**	 instance
**		the instance in question.
**	 val
**		pointer to the string containing the new value.
**  Outputs:
**	 none
**  Returns:
**	 OK
**		if the value was set
**	 MO_NO_INSTANCE
**		if the class is not attached
**	 MO_NO_WRITE
**		if the class may not be changed.
**	 other
**		error status returned by a method.
**  History:
**	23-sep-92 (daveb)
**	    documented
**	 6-Apr-04 (gordy)
**	    Permit access if MO_ANY_WRITE attribute is set.
**	24-Oct-05 (toumi01) BUG 115449
**	    Don't hold onto MO mutex if class' processing will try
**	    to take the mutex, and would thus deadlock on ourself.
*/
STATUS
MOset(i4 valperms,
      char *classid,
      char *instance,
      char *val )
{
    STATUS stat = OK;
    MO_CLASS *cp;
    PTR idata;

    MO_once();
    stat = MO_mutex();
    if( stat != OK )
	return( stat );
    MO_nset++;

    /* get class and instance data */

    if( OK == (stat = MO_getclass( classid, &cp ) ) )
    {
	if( (cp->perms & MO_ANY_WRITE) != 0  ||  
	    (valperms & MO_WRITE & cp->perms) != 0 )
	    stat = (*cp->idx)( MO_GET, cp->cdata, 0, instance, &idata );
	else
	    stat = MO_NO_WRITE;
    }

    if( stat == OK )
    {
	if (cp->cflags & MO_NO_MUTEX)
	    (VOID) MO_unmutex();
	stat = (*cp->set)( cp->offset, 0, val, cp->size, idata );
	if (cp->cflags & MO_NO_MUTEX)
	{
	    stat = MO_mutex();
	    if( stat != OK )
		return( stat );
	}
    }

    if( stat == OK )
	(VOID) MO_tell_class( cp, instance, val, MO_SET );

    (VOID) MO_unmutex();
    return( stat );
}
Пример #2
0
VOID
MO_once(void)
{
    i4	state;
 
    if( MO_classes == NULL )
    {
	/* tricky recursion problem here -- i_sem
	   wants to do an attach, but we aren't ready.
	   This means no monitoring of MO_sem, sigh.  FIXME. */
	state = MO_disabled;
	MO_disabled = MO_DISABLE;
	(VOID) MUi_semaphore( &MO_sem );
	MUn_semaphore( &MO_sem, "MO" );
	MO_semcnt = 0;
	MO_disabled = (state) ? TRUE : FALSE;

	(VOID) MO_mutex();
	MUn_semaphore( &MO_sem, "MO" );
	MO_classes = SPinit( &MOclass_tree, STcompare );
	MO_instances = SPinit( &MOinstance_tree, MO_instance_compare );
	MO_strings = SPinit( &MOstring_tree, STcompare );
	MO_monitors = SPinit( &MOmonitor_tree, MO_mon_compare );
	(VOID) MO_unmutex();

	/* MO classes */

	(void) MOclassdef( MAXI2, MO_cdefs );
	(void) MOclassdef( MAXI2, MO_mem_classes );
	(void) MOclassdef( MAXI2, MO_meta_classes ); 
	(void) MOclassdef( MAXI2, MO_mon_classes ); 
	(void) MOclassdef( MAXI2, MO_str_classes );
	(void) MOclassdef( MAXI4, MO_tree_classes );

	/* tables */

	MO_classes->name = "mo_classes";
	MO_instances->name = "mo_instances";
	MO_strings->name = "mo_strings";
	MO_monitors->name = "mo_monitors";

	(void) MOsptree_attach( MO_classes );
	(void) MOsptree_attach( MO_instances );
	(void) MOsptree_attach( MO_strings );
	(void) MOsptree_attach( MO_monitors );
    }
}
Пример #3
0
STATUS
MOon_off( i4  operation, i4  *old_state )
{
    STATUS stat = OK;

    stat = MO_mutex();
    if( stat != OK )
	return( stat );

    *old_state = MO_disabled;
    if( operation != MO_INQUIRE )
	MO_disabled = (operation) ? TRUE : FALSE;

    (VOID) MO_unmutex();

    return( stat );
}
Пример #4
0
STATUS
MOget(i4 valperms,
      char *classid,
      char *instance,
      i4  *lsbufp,
      char *sbuf,
      i4  *operms )
{
    STATUS stat;
    MO_once();
    stat = MO_mutex();
    if( stat == OK )
    {
	stat = MO_get( valperms, classid, instance, lsbufp, sbuf, operms );
	(VOID) MO_unmutex();
    }
    return( stat );
}
Пример #5
0
STATUS
MOtell_monitor( char *classid, char *instance, char *value, i4  msg )
{
    MO_CLASS *cp;
    STATUS ret_val = OK;

    MO_once();
    ret_val = MO_mutex();
    if( ret_val == OK )
    {
	ret_val = MO_getclass( classid, &cp );
	if( ret_val == OK && cp->monitor != NULL )
	    ret_val = MO_tell_class( cp, instance, value, msg );

	(VOID) MO_unmutex();
    }
    return( ret_val );
}
Пример #6
0
/*{
**  Name:	MOdetach - detach an attached instance
**
**  Description:
**
**	Detaches an attached instance.  Subsequent attempts to get or
**	set it will fail, and an attempts to attach it will succeed.
**
**	Frees memory allocated by MOattach using MEfree.
**
**	If the call succeeds, it must also call the monitors for the
**	class with the MO_DETACH event, the instance id, and a NULL
**	value.
**
**  Inputs:
**	 classid
**		the classid of the object.
**	 instance
**		the instance of the object.
**  Outputs:
**	 none
**  Returns:
**	 OK
**		if the classid was detached.
**	 MO_NO_INSTANCE
**		if classid is not attached.
**	 MO_NO_DETACH
**		if the object was attached as MO_PERMANENT.
**
**    History:
**	15-jul-92 (daveb)
**	    Go back to single-instance attach/detach, as with
**	    MOcdata_index most bulky static one-offs will be
**	    right in the class definitions anyway, and this
**	    is simpler for the dynamic attach.
**	02-sep-1999 (somsa01)
**	    We were calling MO_tell_class AFTER releasing the MO mutex.
*/
STATUS
MOdetach( char *classid, char *instance )
{
    MO_INSTANCE	*ip;
    MO_CLASS	*cp;
    STATUS stat = OK;
    STATUS mutex_stat = OK;

    MO_once();
    mutex_stat = MO_mutex();
    do
    {
	if( mutex_stat != OK )		/* got mutex */
	    break;

	MO_ndetach++;

	ip = MO_getinstance( classid, instance );
	if( NULL == ip )
	{
	    stat = MO_NO_INSTANCE;
	    break;
	}

	cp = ip->classdef;
	if( cp->perms & MO_PERMANENT )
	{
	    stat = MO_NO_DETACH;
	    break;
	}

	/*
	** We have detachable instance, do it
	*/

	/* detach twin, if any, giving up it it won't go away */

	if( CMalpha( classid ) && NULL != cp->twin &&
	   (stat = MOdetach( cp->twin->node.key, ip->instance)) != OK )
	    break;

	/* delete saved instance string */

	if( (ip->iflags & MO_INSTANCE_VAR) != 0 )
	    MO_delstring( ip->instance );

	/* and finally delete this node */

	SPdelete( &ip->node, MO_instances );
	MO_free( (PTR)ip, sizeof(*ip) );

    } while( FALSE );

    if( mutex_stat == OK )
	(VOID) MO_unmutex();
    else
	stat = mutex_stat;

    if( stat == OK )
    {
	if ( (stat = MO_mutex()) == OK)
	{
	    (VOID) MO_tell_class( cp, instance, (char *)NULL, MO_DETACH );
            MO_unmutex ();
	}
    }

    return( stat );
}
Пример #7
0
STATUS
MOattach( i4  flags, char *classid, char *instance, PTR idata )
{
    MO_INSTANCE	*ip;
    MO_CLASS	*cp;
    STATUS	stat;

    stat = OK;

    if( MO_disabled )
	return( stat );

    MO_once();
    stat = MO_mutex();
    if( stat == OK )		/* got mutex */
    {
	do
	{
	    if( stat != OK )
		break;

	    MO_nattach++;

# ifdef xDEBUG
	    SIprintf("attach %s:%s object %p\n",
		     classid,
		     instance,
		     idata );
# endif

	    /* check for special error cases */

	    ip = MO_getinstance( classid, instance );
	    if( ip != NULL )
	    {
		stat = MO_ALREADY_ATTACHED;
		break;
	    }

	    /* Get class, error if missing */

	    if( OK != MO_getclass( classid, &cp ) )
	    {
		stat = MO_NO_CLASSID;
		break;
	    }

	    /* Release mutex to prevent deadlock in MO_alloc call */
	    (VOID) MO_unmutex();
	    ip = (MO_INSTANCE *)MO_alloc( sizeof(*ip), &stat );
            stat = MO_mutex();
	    if( NULL == ip )
		break;

	    ip->classdef = cp;
	    ip->iflags = flags;
	    if( (flags & MO_INSTANCE_VAR) == 0 )
	    {
		ip->instance = instance;
	    }
	    else
	    {
		ip->instance = MO_defstring( instance, &stat );
		if( ip->instance == NULL )
		{
		    MO_free( (PTR)ip, sizeof(*ip) );
		    break;
		}
	    }
	    ip->idata = idata;
	    ip->node.key = (PTR)ip;

	    (VOID) SPenq( &ip->node, MO_instances );

	} while( FALSE );

	(VOID) MO_unmutex();

	/* Attach twin if needed */

	if( stat == OK && cp->twin != NULL && !CMdigit( (char *)cp->node.key ) )
	    stat = MOattach( flags, cp->twin->node.key, instance, idata );
    }

# if xDEBUG
    if( stat != OK )
	TRdisplay("attach (%s:%s) failed status %d\n",
		  classid, instance, stat );
# endif

    if( stat == OK )
    {
	if ( (stat = MO_mutex()) == OK)
	{
	    (VOID) MO_tell_class( cp, instance, (char *)NULL, MO_ATTACH );
            MO_unmutex ();
	}
    }

    return( stat );
}
Пример #8
0
STATUS
MOset_monitor(	char *classid,
		PTR mon_data,
		char *qual_regexp,
		MO_MONITOR_FUNC *monitor,
		MO_MONITOR_FUNC **old_monitor )
{
    MO_MON_BLOCK *mp;		/* our monitor block */
    MO_MON_BLOCK *fmp;		/* first monitor block */
    MO_MON_BLOCK *pmp;		/* previous monitor block */
    MO_CLASS *cp;		/* class in question (not classid) */
    char *saved_qual = NULL;

    STATUS ret_val = OK;
    STATUS mutex_stat;

    mutex_stat = MO_mutex();
    do
    {
	if( mutex_stat != OK )
	    break;

	/* if we'll need it, save any qual_regexp string */

	if( monitor != NULL && qual_regexp != NULL )
	{
	    saved_qual = MO_defstring( qual_regexp, &ret_val );
	    if( saved_qual == NULL )
		break;

	    /* FIXME maybe compile it here too? */
	}

	/* locate the class def, we need it everywhere */

	if( (ret_val = MO_getclass( classid, &cp )) != OK )
	    break;

	/* see if this is a replacement for an existing monitor */

	mp = NULL;
	if( (mp = MO_getmon( cp, mon_data ) ) != NULL )
	{
	    /* yes, replace it with new values as appropriate */

	    *old_monitor = mp->monitor;
	    if( monitor == NULL ) /* delete this monitor */
	    {
		MO_delmon( mp );
	    }
	    else		/* replace this one's values */
	    {
		mp->monitor = monitor;
		mp->mon_data = mon_data;

		/* delete old qual string */
		if( mp->qual_regexp != NULL )
		    MO_delstring( mp->qual_regexp );
		mp->qual_regexp = saved_qual;
	    }
	}
	else if( monitor == NULL ) /* huh!? */
	{
	    ret_val = MO_BAD_MONITOR;
	    break;
	}
	else			/* make a new one and link it in. */
	{
	    *old_monitor = NULL;

	    /* if it's an OID, get the class def instead */

	    if( CMdigit( (char *)cp->node.key ) && cp->twin != NULL )
		cp = cp->twin;

	    /* get a new monitor block */

	    mp = (MO_MON_BLOCK *)MO_alloc( sizeof( *mp ), &ret_val );
	    if( mp == NULL )
		break;

	    /* fill in the new block, and link in to the tree */

	    mp->node.key = (PTR)mp;
	    mp->mo_class = cp;
	    mp->monitor = monitor;
	    mp->mon_data = mon_data;
	    mp->qual_regexp = saved_qual;
	    (void) SPenq( &mp->node, MO_monitors );

	    /* Fill in the class with first monitor for the class.
	       The loop below goes backwards until pmp is null or
	       doesn't have the same class definition.  When it exits,
	       fmp is at the first monitor block for the class */

	    for( fmp = mp;
		(pmp = (MO_MON_BLOCK *)SPfprev( &fmp->node )) != NULL &&
		pmp->mo_class == cp; fmp = pmp )
		continue;

	    fmp->mo_class->monitor = fmp;
	    if( cp->twin )
		cp->twin->monitor = fmp;
	}

    } while ( FALSE );

    if( mutex_stat != OK )
    {
	ret_val = mutex_stat;
    }
    else
    {
	if( ret_val == OK )
	    MO_nset_monitor++;
	else if( saved_qual != NULL )
	    MO_delstring( saved_qual );

	(void) MO_unmutex();
    }

    return( ret_val );
}