TSCache.cpp
上传用户:nameszq
上传日期:2014-08-12
资源大小:336k
文件大小:12k
源码类别:

金融证券系统

开发平台:

Visual C++

  1. // TSCache.cpp: implementation of the CTSCache class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "TSCache.h"
  6. #include "TW.h"
  7. #include "SpTime.h"
  8. #include "TWSocket.h"
  9. #ifdef _DEBUG
  10. #undef THIS_FILE
  11. static char THIS_FILE[]=__FILE__;
  12. #define new DEBUG_NEW
  13. #endif
  14. //////////////////////////////////////////////////////////////////////
  15. // Construction/Destruction
  16. //////////////////////////////////////////////////////////////////////
  17. CTSCache & CTSCache::GetInstance()
  18. {
  19. static CTSCache s_tscache;
  20. return s_tscache;
  21. }
  22. CTSCache::CTSCache()
  23. {
  24. m_nBufLen = 0;
  25. }
  26. CTSCache::~CTSCache()
  27. {
  28. }
  29. void CTSCache::SetLocalLatest(CSPTime t)
  30. {
  31. m_tmLocalLatest = t;
  32. }
  33. CSPTime CTSCache::GetLocalLatest()
  34. {
  35. return m_tmLocalLatest;
  36. }
  37. int CTSCache::OnReceive( BYTE * buf, size_t len )
  38. {
  39. CSingleLock lock(&m_mutexBuffer,TRUE);
  40. if( NULL == buf || len <= 0 )
  41. return 0;
  42. if( len > sizeof(m_buffer) )
  43. return 0;
  44. if( m_nBufLen + len > sizeof(m_buffer) )
  45. m_nBufLen = 0; // discard old
  46. memcpy( m_buffer+m_nBufLen, buf, len );
  47. m_nBufLen += len;
  48. int packets = DecodePacket();
  49. while( packets > 0 )
  50. packets = DecodePacket();
  51. return len;
  52. }
  53. int CTSCache::DecodePacket( )
  54. {
  55. if( m_nBufLen <= 0 )
  56. return 0;
  57. int nPacketLen = FindFirstPacketLength();
  58. if( nPacketLen > 0 && nPacketLen <= (int)m_nBufLen )
  59. {
  60. TryGetPacket( nPacketLen );
  61. DiscardPacket( nPacketLen );
  62. return 1;
  63. }
  64. if( m_nBufLen > sizeof(m_buffer)/2 )
  65. m_nBufLen = 0; // truncate if too big and no packets found.
  66. return 0;
  67. }
  68. int CTSCache::FindFirstPacketLength( )
  69. {
  70. AlignBuffer(0, TRUE);
  71. size_t len = TryGetLength( m_buffer, m_nBufLen );
  72. size_t wantlen = len + sizeof(TW_HEADER);
  73. if( wantlen <= m_nBufLen )
  74. return wantlen;
  75. // else if( wantlen < sizeof(m_buffer) )
  76. // return 0;
  77. if( CTWSocket::GetInstance().IsReceiving() ) // 在接收大包
  78. return 0;
  79. len = AlignBuffer(4, FALSE);
  80. return len;
  81. }
  82. size_t CTSCache::AlignBuffer( int nStart, BOOL bRemove )
  83. {
  84. if( m_nBufLen <= 4 )
  85. return 0;
  86. size_t i = 0;
  87. for( i=nStart; i<m_nBufLen-4; i++ )
  88. {
  89. if( TW_MAGIC_BYTE == m_buffer[i] )
  90. {
  91. if( TW_MAGIC_BYTE == m_buffer[i+1]
  92. && TW_MAGIC_BYTE == m_buffer[i+2]
  93. && TW_MAGIC_BYTE == m_buffer[i+3] )
  94. {
  95. break;
  96. }
  97. }
  98. }
  99. if( i > 0 && i+sizeof(TW_HEADER) < m_nBufLen )
  100. {
  101. int newlen = TryGetLength(m_buffer+i,sizeof(TW_HEADER));
  102. if( newlen > 0 && i+sizeof(TW_HEADER)+newlen <= m_nBufLen )
  103. {
  104. if( bRemove )
  105. {
  106. m_nBufLen = m_nBufLen - i;
  107. memmove( m_buffer, m_buffer+i, m_nBufLen );
  108. }
  109. return i;
  110. }
  111. }
  112. return 0;
  113. }
  114. int CTSCache::TryGetPacket( int nPacketLen )
  115. {
  116. if( nPacketLen <= 0 || nPacketLen > (int)m_nBufLen )
  117. return 0;
  118. PRCV_DATA prcvdata = NULL;
  119. PRCV_DATA prcvdata2 = NULL;
  120. int nLen = 0;
  121. prcvdata = new RCV_DATA();
  122. memset( prcvdata, 0, sizeof(RCV_DATA) );
  123.   nLen = TryGetInit( m_buffer, nPacketLen, prcvdata );
  124. if( nLen > 0 )
  125. {
  126. { // clear
  127. CSingleLock lock(&m_mutexReports,TRUE);
  128. m_aReports.RemoveAll();
  129. m_mapReports.RemoveAll();
  130. }
  131. PushReport( prcvdata->m_pReport, prcvdata->m_nPacketNum );
  132. PushPacket( RCV_REPORT, prcvdata );
  133. prcvdata = NULL;
  134. StoreReports( );
  135. return 1;
  136. }
  137. if( prcvdata ) FreePacket(prcvdata);
  138. prcvdata = new RCV_DATA();
  139. memset( prcvdata, 0, sizeof(RCV_DATA) );
  140. nLen = TryGetReport( m_buffer, nPacketLen, prcvdata );
  141. if( nLen > 0 )
  142. {
  143. PushReport( prcvdata->m_pReport, prcvdata->m_nPacketNum );
  144. PushPacket( RCV_REPORT, prcvdata );
  145. prcvdata = NULL;
  146. return 1;
  147. }
  148. if( prcvdata ) FreePacket(prcvdata);
  149. prcvdata = new RCV_DATA();
  150. prcvdata2 = new RCV_DATA();
  151. memset( prcvdata, 0, sizeof(RCV_DATA) );
  152. memset( prcvdata2, 0, sizeof(RCV_DATA) );
  153. nLen = TryGetMinute( m_buffer, nPacketLen, prcvdata, prcvdata2 );
  154. if( nLen > 0 )
  155. {
  156. PushReport( prcvdata2->m_pReport, prcvdata2->m_nPacketNum );
  157. PushPacket( RCV_FILEDATA, prcvdata );
  158. PushPacket( RCV_REPORT, prcvdata2 );
  159. prcvdata = NULL;
  160. prcvdata2 = NULL;
  161. return 1;
  162. }
  163. if( prcvdata ) FreePacket(prcvdata);
  164. if( prcvdata2 ) FreePacket(prcvdata2);
  165. prcvdata = new RCV_DATA();
  166. memset( prcvdata, 0, sizeof(RCV_DATA) );
  167. nLen = TryGetHistory( m_buffer, nPacketLen, prcvdata );
  168. if( nLen > 0 )
  169. {
  170. PushPacket( RCV_FILEDATA, prcvdata );
  171. prcvdata = NULL;
  172. return 1;
  173. }
  174. if( prcvdata ) FreePacket(prcvdata);
  175. prcvdata = new RCV_DATA();
  176. memset( prcvdata, 0, sizeof(RCV_DATA) );
  177. nLen = TryGetMultisort( m_buffer, nPacketLen, prcvdata );
  178. if( nLen > 0 )
  179. {
  180. PushPacket( RCV_FILEDATA, prcvdata );
  181. prcvdata = NULL;
  182. return 1;
  183. }
  184. if( prcvdata ) FreePacket(prcvdata);
  185. prcvdata = new RCV_DATA();
  186. memset( prcvdata, 0, sizeof(RCV_DATA) );
  187. nLen = TryGetDetail( m_buffer, nPacketLen, prcvdata );
  188. if( nLen > 0 )
  189. {
  190. PushPacket( RCV_REPORT, prcvdata );
  191. prcvdata = NULL;
  192. return 1;
  193. }
  194. if( prcvdata ) FreePacket(prcvdata);
  195. prcvdata = new RCV_DATA();
  196. memset( prcvdata, 0, sizeof(RCV_DATA) );
  197. nLen = TryGetBase( m_buffer, nPacketLen, prcvdata );
  198. if( nLen > 0 )
  199. {
  200. PushPacket( RCV_FILEDATA, prcvdata );
  201. prcvdata = NULL;
  202. return 1;
  203. }
  204. if( prcvdata ) FreePacket(prcvdata);
  205. return 0;
  206. }
  207. int CTSCache::DiscardPacket( int nPacketLen )
  208. {
  209. if( nPacketLen > 0 && nPacketLen <= (int)m_nBufLen )
  210. {
  211. m_nBufLen = m_nBufLen - nPacketLen;
  212. if( m_nBufLen > 0 )
  213. memmove( m_buffer, m_buffer+nPacketLen, m_nBufLen );
  214. return nPacketLen;
  215. }
  216. return 0;
  217. }
  218. ///////////////////////////////////////////////////////////////////////////////////
  219. // Packets
  220. BOOL CTSCache::PushPacket( UINT nMsgType, PRCV_DATA pRCV_DATA )
  221. {
  222. ASSERT( pRCV_DATA && pRCV_DATA->m_pData );
  223. CSingleLock lock(&m_mutexPackets,TRUE);
  224. TS_PACKET packet;
  225. packet.m_nMsgType = nMsgType;
  226. packet.m_pRCV_DATA = pRCV_DATA;
  227. m_aPackets.Add( packet );
  228. return TRUE;
  229. }
  230. BOOL CTSCache::PopPacket( UINT & nMsgType, PRCV_DATA & pRCV_DATA )
  231. {
  232. CSingleLock lock(&m_mutexPackets,TRUE);
  233. if( m_aPackets.GetSize() > 0 )
  234. {
  235. nMsgType = m_aPackets.ElementAt(0).m_nMsgType;
  236. pRCV_DATA = m_aPackets.ElementAt(0).m_pRCV_DATA;
  237. m_aPackets.RemoveAt(0);
  238. return TRUE;
  239. }
  240. return FALSE;
  241. }
  242. void CTSCache::FreePacket( PRCV_DATA pRCV_DATA )
  243. {
  244. if( pRCV_DATA )
  245. {
  246. if( pRCV_DATA->m_pData )
  247. delete [] pRCV_DATA->m_pData;
  248. delete pRCV_DATA;
  249. }
  250. }
  251. ///////////////////////////////////////////////////////////////////////////////////
  252. // Reports
  253. CString GetNetTSReportsFileName()
  254. {
  255. static CString sReportsFile;
  256. if( sReportsFile.IsEmpty() )
  257. {
  258. sReportsFile = AfxGetQSProfile().GetWorkDirectory() + "dat/report.now";
  259. }
  260. return sReportsFile;
  261. }
  262. BOOL CTSCache::StoreReports( )
  263. {
  264. CSingleLock lock(&m_mutexReports,TRUE);
  265. CFile file;
  266. if( m_aReports.GetSize() > 0 && file.Open( GetNetTSReportsFileName(), CFile::modeWrite | CFile::modeCreate ) )
  267. {
  268. CSPTime sptime(m_aReports.ElementAt(0).m_time);
  269. DWORD date = sptime.ToStockTimeDay();
  270. int size = m_aReports.GetSize();
  271. SetLocalLatest( sptime );
  272. file.SeekToBegin();
  273. file.Write( &date, sizeof(date) );
  274. file.Write( &size, sizeof(size) );
  275. file.Write( m_aReports.GetData(), sizeof(RCV_REPORT_STRUCTEx)*m_aReports.GetSize() );
  276. file.Close();
  277. return TRUE;
  278. }
  279. return FALSE;
  280. }
  281. BOOL CTSCache::LoadReports( )
  282. {
  283. CSingleLock lock(&m_mutexReports,TRUE);
  284. CFile file;
  285. if( file.Open( GetNetTSReportsFileName(), CFile::modeRead ) )
  286. {
  287. DWORD date = -1;
  288. int size = 0;
  289. DWORD len = file.GetLength();
  290. file.SeekToBegin();
  291. if( sizeof(date) != file.Read( &date, sizeof(date) )
  292. || sizeof(size) != file.Read( &size, sizeof(size) ) )
  293. {
  294. file.Close();
  295. return FALSE;
  296. }
  297. if( size <= 0 || size > 50000 || size*sizeof(RCV_REPORT_STRUCTEx)+sizeof(DWORD)+sizeof(int) != len )
  298. {
  299. file.Close();
  300. return FALSE;
  301. }
  302. CSPTime sptime;
  303. sptime.FromStockTimeDay( date );
  304. SetLocalLatest( sptime );
  305. m_aReports.RemoveAll();
  306. m_mapReports.RemoveAll();
  307. m_aReports.SetSize( size );
  308. file.Read( m_aReports.GetData(), sizeof(RCV_REPORT_STRUCTEx)*size );
  309. for( int nNo=0; nNo<m_aReports.GetSize(); nNo++ )
  310. {
  311. m_aReports[nNo].m_cbSize = sizeof(RCV_REPORT_STRUCTEx);
  312. m_mapReports.SetAt( m_aReports[nNo].m_szLabel, (void *)nNo );
  313. }
  314. file.Close();
  315. return TRUE;
  316. }
  317. return FALSE;
  318. }
  319. BOOL CTSCache::ReserveReportsSize( int size )
  320. {
  321. CSingleLock lock(&m_mutexReports,TRUE);
  322. if( m_aReports.GetSize() < size )
  323. m_aReports.SetSize( size );
  324. return TRUE;
  325. }
  326. BOOL CTSCache::PushReport( int nNo, RCV_REPORT_STRUCTEx * pBuf )
  327. {
  328. if( NULL == pBuf )
  329. return FALSE;
  330. CSingleLock lock(&m_mutexReports,TRUE);
  331. ASSERT( pBuf->m_cbSize == sizeof(RCV_REPORT_STRUCTEx) );
  332. pBuf->m_cbSize = sizeof(RCV_REPORT_STRUCTEx);
  333. if( nNo >= 0 && nNo < m_aReports.GetSize() )
  334. {
  335. if( pBuf->m_fLastClose < 1e-4 ) pBuf->m_fLastClose = m_aReports.ElementAt(nNo).m_fLastClose;
  336. if( 0 == pBuf->m_wMarket ) pBuf->m_wMarket = m_aReports.ElementAt(nNo).m_wMarket;
  337. if( strlen(pBuf->m_szName) <= 0 ) memcpy(pBuf->m_szName,m_aReports.ElementAt(nNo).m_szName,sizeof(pBuf->m_szName));
  338. if( pBuf->m_time < m_aReports.ElementAt(nNo).m_time )
  339. return FALSE;
  340. }
  341. m_aReports.SetAtGrow( nNo, *pBuf );
  342. m_mapReports.SetAt( pBuf->m_szLabel, (void *)nNo );
  343. return TRUE;
  344. }
  345. BOOL CTSCache::PushReport( char * pszStockCode, RCV_REPORT_STRUCTEx * pBuf )
  346. {
  347. if( NULL == pszStockCode || strlen(pszStockCode) <= 0 || NULL == pBuf )
  348. return FALSE;
  349. CSingleLock lock(&m_mutexReports,TRUE);
  350. // look for it in map
  351. void * rValue = NULL;
  352. if( m_mapReports.Lookup( pszStockCode, rValue ) )
  353. {
  354. int nNo = (int)rValue;
  355. ASSERT( nNo >= 0 && nNo < m_aReports.GetSize() && 0 == strncmp(pszStockCode, m_aReports.ElementAt(nNo).m_szLabel, sizeof(m_aReports.ElementAt(nNo).m_szLabel)) );
  356. if( nNo >= 0 && nNo < m_aReports.GetSize()
  357. && ( 0 == (m_aReports.ElementAt(nNo).m_szLabel[0] )
  358. || 0 == strncmp(pszStockCode, m_aReports.ElementAt(nNo).m_szLabel, sizeof(m_aReports.ElementAt(nNo).m_szLabel)) ) )
  359. return PushReport( nNo, pBuf );
  360. else // something error
  361. m_mapReports.RemoveKey( pszStockCode );
  362. }
  363. ASSERT( pBuf->m_cbSize == sizeof(RCV_REPORT_STRUCTEx) );
  364. pBuf->m_cbSize = sizeof(RCV_REPORT_STRUCTEx);
  365. int nNo = m_aReports.Add( *pBuf );
  366. m_mapReports.SetAt( pszStockCode, (void *)nNo );
  367. return TRUE;
  368. }
  369. int CTSCache::PushReport( RCV_REPORT_STRUCTEx * pBuf, int size )
  370. {
  371. if( NULL == pBuf || size <= 0 )
  372. return 0;
  373. for( int i=0; i<size; i++ )
  374. PushReport( pBuf[i].m_szLabel, &(pBuf[i]) );
  375. return size;
  376. }
  377. int CTSCache::GetTotalNumber()
  378. {
  379. CSingleLock lock(&m_mutexReports,TRUE);
  380. if( m_aReports.GetSize() <= 0 )
  381. {
  382. LoadReports( );
  383. }
  384. return m_aReports.GetSize();
  385. }
  386. BOOL CTSCache::GetStockByNoEx( int nNo, RCV_REPORT_STRUCTEx * pBuf )
  387. {
  388. CSingleLock lock(&m_mutexReports,TRUE);
  389. if( nNo < 0 || nNo >= m_aReports.GetSize() )
  390. return FALSE;
  391. if( pBuf && pBuf->m_cbSize > 0 )
  392. {
  393. memcpy( pBuf, &(m_aReports.ElementAt(nNo)), pBuf->m_cbSize );
  394. }
  395. else if( pBuf )
  396. {
  397. memcpy( pBuf, &(m_aReports.ElementAt(nNo)), sizeof(RCV_REPORT_STRUCTEx) );
  398. }
  399. return TRUE;
  400. }
  401. BOOL CTSCache::GetStockByCodeEx(char * pszStockCode,int nMarket,RCV_REPORT_STRUCTEx * pBuf)
  402. {
  403. if( NULL == pszStockCode || strlen(pszStockCode) <= 0 )
  404. return FALSE;
  405. CSingleLock lock(&m_mutexReports,TRUE);
  406. // look for it in map
  407. void * rValue = NULL;
  408. if( m_mapReports.Lookup( pszStockCode, rValue ) )
  409. {
  410. int nNo = (int)rValue;
  411. ASSERT( nNo >= 0 && nNo < m_aReports.GetSize() && 0 == strncmp(pszStockCode, m_aReports.ElementAt(nNo).m_szLabel, sizeof(m_aReports.ElementAt(nNo).m_szLabel)) );
  412. if( nNo >= 0 && nNo < m_aReports.GetSize()
  413. && 0 == strncmp(pszStockCode, m_aReports.ElementAt(nNo).m_szLabel, sizeof(m_aReports.ElementAt(nNo).m_szLabel)) )
  414. return GetStockByNoEx( nNo, pBuf );
  415. else // something error
  416. m_mapReports.RemoveKey( pszStockCode );
  417. }
  418. return FALSE;
  419. }