/*{ ** 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 ); }
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 ); }
STATUS MO_get(i4 valperms, char *classid, char *instance, i4 *lsbufp, char *sbuf, i4 *operms ) { STATUS stat; MO_CLASS *cp; PTR idata; MO_nget++; stat = OK; *sbuf = EOS; /* get class and instance data */ if( OK == (stat = MO_getclass( classid, &cp ) ) ) { if( (cp->perms & MO_ANY_READ) != 0 || (valperms & MO_READ & cp->perms) != 0 ) stat = (*cp->idx)( MO_GET, cp->cdata, 0, instance, &idata ); else stat = MO_NO_READ; } if( stat == OK ) stat = (*cp->get)( cp->offset, cp->size, idata, *lsbufp, sbuf ); if( stat == OK || stat == MO_VALUE_TRUNCATED ) { *operms = cp->perms; (VOID) MO_tell_class( cp, instance, sbuf, MO_GET ); } return( stat ); }
/*{ ** 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 ); }
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 ); }
STATUS MO_getnext(i4 valperms, i4 lclassid, i4 linstance, char *classid, char *instance, i4 *lsbufp, char *sbuf, i4 *operms ) { STATUS stat = OK; STATUS xstat = OK; MO_INSTANCE *ip; MO_CLASS *cp; /* this class */ PTR idata; MO_ngetnext++; # ifdef xDEBUG SIprintf("getnext entry: %s:%s\n", classid, instance ); # endif ip = NULL; cp = NULL; *sbuf = EOS; if( *instance != EOS ) { ip = MO_getinstance( classid, instance ); if( ip != NULL ) cp = ip->classdef; else if( OK != MO_getclass( classid, &cp ) ) stat = MO_NO_CLASSID; } else if( *classid != EOS && OK != MO_getclass( classid, &cp ) ) { stat = MO_NO_CLASSID; } /* ** Now do the real work: Given the starting point implied ** by ip and cp, find the next visible instance. */ if( stat == OK ) { if( cp == NULL ) /* start with first class */ { cp = (MO_CLASS *) SPfhead( MO_classes ); ip = NULL; } /* ** Loop over classes looking for the next valid instance. ** ** On exit, if cp != NULL, it's the class of the found instance; ** if NULL, then we never found a good instance. */ for( ; cp != NULL ; cp = (MO_CLASS *)SPnext( &cp->node, MO_classes ) ) { if( (cp->perms & MO_ANY_READ) != 0 || (valperms & MO_READ & cp->perms) != 0 ) { stat = (*cp->idx)( MO_GETNEXT, cp->cdata, linstance, instance, &idata ); if( stat == OK ) { stat = (*cp->get)( cp->offset, cp->size, idata, *lsbufp, sbuf ); if( stat == OK ) break; } } /* Now caller's ip and instance are bogus; set to search state */ ip = NULL; *instance = EOS; } if( cp == NULL ) stat = MO_NO_NEXT; if( stat == OK || MO_IS_TRUNCATED( stat ) ) xstat = MOstrout( MO_CLASSID_TRUNCATED, cp->node.key, lclassid, classid ); if( stat == OK ) stat = xstat; } *lsbufp = (i4)STlength( sbuf ); if( stat == OK || stat == MO_VALUE_TRUNCATED ) { *operms = cp->perms; (VOID) MO_tell_class( cp, instance, sbuf, MO_GET ); } # ifdef xDEBUG SIprintf("getnext exit: (%d) %s:%s - %s\n", stat, classid, instance, sbuf ); # endif return( stat ); }