如何找到bug(8): SequentialInputHandler::run()取数逻辑
404 /************************************/ 405 void SequentialInputHandler::run(void) 406 /************************************/ 407 { 408 409 410 DEBUG_TEXT(DFDB_ROSFM, 15, "SequentialInputHandler::run: Entered"); 411 std::cout << "SequentialInputHandler::run: Entered" << std::endl; 412 bool busy; 413 414 //wangl 415 /*----------------------------*/ 416 std::vector<LVL1ID> l1_vec; 417 unsigned int sendSize=1; 418 l1_vec.clear() ; 419 /*----------------------------*/ 420 /*while(true) { 421 DFThread::yieldOrCancel(); 422 m_statistics.yield++; 423 } 424 return ;*/ 425 426 // first, erase unsyncronized RODs 427 std::vector<LVL1ID> *channel_l1ids; 428 channel_l1ids = new std::vector<LVL1ID>[m_numberOfDataChannels] ; 429 while(true) { 430 for(int chan = 0; chan < m_numberOfDataChannels; chan++) { 431 bool isReady = m_dataChannels[chan]->readyToReadout(); 432 if (isReady) { 433 unsigned int FragmentL1id = m_dataChannels[chan]->inputFragment(); 434 channel_l1ids[chan].push_back(FragmentL1id) ; 435 if(areFragmentsThere(FragmentL1id)) { 436 //DEBUG_TEXT(DFDB_ROSFM, 15, "ros ready l1id: " << FragmentL1id); 437 l1_vec.push_back(FragmentL1id) ; 438 break ; 439 } 440 } 441 } 442 443 444 if(l1_vec.size() > 0) { 445 LVL1ID firstId = l1_vec[0] ; 446 for(int chan = 0; chan < m_numberOfDataChannels; chan++) { 447 for(int i=0; i<channel_l1ids[chan].size(); i++) { 448 LVL1ID id = channel_l1ids[chan][i] ; 449 if(id < firstId) { 450 DEBUG_TEXT(DFDB_ROSFM, 8, "release unsyncronized ROD: " << id << ", channel: " << chan); 451 m_dataChannels[chan]->releaseFragment(id) ; 452 } 453 } 454 } 455 m_outStandingEvents.clear() ; //I think this is wrong!! 456 break ; 457 } 458 DFThread::yieldOrCancel(); 459 } 460 //DEBUG_TEXT(DFDB_ROSFM, 15, "deleting vector pointer .." ); 461 delete [] channel_l1ids ; 462 std::cout << "InputHandler got first ROD: " << l1_vec[0] << std::endl ; 463 if( l1_vec.size() >= sendSize ) 464 { 465 LVL1Message outmsg(l1_vec); 466 if(!outmsg.send(m_l2svPort)) std::cerr<<"fail send "<<std::endl; 467 l1_vec.clear(); 468 } 469 470 //////////////////////////////// 471 std::cout << "now we are going to recv data!" << std::endl; 472 473 while(true) { 474 475 struct timeval t0, t1 ; 476 477 busy = true; 478 479 while(busy) { 480 busy = false; 481 482 483 for(int chan = 0; chan < m_numberOfDataChannels; chan++) { 484 485 bool isReady = m_dataChannels[chan]->readyToReadout(); 486 487 if (isReady) { 488 489 busy = true; 490 DEBUG_TEXT(DFDB_ROSFM, 15, "SequentialInputHandler::run: Inputting data via ROL " << chan); 491 unsigned int FragmentL1id ; 492 493 FragmentL1id = m_dataChannels[chan]->inputFragment(); 494 495 //m_dataChannels[chan]->releaseFragment(FragmentL1id); 496 pushL1id(FragmentL1id,chan); // zengtx 497 if(areFragmentsThere(FragmentL1id)) 498 { 499 DEBUG_TEXT(DFDB_ROSFM, 15, "ros ready l1id: " << FragmentL1id); 500 l1_vec.push_back(FragmentL1id) ; 501 } 502 if( l1_vec.size() >= sendSize ) 503 { 504 LVL1Message outmsg(l1_vec); 505 if(!outmsg.send(m_l2svPort)) std::cerr<<"fail send "<<std::endl; 506 l1_vec.clear(); 507 } 508 } 509 } 510 511 } 512 513 if( l1_vec.size()>0 ) 514 { 515 LVL1Message outmsg(l1_vec); 516 if(!outmsg.send(m_l2svPort)) std::cerr<<"fail send "<<std::endl; 517 l1_vec.clear(); 518 } 519 520 521 // We have scanned all ROLs but none has data or all pages are used in the memory pool of the 522 // respective ROL. There is nothing to do. Therefore: 523 DFThread::yieldOrCancel(); 524 m_statistics.yield++; 525 } 526 527 } 528
查看了取数逻辑,整个SequentialInputHandler::run()函数包括两个部分:
1. 同步?删掉L1id小于0的Fragment? 我的理解是取到了第一个完整的事例 第410-469行
2. 真正取数部分,第470-525行
同步的部分,用了一个vector数组来记录每个dataChannel取到的Fragment的L1id. 类似于:
0 | 1 | 2 | 3 | 4 | |
0 | 1 | 2 | 3 | 4 | 5 |
0 | 1 | ||||
0 | 1 | ||||
0 |
以上面的表格为例:
第一行为dataChannel 1, 收了5个Fragment,
第二行为dataChannel 2, 收了6个Fragment,
第三行为dataChannel 3, 收了2个Fragment,
第四行为dataChannel 4, 收了2个Fragment,
第五行为dataChannel 5, 收了1个Fragment.
....
等所有通道的第一个Fragment(即L1id=0的Fragment)都收到以后,就进行了一个判断:
449 if(id < firstId) { 450 DEBUG_TEXT(DFDB_ROSFM, 8, "release unsyncronized ROD: " << id << ", channel: " << chan); 451 m_dataChannels[chan]->releaseFragment(id) ; 452 }
将 L1id 小于 0 的Fragment release掉,但是这在目前的取数逻辑里是不可能发生的。L1id咋可能小于0呢?
然后问题来了,干完这个同步以后,将m_outStandingEvents clear掉了,这个时候,各个通道已经收到的Fragment的计数都被清除了,后面在继续取数的过程中,判断Fragment是否到齐的逻辑就出现了问题。所以应该把这句话去掉!
444 if(l1_vec.size() > 0) {
445 LVL1ID firstId = l1_vec[0] ; 446 for(int chan = 0; chan < m_numberOfDataChannels; chan++) { 447 for(int i=0; i<channel_l1ids[chan].size(); i++) { 448 LVL1ID id = channel_l1ids[chan][i] ; 449 if(id < firstId) { 450 DEBUG_TEXT(DFDB_ROSFM, 8, "release unsyncronized ROD: " << id << ", channel: " << chan); 451 m_dataChannels[chan]->releaseFragment(id) ; 452 } 453 } 454 } 455 m_outStandingEvents.clear() ; //I think this is wrong!!