v_result v_participantSetQos( v_participant p, v_participantQos qos) { v_message builtinMsg; v_kernel kernel; v_qosChangeMask cm; v_result result; assert(C_TYPECHECK(p,v_participant)); /* Do not use C_TYPECHECK on qos parameter, since it might be allocated on heap! */ kernel = v_objectKernel(p); c_lockWrite(&p->lock); result = v_participantQosSet(p->qos, qos, &cm); if ((result == V_RESULT_OK) && (cm != 0)) { builtinMsg = v_builtinCreateParticipantInfo(kernel->builtin,p); c_lockUnlock(&p->lock); v_writeBuiltinTopic(kernel, V_PARTICIPANTINFO_ID, builtinMsg); c_free(builtinMsg); } else { c_lockUnlock(&p->lock); } return result; }
void v_subscriberRemoveReader( v_subscriber s, v_reader r) { v_reader found; v_partition d; c_iter iter; assert(s != NULL); assert(r != NULL); iter = c_iterNew(NULL); c_lockWrite(&s->lock); found = c_remove(s->readers,r,NULL,NULL); v_partitionAdminWalk(s->partitions,collectPartitions,iter); while ((d = c_iterTakeFirst(iter)) != NULL) { /* ES, dds1576: The unsubscribe here is performed for all partitions, * however for the K_DATAREADER class not all partitions were * actually subscribed too. Instead of verifying if a partition was * subscribed too or not, the unsubscribe is just executed every time * as this is 'cheaper' then performing the access check again. * If a partition was not subscribed too then the unsubcribe will have no * effect. */ v_readerUnSubscribe(r,d); c_free(d); } c_lockUnlock(&s->lock); c_iterFree(iter); c_free(found); }
void v_subscriberUnSubscribe( v_subscriber s, const c_char *partitionExpr) { v_partition d; v_dataReaderConnectionChanges arg; v_partitionPolicy old; assert(s != NULL); assert(C_TYPECHECK(s,v_subscriber)); arg.addedPartitions = NULL; c_lockWrite(&s->lock); arg.removedPartitions = v_partitionAdminRemove(s->partitions, partitionExpr); old = s->qos->partition; s->qos->partition = v_partitionPolicyRemove(old, partitionExpr, c_getBase(c_object(s))); c_free(old); c_setWalk(s->readers, qosChangedAction, &arg); d = v_partition(c_iterTakeFirst(arg.removedPartitions)); while (d != NULL) { c_free(d); d = v_partition(c_iterTakeFirst(arg.removedPartitions)); } c_iterFree(arg.removedPartitions); c_lockUnlock(&s->lock); }
v_partition v_addPartition( v_kernel kernel, v_partition partition) { v_partition found; assert(kernel != NULL); assert(C_TYPECHECK(kernel,v_kernel)); assert(partition != NULL); assert(C_TYPECHECK(partition,v_partition)); c_lockWrite(&kernel->lock); found = c_insert(kernel->partitions,partition); c_lockUnlock(&kernel->lock); if (found != partition) { assert(v_objectKind(found) == K_DOMAIN); if (v_objectKind(found) != K_DOMAIN) { partition = NULL; } else { partition = found; } } return partition; }
void v_subscriberAddReader( v_subscriber s, v_reader r) { v_reader found; v_partition d; c_iter iter; assert(s != NULL); assert(r != NULL); iter = c_iterNew(NULL); c_lockWrite(&s->lock); v_partitionAdminWalk(s->partitions,collectPartitions,iter); while ((d = c_iterTakeFirst(iter)) != NULL) { v_readerSubscribe(r,d); c_free(d); } found = c_setInsert(s->readers,r); c_lockUnlock(&s->lock); if (found != r) { OS_REPORT_1(OS_ERROR, "v_subscriberAddReader", 0, "shared <%s> name already defined", r->qos->share.name); } c_iterFree(iter); }
void v_participantRenewLease( v_participant p, v_duration leasePeriod) { assert(p != NULL); assert(C_TYPECHECK(p, v_participant)); c_lockWrite(&p->lock); v_leaseRenew(p->lease, leasePeriod); c_lockUnlock(&p->lock); }
c_bool v_isEnabledStatistics( v_kernel k, const char *categoryName) { c_bool result; c_lockRead(&k->lock); result = isEnabledStatisticsUnlocked(k, categoryName); c_lockUnlock(&k->lock); return result; }
c_iter v_subscriberLookupReaders( v_subscriber s) { c_iter list; assert(s != NULL); c_lockRead(&s->lock); list = ospl_c_select(s->readers,0); c_lockUnlock(&s->lock); return list; }
v_subscriberQos v_subscriberGetQos( v_subscriber s) { v_subscriberQos qos; assert(s != NULL); c_lockRead(&s->lock); qos = v_subscriberQosNew(v_objectKernel(s), s->qos); c_lockUnlock(&s->lock); return qos; }
const c_char * v_serviceStateGetName( v_serviceState serviceState) { c_char *name; assert(C_TYPECHECK(serviceState, v_serviceState)); c_lockRead(&serviceState->lock); name = v_entityName(serviceState); c_lockUnlock(&serviceState->lock); return (const c_char *)name; }
v_serviceStateKind v_serviceStateGetKind( v_serviceState serviceState) { v_serviceStateKind kind; assert(C_TYPECHECK(serviceState, v_serviceState)); c_lockRead(&serviceState->lock); kind = serviceState->stateKind; c_lockUnlock(&serviceState->lock); return kind; }
c_iter v_partitionLookupSubscribers( v_partition partition) { c_iter participants; c_iter result; c_iter entities; c_iter partitions; v_participant participant; v_entity entity; v_entity partition2; result = NULL; participants = v_resolveParticipants(v_objectKernel(partition), "*"); participant = v_participant(c_iterTakeFirst(participants)); while (participant != NULL) { c_lockRead(&participant->lock); entities = c_select(participant->entities, 0); c_lockUnlock(&participant->lock); entity = v_entity(c_iterTakeFirst(entities)); while (entity != NULL) { if(v_objectKind(entity) == K_SUBSCRIBER) { partitions = v_subscriberLookupPartitions(v_subscriber(entity), v_partitionName(partition)); if (c_iterLength(partitions) > 0) { result = c_iterInsert(result, entity); /* transfer refcount */ } else { c_free(entity); } partition2 = v_entity(c_iterTakeFirst(partitions)); while (partition2 != NULL) { c_free(partition2); partition2 = v_entity(c_iterTakeFirst(partitions)); } c_iterFree(partitions); } /* entity is already free or refcount transferred to result */ entity = v_entity(c_iterTakeFirst(entities)); } c_iterFree(entities); c_free(participant); participant = v_participant(c_iterTakeFirst(participants)); } c_iterFree(participants); return result; }
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; }
c_iter v_subscriberLookupPartitions( v_subscriber s, const c_char *partitionExpr) { c_iter list; assert(s != NULL); c_lockRead(&s->lock); list = v_partitionAdminLookup(s->partitions, partitionExpr); c_lockUnlock(&s->lock); return list; }
void v_enableStatistics( v_kernel k, const char *categoryName) { v_statisticsCategory category; c_lockWrite(&k->lock); /* Only add this if it is not yet enabled */ if (!isEnabledStatisticsUnlocked(k, categoryName)) { category = v_statisticsCategoryNew(k, categoryName); c_append(k->enabledStatisticsCategories, category); } c_lockUnlock(&k->lock); }
void v_participantNotify( v_participant _this, v_event event, c_voidp userData) { /* 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 as observer cannot be locked within any * Notify method to avoid deadlocks. * For consistency _this must be locked by v_observerLock(_this) before * calling this method. */ assert(_this != NULL); assert(C_TYPECHECK(_this,v_participant)); if (event) { switch (event->kind) { case V_EVENT_NEW_GROUP: assert(event->userData); c_mutexLock(&_this->newGroupListMutex); c_listInsert(_this->newGroupList,v_group(event->userData)); c_mutexUnlock(&_this->newGroupListMutex); break; case V_EVENT_LIVELINESS_ASSERT: c_lockWrite(&_this->lock); c_walk(_this->entities, assertLivelinessPublisher, event); c_lockUnlock(&_this->lock); break; case V_EVENT_SERVICESTATE_CHANGED: case V_EVENT_DATA_AVAILABLE: case V_EVENT_HISTORY_DELETE: case V_EVENT_HISTORY_REQUEST: case V_EVENT_PERSISTENT_SNAPSHOT: /*Do nothing here.*/ break; default: OS_REPORT_1(OS_WARNING,"v_participantNotify",0, "Notify encountered unknown event kind (%d)", event->kind); break; } } }
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_participantRemove( v_participant p, v_entity e) { v_entity found; assert(p != NULL); assert(C_TYPECHECK(p,v_participant)); assert(e != NULL); assert(C_TYPECHECK(e,v_entity)); c_lockWrite(&p->lock); found = c_remove(p->entities,e,NULL,NULL); c_lockUnlock(&p->lock); c_free(found); }
void v_participantAdd( v_participant p, v_entity e) { v_entity found; assert(p != NULL); assert(C_TYPECHECK(p,v_participant)); assert(e != NULL); assert(C_TYPECHECK(e,v_entity)); c_lockWrite(&p->lock); found = c_setInsert(p->entities,e); c_lockUnlock(&p->lock); assert(found == e); }
c_iter v_subscriberLookupReadersByTopic( v_subscriber s, const c_char *topicName) { struct lookupReaderByTopicArg arg; assert(s != NULL); arg.list = NULL; arg.topicName = topicName; c_lockRead(&s->lock); c_setWalk(s->readers, (c_action)lookupReaderByTopic, &arg); c_lockUnlock(&s->lock); return arg.list; }
v_participant v_removeParticipant( v_kernel kernel, v_participant p) { v_participant found; assert(kernel != NULL); assert(C_TYPECHECK(kernel,v_kernel)); assert(p != NULL); assert(C_TYPECHECK(p,v_participant)); c_lockWrite(&kernel->lock); found = c_remove(kernel->participants,p,NULL,NULL); c_lockUnlock(&kernel->lock); return found; }
void v_subscriberConnectNewGroup( v_subscriber s, v_group g) { c_bool connect; c_iter addedPartitions; v_partition d; c_lockWrite(&s->lock); connect = v_partitionAdminFitsInterest(s->partitions, g->partition); if (connect) { addedPartitions = v_partitionAdminAdd(s->partitions, v_partitionName(g->partition)); d = v_partition(c_iterTakeFirst(addedPartitions)); while (d != NULL) { c_free(d); d = v_partition(c_iterTakeFirst(addedPartitions)); } c_iterFree(addedPartitions); c_setWalk(s->readers, (c_action)v_readerSubscribeGroup, g); } else { /* * Check if group fits interest. This extra steps are needed because * the groupActionStream does not create the groups that match the * subscriber qos partition expression on creation. It only needs to * connect to new groups once they are created. This is a different * approach then for a data reader. */ /* * Because already existing partitions are created and added to the * subscriber of the groupActionStream at creation time, these * partitions can be resolved from the subscriber. This is necessary to * determine whether the groupActionStream should connect to the new * group or if it is already connected. */ if (v_partitionAdminExists(s->partitions, v_partitionName(g->partition))) { c_setWalk(s->readers, (c_action)notifyGroupQueues, g); } } c_lockUnlock(&s->lock); }
void v_participantConnectNewGroup ( v_participant _this, v_event event) { v_group g; c_mutexLock(&_this->newGroupListMutex); g = c_take(_this->newGroupList); while (g) { c_mutexUnlock(&_this->newGroupListMutex); c_lockWrite(&_this->lock); c_walk(_this->entities, connectNewGroup, g); c_lockUnlock(&_this->lock); c_mutexLock(&_this->newGroupListMutex); g = c_take(_this->newGroupList); } c_mutexUnlock(&_this->newGroupListMutex); }
v_topic v_lookupTopic( v_kernel kernel, const char *name) { v_topic topicFound; C_STRUCT(v_topic) dummyTopic; c_base base = c_getBase(c_object(kernel)); /* Create a dummy topic for look-up */ memset(&dummyTopic, 0, sizeof(dummyTopic)); ((v_entity)(&dummyTopic))->name = c_stringNew(base,name); topicFound = NULL; c_lockRead(&kernel->lock); /* This does not remove anything because the alwaysFalse function always * returns false */ c_remove(kernel->topics, &dummyTopic, alwaysFalse, &topicFound); c_lockUnlock(&kernel->lock); c_free(((v_entity)(&dummyTopic))->name); return topicFound; }
v_topic v_removeTopic( v_kernel kernel, v_topic topic) { v_topic found; assert(kernel != NULL); assert(C_TYPECHECK(kernel,v_kernel)); assert(topic != NULL); assert(C_TYPECHECK(topic,v_topic)); c_lockWrite(&kernel->lock); found = c_remove(kernel->topics,topic,NULL,NULL); c_lockUnlock(&kernel->lock); if (found == NULL) { return NULL; } if (v_objectKind(found) != K_TOPIC) { return NULL; } return found; }
v_partition v_removePartition( v_kernel kernel, v_partition partition) { v_partition found; assert(kernel != NULL); assert(C_TYPECHECK(kernel,v_kernel)); assert(partition != NULL); assert(C_TYPECHECK(partition,v_partition)); c_lockWrite(&kernel->lock); found = c_remove(kernel->partitions,partition,NULL,NULL); c_lockUnlock(&kernel->lock); if (found == NULL) { return NULL; } if (v_objectKind(found) != K_DOMAIN) { return NULL; } return found; }
c_iter v_resolveTopics( v_kernel kernel, const c_char *name) { c_iter list; c_collection q; q_expr expr; c_value params[1]; assert(kernel != NULL); assert(C_TYPECHECK(kernel,v_kernel)); expr = (q_expr)q_parse("name like %0"); params[0] = c_stringValue((char *)name); q = c_queryNew(kernel->topics,expr,params); q_dispose(expr); c_lockRead(&kernel->lock); list = c_select(q,0); c_lockUnlock(&kernel->lock); c_free(q); return list; }
v_topic v__addTopic( v_kernel kernel, v_topic topic) { v_topic found; assert(kernel != NULL); assert(C_TYPECHECK(kernel,v_kernel)); assert(topic != NULL); assert(C_TYPECHECK(topic,v_topic)); c_lockWrite(&kernel->lock); found = c_insert(kernel->topics,topic); c_lockUnlock(&kernel->lock); if (found != topic) { if (v_objectKind(found) != K_TOPIC) { return NULL; } topic = found; } return topic; }
/************************************************************** * 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_result v_subscriberSetQos( v_subscriber s, v_subscriberQos qos) { v_result result; v_qosChangeMask cm; v_dataReaderConnectionChanges arg; v_partition d; v_accessMode access; assert(s != NULL); arg.addedPartitions = NULL; arg.removedPartitions = NULL; c_lockWrite(&s->lock); /* ES, dds1576: When the QoS is being set we have to verify that the partitions * listed in the qos do not have an invalid access mode set. For a subscriber * an invalid mode is characterized as 'write' mode. If the partitionAccess * check returns ok, then everything continue as normal. If the * partitionAccess check returns something else, then the setQos operation * is aborted. Please see the partitionAccess check operation to know when * a partition expression is not allowed. */ if(qos && qos->partition) { access = v_kernelPartitionAccessMode(v_objectKernel(s), qos->partition); } else { access = V_ACCESS_MODE_READ_WRITE;/* default */ } if(access == V_ACCESS_MODE_READ_WRITE || access == V_ACCESS_MODE_READ) { result = v_subscriberQosSet(s->qos, qos, v_entity(s)->enabled, &cm); if ((result == V_RESULT_OK) && (cm != 0)) { c_lockUnlock(&s->lock); /* since creation builtin topic might lock subscriber again. */ if (cm & V_POLICY_BIT_PARTITION) { /* partition policy has changed! */ v_partitionAdminSet(s->partitions, s->qos->partition, &arg.addedPartitions, &arg.removedPartitions); } c_setWalk(s->readers, qosChangedAction, &arg); d = v_partition(c_iterTakeFirst(arg.addedPartitions)); while (d != NULL) { c_free(d); d = v_partition(c_iterTakeFirst(arg.addedPartitions)); } c_iterFree(arg.addedPartitions); d = v_partition(c_iterTakeFirst(arg.removedPartitions)); while (d != NULL) { c_free(d); d = v_partition(c_iterTakeFirst(arg.removedPartitions)); } c_iterFree(arg.removedPartitions); } else { c_lockUnlock(&s->lock); } } else { result = V_RESULT_PRECONDITION_NOT_MET; c_lockUnlock(&s->lock); } return result; }