v_topicAdapter v_topicAdapterWrap( v_participant p, v_topic topic) { v_topicAdapter adapter = NULL; v_kernel kernel; assert(p != NULL); assert(C_TYPECHECK(p,v_participant)); assert(topic != NULL); assert(C_TYPECHECK(topic,v_topic)); kernel = v_objectKernel(p); adapter = v_topicAdapter(v_objectNew(kernel,K_TOPIC_ADAPTER)); if (adapter != NULL) { v_topicAdapterInit(adapter, topic, p, v_topicName(topic)); } else { OS_REPORT(OS_ERROR, "v_topicAdapterWrap", V_RESULT_INTERNAL_ERROR, "Failed to allocate TopicAdapter for topic '%s'.", v_topicName(topic)); } return adapter; }
c_bool v_networkReaderWrite( v_networkReader reader, v_message message, v_networkReaderEntry entry, c_ulong sequenceNumber, v_gid sender, c_bool sendTo, /* for p2p writing */ v_gid receiver) { c_bool result; v_networkQueue bestQueue; assert(reader != NULL); assert(C_TYPECHECK(reader, v_networkReader)); assert(reader->remoteActivity == TRUE); /* First select the best queue */ if (message != NULL) { bestQueue = v_networkReaderSelectBestQueue( reader, message->qos, sendTo, v_partitionName(v_group(entry->group)->partition), v_topicName(v_groupTopic(entry->group))); } else { bestQueue = reader->defaultQueue; } result = v_networkQueueWrite(bestQueue, message, entry, sequenceNumber, sender, sendTo, receiver); return result; }
static c_bool walkProperty( c_metaObject object, c_metaWalkActionArg actionArg) { toolActionData actionData = (toolActionData)actionArg; c_object o; c_voidp addr; o = c_iterObject(actionData->stack, 0); if (c_baseObjectKind(object) == M_ATTRIBUTE) { addr = C_DISPLACE(o, (c_address)c_property(object)->offset); if (c_typeIsRef(c_property(object)->type)) { addr = *(c_voidp *)addr; if (c_baseObjectKind(c_property(object)->type) == M_COLLECTION) { if (addr) { if (c_iterContains(actionData->stack, addr)) { printf("Ignore cyclic reference 0x"PA_ADDRFMT"\n", (os_address)addr); } else { OBJECT_PUSH(actionData, addr); iprintf("%s ",_METANAME(object)); printType(c_property(object)->type, actionData); OBJECT_POP(actionData); } } else { iprintf(" %s <0x"PA_ADDRFMT">", _METANAME(object), (os_address)addr); } } else { iprintf(" %s <0x"PA_ADDRFMT">", _METANAME(object), (os_address)addr); if (addr) { /* Section for code to print additional type specific info. */ if (c_property(object)->type == v_topic_t) { printf(" /* topic name is: %s */", v_topicName(addr)); } if (c_property(object)->type == v_partition_t) { printf(" /* Partition: %s */", v_partitionName(addr)); } if (c_property(object)->type == c_type_t(c_getBase(object))) { printf(" /* Type: %s */", _METANAME(c_type(addr))); } } } printf("\n"); } else { OBJECT_PUSH(actionData, addr); iprintf("%s ",_METANAME(object)); printType(c_property(object)->type, actionData); printf("\n"); OBJECT_POP(actionData); } } return TRUE; }
static c_bool isGroupConnected( v_group group, c_voidp args) { struct groupConnected* data; assert(C_TYPECHECK(group, v_group)); data = (struct groupConnected*)args; if(strcmp(v_partitionName(group->partition), v_partitionName(data->group->partition)) == 0){ if(strcmp(v_topicName(group->topic), v_topicName(data->group->topic)) == 0){ data->connected = TRUE; } } return (!data->connected); }
static v_networkHashValue v_networkReaderEntryCalculateHashValue( v_networkReaderEntry entry) { v_networkHashValue result = {0xa0, 0x22, 0x8d, 0x07}; const char *partitionName; const char *topicName; const char *currentPtr; partitionName = v_partitionName(v_groupPartition(entry->group)); topicName = v_topicName(v_groupTopic(entry->group)); currentPtr = partitionName; while (*currentPtr != '\0') { /* gcc2.96 gave internal compile errrors (with optimisation enabled) * when compiling the NW_ROT_CHAR macro twice in same command : * these assignments are deliberatly split over 2 lines as workaround. */ result.h1 = NW_ROT_CHAR(result.h1, 1); result.h1 += NW_ROT_CHAR(*currentPtr, 4); result.h2 = NW_ROT_CHAR(result.h2, 2); result.h2 += NW_ROT_CHAR(*currentPtr, 7); result.h3 = NW_ROT_CHAR(result.h3, 3); result.h3 += NW_ROT_CHAR(*currentPtr, 1); result.h4 = NW_ROT_CHAR(result.h4, 4); result.h4 += NW_ROT_CHAR(*currentPtr, 5); currentPtr = &(currentPtr[1]); } currentPtr = topicName; while (*currentPtr != '\0') { result.h1 = NW_ROT_CHAR(result.h1, 4); result.h1 += NW_ROT_CHAR(*currentPtr, 7); result.h2 = NW_ROT_CHAR(result.h2, 3); result.h2 += NW_ROT_CHAR(*currentPtr, 1); result.h3 = NW_ROT_CHAR(result.h3, 2); result.h3 += NW_ROT_CHAR(*currentPtr, 5); result.h4 = NW_ROT_CHAR(result.h4, 1); result.h4 += NW_ROT_CHAR(*currentPtr, 4); currentPtr = &(currentPtr[1]); } return result; }
static c_bool checkTopic ( c_object o, c_voidp arg) { v_dataReaderEntry entry; c_char *topicName = (c_char *)arg; if(v_object(o)->kind == K_DATAREADERENTRY){ entry = v_dataReaderEntry(o); if (strcmp(v_topicName(entry->topic),topicName) == 0) { return FALSE; } } return TRUE; }
void nw_receiveChannelAddGroup( nw_receiveChannel channel, v_networkReaderEntry entry) { NW_CONFIDENCE(channel != NULL); if (channel != NULL) { /* Add entry to hashtable */ nw_entryHashInsert(channel->hash, entry); NW_TRACE_3(Groups, 2, "Channel %u added new group with partition %s and topic %s", ((nw_channel)(channel))->channelId, v_partitionName(v_groupPartition(entry->group)), v_topicName(v_groupTopic(entry->group))); } }
static void nw_entryHashInsert( nw_entryHash entryHash, v_networkReaderEntry entry) { nw_entryHashItem *itemPtr; nw_bool ready = FALSE; int cmpRes; const c_char *partitionName; const c_char *topicName; partitionName = v_partitionName(v_groupPartition(entry->group)); topicName = v_topicName(v_groupTopic(entry->group)); itemPtr = &NW_ITEM_FROM_HASHVALUE(entryHash, entry->hashValue); while ((*itemPtr != NULL) && !ready) { cmpRes = strcmp((*itemPtr)->topicName, topicName); if (cmpRes == 0) { cmpRes = strcmp((*itemPtr)->partitionName, partitionName); if (cmpRes == 0) { ready = TRUE; } else if (cmpRes < 0) { itemPtr = &((*itemPtr)->next); } else { /* No entry was found and no entry will be found, insert new */ nw_entryHashItemInsert(entry->hashValue, partitionName, topicName, entry, itemPtr); ready = TRUE; } } else if (cmpRes < 0) { itemPtr = &((*itemPtr)->next); } else { /* No entry found, and will not be found */ nw_entryHashItemInsert(entry->hashValue, partitionName, topicName, entry, itemPtr); ready = TRUE; } } if (!ready) { /* No proper place found, we are at the tail now */ nw_entryHashItemInsert(entry->hashValue, partitionName, topicName, entry, itemPtr); } }
c_ulong nw_sendChannelWrite( nw_sendChannel sendChannel, v_networkReaderEntry entry, v_message message, nw_signedLength *maxBytes, plugSendStatistics pss) { c_ulong result = 0; nw_channel channel = (nw_channel)sendChannel; NW_CONFIDENCE(channel); result = nw_bridgeWrite(channel->owningBridge, channel->channelId, entry->networkPartitionId, message, entry->hashValue, v_partitionName(v_groupPartition(entry->group)), v_topicName(v_groupTopic(entry->group)),maxBytes, pss); return result; }
void d_reportLocalGroup( d_durability d, const char *threadName, v_group group) { const c_char* durability; v_topicQos qos; if(group){ qos = v_topicQosRef(group->topic); switch(qos->durability.kind){ case V_DURABILITY_VOLATILE: durability = "VOLATILE"; break; case V_DURABILITY_TRANSIENT_LOCAL: durability = "TRANSIENT LOCAL"; break; case V_DURABILITY_TRANSIENT: durability = "TRANSIENT"; break; case V_DURABILITY_PERSISTENT: durability = "PERSISTENT"; break; default: durability = "<<UNKNOWN>>"; assert(FALSE); break; } } else { durability = "<<UNKNOWN>>"; assert(FALSE); } d_printTimedEvent(d, D_LEVEL_FINE, threadName, "Group found: %s.%s (%s)\n", v_partitionName(v_groupPartition(group)), v_topicName(v_groupTopic(group)), durability); }
static void nw_channelWriterMain( v_entity e, c_voidp arg) { v_networkReader reader; nw_channelWriter channelWriter; c_bool newGroupAvailable; v_networkQueue qosQueue; v_networkReaderWaitResult waitResult; c_long bytesWritten; /* Total number of messages sent to the network */ c_ulong writtenCountMessages; /* Total number of bytes sent to the network */ c_ulong writtenCountBytes; /* Total number of bytes sent to the network during one burst */ c_ulong writtenCountBytesThisBurst; /* Number of message sent to the network after last report */ c_ulong writtenCountMessagesReport; v_message message; v_networkReaderEntry entry; c_ulong sequenceNumber; v_gid sender; c_bool sendTo; v_gid receiver; c_time sendBefore; c_ulong priority; c_bool more = TRUE; c_bool slowingDown; c_ulong timeoutCount; nw_signedLength credits; v_networking n; NW_STRUCT(plugSendStatistics) pss = {0,0,0,0,0,0,0,0,0,0, {0, {{0,0}, 0}, {{0,0}, 0}, {0.0,0}}, {0, {{0,0}, 0}, {{0,0}, 0}, {0.0,0}}, 0,0,0}; v_fullCounterInit(&(pss.adminQueueAcks)); v_fullCounterInit(&(pss.adminQueueData)); reader = v_networkReader(e); channelWriter = (nw_channelWriter)arg; /* This line is needed as long as the discovery channel is not yet implemented */ writtenCountBytesThisBurst = 0; writtenCountMessages = 0; writtenCountBytes = 0; writtenCountMessagesReport = 0; slowingDown = FALSE; timeoutCount = 0; credits = 0; while (!(int)nw_runnableTerminationRequested((nw_runnable)channelWriter)) { /* Wait for data on the reader */ if (!slowingDown) { waitResult = v_networkReaderWait(reader, channelWriter->queueId, &qosQueue); } else { waitResult = v_networkReaderWaitDelayed(reader, channelWriter->queueId, &qosQueue); NW_CONFIDENCE(waitResult & (V_WAITRESULT_TIMEOUT | V_WAITRESULT_TRIGGERED)); } if ((waitResult & V_WAITRESULT_TRIGGERED) && (!nw_runnableTerminationRequested((nw_runnable)channelWriter))) { /* If necessary, check if any new groups need to be added */ newGroupAvailable = nw_channelUserRetrieveNewGroup( (nw_channelUser)channelWriter, &entry); while (newGroupAvailable) { /* Create a new channel on the network */ /* No, do not call any function. With the new design, * a channelWriter does not need to know anything about this * new group. Maybe at a later stage. */ /* nw_channelAddGroup((nw_channel)channelWriter->sendChannel, entry); */ /* And notify we are connected */ v_networkReaderEntryNotifyConnected(entry,channelWriter->serviceName); newGroupAvailable = nw_channelUserRetrieveNewGroup( (nw_channelUser)channelWriter, &entry); } } /* Resend data should also obey max_burst_size * Each clocktick, the remaining credits of the last period and a * third of the new max_burst_size budget may be used for resend data. * The rest of the budget is assigned after that, and can be used to * flush stored buffers of send fresh data. */ if (waitResult & V_WAITRESULT_TIMEOUT) { /* * The periodic action is needed for every clocktick. * This will also update the credits, for the amount of bandwidth * available in the coming period. */ /*stat update routine */ n = v_networking(v_subscriber(v_reader(reader)->subscriber)->participant); /* update statistics */ if (v_entity(n)->statistics) { if (!pss.enabled) { pss.enabled =1; } /* sync plug stats */ nw_updatePlugSendStatistics(&pss,channelWriter); nw_SendChannelUpdate(v_networkingStatistics(v_entity(n)->statistics)->channels[channelWriter->stat_channel_id],channelWriter->scs); } nw_sendChannelPeriodicAction(channelWriter->sendChannel,&credits,&pss); /*struc call*/ /* A flush is needed if we are slowing down. */ if (slowingDown) { /* The return value is true is all data has been sent. * Afterwards, credits will contain the new amount of allowed * bytes. * We are using a special flush function here that flushes full * buffers only */ slowingDown = !nw_sendChannelFlush(channelWriter->sendChannel, FALSE, &credits, &pss); } } if ((waitResult & V_WAITRESULT_MSGWAITING) && !slowingDown) { /* Messages are waiting... */ writtenCountBytesThisBurst = 0; more= TRUE; while (more && ((nw_signedLength)writtenCountBytesThisBurst <= credits)) { /* Take any new messages */ v_networkQueueTakeFirst(qosQueue, &message, &entry, &sequenceNumber, &sender, &sendTo, &receiver, &sendBefore, &priority, &more); NW_CONFIDENCE(message != NULL); NW_CONFIDENCE(entry != NULL); if (!(NW_SECURITY_CHECK_FOR_PUBLISH_PERMISSION_OF_SENDER_ON_SENDER_SIDE(entry))) { bytesWritten = 0; /* indicates that nothing has been written */ NW_REPORT_WARNING_2( "nw_channelWriterMain", "Channel \"%s\" could not deliver message 0x%x : message dropped!", ((nw_runnable)channelWriter)->name, message); } else { bytesWritten = nw_sendChannelWrite(channelWriter->sendChannel, entry, message, &credits ,&pss); /* stat struc plug vars */ if (bytesWritten == 0) { NW_REPORT_WARNING_2( "nw_channelWriterMain", "Channel \"%s\" could not deliver message 0x%x : message dropped!", ((nw_runnable)channelWriter)->name, message); } /*numberOfMessagesSent stats*/ if (pss.enabled) { channelWriter->scs->numberOfMessagesSent++; } assert( bytesWritten > 0); /* if permission grantedm the value must be greater 0 */ } writtenCountBytesThisBurst += bytesWritten; #define NW_IS_BUILTIN_DOMAINNAME(name) ((int)(name)[0] == (int)'_') /* Do not trace for internal partitions */ if (bytesWritten>0 && /* might be 0 if access control refuses write permission */ !NW_IS_BUILTIN_DOMAINNAME( v_partitionName(v_groupPartition(entry->group)))) { #undef NW_IS_BUILTIN_DOMAINNAME writtenCountBytes += bytesWritten; writtenCountMessages++; writtenCountMessagesReport++; if (writtenCountMessagesReport == channelWriter->reportInterval) { NW_TRACE_3(Send, 3, "Channel %s: %u messages (%u bytes) " "taken from queue and written to network", ((nw_runnable)channelWriter)->name, writtenCountMessages, writtenCountBytes); writtenCountMessagesReport = 0; } NW_TRACE_3(Send, 4, "Channel %s: data message taken from queue, " "and written to network (partition = %s, topic = %s)", ((nw_runnable)channelWriter)->name, v_partitionName(v_groupPartition(entry->group)), v_topicName(v_groupTopic(entry->group))); } c_free(message); c_free(entry); } slowingDown = !nw_sendChannelFlush(channelWriter->sendChannel, TRUE, &credits, &pss); } } NW_TRACE_3(Send, 2, "Channel %s: %u messages (%u bytes) taken from queue and " "written to network", ((nw_runnable)channelWriter)->name, writtenCountMessages, writtenCountBytes); }
static c_type sampleTypeNew( v_topic topic) { c_metaObject o; c_type msgType,sampleType,foundType; c_base base; c_char *name; os_size_t length; int sres; assert(C_TYPECHECK(topic,v_topic)); assert(topic); name = NULL; foundType = NULL; if (v_topicName(topic) == NULL) { OS_REPORT(OS_ERROR, "v_index::sampleTypeNew failed",V_RESULT_ILL_PARAM, "failed to retreive topic name"); return NULL; } base = c_getBase(topic); if (base == NULL) { OS_REPORT(OS_ERROR, "v_index::sampleTypeNew failed",V_RESULT_ILL_PARAM, "failed to retreive base"); return NULL; } msgType = c_keep(v_topicMessageType(topic)); if (msgType == NULL) { OS_REPORT(OS_ERROR, "v_index::sampleTypeNew failed",V_RESULT_ILL_PARAM, "failed to retreive topic message type"); return NULL; } sampleType = c_type(c_metaDefine(c_metaObject(base),M_CLASS)); if (sampleType) { c_class(sampleType)->extends = v_dataReaderSample_t(base); o = c_metaDeclare(c_metaObject(sampleType),"message",M_ATTRIBUTE); if (o) { c_property(o)->type = c_keep(msgType); c_metaObject(sampleType)->definedIn = c_keep(base); c_metaFinalize(c_metaObject(sampleType)); #define SAMPLE_FORMAT "v_indexSample<%s>" #define SAMPLE_NAME "v_indexSample<>" /* sizeof contains \0 */ length = sizeof(SAMPLE_NAME) + strlen(v_topicName(topic)); name = os_malloc(length); sres = snprintf(name,length,SAMPLE_FORMAT,v_topicName(topic)); assert(sres >= 0 && (os_size_t) sres == (length-1)); OS_UNUSED_ARG(sres); #undef SAMPLE_FORMAT #undef SAMPLE_NAME foundType = c_type(c_metaBind(c_metaObject(base), name, c_metaObject(sampleType))); c_free(o); } else { foundType = NULL; } c_free(sampleType); } else { OS_REPORT(OS_ERROR, "v_index::sampleTypeNew failed",V_RESULT_ILL_PARAM, "failed to retreive topic sample type"); } os_free(name); c_free(msgType); return foundType; }
static c_type createInstanceType ( v_topic topic, c_char *keyExpr, c_array *keyListRef) { c_metaObject o; c_type instanceType, baseType, foundType; c_type sampleType, keyType, keyInstanceType; c_base base; c_char *name; os_size_t length; int sres; assert(C_TYPECHECK(topic,v_topic)); foundType = NULL; if (keyExpr) { keyType = v_topicKeyTypeCreate(topic,keyExpr,keyListRef); } else { keyExpr = v_topicKeyExpr(topic); keyType = v_topicKeyType(topic); *keyListRef = c_keep(v_topicMessageKeyList(topic)); } sampleType = sampleTypeNew(topic); if (sampleType) { base = c_getBase(topic); baseType = v_dataReaderInstance_t(base); instanceType = c_type(c_metaDefine(c_metaObject(base),M_CLASS)); if (instanceType != NULL) { c_class(instanceType)->extends = c_keep(c_class(baseType)); o = c_metaDeclare(c_metaObject(instanceType), "sample",M_ATTRIBUTE); c_property(o)->type = c_keep(sampleType); c_free(o); o = c_metaDeclare(c_metaObject(instanceType), "oldest",M_ATTRIBUTE); c_property(o)->type = (c_type)c_metaResolveType(c_metaObject(base), "c_voidp"); assert(c_property(o)->type); c_free(o); c_metaFinalize(c_metaObject(instanceType)); #define INSTANCE_NAME "v_indexInstance<v_indexSample<>>" #define INSTANCE_FORMAT "v_indexInstance<v_indexSample<%s>>" /* The sizeof contains \0 */ length = sizeof(INSTANCE_NAME) + strlen(v_topicName(topic)); name = os_alloca(length); sres = snprintf(name,length,INSTANCE_FORMAT,v_topicName(topic)); assert(sres >= 0 && (os_size_t) sres == (length-1)); OS_UNUSED_ARG(sres); #undef INSTANCE_NAME #undef INSTANCE_FORMAT foundType = c_type(c_metaBind(c_metaObject(base), name, c_metaObject(instanceType))); if (foundType == NULL) { OS_REPORT(OS_ERROR, "v_index::createInstanceType",V_RESULT_INTERNAL_ERROR, "Could not create instance type"); } os_freea(name); if (keyType != NULL) { keyInstanceType = c_type(c_metaDefine(c_metaObject(base),M_CLASS)); if (keyInstanceType) { c_class(keyInstanceType)->extends = c_keep(c_class(instanceType)); o = c_metaDeclare(c_metaObject(keyInstanceType), "key",M_ATTRIBUTE); c_property(o)->type = c_keep(keyType); c_free(o); c_metaFinalize(c_metaObject(keyInstanceType)); #define INSTANCE_NAME "v_indexKeyInstance<v_indexSample<>,>" #define INSTANCE_FORMAT "v_indexKeyInstance<v_indexSample<%s>,%s>" /* The sizeof contains \0 */ length = sizeof(INSTANCE_NAME) + strlen(v_topicName(topic)) + strlen(keyExpr); name = os_alloca(length); sres = snprintf(name, length, INSTANCE_FORMAT, v_topicName(topic), keyExpr); assert(sres >= 0 && (os_size_t) sres == (length-1)); OS_UNUSED_ARG(sres); #undef INSTANCE_NAME #undef INSTANCE_FORMAT c_free(foundType); /* Will be overwritten, so free */ foundType = c_type(c_metaBind(c_metaObject(base), name, c_metaObject(keyInstanceType))); if (foundType == NULL) { OS_REPORT(OS_ERROR, "v_index::createInstanceType",V_RESULT_INTERNAL_ERROR, "Could not create key instance type"); } os_freea(name); c_free(keyInstanceType); } c_free(keyType); } c_free(instanceType); c_free(baseType); } else { foundType = baseType; /* transfer refCount to caller */ } c_free(sampleType); } return foundType; }