Barst  2.0
A server that controls lab hardware.
Barst.cpp
1 // Barst.cpp : Defines the entry point for the console application.
2 //
3 
4 #include "stdafx.h"
5 #include "cpl defs.h"
6 #include "named pipes.h"
7 #include "Log buffer.h"
8 #include "mem pool.h"
9 #include "ftdi device.h"
10 #include "rtv device.h"
11 #include "serial device.h"
12 #include "mcdaq_device.h"
13 #include "misc tools.h"
14 
15 
16 
17 CMainManager::CMainManager() : CDevice(_T("Main"))
18 {
19  m_pcComm= NULL;
20  m_pcMemPool= new CMemPool; // main program buffer pool
21  m_hClose= CreateEvent(NULL, TRUE, FALSE, NULL);
22  m_bError= false;
23  if (!m_hClose)
24  m_bError= true;
25 }
26 
27 // when shutting down, first the pipe is disconnected.
28 CMainManager::~CMainManager()
29 {
30  if (m_pcComm)
31  m_pcComm->Close();
32  for (size_t i= 0; i<m_acManagers.size(); ++i)
33  delete m_acManagers[i];
34  CloseHandle(m_hClose);
35  delete m_pcComm;
36  delete m_pcMemPool;
37 }
38 
39 // only one thread ever calls this since there's only thread in this communicator
40 void CMainManager::ProcessData(const void *pHead, DWORD dwSize, __int64 llId)
41 {
42  if (m_bError)
43  return;
44  SData sData;
45  sData.pDevice= this;
46  sData.dwSize= sizeof(SBaseIn);
47  SBaseIn sBase;
48  memset(&sBase, 0, sizeof(SBaseIn));
49  sBase.dwSize= sizeof(SBaseIn);
50  sBase.nChan= -1;
51  bool bRes= true;
52 
53  if (!pHead || dwSize < sizeof(SBaseIn) || dwSize != ((SBaseIn*)pHead)->dwSize) // incorrect size read
54  {
55  sBase.nError= SIZE_MISSMATCH;
56  } else if (((SBaseIn*)pHead)->eType == eVersion && ((SBaseIn*)pHead)->dwSize == sizeof(SBaseIn) &&
57  ((SBaseIn*)pHead)->nChan == -1) // send lib version
58  {
59  sBase.dwInfo= BARST_VERSION;
60  sBase.eType= eVersion;
61  } else if (((SBaseIn*)pHead)->eType == eDelete && ((SBaseIn*)pHead)->dwSize == sizeof(SBaseIn)) // close manager
62  {
63  if (((SBaseIn*)pHead)->nChan == -1) // close main program
64  SetEvent(m_hClose);
65  else if (((SBaseIn*)pHead)->nChan >= 0 && ((SBaseIn*)pHead)->nChan < m_acManagers.size() &&
66  m_acManagers[((SBaseIn*)pHead)->nChan]) // close other manager
67  {
68  delete m_acManagers[((SBaseIn*)pHead)->nChan];
69  m_acManagers[((SBaseIn*)pHead)->nChan]= NULL;
70  }
71  else
72  sBase.nError= INVALID_CHANN;
73  sBase.nChan= ((SBaseIn*)pHead)->nChan;
74  sBase.eType= eDelete;
75  } else if (((SBaseIn*)pHead)->eType == eSet && ((SBaseIn*)pHead)->dwSize == sizeof(SBaseIn)) // add a manager
76  {
77  // prepare array element for manager
78  size_t t= 0;
79  for (; t < m_acManagers.size() && m_acManagers[t]; ++t);
80  if (t == m_acManagers.size())
81  m_acManagers.push_back(NULL);
82  sBase.eType= eSet;
83  switch (((SBaseIn*)pHead)->eType2) // the device to open
84  {
85  case eFTDIMan:
86  {
87  int nPos= -1;
88  for (size_t i= 0; i < m_acManagers.size() && nPos == -1; ++i) // make sure it isn't open already
89  if (m_acManagers[i] && _tcscmp(FTDI_MAN_STR, m_acManagers[i]->m_csName.c_str()) == 0)
90  nPos= (int)i;
91  if (nPos != -1) // found
92  {
93  sBase.nError= ALREADY_OPEN;
94  sBase.nChan= nPos;
95  break;
96  }
97  CManagerFTDI* pMan= new CManagerFTDI(m_pcComm, m_csPipe.c_str(), (int)t, sBase.nError);
98  if (!sBase.nError)
99  {
100  sBase.nChan= (int)t;
101  m_acManagers[t]= pMan;
102  } else
103  delete pMan;
104  break;
105  }
106  case eRTVMan:
107  {
108  int nPos= -1;
109  for (size_t i= 0; i < m_acManagers.size() && nPos == -1; ++i) // make sure it isn't open already
110  if (m_acManagers[i] && _tcscmp(RTV_MAN_STR, m_acManagers[i]->m_csName.c_str()) == 0)
111  nPos= (int)i;
112  if (nPos != -1) // found
113  {
114  sBase.nError= ALREADY_OPEN;
115  sBase.nChan= nPos;
116  break;
117  }
118  CManagerRTV* pMan= new CManagerRTV(m_pcComm, m_csPipe.c_str(), (int)t, sBase.nError);
119  if (!sBase.nError)
120  {
121  sBase.nChan= (int)t;
122  m_acManagers[t]= pMan;
123  } else
124  delete pMan;
125  break;
126  }
127  case eSerialMan:
128  {
129  int nPos= -1;
130  for (size_t i= 0; i < m_acManagers.size() && nPos == -1; ++i) // make sure it isn't open already
131  if (m_acManagers[i] && _tcscmp(SERIAL_MAN_STR, m_acManagers[i]->m_csName.c_str()) == 0)
132  nPos= (int)i;
133  if (nPos != -1) // found
134  {
135  sBase.nError= ALREADY_OPEN;
136  sBase.nChan= nPos;
137  break;
138  }
139  CManagerSerial* pMan= new CManagerSerial(m_pcComm, m_csPipe.c_str(), (int)t, sBase.nError);
140  if (!sBase.nError)
141  {
142  sBase.nChan= (int)t;
143  m_acManagers[t]= pMan;
144  } else
145  delete pMan;
146  break;
147  }
148  case eMCDAQMan:
149  {
150  int nPos= -1;
151  for (size_t i= 0; i < m_acManagers.size() && nPos == -1; ++i) // make sure it isn't open already
152  if (m_acManagers[i] && _tcscmp(MCDAQ_MAN_STR, m_acManagers[i]->m_csName.c_str()) == 0)
153  nPos= (int)i;
154  if (nPos != -1) // found
155  {
156  sBase.nError= ALREADY_OPEN;
157  sBase.nChan= nPos;
158  break;
159  }
160  CManagerMCDAQ* pMan= new CManagerMCDAQ(m_pcComm, m_csPipe.c_str(), (int)t, sBase.nError);
161  if (!sBase.nError)
162  {
163  sBase.nChan= (int)t;
164  m_acManagers[t]= pMan;
165  } else
166  delete pMan;
167  break;
168  }
169  default:
170  sBase.nError= INVALID_MAN;
171  break;
172  }
173  } else if (((SBaseIn*)pHead)->nChan == -1 && ((SBaseIn*)pHead)->eType == eQuery)
174  {
175  sData.dwSize = sizeof(SBaseIn) + sizeof(SBase) + sizeof(SPerfTime);
176  void *pHead = sData.pHead = m_pcMemPool->PoolAcquire(sData.dwSize);
177  if (pHead)
178  {
179  ((SBaseIn*)pHead)->dwSize= sizeof(SBaseIn) + sizeof(SBase) + sizeof(SPerfTime);
180  ((SBaseIn*)pHead)->eType= eQuery;
181  ((SBaseIn*)pHead)->nChan= -1;
182  ((SBaseIn*)pHead)->nError= 0;
183  pHead = (char*)pHead + sizeof(SBaseIn);
184 
185  ((SBase *)pHead)->dwSize = sizeof(SPerfTime) + sizeof(SBase);
186  ((SBase *)pHead)->eType = eServerTime;
187  pHead= (char *)pHead + sizeof(SBase);
188 
189  FILETIME sTime;
190  ULARGE_INTEGER ulTime;
191  ((SPerfTime *)pHead)->dRelativeTime = g_cTimer.Seconds();
192  GetSystemTimeAsFileTime(&sTime);
193  ulTime.HighPart = sTime.dwHighDateTime;
194  ulTime.LowPart = sTime.dwLowDateTime;
195  ((SPerfTime *)pHead)->dUTCTime = ulTime.QuadPart / 10000000.0;
196  m_pcComm->SendData(&sData, llId);
197  }
198  } else if (((SBaseIn*)pHead)->nChan < 0 || ((SBaseIn*)pHead)->nChan >= m_acManagers.size() ||
199  !m_acManagers[((SBaseIn*)pHead)->nChan]) // verify manager exists
200  {
201  sBase.nError= INVALID_CHANN;
202  sBase.eType= ((SBaseIn*)pHead)->eType;
203  } else if (((SBaseIn*)pHead)->eType == eQuery && ((SBaseIn*)pHead)->dwSize == sizeof(SBaseIn)) // send info on this manager
204  {
205  bRes= false;
206  DWORD dwResSize= m_acManagers[((SBaseIn*)pHead)->nChan]->GetInfo(NULL, 0); // size of response
207  sData.pHead= m_pcMemPool->PoolAcquire(dwResSize);
208  if (sData.pHead)
209  {
210  m_acManagers[((SBaseIn*)pHead)->nChan]->GetInfo(sData.pHead, dwResSize); // get response
211  sData.dwSize= dwResSize;
212  m_pcComm->SendData(&sData, llId);
213  }
214  } else if (((SBaseIn*)pHead)->eType == ePassOn) // pass following data to manager
215  {
216  bRes= false;
217  m_acManagers[((SBaseIn*)pHead)->nChan]->ProcessData((char*)pHead + sizeof(SBaseIn), dwSize-sizeof(SBaseIn), llId);
218  } else
219  sBase.nError= INVALID_COMMAND;
220 
221  if (bRes) // respond
222  {
223  sData.pHead= m_pcMemPool->PoolAcquire(sData.dwSize);
224  if (sData.pHead)
225  {
226  memcpy(sData.pHead, &sBase, sizeof(SBaseIn));
227  m_pcComm->SendData(&sData, llId);
228  }
229  }
230 }
231 
232 int CMainManager::Run(int argc, TCHAR* argv[])
233 {
234  if (argc != 4 && argc != 5)
235  return BAD_INPUT_PARAMS;
236  DWORD dwBuffSizeIn, dwBuffSizeOut; // size of pipe buffers
237  std::tstringstream in(argv[2]), out(argv[3]);
238  g_llMaxQueueBytes = -1;
239  if (argc == 5)
240  {
241  std::tstringstream ssMaxBytes(argv[4]);
242  ssMaxBytes >> g_llMaxQueueBytes; // queue limit, -1 means
243  }
244  in >> dwBuffSizeIn; // user writing to pipe size
245  out >> dwBuffSizeOut; // user reading from pipe
246  m_csPipe= argv[1]; // pipe name to use
247 
248  if (in.fail() || out.fail() || _tcschr(argv[2], _T('-'))
249  || _tcschr(argv[3], _T('-'))) // cannot be negative #
250  return BAD_INPUT_PARAMS;
251  // check if it exists already
252  HANDLE hPipe= CreateFile(argv[1], GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
253  if (hPipe != INVALID_HANDLE_VALUE || GetLastError() == ERROR_PIPE_BUSY)
254  return ALREADY_OPEN;
255  CloseHandle(hPipe);
256  m_pcComm= new CPipeServer(); // main program pipe
257  int nRes;
258  // only use one thread to ensure thread safety
259  if (nRes= static_cast<CPipeServer*>(m_pcComm)->Init(argv[1], 1, dwBuffSizeIn, dwBuffSizeOut, this, NULL))
260  return nRes;
261  if (WAIT_OBJECT_0 != WaitForSingleObject(m_hClose, INFINITE)) // wait here until closing
262  return WIN_ERROR(GetLastError(), nRes);
263  return 0;
264 }
265 
266 
267 int _tmain(int argc, _TCHAR* argv[])
268 {
269  InitializeQueueLimit();
270  g_cTimer.ResetTimer();
271 #ifndef _DEBUG
272  ShowWindow(GetConsoleWindow(), SW_HIDE);
273 #endif
274  CMainManager* pMainManager= new CMainManager;
275  int nRes= pMainManager->Run(argc, argv); // program sits here until stopped
276  delete pMainManager;
277  return nRes;
278 }
279 
280 // WM_COPYDATA http://www.cplusplus.com/forum/windows/23232/
281 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms633573%28v=vs.85%29.aspx
282 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms632593%28v=vs.85%29.aspx
virtual int SendData(const SData *pData, __int64 llId)=0
void ResetTimer()
Definition: misc tools.cpp:99
int Run(int argc, TCHAR *argv[])
Definition: Barst.cpp:232
double Seconds() const
Definition: misc tools.cpp:63
virtual void Close()=0
void ProcessData(const void *pHead, DWORD dwSize, __int64 llId)
Definition: Barst.cpp:40
const std::tstring m_csName
Definition: base classses.h:98