RTDB_API RTK_CURSOR PMC_API create_tag( RTK_CURSOR group, PCTAG_KEY tag, PCSTATIC_TAG_DATA sd ) { RTK_CURSOR handle; RTK_GROUP * grp; RTK_TAG t; handle = open_tag_g(group, tag); if(handle){ return handle; } if(g_dwTags >= g_dwMaxTags){ rtk_set_last_error(RTDB_HARD_CONSTRAINTS); return 0; } grp = (RTK_GROUP*)cursor_get_item(group); if(!grp){ return 0; } ZeroMemory(&t, sizeof(t)); t.key = *tag; make_unified_key(t.key); t.s = *sd; t.node = grp->node; t.group = grp->key; handle = (RTK_CURSOR)_HTAG::create((TAG_TABLE*)grp->itemtable, t.key, t); RTK_TAG * pTag = (RTK_TAG*)cursor_get_item(handle); if(pTag){ ZeroMemory(&pTag->d, sizeof(pTag->d)); set_value_type(pTag->d.Value.Flags, get_value_type(pTag->s.Flags)); RtkInitializeListHead(&pTag->d.DeviceLink); RtkInitializeListHead(&pTag->d.RefreshLink); FIRE_EVENT(OnAddTag, (pTag)); g_dwTags++; } return handle; }
/* getBufferValues Environment : buffer lock acquired at least non-exclusively Algorithm description: on entry, we've got three time ranges a) time range for which this buffer has archive data b) time range that client demands archive data c) time range of the tag data array we denote them as Ta, Tb, Tc, respectively. Ta and Tb must intersect, or else there is a bug(should not go here). Tb and Tc might intersect, in which case there will be some archived data returned. Or they might not intersect, in which case there'll be no archived data returned. Either case, the number of tag data returned is determined by the intersection length of Tc and Tb and irrelavant of time range Ta. Time range Ta only serves as a hint to find a tag's archive data by timestamp. */ __uint CArchiveBuffer::getBufferValues( PCTAG_NAME tag, hislog_key_t startTime, __uint count, __uint step, hislog_item_t * buffer ) { __uint ret; archive_index_table_item_t * ti; archive_item_t * values; archive_item_t * item, * margin; hislog_key_t endTime; hislog_key_t Tc_1, Tc_2; __uint n; assert(isValid()); endTime = startTime + (count - 1) * step; __try{ ti = (archive_index_table_item_t*)bsearch( tag, m_indices, m_hdr->tagCount, sizeof(archive_index_table_item_t), _compareTagName ); if(!ti){ return 0; } if(ti->valueCount < 2){ return 0; } values = (archive_item_t *)((__u8*)m_archive.GetPointer() + ti->dataOffset); //3 now we gonna get the timed value from this array //3 A quich and dirty implementation ret = 0; // align them to grid points Tc_1 = commModeCeil(startTime, values[0].time, step); Tc_2 = commModeFloor(startTime, values[ti->valueCount - 1].time, step); // compute the intersection of range [Tc_1, Tc_2] and [startTime, endTime] Tc_1 = Tc_1 > startTime? Tc_1 : startTime; Tc_2 = Tc_2 > endTime? endTime : Tc_2; if(Tc_1 > Tc_2){ // no intersection return 0; } if(Tc_1 < m_startTime || Tc_2 > m_endTime){ // this is an invalid archive, we don't proceed for fear // that unexpected result might occur rtk_set_last_error(HISLOG_INVALID_ARCHIVE); return 0; } assert(!((Tc_1 - startTime) % step)); assert(!((Tc_2 - startTime) % step)); // prolog if(Tc_1 > startTime){ // make compensation n = (Tc_1 - startTime) / step; ret += n; startTime += n * step; buffer += n; } item = values; margin = &values[ti->valueCount - 1]; // actual values in the archive do{ item = _locateItem(item, margin, startTime); assert(item); assert(item->time <= startTime); // get value for startTime if(item->time == startTime || item == margin){ *buffer = item->value; }else{ // interpolate interpolate( &item->value, &item[1].value, buffer, item->time, item[1].time, startTime ); } buffer++; ret++; startTime += step; }while(startTime <= Tc_2 && ret < count); }__except(EXCEPTION_EXECUTE_HANDLER){ rtk_set_last_error(HISLOG_INVALID_ARCHIVE); return 0; } return ret; }