/** * 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; }
/************************************************************** * Protected functions **************************************************************/ void v_serviceNotify( v_service service, v_event event, c_voidp userData) { v_group group; assert(service != NULL); assert(C_TYPECHECK(service, v_service)); if (event != NULL) { switch (event->kind) { case V_EVENT_SERVICESTATE_CHANGED: break; case V_EVENT_NEW_GROUP: group = v_group(event->userData); if ((group != NULL) && (v_observer(service)->eventData != NULL)) { /* Update new group admin */ c_insert((c_set)v_observer(service)->eventData, group); } /* This allows receiving the event by means of a waitset.*/ v_observableNotify(v_observable(service), event); break; case V_EVENT_HISTORY_DELETE: /* This allows receiving the event by means of a waitset.*/ v_observableNotify(v_observable(service), event); break; case V_EVENT_HISTORY_REQUEST: /* This allows receiving the event by means of a waitset.*/ v_observableNotify(v_observable(service), event); break; case V_EVENT_CONNECT_WRITER: case V_EVENT_PERSISTENT_SNAPSHOT: /* This allows receiving the event by means of a waitset.*/ v_observableNotify(v_observable(service), event); break; default: break; } } v_participantNotify(v_participant(service), event, userData); }
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; }
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; }
/************************************************************** * 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; }