__bool CWaitableTransaction::Wait(__uint TimeOut, __bool ProcessMessage) { #ifdef _WIN32 DWORD res; InterlockedIncrement((PLONG)&m_iRefcount); if(ProcessMessage){ bool bExit = false; RTK_TIME tm, now; rtk_time_mark(&tm); HANDLE hEvent = Event.Handle(); while(!bExit){ res = MsgWaitForMultipleObjects( 1, &hEvent, FALSE, TimeOut, QS_ALLEVENTS ); switch(res){ case WAIT_OBJECT_0: bExit = true; break; case WAIT_TIMEOUT: bExit = true; break; case WAIT_OBJECT_0 + 1: rtk_time_mark(&now); double elapsed = rtk_time_diff(&now, &tm) * 1000; tm = now; if(TimeOut > elapsed){ TimeOut -= (__uint)elapsed; }else{ bExit = true; res = WAIT_TIMEOUT; break; } MSG msg; while(PeekMessage(&msg, 0, 0, 0, TRUE)){ TranslateMessage(&msg); DispatchMessage(&msg); } break; } } }else{ res = Event.Wait(TimeOut); } m_bWaitResult = res == WAIT_OBJECT_0? __true : __false; InterlockedDecrement((PLONG)&m_iRefcount); return m_bWaitResult; #else m_bWaitResult = Event.Wait(TimeOut) ==WAIT_OBJECT_0? __true : __false; #endif }
void CTransactionContainer::reap() { WriteLock(); CTList::iterator p; p=tlist.begin(); double diff; RTK_TIME tm; CTransaction *t; rtk_time_mark(&tm); while(p!=tlist.end()){ t = *p; assert(&(*p)->birth == &((*p)->birth)); diff = rtk_time_diff(&tm,&((*p)->birth)); if(diff > t->life && !t->m_iRefcount){ p=tlist.erase(p); char guid_name[128]; t->Guid.to_string(guid_name); DEBUG_PRINTF(( ">>T %s,too old(%.0f>%.0f),removing.\n", guid_name,diff, t->life )); t->OnTimeout(); delete t; }else{ p++; } } Release(); }
CTransaction::CTransaction() { Guid.create(); rtk_time_mark(&birth); m_iRefcount = 0; m_Parent = 0; life = g_TransactionLife; }
void CPacketMan::reap_packets() { RTK_TIME now; rtk_time_mark(&now); reap_sent(&now); reap_received(&now); }
__uint _fastcall _read_tags( __uint count, PCTAG_NAME names, Ppmc_value_t values, __uint & existed ) { RTK_CURSOR hNode, hTag; NODE_KEY cachedNode; RTK_TAG *pTag; __uint i, valids; valids = 0; existed = 0; ZeroMemory(values, sizeof(values[0]) * count); if(!lock_rtdb(false, 1000)){ return 0; } hNode = 0; hTag = 0; RTK_TIME now; rtk_time_mark(&now); hNode = 0; memset(&cachedNode, 0, sizeof(cachedNode)); for(i=0; i<count; i++){ if(!(cachedNode == names[i].node)){ close_handle(hNode); hNode = 0; } if(!hNode){ hNode = open_node(&names[i].node); cachedNode = names[i].node; } if(!hNode){ values[i].Flags &= ~TF_Valid; continue; } hTag = open_tag(hNode, &names[i].sname); if(hTag){ existed++; pTag = (RTK_TAG*)cursor_get_item(hTag); double diff; diff = rtk_time_diff(&now, &pTag->d.CachedTime); if(diff > (g_fltTagLife*2)){ mark_expired(pTag); } values[i] = pTag->d.Value; valids++; close_handle(hTag); }else{ values[i].Flags &= ~TF_Valid; } } close_handle(hNode); unlock_rtdb(); return valids; }
void CPacketMan::dbg_dump() { RECEIVE_ITEM *h; RITEM_LIST::iterator p; RTK_TIME now; int i=0; SITEM_LIST::iterator sit; SEND_ITEM *si; PRTK_LIST_ENTRY entry, headEntry; rtk_time_mark(&now); if(r_lst.size()){ utils_error("%d packets under construction:-->\n", r_lst.size()); p = r_lst.begin(); while(p != r_lst.end()){ headEntry = &(p->second); entry = headEntry->Flink; while(entry != headEntry){ h = RTK_CONTAINING_RECORD(entry, RECEIVE_ITEM, li); utils_error("NO.%d, Age=%.3f, life=%.3f, ", i, rtk_time_diff(&now, &h->birthday), h->life ); utils_error("Got %d of Total %d fragments, size %d bytes\n", h->header->total_frag - h->unreceived_fragments, h->header->total_frag, h->header->data_size ); entry = entry->Flink; } p++; i++; } } if(s_lst.size()){ utils_error("%d packets in send queue:------>\n", s_lst.size()); sit = s_lst.begin(); i = 0; while(sit != s_lst.end()){ headEntry = &sit->second; entry = headEntry->Flink; while(entry != headEntry){ si = RTK_CONTAINING_RECORD(entry, SEND_ITEM, li); entry = entry->Flink; utils_error("No.%d, %d fragments, age=%.3f, life=%.3f\n", i, si->header->total_frag, rtk_time_diff(&now, &si->birthday), si->life ); i++; } sit++; } } }
double CExpression::vexp ( arbore a ) { double v; SYSTEMTIME tm; GetSystemTime(&tm); if (a->operatie==NULL) {error_code=10;return 0;} switch(a->operatie){ case '+' : return( vexp(a->left)+vexp(a->right) ); case '-' : return( vexp(a->left)-vexp(a->right) ); case '*' : return( vexp(a->left)*vexp(a->right) ); case '%': { v = vexp(a->right); if(v == 0){ error_code = DIVISION_BY_0; return 0; } return (int)vexp(a->left) % (int)v; } case '/' : v=vexp(a->right) ; if (v==0){ error_code=DIVISION_BY_0; return -vexp(a->left)/0.001; }else{ return(vexp(a->left)/v); } case 150 : return(sin(vexp(a->left))); case 151 : return(cos(vexp(a->left))); case 152 : return(exp(vexp(a->left))); case 153 : v=vexp(a->left) ; if (v<0) {error_code=INVALID_DOMAIN;return 0;} else return(sqrt(v)); case 154 : v=vexp(a->left) ; if (v<=0) {error_code=INVALID_DOMAIN;return 0;} else return(log(v)); case 155 : return (tan (vexp(a->left))); case 156 : return (1 / tan (vexp(a->left))); case 157 : return (asin (vexp(a->left))); case 158 : return (acos (vexp(a->left))); case 159 : return (atan (vexp(a->left))); case 173 : return (fabs (vexp(a->left))); case 160 : return tm.wYear; case 161 : return tm.wMonth; case 162 : return tm.wDay; case 163 : return tm.wHour; case 164 : return tm.wMinute; case 165 : return tm.wSecond; case 166 : return max(vexp(a->left),vexp(a->right)); case 167 : return min(vexp(a->left),vexp(a->right)); case 168 : return rng_rand(0,RAND_MAX)*vexp(a->left)/RAND_MAX; //case '|' : return(fabs(vexp(a->left))); case '^' : return(pow(vexp(a->left),vexp(a->right))); case '@' : return (a->valoare); //logical operations evaluation case '<' : return( vexp(a->left) < vexp(a->right) ); case '>' : return( vexp(a->left) > vexp(a->right) ); case '!' : return(!vexp(a->right)) ; // added by chenj, @2008-5-22 case '=' : return( vexp(a->left) == vexp(a->right) ); case '&' : return (int)(vexp(a->left)) & (int)(vexp(a->right)); case '|' : return (int)(vexp(a->left)) | (int)(vexp(a->right)); case 169: { RTK_TIME t; rtk_time_mark(&t); return (double)(__int64)t.Data / 1e7; } case 170: { /* last update time */ PRTK_TAG tte; __r8 retval = 0; tte = (PRTK_TAG)a->left->pvObj; if(!tte){ error_code=UNDEFINED_VARIABLE; retval = 0; }else{ if(!(tte->d.Value.Flags & TF_Valid)){ error_code=UNDEFINED_VARIABLE; retval = 0; }else{ PRTK_TIME pTime = (PRTK_TIME)&tte->d.BinaryAddress[8]; retval = (double)(__int64)pTime->Data / 1e7; rtk_time_mark(pTime); } } return retval; } case 171 : { // a database tag PRTK_TAG tte; __r8 retval = 0; tte = (PRTK_TAG)a->pvObj; if(!tte){ error_code=UNDEFINED_VARIABLE; retval = 0; }else{ if(!(tte->d.Value.Flags & TF_Valid)){ error_code=UNDEFINED_VARIABLE; retval = 0; }else{ pmc_value_t dblVal; set_value_type(dblVal.Flags, dt_real8); pmc_type_cast(&tte->d.Value, &dblVal); retval = dblVal.Value.dbl; } } return retval; } case 172: { /* span time */ PRTK_TAG tte; RTK_TIME now; __r8 retval = 0; tte = (PRTK_TAG)a->left->pvObj; if(!tte){ error_code=UNDEFINED_VARIABLE; retval = 0; }else{ if(!(tte->d.Value.Flags & TF_Valid)){ error_code=UNDEFINED_VARIABLE; retval = 0; }else{ PRTK_TIME pTime = (PRTK_TIME)&(tte->d.BinaryAddress[8]); rtk_time_mark(&now); if(pTime->Data != 0){ /* yes, the field is previouly stored with a resonable value, thus valid for a sub-operation to get a duration time */ retval = rtk_time_diff(&now, pTime); }else{ /* this might be the first time that a time-span was requested for this tag */ retval = 0; } *pTime = now; } } return retval; } } return 0; }
/* MergePacket() if an incoming packet belongs to a large packet(thus a fragment), merge it with previously received fragments, then make a second decision whether all fragments of the large packet has been received. */ RECEIVE_ITEM * CPacketMan::MergePacket(RTK_PACKET * input_packet) { RECEIVE_ITEM *ri; RITEM_LIST::iterator p; std::pair<RITEM_LIST::iterator, bool> pr; __uint packetSize; PRTK_LIST_ENTRY headEntry, entry; assert(IsFragment(input_packet)); packetSize = input_packet->total_frag * m_mtu + sizeof(RECEIVE_ITEM); p = r_lst.find(input_packet->guid); if(p != r_lst.end()){ headEntry = entry = p->second.Flink; do{ ri = RTK_CONTAINING_RECORD(entry, RECEIVE_ITEM, li); entry = entry->Flink; }while(entry != headEntry && ri->header->grp_id != input_packet->grp_id); if(ri->header->grp_id != input_packet->grp_id){ ri = 0; } }else{ ri = 0; headEntry = 0; } if(!ri){ /* ok, this is the first arriving fragment of the large packet perhaps also the first group, if existed a new node must be allocated */ ri = (RECEIVE_ITEM*)Alloc(packetSize); if(!ri){ return 0; } memset(ri, 0, sizeof(RECEIVE_ITEM)); if(headEntry){ // new member of the group, chain them RtkInsertTailList(headEntry, &ri->li); }else{ static RTK_LIST_ENTRY theFirstEntry; // first packet in the group, add to list pr = r_lst.insert(RITEM_LIST::value_type(input_packet->guid, theFirstEntry)); if(!pr.second){ Free(ri); return 0; } headEntry = &pr.first->second; RtkInitializeListHead(headEntry); RtkInsertTailList(headEntry, &ri->li); } ri->header = (PRTK_PACKET)(ri + 1); // copy input_packet to header *ri->header = *input_packet; // and modify some fields rtk_time_mark(&ri->birthday); ri->life = rtkm_receive_fragments_life * input_packet->total_frag; ri->unreceived_fragments = ri->header->total_frag; ri->header->data_size = 0; ri->header->frgmt_id = 0; } // put the packet into the RECEIVE_ITEM ri->max_frgmt_id_received >= input_packet->frgmt_id? 0 : ri->max_frgmt_id_received = input_packet->frgmt_id; if(ri->header->total_frag > input_packet->frgmt_id){ ri->header->data_size += input_packet->data_size; ri->bitmap[input_packet->frgmt_id] = 1; memcpy( ri->header->data + input_packet->offset, input_packet->data, input_packet->data_size ); ri->unreceived_fragments--; }else{ // a fragment claiming a segid larger than the total // segment count, simply discard this arrogant // fragment. // 2004/11/1, we should have already checked against // this in WillingToAccept, so, just assert here assert(0); } return ri; }
/* generate a fragment list for a large data packet 2004/8/2 jackie ---------------------------------------------------- now we're to fix a bug when multiple calls of SplitPacket with the same guid is being made, this is not impossible as it might look like. The server process is often in a loop servicing some clients, in each round of the loop it gives out some data, note the data is sent over vbus layer using the same GUID that the client is expecting. In this case, if the sent data is large enough it must go to this place to be split, so we can see the send operation is bound to fail because the s_lst won't permit another send_item with a same GUID. If we got another packet with a same GUID, we append the latter one to the previous ones in the queue. Because the client might be incidently calling send_rtk_data_with_guid twice, in which case the appending is not desired, so we need the client's explicit statement that appending is permited, we use a new flag in packet_type. The new flag also serves as a guarding flag to the s_lst reaper that the packet is not to be deleted, because some other fragments is just on the way to send_rtk_data_with_guid. */ SEND_ITEM *CPacketMan::SplitPacket(const RTK_PACKET *input) { char *heap, *p; __uint fragments, header_size, last_data_size, heap_size; int i, offset, effective_load; RTK_PACKET * frag; SEND_ITEM * si, * previousItem; SITEM_LIST::iterator pit; std::pair<SITEM_LIST::iterator, bool> pr; PRTK_LIST_ENTRY headEntry, entry; __u16 groupId; pit = s_lst.find(input->guid); if(pit != s_lst.end()){ headEntry = &pit->second; entry = headEntry->Blink; assert(!RtkIsListEmpty(entry)); previousItem = RTK_CONTAINING_RECORD(entry, SEND_ITEM, li); if(!(previousItem->header->packet_type & PF_PacketGroup)){ /* sending another packet of the same GUID without group flag set is not permited. */ return NULL; } groupId = previousItem->header->grp_id + 1; }else{ previousItem = NULL; si = 0; headEntry = 0; groupId = 0; } // calculate size needed header_size = sizeof(RTK_PACKET) - sizeof(input->data); effective_load = m_mtu - header_size; fragments = (input->data_size + effective_load - 1) / effective_load; heap_size = fragments * m_mtu; heap_size += sizeof(SEND_ITEM); // create the send_item heap = (char *)Alloc(heap_size); if(!heap){ return 0; } si = (SEND_ITEM*)heap; memset(si, 0, sizeof(SEND_ITEM)); si->header = (RTK_PACKET*)(si + 1); // insert the send_item into the s_lst if(!headEntry){ static RTK_LIST_ENTRY theFirstEntry; pr = s_lst.insert(SITEM_LIST::value_type(input->guid, theFirstEntry)); if(!pr.second){ Free(heap); return 0; } headEntry = &pr.first->second; RtkInitializeListHead(headEntry); RtkInsertTailList(headEntry, &si->li); }else{ // appending the fragments to the existing item RtkInsertTailList(headEntry, &si->li); } last_data_size = input->data_size % effective_load; offset = 0; for(i = 0, p = (char*)si->header, frag = (RTK_PACKET*)p; i<fragments; i++, p += m_mtu, frag = (RTK_PACKET*)p, offset += effective_load ){ // copy contents of input_packet to fragment *frag = *input; // then modify some fields frag->frgmt_id = i; frag->total_frag = fragments; frag->data_size = i==fragments-1? last_data_size : effective_load; frag->offset = offset; frag->grp_id = groupId; memcpy(frag->data, input->data + offset, frag->data_size); } rtk_time_mark(&si->birthday); si->life = rtkm_send_fragments_life * fragments; if(input->packet_type & PF_PacketGroup){ si->life *= 5; } return si; }