NEST  2.6.0,not_revisioned_source_dir@0
universal_data_logger.h
Go to the documentation of this file.
1 /*
2  * universal_data_logger.h
3  *
4  * This file is part of NEST.
5  *
6  * Copyright (C) 2004 The NEST Initiative
7  *
8  * NEST is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * NEST is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with NEST. If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 
23 #ifndef UNIVERSAL_DATA_LOGGER_H
24 #define UNIVERSAL_DATA_LOGGER_H
25 
26 #include "nest.h"
27 #include "event.h"
28 #include "recordables_map.h"
29 #include "nest_time.h"
30 
31 #include <vector>
32 
33 namespace nest {
34 
35  class Network;
36 
86  template <typename HostNode>
87  class UniversalDataLogger {
88 
89  public:
90 
94  UniversalDataLogger(HostNode&);
95 
108  port connect_logging_device(const DataLoggingRequest&,
109  const RecordablesMap<HostNode>&);
110 
121  void handle(const DataLoggingRequest&);
122 
132  void record_data(long_t);
133 
135  void reset();
136 
141  void init();
142 
143  private:
144 
151  class DataLogger_ {
152  public:
153  DataLogger_(const DataLoggingRequest&,
154  const RecordablesMap<HostNode>&);
155  index get_mm_gid() const { return multimeter_; }
156  void handle(HostNode&, const DataLoggingRequest&);
157  void record_data(const HostNode&, long_t);
158  void reset();
159  void init();
160 
161  private:
162  index multimeter_;
163  size_t num_vars_;
164 
165  Time recording_interval_;
166  long_t rec_int_steps_;
167  long_t next_rec_step_;
168 
170  std::vector<typename RecordablesMap<HostNode>::DataAccessFct> node_access_;
171 
179  std::vector<DataLoggingReply::Container> data_;
180 
182  std::vector<size_t> next_rec_;
183  };
184 
185  HostNode& host_;
186 
191  std::vector<DataLogger_> data_loggers_;
192  typedef typename std::vector<DataLogger_>::iterator DLiter_;
193 
195  UniversalDataLogger(const UniversalDataLogger&);
196 
198  UniversalDataLogger const& operator=(const UniversalDataLogger&);
199  };
200 
201  // must be defined in this file, since it is required by check_connection(),
202  // which typically is in h-files.
203  template <typename HostNode>
204  port nest::UniversalDataLogger<HostNode>::connect_logging_device(const DataLoggingRequest& req,
205  const RecordablesMap<HostNode>& rmap)
206  {
207  // rports are assigned consecutively, the caller may not request specific rports.
208  if ( req.get_rport() != 0 )
209  throw IllegalConnection("UniversalDataLogger::connect_logging_device(): "
210  "Connections from multimeter to node must request rport 0.");
211 
212  // ensure that we have not connected this multimeter before
213  const index mm_gid = req.get_sender().get_gid();
214  const size_t n_loggers = data_loggers_.size();
215  size_t j = 0;
216  while ( j < n_loggers && data_loggers_[j].get_mm_gid() != mm_gid )
217  ++j;
218  if ( j < n_loggers )
219  throw IllegalConnection("UniversalDataLogger::connect_logging_device(): "
220  "Each multimeter can only be connected once to a given node.");
221 
222  // we now know that we have no DataLogger_ for the given multimeter, so we create one and push it
223  data_loggers_.push_back(DataLogger_(req, rmap));
224 
225  // rport is index plus one, i.e., size
226  return data_loggers_.size();
227  }
228 
229  template <typename HostNode>
230  nest::UniversalDataLogger<HostNode>::DataLogger_::DataLogger_(const DataLoggingRequest& req,
231  const RecordablesMap<HostNode>& rmap):
232  multimeter_(req.get_sender().get_gid()),
233  num_vars_(0),
234  recording_interval_(Time::neg_inf()),
235  rec_int_steps_(0),
236  next_rec_step_(-1), // flag as uninitialized
237  node_access_(),
238  data_(),
239  next_rec_(2,0)
240  {
241  const std::vector<Name>& recvars = req.record_from();
242  for ( size_t j = 0 ; j < recvars.size() ; ++j )
243  {
244  typename RecordablesMap<HostNode>::const_iterator rec
245  = rmap.find(recvars[j].toString()); // .toString() required as work-around for #339,
246  // remove when #348 is solved.
247 
248  if ( rec == rmap.end() )
249  {
250  // delete all access information again: the connect either succeeds
251  // for all entries in recvars, or it fails, leaving the logger untouched
252  node_access_.clear();
253  throw IllegalConnection("UniversalDataLogger::connect_logging_device(): "
254  "Unknown recordable " + recvars[j].toString());
255  }
256 
257  node_access_.push_back(rec->second);
258  }
259 
260  num_vars_ = node_access_.size();
261 
262  if ( num_vars_ > 0 && req.get_recording_interval() < Time::step(1) )
263  throw IllegalConnection("UniversalDataLogger::connect_logging_device(): "
264  "recording interval must be >= resolution.");
265 
266  recording_interval_ = req.get_recording_interval();
267  }
268 
269 }
270 
271 #endif // UNIVERSAL_DATA_LOGGER_H
size_t index
Unsigned long type for enumerations.
Definition: nest.h:109
long_t port
Connection port number to distinguis outgoing connections.
Definition: nest.h:155
Default types used by the NEST kernel.
long long_t
Integer number with at least 32 bit.
Definition: nest.h:96