u_instanceHandle u_instanceHandleNew( v_public object) { v_handle handle; u_instanceHandleTranslator translator; c_long id; if (object) { handle = v_publicHandle(object); if (handle.serial != (handle.serial & HANDLE_SERIAL_MASK)) { handle.serial = (handle.serial & HANDLE_SERIAL_MASK); OS_REPORT(OS_ERROR,"u_instanceHandleNew",0, "handle.serial exceeds HANDLE_SERIAL_MASK"); } id = u_userServerId(v_public(object)); if (id != (id & HANDLE_SERVER_MASK)) { id = (id & HANDLE_SERVER_MASK); OS_REPORT(OS_ERROR,"u_instanceHandleNew",0, "ServerId exceeds HANDLE_SERVER_MASK"); } translator.lid.lifecycleId = (handle.serial | id); translator.lid.localId = handle.index; } else { translator.handle = 0; } return translator.handle; }
void v_entryRemoveGroup( v_entry entry, v_group group) { c_query query; q_expr qExpr; c_value params[2]; c_iter groups; v_proxy proxy, proxy2; v_handle handle; assert(entry != NULL); assert(C_TYPECHECK(entry,v_entry)); assert(group != NULL); assert(C_TYPECHECK(group,v_group)); handle = v_publicHandle(v_public(group)); qExpr = (q_expr)q_parse("source.index = %0 and source.server = %1"); params[0] = c_longValue(handle.index); params[1] = c_addressValue(handle.server); query = c_queryNew(entry->groups, qExpr, params); q_dispose(qExpr); groups = c_select(query, 0); c_free(query); assert(c_iterLength(groups) <= 1); proxy = v_proxy(c_iterTakeFirst(groups)); proxy2 = c_remove(entry->groups, proxy, NULL, NULL); c_iterFree(groups); c_free(proxy); c_free(proxy2); }
/** * PRE: observer must be locked. */ void v_groupStreamNotifyDataAvailable( v_groupStream stream) { /* This Notify method is part of the observer-observable pattern. * It is designed to be invoked when _this object as observer receives * an event from an observable object. * It must be possible to pass the event to the subclass of itself by * calling <subclass>Notify(_this, event, userData). * This implies that _this cannot be locked within any Notify method * to avoid deadlocks. * For consistency _this must be locked by v_observerLock(_this) before * calling this method. */ C_STRUCT(v_event) event; c_bool changed; assert(stream != NULL); assert(C_TYPECHECK(stream,v_groupStream)); changed = v_statusNotifyDataAvailable(v_entity(stream)->status); if (changed) { event.kind = V_EVENT_DATA_AVAILABLE; event.source = v_publicHandle(v_public(stream)); event.userData = NULL; v_observableNotify(v_observable(stream), &event); } return; }
c_bool v_waitsetDetach ( v_waitset _this, v_observable o) { c_bool result; v_proxy found; findProxyArgument arg; void* userDataRemoved = NULL; assert(_this != NULL); assert(C_TYPECHECK(_this,v_waitset)); arg.observable = v_publicHandle(v_public(o)); arg.proxy = NULL; v_waitsetLock(_this); c_setWalk(_this->observables,findProxy,&arg); if (arg.proxy != NULL) { /* proxy to the observer found */ found = c_remove(_this->observables,arg.proxy,NULL,NULL); assert(found == arg.proxy); c_free(found); } v_waitsetUnlock(_this); result = v_observableRemoveObserver(o,v_observer(_this), &userDataRemoved); v_waitsetClearRemovedObserverPendingEvents(_this, userDataRemoved); /* wakeup blocking threads to evaluate new condition. */ if (v_observerWaitCount(_this)) { v_waitsetTrigger(_this, NULL); } return result; }
c_bool v_waitsetAttach ( v_waitset _this, v_observable o, c_voidp userData) { c_bool result; v_proxy proxy; findProxyArgument arg; assert(_this != NULL); assert(C_TYPECHECK(_this,v_waitset)); arg.observable = v_publicHandle(v_public(o)); arg.proxy = NULL; v_waitsetLock(_this); c_setWalk(_this->observables, findProxy,&arg); if (arg.proxy == NULL) { /* no proxy to the observer exists */ proxy = v_proxyNew(v_objectKernel(_this), arg.observable, userData); c_insert(_this->observables,proxy); c_free(proxy); } v_waitsetUnlock(_this); result = v_observableAddObserver(o,v_observer(_this), userData); /* wakeup blocking threads to evaluate new condition. */ if (v_observerWaitCount(_this)) { v_waitsetTrigger(_this, NULL); } return result; }
c_bool v_entryAddGroup( v_entry entry, v_group group) { v_proxy proxy; v_proxy found; c_bool result; assert(C_TYPECHECK(entry,v_entry)); assert(C_TYPECHECK(group,v_group)); proxy = v_proxyNew(v_objectKernel(group), v_publicHandle(v_public(group)), NULL); found = c_insert(entry->groups, proxy); if(found != proxy){ /* The group was already available in the groupset. This can happen if * the reader gets notified of the group it has just created. In that * case the administration should not be updated. */ result = FALSE; } else { result = TRUE; } c_free(proxy); return result; }
u_handle u_handleNew( v_public object) { v_handle handle; assert (object != NULL); handle = v_publicHandle(object); return handle; }
void v_participantDeleteHistoricalData( v_participant participant, const c_char* partitionExpr, const c_char* topicExpr) { c_iter matchingGroups; v_group group; c_time t; c_value params[2]; C_STRUCT(v_event) event; C_STRUCT(v_historyDeleteEventData) hde; assert(participant != NULL); assert(C_TYPECHECK(participant, v_participant)); assert(partitionExpr); assert(topicExpr); if(partitionExpr && topicExpr){ params[0] = c_stringValue((c_string)partitionExpr); params[1] = c_stringValue((c_string)topicExpr); c_lockRead(&participant->lock); t = v_timeGet(); matchingGroups = v_groupSetSelect( v_objectKernel(participant)->groupSet, "partition.name like %0 AND topic.name like %1", params); c_lockUnlock(&participant->lock); group = v_group(c_iterTakeFirst(matchingGroups)); while(group){ v_groupDeleteHistoricalData(group, t); c_free(group); group = v_group(c_iterTakeFirst(matchingGroups)); } c_iterFree(matchingGroups); hde.partitionExpression = (c_char *)partitionExpr; hde.topicExpression = (c_char *)topicExpr; hde.deleteTime = t; event.kind = V_EVENT_HISTORY_DELETE; event.source = v_publicHandle(v_public(participant)); event.userData = &hde; v_observableNotify(v_observable(v_objectKernel(participant)),&event); } return; }
void v_participantResendManagerRemoveWriter( v_participant p, v_writer w) { C_STRUCT(v_proxy) wp; v_proxy found; wp.source = v_publicHandle(v_public(w)); wp.userData = NULL; c_mutexLock(&p->resendMutex); found = c_remove(p->resendWriters, &wp, NULL, NULL); c_free(found); /* remove local reference transferred from collection */ c_mutexUnlock(&p->resendMutex); }
void v_participantAssertLiveliness( v_participant p) { C_STRUCT(v_event) event; assert(p != NULL); assert(C_TYPECHECK(p,v_participant)); event.kind = V_EVENT_LIVELINESS_ASSERT; event.source = v_publicHandle(v_public(p)); event.userData = NULL; /* Walk over all entities and assert liveliness on all writers */ c_lockWrite(&p->lock); c_walk(p->entities, assertLivelinessPublisher, &event); c_lockUnlock(&p->lock); }
void v_waitsetTrigger( v_waitset _this, c_voidp eventArg) { C_STRUCT(v_event) event; assert(_this != NULL); assert(C_TYPECHECK(_this,v_waitset)); v_waitsetLock(_this); event.kind = V_EVENT_TRIGGER; event.source = v_publicHandle(v_public(_this)); event.userData = NULL; v_waitsetWakeup(_this, &event, eventArg); v_waitsetUnlock(_this); }
void v_serviceFillNewGroups( v_service service) { c_set newGroups; C_STRUCT(v_event) ge; v_group g, oldGroup; c_iter oldGroups; v_kernel kernel; assert(service != NULL); assert(C_TYPECHECK(service, v_service)); kernel = v_objectKernel(service); newGroups = (c_voidp)c_setNew(v_kernelType(kernel, K_GROUP)); if (newGroups != NULL) { addAllGroups(newGroups, kernel->groupSet); v_observerLock(v_observer(service)); g = v_group(c_read(newGroups)); /* need a group for the event */ if(v_observer(service)->eventData != NULL){ oldGroups = ospl_c_select((c_set)v_observer(service)->eventData, 0); oldGroup = v_group(c_iterTakeFirst(oldGroups)); while(oldGroup){ newGroups = c_setInsert(newGroups, oldGroup); c_free(oldGroup); oldGroup = v_group(c_iterTakeFirst(oldGroups)); } c_iterFree(oldGroups); } /* just for safety, when assertion are compiled out, free the prev set */ c_free((c_object)v_observer(service)->eventData); v_observer(service)->eventData = (c_voidp)newGroups; ge.kind = V_EVENT_NEW_GROUP; ge.source = v_publicHandle(v_public(kernel)); ge.userData = g; v_observerNotify(v_observer(service), &ge, NULL); v_observerUnlock(v_observer(service)); c_free(g); } }
void v_participantResendManagerAddWriter( v_participant p, v_writer w) { v_proxy wp, found; assert(C_TYPECHECK(p,v_participant)); wp = v_proxyNew(v_objectKernel(w), v_publicHandle(v_public(w)), NULL); c_mutexLock(&p->resendMutex); found = c_insert(p->resendWriters, wp); assert((found->source.index == wp->source.index) && (found->source.serial == wp->source.serial)); c_condBroadcast(&p->resendCond); c_mutexUnlock(&p->resendMutex); c_free(wp); }
c_bool v_entryGroupExists( v_entry entry, v_group group) { c_bool r; struct groupExistsArg arg; assert(entry != NULL); assert(C_TYPECHECK(entry,v_entry)); assert(group != NULL); assert(C_TYPECHECK(group,v_group)); arg.exists = FALSE; arg.proxy = v_proxyNew(v_objectKernel(group), v_publicHandle(v_public(group)), NULL); r = c_tableWalk(entry->groups, groupExists, &arg); c_free(arg.proxy); return arg.exists; }
v_result v_kernelCreatePersistentSnapshot( v_kernel _this, const c_char * partition_expression, const c_char * topic_expression, const c_char * uri) { v_result result = V_RESULT_OK; C_STRUCT(v_event) event; v_persistentSnapshotRequest request; request = v_persistentSnapshotRequestNew(_this, partition_expression, topic_expression, uri); if(request) { event.kind = V_EVENT_PERSISTENT_SNAPSHOT; event.source = v_publicHandle(v_public(_this)); event.userData = request; v_observableNotify(v_observable(_this),&event); } else { result = V_RESULT_OUT_OF_MEMORY; } return result; }
/************************************************************** * register/deregister of leases **************************************************************/ v_result v_leaseManagerRegister( v_leaseManager _this, v_lease lease, v_leaseActionId actionId, v_public actionObject, c_bool repeatLease) { c_bool obsAdded; v_leaseAction leaseAction; v_leaseAction found; v_result result; v_kernel k; assert(_this != NULL); assert(C_TYPECHECK(_this, v_leaseManager)); assert(lease != NULL); assert(C_TYPECHECK(lease, v_lease)); assert(actionObject != NULL); assert(C_TYPECHECK(actionObject, v_public)); /* Step 1: Create a lease action object. This object will contain the relevant * information needed when reacting to an expired lease. This action information * can be different depending on which lease manager a lease is being registered * to, hence why the leaseAction object resides at leaseManager level and not * at lease level as it did in the past */ k = v_objectKernel(_this); leaseAction = v_leaseAction(v_objectNew(k, K_LEASEACTION)); if(!leaseAction) { OS_REPORT(OS_ERROR, "v_leaseManager", 0, "Failed to create a v_leaseManager object. " "Most likely not enough shared memory available to " "complete the operation."); result = V_RESULT_OUT_OF_MEMORY; } else { leaseAction->lease = v_lease(c_keep(lease)); assert(leaseAction->lease); leaseAction->actionId = actionId; leaseAction->actionObject = v_publicHandle(actionObject); leaseAction->repeat = repeatLease; /* Step 2: insert the leaseAction object into the set of leases. */ c_mutexLock(&_this->mutex); found = c_setInsert(_this->leases, leaseAction); if(!found) { /* Because the leaseAction object was just allocated we only have * to check if found is a NULL pointer. As it can never find the * action already being present in the set. */ OS_REPORT(OS_ERROR, "v_leaseManager", 0, "Unable to register the lease to the list of " "leases of the leaseManager object! Most likely not enough shared " "memory available to complete the operation."); result = V_RESULT_OUT_OF_MEMORY; c_free(leaseAction); leaseAction = NULL; } else { assert(found == leaseAction); /* Step 3: Determine if the newly inserted leaseAction will become the * 'next lease to expire'. E.G., if the lease contained within the * leaseAction object has an expiry time that is the closest to the * present time compared to the other leases managed within this lease * manager. To prevent the lease time from changing while we evaluate the * lease we will lock the lease object. */ v_leaseLock(lease); if(!_this->firstLeaseToExpire) { _this->firstLeaseToExpire = c_keep(leaseAction); /* head changed, so signal */ c_condBroadcast(&_this->cond); } else if ((_this->firstLeaseToExpire->lease != lease) && (c_timeCompare(v_leaseExpiryTime(_this->firstLeaseToExpire->lease), v_leaseExpiryTimeNoLock(lease)) == C_GT)) { c_free(_this->firstLeaseToExpire); _this->firstLeaseToExpire = c_keep(leaseAction); /* head changed, so signal */ c_condBroadcast(&_this->cond); }/* else do nothing as the newly added lease expires after the firstLeaseToExpire */ /* Step 4: Now that the lease was successfully inserted into the lease manager, * we need to register the leaseManager as an observer of the lease to ensure that the * lease manager is notified if the lease expiry time and/or duration changes. */ obsAdded = v_leaseAddObserverNoLock(lease, _this); if(!obsAdded) { OS_REPORT(OS_ERROR, "v_leaseManager", 0, "Unable to register the lease manager to the list of " "observers of the lease object! Possibly not enough " "shared memory available to complete the operation."); result = V_RESULT_INTERNAL_ERROR; v_leaseUnlock(lease); /* Remove the lease from the leaseManager */ found = c_setRemove(_this->leases, leaseAction, NULL, NULL); if(found != leaseAction) { OS_REPORT(OS_ERROR, "v_leaseManager", 0, "Unable to unregister the lease to the list of " "leases of the leaseManager object after previous internal error!"); } c_free(leaseAction); leaseAction = NULL; } else { /* Now that the lease manager is in the observer list of the lease, we can unlock the lease * as from now on we will be notified of any changes to the lease expiry time and/or duration */ v_leaseUnlock(lease); result = V_RESULT_OK; } } c_mutexUnlock(&_this->mutex); } if(leaseAction) { /* Done with the leaseAction object in this operation. If the object is not a NULL * pointer then everything went ok. The leases set of the leaseManager should be * the only one maintaining a ref count now (and possibly the 'firstLeaseToExpire' * attribute. But we do not need the leaseAction object in this operation anymore * and we are not returning it, so we need to lower the ref count for the new operation */ c_free(leaseAction); }/* else do nothing */ return result; }
/************************************************************** * Public functions **************************************************************/ c_bool v_serviceStateChangeState( v_serviceState serviceState, v_serviceStateKind stateKind) { c_bool changed; C_STRUCT(v_event) event; assert(C_TYPECHECK(serviceState, v_serviceState)); c_lockWrite(&serviceState->lock); switch (stateKind) { case STATE_NONE: break; case STATE_DIED: if ((serviceState->stateKind != STATE_NONE) && (serviceState->stateKind != STATE_TERMINATED)) { serviceState->stateKind = stateKind; } break; case STATE_INITIALISING: if ((serviceState->stateKind == STATE_NONE) || (serviceState->stateKind == STATE_DIED)) { serviceState->stateKind = stateKind; } break; case STATE_OPERATIONAL: if (serviceState->stateKind == STATE_INITIALISING) { serviceState->stateKind = stateKind; } break; case STATE_INCOMPATIBLE_CONFIGURATION: if ((serviceState->stateKind == STATE_OPERATIONAL) || (serviceState->stateKind == STATE_INITIALISING)) { serviceState->stateKind = stateKind; } break; case STATE_TERMINATING: if ((serviceState->stateKind == STATE_INITIALISING) || (serviceState->stateKind == STATE_OPERATIONAL)) { serviceState->stateKind = stateKind; } break; case STATE_TERMINATED: if (serviceState->stateKind == STATE_TERMINATING) { serviceState->stateKind = stateKind; } break; default: OS_REPORT_1(OS_ERROR,"Kernel::ServiceState",0, "Unkown state (%d) kind provided.",stateKind); assert(FALSE); /* unknown state */ break; } if (serviceState->stateKind == stateKind) { changed = TRUE; } else { changed = FALSE; } c_lockUnlock(&serviceState->lock); event.kind = V_EVENT_SERVICESTATE_CHANGED; event.source = v_publicHandle(v_public(serviceState)); event.userData = NULL; v_observableNotify(v_observable(serviceState),&event); return changed; }
v_historyResult v_readerWaitForHistoricalDataWithCondition( v_reader _this, c_char* filter, c_char* params[], c_ulong paramsLength, c_time minSourceTime, c_time maxSourceTime, struct v_resourcePolicy *resourceLimits, c_time timeout) { c_iter entries; c_object e; v_historyResult result; v_historicalDataRequest request; c_bool doRequest, doWait; struct historicalWaitArg arg; C_STRUCT(v_event) event; arg._expire_time = c_timeAdd(v_timeGet(), timeout); arg._status = TRUE; request = v_historicalDataRequestNew(v_objectKernel(_this), filter, params, paramsLength, minSourceTime, maxSourceTime, resourceLimits); if(request){ V_READER_LOCK(_this); if(_this->historicalDataRequest) { /* Historical data request already in progress or complete, check * whether request is equal to the original one. */ doRequest = FALSE; if(v_historicalDataRequestEquals(request, _this->historicalDataRequest)){ /* Request is equal to original request*/ result = V_HISTORY_RESULT_OK; if(_this->historicalDataComplete){ /* Request has already been fulfilled. Consider this call * a no-operation. */ doWait = FALSE; } else { /* Request is still in progress, wait for data to arrive*/ doWait = TRUE; } } else { /* The requested parameters are not equal to the originally * requested set. Return a precondition not met. */ doWait = FALSE; result = V_HISTORY_RESULT_PRE_NOT_MET; } c_free(request); } else { /* No active request, so validate it now.*/ if(v_historicalDataRequestIsValid(request, _this)){ /* This request is valid, so request data.*/ doRequest = TRUE; doWait = TRUE; result = V_HISTORY_RESULT_OK; _this->historicalDataRequest = request; } else { /* Request is not valid, so return bad parameter.*/ doRequest = FALSE; doWait = FALSE; result = V_HISTORY_RESULT_BAD_PARAM; c_free(request); } } V_READER_UNLOCK(_this); } else { doRequest = FALSE; doWait = FALSE; result = V_HISTORY_RESULT_ERROR; } if(doWait){ v_readerEntrySetLock(_this); entries = c_select(_this->entrySet.entries, 0); v_readerEntrySetUnlock(_this); if(doRequest){ /* Historical data must be requested, since this is the first time * the operation is called and the request is valid. */ if (_this->qos->durability.kind == V_DURABILITY_VOLATILE) { /* If reader is volatile, the historical data from the * group(s) has/have not been retrieved yet, so do it now. */ e = c_iterTakeFirst(entries); while (e != NULL) { getHistoricalData(e, _this->historicalDataRequest); c_free(e); e = c_iterTakeFirst(entries); } c_iterFree(entries); } event.kind = V_EVENT_HISTORY_REQUEST; event.source = v_publicHandle(v_public(_this)); event.userData = _this->historicalDataRequest; v_observableNotify(v_observable(v_objectKernel(_this)),&event); } V_READER_LOCK(_this); if(!_this->historicalDataComplete){ if (c_timeCompare(timeout, C_TIME_INFINITE) != C_EQ) { if (c_condTimedWait(&_this->historicalDataCondition, &V_READER_GET_LOCK(_this), timeout) != SYNC_RESULT_SUCCESS) { result = V_HISTORY_RESULT_TIMEOUT; } } else if (c_condWait(&_this->historicalDataCondition, &V_READER_GET_LOCK(_this)) != SYNC_RESULT_SUCCESS) { result = V_HISTORY_RESULT_TIMEOUT; } assert( (result == V_HISTORY_RESULT_OK) == _this->historicalDataComplete); } V_READER_UNLOCK(_this); } return result; }