fix8  version 1.4.0
Open Source C++ FIX Framework
seqedit.cpp
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------------------
2 /*
3 
4 Fix8 is released under the GNU LESSER GENERAL PUBLIC LICENSE Version 3.
5 
6 Fix8 Open Source FIX Engine.
7 Copyright (C) 2010-16 David L. Dight <fix@fix8.org>
8 
9 Fix8 is free software: you can redistribute it and / or modify it under the terms of the
10 GNU Lesser General Public License as published by the Free Software Foundation, either
11 version 3 of the License, or (at your option) any later version.
12 
13 Fix8 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
14 even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 
16 You should have received a copy of the GNU Lesser General Public License along with Fix8.
17 If not, see <http://www.gnu.org/licenses/>.
18 
19 THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
20 COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY
21 KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO
23 THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
24 YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
25 
26 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT
27 HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED
28 ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
29 CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT
30 NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR
31 THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH
32 HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
33 
34 */
35 //-----------------------------------------------------------------------------------------
59 //-----------------------------------------------------------------------------------------
60 #include "precomp.hpp"
61 // f8 headers
62 #include <fix8/f8includes.hpp>
63 #include <fix8/usage.hpp>
64 
65 #ifdef FIX8_HAVE_GETOPT_H
66 #include <getopt.h>
67 #endif
68 
69 #ifdef _MSC_VER
70 #define ssize_t int
71 #endif
72 
73 //-----------------------------------------------------------------------------------------
74 using namespace std;
75 using namespace FIX8;
76 
77 //-----------------------------------------------------------------------------------------
78 const string GETARGLIST("hvdDR:S:iq");
79 
80 //-----------------------------------------------------------------------------------------
81 void print_usage();
82 
83 //-----------------------------------------------------------------------------------------
84 int main(int argc, char **argv)
85 {
86  bool dump(false), rawdump(false), indexonly(false), quiet(false);
87  int val;
88  unsigned next_send(0), next_receive(0);
89 
90 #ifdef FIX8_HAVE_GETOPT_LONG
91  const option long_options[]
92  {
93  { "help", 0, 0, 'h' },
94  { "dump", 0, 0, 'd' },
95  { "version", 0, 0, 'v' },
96  { "rawdump", 0, 0, 'D' },
97  { "index", 0, 0, 'i' },
98  { "quiet", 0, 0, 'q' },
99  { "send", 1, 0, 'S' },
100  { "receive", 1, 0, 'R' },
101  { 0 },
102  };
103 
104  while ((val = getopt_long (argc, argv, GETARGLIST.c_str(), long_options, 0)) != -1)
105 #else
106  while ((val = getopt (argc, argv, GETARGLIST.c_str())) != -1)
107 #endif
108  {
109  switch (val)
110  {
111  case 'v':
112  cout << "seqedit for " FIX8_PACKAGE " version " FIX8_VERSION << endl;
113  cout << "Released under the GNU LESSER GENERAL PUBLIC LICENSE, Version 3. See <http://fsf.org/> for details." << endl;
114  return 0;
115  case 'h': print_usage(); return 0;
116  case 'D': rawdump = true; // drop through
117  case 'd': dump = true; break;
118  case 'i': indexonly = true; break;
119  case 'q': quiet = true; break;
120  case 'S': next_send = stoul(optarg); break;
121  case 'R': next_receive = stoul(optarg); break;
122  case ':': case '?': return 1;
123  default: break;
124  }
125  }
126 
127  if (optind >= argc)
128  {
129  cerr << "no input persistence file prefix specified" << endl;
130  return 1;
131  }
132 
133  const string dbFname(argv[optind]);
134  const string dbIname(dbFname + ".idx");
135  struct fdset
136  {
137  int fod, iod;
138  fdset() : fod(), iod() {}
139  ~fdset() { close(iod); close(fod); }
140  }
141  fds;
142 
143  if ((fds.fod = open(dbFname.c_str(), O_RDONLY | O_BINARY)) < 0)
144  {
145  cerr << "Error opening existing database: " << dbFname << " (" << strerror(errno) << ')' << endl;
146  return 1;
147  }
148  if ((fds.iod = open(dbIname.c_str(), O_RDWR | O_BINARY)) < 0)
149  {
150  cerr << "Error opening existing database index: " << dbIname << " (" << strerror(errno) << ')' << endl;
151  return 1;
152  }
153 
154  IPrec iprec;
155  ssize_t blrd(read(fds.iod, static_cast<void *>(&iprec), sizeof(IPrec)));
156  if (blrd <= 0)
157  {
158  cerr << "Error reading existing database index: " << dbIname << " (" << strerror(errno) << ')' << endl;
159  return 1;
160  }
161 
162  if (!rawdump && !quiet)
163  {
164  cout << endl;
165  cout << "Next send receive" << endl;
166  cout << "==============================" << endl;
167  cout << "Current " << left << setw(10) << iprec._prec._offset << right << setw(10) << iprec._prec._size << endl;
168  }
169 
170  if (!dump)
171  {
172  if (next_send > 0 || next_receive > 0)
173  {
174  if (next_send)
175  iprec._prec._offset = next_send;
176  if (next_receive)
177  iprec._prec._size = next_receive;
178  if (lseek(fds.iod, 0, SEEK_SET) < 0)
179  {
180  ostringstream eostr;
181  cerr << "Error could not seek to 0 for seqnum persitence: " << dbIname << endl;
182  return 1;
183  }
184  if (write (fds.iod, static_cast<void *>(&iprec), sizeof(iprec)) != sizeof(iprec))
185  {
186  ostringstream eostr;
187  cerr << "Error writing seqnum persitence: " << dbIname << endl;
188  return 1;
189  }
190 
191  if (!quiet)
192  cout << "New " << left << setw(10) << iprec._prec._offset << right << setw(10) << iprec._prec._size << endl;
193  }
194  cout << endl;
195  }
196  else for(;;)
197  {
198  blrd = read(fds.iod, static_cast<void *>(&iprec), sizeof(IPrec));
199  if (blrd < 0)
200  {
201  cerr << "Error reading existing database index: " << dbIname << " (" << strerror(errno) << ')' << endl;
202  return 1;
203  }
204  if (blrd == 0)
205  break; // eof
206 
207  if (!rawdump)
208  cout << iprec << endl;
209 
210  if (iprec._seq == 0)
211  continue;
212 
213  char buff[FIX8_MAX_MSG_LENGTH] {};
214 
215  if (lseek(fds.fod, iprec._prec._offset, SEEK_SET) < 0)
216  {
217  cerr << "Error could not seek to correct index location " << iprec._prec._offset << " for get: " << dbFname << endl;
218  return 1;
219  }
220 
221  int bytes_read = 0;
222  if ((bytes_read = read(fds.fod, buff, iprec._prec._size)) != iprec._prec._size)
223  {
224  cerr << "Error could not read message record for seqnum " << iprec._seq << " from: " << dbFname
225  << ": trying to read " << iprec._prec._size << ", but available " << bytes_read
226  << endl;
227  return 1;
228  }
229 
230  if (rawdump)
231  cout.write(buff, iprec._prec._size);
232  else if (!indexonly)
233  cout << buff << endl;
234  }
235 
236  return 0;
237 }
238 
239 //-----------------------------------------------------------------------------------------
241 {
242  UsageMan um("seqedit", GETARGLIST, "<perist file prefix>");
243  um.setdesc("seqedit -- edit next expected send/receive for file based persister. Note: fix8pro users should use f8pseqedit which works with any persister");
244  um.add('R', "receive", "set next expected receive sequence number");
245  um.add('S', "send", "set next send sequence number");
246  um.add('d', "dump", "dump all the records in both the index and the data file");
247  um.add('D', "rawdump", "dump all the raw data records referenced in the index");
248  um.add('h', "help", "help, this screen");
249  um.add('i', "index", "only dump the index not the data records");
250  um.add('q', "quiet", "set the sequence numbers silently");
251  um.add('v', "version", "print version, exit");
252  um.add("e.g.");
253  um.add("@seqedit client.DLD_TEX.TEX_DLD");
254  um.add("@seqedit -R 23417 -S 2341 client.DLD_TEX.TEX_DLD");
255  um.add("@seqedit -d client.DLD_TEX.TEX_DLD");
256  um.add("@seqedit -D client.DLD_TEX.TEX_DLD");
257  um.add("@seqedit -id client.DLD_TEX.TEX_DLD");
258  um.add("@seqedit -S 2005 server.TEX_DLD.DLD_TEX");
259  um.print(cerr);
260 }
261 
Prec _prec
Definition: persist.hpp:384
#define O_BINARY
Definition: persist.hpp:350
bool quiet(false)
bool add(const char sw, const std::string &lsw, const std::string &help)
Definition: usage.hpp:73
#define FIX8_PACKAGE
Definition: f8config.h:601
int32_t _size
Definition: persist.hpp:362
unsigned next_receive(0)
uint32_t _seq
Definition: persist.hpp:383
unsigned next_send(0)
void setdesc(const std::string &desc)
Definition: usage.hpp:91
const string GETARGLIST("hvdDR:S:iq")
void print(std::ostream &os) const
Definition: usage.hpp:95
#define FIX8_MAX_MSG_LENGTH
Definition: f8config.h:576
off_t _offset
Definition: persist.hpp:361
#define FIX8_VERSION
Definition: f8config.h:742
void print_usage()
Definition: seqedit.cpp:240
int main(int argc, char **argv)
Definition: seqedit.cpp:84
Convenient program help/usage wrapper. Generates a standardised usage message.
Definition: usage.hpp:42