OnixS C++ Eurex T7 Market and Reference Data Interface (EMDI, RDI, EOBI) Handlers  8.1.0
API documentation
MdiDataRepository.cpp
Go to the documentation of this file.
1 /*
2 * Copyright Onix Solutions Limited [OnixS]. All rights reserved.
3 *
4 * This software owned by Onix Solutions Limited [OnixS] and is protected by copyright law
5 * and international copyright treaties.
6 *
7 * Access to and use of the software is governed by the terms of the applicable ONIXS Software
8 * Services Agreement (the Agreement) and Customer end user license agreements granting
9 * a non-assignable, non-transferable and non-exclusive license to use the software
10 * for it's own data processing purposes under the terms defined in the Agreement.
11 *
12 * Except as otherwise granted within the terms of the Agreement, copying or reproduction of any part
13 * of this source code or associated reference material to any other location for further reproduction
14 * or redistribution, and any amendments to this copyright notice, are expressly prohibited.
15 *
16 * Any reproduction or redistribution for sale or hiring of the Software not in accordance with
17 * the terms of the Agreement is a violation of copyright law.
18 */
19 #include <boost/bind.hpp>
20 
22 
23 #include "MessageOperator.h"
25 
26 #include "MdiDataRepository.h"
27 
28 
29 namespace OnixS {
30 namespace Eurex {
31 namespace MarketData {
32 namespace Implementation {
33 
35 
36 namespace {
37 
38 bool extractMarketSegmentId(const CORE::FieldSet& msg, MarketSegmentId& marketSegmentId)
39 {
40  const CORE::FieldValue& marketSegmentIdValue = msg[Tags::MarketSegmentID];
41  if(CORE::DataTypes::Null == marketSegmentIdValue.type())
42  return false;
43  if(!marketSegmentIdValue.convertTo(marketSegmentId))
44  return false;
45 
46  BOOST_ASSERT(marketSegmentId != UndefinedMarketSegmentId);
47 
48  return true;
49 }
50 
51 MarketSegmentId getMarketSegmentId(const CORE::Message& msg, TemplateId templateId)
52 {
53  MarketSegmentId marketSegmentId = UndefinedMarketSegmentId;
54 
55  if (ComplexInstrumentTemplateId == templateId || FlexibleInstrumentTemplateId == templateId)
56  {
57  try
58  {
59  const CORE::FieldIndex fieldIndex = msg.structure().find(Tags::NoMarketSegments);
60 
61  BOOST_ASSERT(fieldIndex != static_cast<CORE::FieldIndex>(CORE::FieldIndexTraits::OutOfRange));
62 
63  const CORE::FieldValue& fieldValue = msg.indexed()[fieldIndex];
64  const CORE::RepeatingGroup* group = fieldValue.get<const CORE::RepeatingGroup*>();
65 
66  BOOST_ASSERT(group != nullptr);
67 
68  if(!extractMarketSegmentId((*group)[0], marketSegmentId))
69  throw OnixS::BadArgumentException(BOOST_CURRENT_FUNCTION, "Unable to extract marketSegmentId");
70  }
71  catch(...)
72  {
73  throw OnixS::BadArgumentException(BOOST_CURRENT_FUNCTION, "Unable to extract marketSegmentId");
74  }
75  }
76  else
77  {
78  if(!extractMarketSegmentId(msg, marketSegmentId))
79  throw OnixS::BadArgumentException(BOOST_CURRENT_FUNCTION, "Unable to extract marketSegmentId");
80  }
81 
82  return marketSegmentId;
83 }
84 }
85 
87  : base(config)
88  , firstMarketSegmentId_(0)
89 {
90  productDataRepositories_.reserve(100);
91 }
92 
94 {
95  clearProductDataRepositories();
96 }
97 
98 void MdiDataRepository::clearProductDataRepositories()
99 {
100  BOOST_FOREACH(MdiProductDataRepository* repo, productDataRepositories_)
101  {
102  BOOST_ASSERT(repo);
103  delete repo;
104  }
105 
106  productDataRepositories_.clear();
107 }
108 
110 {
111  bool operator() (const MdiProductDataRepository* r, const MdiProductDataRepository* l) const
112  {
113  BOOST_ASSERT(r);
114  BOOST_ASSERT(l);
115 
116  return r->marketSegmentId() < l->marketSegmentId();
117  }
118 
119  bool operator() (const MdiProductDataRepository* r, MarketSegmentId l) const
120  {
121  BOOST_ASSERT(r);
122 
123  return r->marketSegmentId() < l;
124  }
125 };
126 
127 MdiProductDataRepository* MdiDataRepository::getOrCreateProductDataRepository(
128  MarketSegmentId marketSegmentId,
129  bool create)
130 {
131  std::vector<MdiProductDataRepository*>::const_iterator it = std::lower_bound(
132  productDataRepositories_.begin(),
133  productDataRepositories_.end(),
134  marketSegmentId,
136  );
137 
138  if ((it != productDataRepositories_.end()) && ((*it)->marketSegmentId() == marketSegmentId))
139  return *it;
140 
141  if (!create)
142  return nullptr;
143 
144  MarketDepth marketDepth = 0;
145 
146  MarketSegmentId2Depth_::const_iterator marketSegmentId2DepthIt = marketSegmentId2Depth_.find(marketSegmentId);
147  if(marketSegmentId2DepthIt == marketSegmentId2Depth_.end())
148  {
149  if (shouldBuildInternalOrderBooks())
150  {
151  TextBuilder tb;
152  tb << "No max market depth for " << marketSegmentId << ", book will not be built.";
153  log(ONIXS_LOG_WARN[this] << tb.toString());
154 
155  config_.listenerHolder->invokeWarning(tb.toString());
156  }
157  }
158  else
159  {
160  marketDepth = marketSegmentId2DepthIt->second;
161 
162  log(ONIXS_LOG_DEBUG[this] << "Max market depth for " << marketSegmentId << ": " << marketDepth);
163  }
164 
165  const bool buildInternalOrderBooks = shouldBuildInternalOrderBooks() && (0 != marketDepth);
166 
168  marketSegmentId,
169  marketDepth,
170  buildInternalOrderBooks,
171  this,
172  config_.logger,
175  boost::bind(&MdiDataRepository::filterSecurityId, this, _1));
176 
177  productDataRepositories_.push_back(rep);
178 
179  std::sort(
180  productDataRepositories_.begin(),
181  productDataRepositories_.end(),
183 
184  return rep;
185 }
186 
187 //void MdiDataRepository::resetRecoveryProcess()
188 //{
189 // firstMarketSegmentId_ = UndefinedMarketSegmentId;
190 // securityIDs_.clear();
191 // marketSegmentIDs_.clear();
192 //}
193 
195  const DataSource& dataSource,
196  const CORE::Message& msg,
197  TemplateId templateId)
198 {
199  const MarketSegmentId marketSegmentId = getMarketSegmentId(msg, templateId);
200 
201  MdiProductDataRepository* const productDataRepository = getOrCreateProductDataRepository(
202  marketSegmentId,
203  marketSegmentIdfilters_.empty()
204  );
205 
206  if (!productDataRepository)
207  {
208  log(ONIXS_LOG_DEBUG[this] << "IM: " << msg);
209  log(ONIXS_LOG_DEBUG[this] << "IM: " << "message filtered, marketSegmentId " << marketSegmentId);
210  return;
211  }
212 
213  productDataRepository->processMessage(msg, templateId, dataSource);
214 }
215 
217 {
218  if (config_.settings.startRecoveryOnPacketGap)
219  {
220  BOOST_FOREACH(MdiProductDataRepository* repo, productDataRepositories_)
221  {
222  BOOST_ASSERT(repo);
223  repo->reset();
224  }
225  }
226 }
227 
229 {
230  BOOST_FOREACH(MdiProductDataRepository* repo, productDataRepositories_)
231  {
232  BOOST_ASSERT(repo);
233  repo->reset();
234  }
235 }
236 
238 {
239  BOOST_FOREACH(MdiProductDataRepository* repo, productDataRepositories_)
240  {
241  BOOST_ASSERT(repo);
242  repo->noDataOnIncrementalFeeds();
243  }
244 }
245 
247 {
248  marketSegmentIdfilters_.clear();
249  std::copy(filters.begin(), filters.end(), std::inserter(marketSegmentIdfilters_, marketSegmentIdfilters_.end()));
250 
251  if (marketSegmentId2Depth_.empty() && shouldBuildInternalOrderBooks())
252  return;
253 }
254 
256 {
257  if(!config_.settings.buildInternalOrderBooks)
258  {
259  TextBuilder tb;
260  tb << "Setting MarketSegmentId2Depth with book build disabled, action has no effect.";
261  log(ONIXS_LOG_WARN[this] << tb.toString());
262 
263  config_.listenerHolder->invokeWarning(tb.toString());
264 
265  return;
266  }
267 
268  marketSegmentId2Depth_.clear();
269  std::copy(map.begin(), map.end(), std::inserter(marketSegmentId2Depth_, marketSegmentId2Depth_.end()));
270 
271  if(marketSegmentIdfilters_.empty())
272  return;
273 }
274 
276 {
277  marketSegmentIdfilters_.clear();
278  clearProductDataRepositories();
279 }
280 
282 {
283  clearProductDataRepositories();
284 
285  if (!marketSegmentIdfilters_.empty())
286  {
287  BOOST_FOREACH(MarketSegmentId marketSegmentId, marketSegmentIdfilters_)
288  {
289  const MdiProductDataRepository* const emdiProductDataRepository =
290  getOrCreateProductDataRepository(marketSegmentId, true);
291 
292  BOOST_ASSERT(emdiProductDataRepository != nullptr); (void) emdiProductDataRepository;
293  }
294  }
295  else
296  {
297  typedef std::pair<MarketSegmentId, MarketDepth> Pair;
298  BOOST_FOREACH(const Pair& pair, marketSegmentId2Depth_)
299  {
300  const MdiProductDataRepository* const emdiProductDataRepository =
301  getOrCreateProductDataRepository(pair.first, true);
302 
303  BOOST_ASSERT(emdiProductDataRepository != nullptr); (void) emdiProductDataRepository;
304  }
305  }
306 }
307 
309 {
310  securityIdFilters_.clear();
311  std::copy(filters.begin(), filters.end(), std::inserter(securityIdFilters_, securityIdFilters_.end()));
312 }
313 
315 {
316  securityIdFilters_.clear();
317 }
318 
319 bool MdiDataRepository::filterSecurityId(const SecurityId& securityId) const
320 {
321  if(securityIdFilters_.empty())
322  return true;
323 
324  return securityIdFilters_.end() != securityIdFilters_.find(securityId);
325 }
326 
327 // for testing only
328 MdiDataRepository::MdiProductDataRepositories_ MdiDataRepository::productDataRepositories()
329 {
330  MdiDataRepository::MdiProductDataRepositories_ productDataRepositories;
331 
332  BOOST_FOREACH(MdiProductDataRepository* repo, productDataRepositories_)
333  {
334  BOOST_ASSERT(repo);
335 
336  productDataRepositories[repo->marketSegmentId()] = repo;
337  }
338 
339  return productDataRepositories;
340 }
341 
342 }}}}
MarketDepthTraits::MarketSegmentId2Depth MarketSegmentId2Depth
void setMarketSegmentIdFilters(const MarketSegmentIdFilters &filters)
UInt32 MarketDepth
Alias for Market depth type.
Definition: Defines.h:43
void setSecurityIdFilters(const SecurityIdFilters &filters)
Util::TextBuilder TextBuilder
Definition: Formatting.h:43
void processMessage(const CORE::Message &, TemplateId, const DataSource &)
Definition: Defines.h:30
FilteringTraits::MarketSegmentIdFilters MarketSegmentIdFilters
const MarketSegmentId UndefinedMarketSegmentId
Definition: Defines.h:45
Int64 SecurityId
Alias for Security Id type.
Definition: Defines.h:51
void onMessage(const DataSource &dataSource, const CORE::Message &msg, TemplateId templateId)
FilteringTraits::SecurityIdFilters SecurityIdFilters
MdiDataRepository(const MdiDataRepositoryConfig &config)
UInt32 MarketSegmentId
Alias for Market Segment ID type.
Definition: Defines.h:40
OnixS::FIX::Core::FAST::TemplateId TemplateId
void setMarketSegmentId2Depth(const MarketSegmentId2Depth &map)