ztsdb
encode.hpp
1 // (C) 2016 Leonardo Silvestri
2 //
3 // This file is part of ztsdb.
4 //
5 // ztsdb is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // ztsdb is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with ztsdb. If not, see <http://www.gnu.org/licenses/>.
17 
18 
19 #ifndef ENCODE_HPP
20 #define ENCODE_HPP
21 
22 
23 #include <cstdint>
24 #include "valuevar.hpp"
25 #include "ast.hpp"
26 #include "misc.hpp"
27 #include "globals.hpp"
28 #include "net_handler.hpp"
29 #include "zts.hpp"
30 
31 
32 namespace zcore {
33 
36  struct ValState {
37  val::Value val;
38  uint64_t exp;
39  uint64_t n;
40  unsigned stage;
46  };
47 
48  template<typename T>
49  val::Value getOrderedVector(const arr::Array<T>& t) {
50  val::SpVI v = make_shared<val::VI>();
51  for (size_t j=0; j<t.ncols(); ++j) {
52  v->push_back(t.getcol(j).isOrdered());
53  }
54  return v;
55  }
56 
57  val::Value convertToList(const vector<unique_ptr<arr::Dname>>& names);
58 
59 
72  struct Encode {
74  Global::conn_id_t peerid_p,
75  Global::reqid_t reqid_p,
76  Global::reqid_t sourceid_p,
77  Global::MsgType msgt_p) :
78  com(c), peerid(peerid_p), reqid(reqid_p), sourceid(sourceid_p), msgt(msgt_p),
79  offset(net::INIT_OFFSET), // so net has space to insert magic nb and size
80  bytes(0)
81  {
82  *this << uint64_t(msgt);
83  *this << reqid;
84  *this << sourceid;
85  }
86 
87  net::NetHandler& com;
88  const Global::conn_id_t peerid;
89  const Global::reqid_t reqid;
90  const Global::reqid_t sourceid;
91  const Global::MsgType msgt;
92 
93  char buf[Global::CHUNKSZ];
94  size_t offset;
95  size_t bytes;
96 
97  Encode& operator <<(const val::Value& v);
98  Encode& operator <<(const E* e);
99 
100  template<typename T>
101  Encode& operator <<(const T& t) {
102  if (offset + sizeof(T) > Global::CHUNKSZ) {
103  flush();
104  }
105  auto h = hton<T>(t);
106  memcpy(buf + offset, &h, sizeof(T));
107  offset += sizeof(T);
108  return *this;
109  }
110 
111  template<typename T>
112  Encode& operator <<(const arr::Array<T>& t) {
113  *this << t.size();
114 
115  // an array is a list of 3 (stage 0)
116  auto rlist = val::VList();
117  rlist.push_back(make_pair("", val::Value(make_shared<val::VI>(t.dim))));
118  rlist.push_back(make_pair("", convertToList(t.names)));
119  rlist.push_back(make_pair("", getOrderedVector(t)));
120  *this << val::Value(make_cow<val::VList>(false, rlist)); // Value, else the wrong
121  // template func is used
122 
123  // followed by (after stage is set to 1) a series of integers or doubles, etc.
124  for (idx_type col=0; col < t.v.size(); ++col) {
125  for (idx_type j=0; j < t.dim[0]; ++j) {
126  *this << static_cast<T>(t.getcol(col)[j]);
127  }
128  }
129  // for some reason (with GCC 4.9) the above is faster than:
130  // for (auto& col : t.v)
131  // for (auto j : col)
132  // *this << j;
133  return *this;
134  }
135 
136 
137  Encode& operator <<(const val::VI& t);
138  Encode& operator <<(const string& t);
139  Encode& operator <<(const arr::zstring& t);
140  Encode& operator <<(const tz::interval& t);
141  Encode& operator <<(const tz::period& t);
142  Encode& operator <<(const arr::zts& t);
143  Encode& operator <<(const bool t);
144 
145 
146  ssize_t flush() {
147  auto res = com.send(peerid, buf, offset);
148  if (res > 0) {
149  bytes += res;
150  }
151  offset = net::INIT_OFFSET;
152  *this << msgt;
153  *this << reqid;
154  *this << sourceid;
155  return res; // what's the point? LLL is it not
156  // better to check res == offset? and
157  // should we throw?
158  }
159 
160  ssize_t flush_end() { // LLL
161  auto res = com.send(peerid, buf, offset);
162  if (res > 0) {
163  bytes += res;
164  }
165  offset = net::INIT_OFFSET;
166  return res; // what's the point? LLL is it not
167  // better to check res == offset? and
168  // should we throw?
169  }
170 
171  private:
172 
173  Encode& operator <<(const val::VClos& t);
174  Encode& operator <<(const val::VConn& t);
175  // note, we don't allow transmission of VBuiltinG, VFuture (a
176  // domain_error exception is raised)
177 
178  };
179 
181  size_t codeLength(const E* e);
182 
184  E* readCode(const char* buf, size_t len);
185 
189  void readValue(const char* buf, size_t len, size_t& off, vector<ValState>& ss, size_t& idx);
190 
192  bool isTransmissible(const val::Value& v);
193 }
194 
195 #endif
E
Definition: ast.hpp:76
net::NetHandler::send
ssize_t send(Global::conn_id_t id, char *buf, size_t len)
Send 'buf' to peer 'id'.
Definition: net_handler.cpp:485
tz::period
Definition: period.hpp:30
zcore::Encode
Definition: encode.hpp:72
arr::Vector< size_t >
arr::ZString
Definition: string.hpp:33
val::VClos
Definition: valuevar.hpp:284
tz::interval
Definition: interval.hpp:31
val::VList
Definition: valuevar.hpp:360
net::NetHandler
Definition: net_handler.hpp:187
zcore::ValState::stage
unsigned stage
Definition: encode.hpp:45
zcore::ValState
Definition: encode.hpp:36
arr::zts
Definition: zts.hpp:35
zcore::ValState::n
uint64_t n
Definition: encode.hpp:39
val::VConn
Definition: valuevar.hpp:101
zcore::ValState::exp
uint64_t exp
expected length
Definition: encode.hpp:38
arr::Array
Definition: array.hpp:109
zcore::ValState::val
val::Value val
value under construction
Definition: encode.hpp:37