hobbes
a language, embedded compiler, and runtime for efficient dynamic expression evaluation, data storage and analysis
file.H
Go to the documentation of this file.
1 /********************************
2  * file : a system for persisting hobbes data
3  ********************************/
4 
5 #ifndef HOBBES_DB_FILE_HPP_INCLUDED
6 #define HOBBES_DB_FILE_HPP_INCLUDED
7 
8 #include <hobbes/lang/type.H>
9 #include <hobbes/lang/tylift.H>
10 #include <string>
11 
12 namespace hobbes {
13 
14 // is this file a db file?
15 bool isDBFile(const std::string&);
16 
17 // is this type stored the same way as an array (unpredictable size)?
18 bool storedAsArray(const MonoTypePtr&);
19 
20 // a file reference is an index into a file where we can find a value of type T (like a pointer)
21 template <typename T>
22  struct fileref {
23  uint64_t index;
24 
26  this->index = x.index;
27  return *this;
28  }
29 
30  fileref(uint64_t index = 0) : index(index) {
31  }
32  };
33 
34 template <typename T, bool InStruct>
35  struct lift< fileref<T>, InStruct > {
36  static MonoTypePtr type(typedb& tenv) {
38  }
39  };
40 
41 // a dbseq is a linked list sequence just like 'seq' except that its links are file offsets rather than memory offsets
42 template <typename T>
43  struct dbseq {
45  typedef std::pair<T, link_t> cons_t;
47 
48  rep_t data;
49 
50  dbseq() : data(unit()) { }
51  dbseq(const T& x, link_t xs) : data(cons_t(x, xs)) { }
52 
53  bool empty() const { return get<unit>(this->data) != 0; }
54  const cons_t* head() const { return get<cons_t>(this->data); }
55  };
56 
57 template <typename T, bool InStruct>
58  struct lift<dbseq<T>*, InStruct> {
59  static MonoTypePtr type(typedb& tenv) {
60  // ^x.()+T*x@n
61  MonoTypePtr tlink = MonoTypePtr(TApp::make(MonoTypePtr(Prim::make("fileref")), list(tvar("x"))));
62  MonoTypePtr tcons = tuple(list(lift<T, true>::type(tenv), tlink));
63 
64  return MonoTypePtr(Recursive::make("x", MonoTypePtr(Variant::make(list(Variant::Member(".f0", primty("unit"), 0), Variant::Member(".f1", tcons, 1))))));
65  }
66  };
67 
68 // determine representation type (this is necessary to differentiate types represented by value or reference)
69 template <typename T>
70  struct frefty {
71  typedef T type;
72  typedef T* ptr;
73  };
74 
75 template <typename T>
76  struct frefty< array<T> > {
77  typedef array<T>* type;
78  typedef array<T>* ptr;
79  };
80 
81 template <typename T>
82  struct frefty< array<T>* > {
83  typedef array<T>* type;
84  typedef array<T>* ptr;
85  };
86 
87 template <typename T>
88  struct frefty< dbseq<T> > {
89  typedef dbseq<T>* type;
90  typedef dbseq<T>* ptr;
91  };
92 
93 template <typename T>
94  struct frefty< dbseq<T>* > {
95  typedef dbseq<T>* type;
96  typedef dbseq<T>* ptr;
97  };
98 
99 template <typename T>
100  struct frefty< recursive<T> > {
101  typedef recursive<T>* type;
102  typedef recursive<T>* ptr;
103  };
104 
105 template <typename T>
106  struct frefty< recursive<T>* > {
107  typedef recursive<T>* type;
108  typedef recursive<T>* ptr;
109  };
110 
111 // common typedefs
113 
114 // what is the size of a type as represented in storage?
115 size_t storageSizeOf(const MonoTypePtr&);
116 
117 // the main compiler interface (no need to import its full definition here)
118 class cc;
119 
120 // data file details are internally defined
121 struct imagefile;
122 
123 // a db reader can only read data from a file
124 class reader {
125 public:
126  reader(imagefile*);
127  reader(const std::string&);
128  virtual ~reader();
129 
130  const std::string& file() const;
131  size_t size() const;
132 
133  // get a description of the type signature of this file
134  MonoTypeSubst signature() const;
135 
136  // find a named variable within this file (and assert that it has a certain type)
137  template <typename T>
138  typename frefty<T>::ptr lookup(const std::string& vn) const {
139  return (typename frefty<T>::ptr)unsafeLookup(vn, lift< typename frefty<T>::type, false >::type(nulltdb));
140  }
141 
142  // determine the file offset of a stored value
143  template <typename T>
145  return fileref< typename frefty<T>::type >(unsafeOffsetOf(lift< typename frefty<T>::type, false >::type(nulltdb), (void*)x));
146  }
147 
148  // load an anonymous stored value
149  template <typename T>
150  typename frefty<T>::ptr load(const fileref<T>& x) {
151  return (typename frefty<T>::ptr)unsafeLoad(lift< typename frefty<T>::type, false >::type(nulltdb), x.index);
152  }
153 
154  // indicate that we're finished with some mapped memory
155  template <typename T>
156  void unmap(T* x) {
157  unsafeUnload(x, sizeof(T));
158  }
159 
160  template <typename T>
161  void unmap(array<T>* xs) {
162  unsafeUnloadArray(xs);
163  }
164 private:
165  typedef std::vector<uint64_t> StoredOffsets;
166  typedef std::vector<size_t> StoredOffsetSizes;
167 
168  StoredOffsets storedOffsets;
169  StoredOffsetSizes storedOffSizes;
170 public:
171  // to speed up dynamic lookups of top-level variables at runtime
172  // (this allows an external user to skip string matching and type structure analysis)
173  inline unsigned int pushOffset(uint64_t offset, const MonoTypePtr& ty) {
174  unsigned int r = (unsigned int)this->storedOffsets.size();
175  this->storedOffsets.push_back(offset);
176  this->storedOffSizes.push_back(is<Array>(ty) ? 0 : storageSizeOf(ty));
177  return r;
178  }
179 
180  inline void* unsafeLoadStoredOffset(unsigned int o) const {
181  if (this->storedOffSizes[o] > 0) {
182  return unsafeLoad(this->storedOffsets[o], this->storedOffSizes[o]);
183  } else {
184  return unsafeLoadArray(this->storedOffsets[o]);
185  }
186  }
187 
188  inline void storedOffsetDetails(unsigned int o, uint64_t* offset, size_t* sz) const {
189  *offset = this->storedOffsets[o];
190  *sz = this->storedOffSizes[o];
191  }
192 public:
193  // for debugging, show the state of parts of this file and its data structures
194  void showFileSummary(std::ostream&) const;
195  void showEnvironment(std::ostream&) const;
196  void showMappings(std::ostream&,size_t) const;
197  void showPageTable(std::ostream&,size_t) const;
198  void show(std::ostream&) const;
199 public:
200  // be careful using these, they require that types are used correctly at runtime
201  void* unsafeLookup(const std::string&, const MonoTypePtr&) const;
202  uint64_t unsafeLookupOffset(const std::string&, const MonoTypePtr&) const;
203  uint64_t unsafeOffsetOf(const MonoTypePtr&, void*) const;
204  uint64_t unsafeOffsetOfVal(bool,void*) const;
205  void* unsafeLoad(const MonoTypePtr&, uint64_t) const;
206  void* unsafeLoad(uint64_t,size_t) const;
207  void* unsafeLoadArray(uint64_t) const;
208  void unsafeUnload(void*, size_t);
209  void unsafeUnloadArray(void*);
210 
211  uint64_t unsafeArrayCapacity(uint64_t) const;
212 
213  int unsafeGetFD() const;
214 public:
215  // helpful diagnostic functions
216  typedef std::pair<uint8_t, short> PageEntry;
218 
219  PageEntries* pageEntries() const;
220 protected:
222 };
223 
224 // a db writer has exclusive access to write data into a file (and may read as well)
225 class writer : public reader {
226 public:
227  writer(const std::string&);
228 
229  // typed top-level allocation out of this file
230  template <typename T>
231  T* define(const std::string& vn) {
232  return (T*)unsafeDefine(vn, lift<T, true>::type(nulltdb));
233  }
234 
235  template <typename T>
236  array<T>* define(const std::string& vn, size_t len) {
237  return (array<T>*)unsafeDefine(vn, lift<T, true>::type(nulltdb), len);
238  }
239 
240  // typed anonymous allocation out of this file
241  template <typename T>
242  T* store() {
243  return (T*)unsafeStore(lift<T, true>::type(nulltdb));
244  }
245 
246  template <typename T>
247  array<T>* store(size_t len) {
248  return (array<T>*)unsafeStore(lift<T, true>::type(nulltdb), len);
249  }
250 
251  // convenience methods for anonymous storage of arrays
252  fileref<array<char>*> store(const char*, size_t);
253  fileref<array<char>*> store(const char*);
254  fileref<array<char>*> store(const array<char>*);
255  fileref<array<char>*> store(const std::string&);
256 
257  template <typename TIter>
259  typedef typename std::iterator_traits<TIter>::value_type T;
260  size_t len = e - b;
261  array<T>* r = store<T>(len);
262  for (size_t i = 0; i < len; ++i) {
263  r->data[i] = *b;
264  ++b;
265  }
266  r->size = len;
267  auto result = offsetOf(r);
268  unmap(r);
269  return result;
270  }
271 public:
272  // be careful using these, they require that types are used correctly at runtime
273  void* unsafeDefine(const std::string&, const MonoTypePtr&);
274  void* unsafeDefine(const std::string&, const MonoTypePtr&, size_t);
275 
276  void* unsafeStore(const MonoTypePtr&);
277  void* unsafeStore(const MonoTypePtr&, size_t);
278 
279  void* unsafeStore(size_t sz, size_t align);
280  uint64_t unsafeStoreToOffset(size_t sz, size_t align);
281 
282  void* unsafeStoreArray(size_t, size_t);
283  uint64_t unsafeStoreArrayToOffset(size_t, size_t);
284 
285  void signalUpdate();
286 private:
287  void* allocNamed(const std::string&, const MonoTypePtr&, size_t);
288  void* allocAnon(size_t sz, size_t align);
289 };
290 
291 // a utility function to create all implied directories in a path (used by uniqueFilename, writer)
292 void ensureDirExists(const std::string&);
293 
294 // a utility function for safely generating new files
295 std::string uniqueFilename(const std::string& prefix, const std::string& suffix);
296 
297 // a utility function for safely moving to new files
298 std::string moveToUniqueFilename(const std::string& oldpath, const std::string& fprefix, const std::string& fsuffix);
299 
300 // make it easy to bind files
301 template <>
302  struct liftValue< reader* > {
303  static MonoTypePtr type(typedb& tenv, reader* r) {
304  MonoTypeSubst fdefs = r->signature();
305  Record::Members ms;
306  for (const auto& m : fdefs) {
307  ms.push_back(Record::Member(m.first, m.second));
308  r->pushOffset(r->unsafeLookupOffset(m.first, m.second), m.second);
309  }
310  return tapp(primty("file"), list(tlong(0), MonoTypePtr(Record::make(ms))));
311  }
312  };
313 
314 template <>
315  struct liftValue< writer* > {
316  static MonoTypePtr type(typedb& tenv, writer* w) {
317  MonoTypeSubst fdefs = w->signature();
318  Record::Members ms;
319  for (const auto& m : fdefs) {
320  ms.push_back(Record::Member(m.first, m.second));
321  w->pushOffset(w->unsafeLookupOffset(m.first, m.second), m.second);
322  }
323  return tapp(primty("file"), list(tlong(1), MonoTypePtr(Record::make(ms))));
324  }
325  };
326 
327 }
328 
329 #endif
330 
frefty< T >::ptr lookup(const std::string &vn) const
Definition: file.H:138
nulltypedb nulltdb
Definition: type.C:2239
T align(T x, T m)
Definition: ptr.H:98
static MonoTypePtr make(const std::string &, const MonoTypePtr &t=MonoTypePtr())
Definition: type.C:613
const cons_t * head() const
Definition: file.H:54
Definition: tylift.H:115
MonoTypeSubst signature() const
Definition: file.C:921
dbseq< T > * type
Definition: file.H:95
array< T > * store(size_t len)
Definition: file.H:247
bool storedAsArray(const MonoTypePtr &)
Definition: file.C:973
StoredOffsetSizes storedOffSizes
Definition: file.H:169
void unmap(array< T > *xs)
Definition: file.H:161
void * unsafeLoadStoredOffset(unsigned int o) const
Definition: file.H:180
bool isDBFile(const std::string &)
Definition: file.C:859
Definition: tylift.H:71
static MonoTypePtr type(typedb &tenv)
Definition: file.H:36
Definition: tylift.H:22
dbseq< T > * ptr
Definition: file.H:96
MonoTypePtr primty(const char *x)
Definition: type.H:1008
std::vector< uint64_t > StoredOffsets
Definition: file.H:165
variant< unit, cons_t > rep_t
Definition: file.H:46
array< PageEntry > PageEntries
Definition: file.H:217
static MonoTypePtr type(typedb &tenv, reader *r)
Definition: file.H:303
recursive< T > * type
Definition: file.H:101
Definition: file.H:70
Definition: boot.H:7
Definition: type.H:425
long size
Definition: tylift.H:84
array< T > * define(const std::string &vn, size_t len)
Definition: file.H:236
llvm::Value * offset(llvm::IRBuilder<> *b, llvm::Value *p, llvm::Value *o0)
Definition: llvm.H:419
array< T > * type
Definition: file.H:77
Definition: file.H:43
imagefile * fdata
Definition: file.H:221
static MonoTypePtr make(const std::string &, const MonoTypePtr &)
Definition: type.C:1431
MonoType::ptr MonoTypePtr
Definition: type.H:71
Definition: file.H:124
fileref(uint64_t index=0)
Definition: file.H:30
dbseq()
Definition: file.H:50
dbseq(const T &x, link_t xs)
Definition: file.H:51
T * store()
Definition: file.H:242
recursive< T > * ptr
Definition: file.H:102
array< T > * type
Definition: file.H:83
Definition: file.H:22
static MonoTypePtr make(const MonoTypePtr &, const MonoTypes &)
Definition: type.C:701
static MonoTypePtr type(typedb &tenv, writer *w)
Definition: file.H:316
T type
Definition: file.H:71
MonoTypePtr tlong(long x)
Definition: type.H:1137
std::pair< T, link_t > cons_t
Definition: file.H:45
static MonoTypePtr type(typedb &tenv)
Definition: file.H:59
Definition: file.H:225
fileref< T > & operator=(const fileref< T > &x)
Definition: file.H:25
std::pair< uint8_t, short > PageEntry
Definition: file.H:216
unsigned int pushOffset(uint64_t offset, const MonoTypePtr &ty)
Definition: file.H:173
std::string show(const Expr &e)
Definition: expr.C:19
dbseq< T > * type
Definition: file.H:89
fileref< array< typename std::iterator_traits< TIter >::value_type > * > store(TIter b, TIter e)
Definition: file.H:258
std::vector< T > list()
Definition: array.H:25
MonoTypePtr tvar(const std::string &vn)
Definition: type.H:1060
void unmap(T *x)
Definition: file.H:156
Definition: tylift.H:81
size_t r(const reader::MetaData &md, size_t o, T *t)
Definition: storage.H:1730
Definition: cc.H:64
void w(const T &x, bytes *out)
Definition: net.H:282
Definition: variant.H:165
uint64_t index
Definition: file.H:23
rep_t data
Definition: file.H:48
frefty< T >::ptr load(const fileref< T > &x)
Definition: file.H:150
std::string moveToUniqueFilename(const std::string &oldpath, const std::string &fprefix, const std::string &fsuffix)
Definition: file.C:1266
bool empty() const
Definition: file.H:53
static MonoTypePtr make(const Members &ms)
Definition: type.C:1037
Definition: type.H:375
fileref< dbseq< T > * > link_t
Definition: file.H:44
recursive< T > * ptr
Definition: file.H:108
array< T > * ptr
Definition: file.H:84
static MonoTypePtr make(const Members &)
Definition: type.C:760
uint32_t result
Definition: regex.C:376
T data[1]
Definition: tylift.H:85
void ensureDirExists(const std::string &)
Definition: file.C:1222
std::vector< Member > Members
Definition: type.H:435
array< T > * ptr
Definition: file.H:78
StoredOffsets storedOffsets
Definition: file.H:168
fileref< array< char > * > strref
Definition: file.H:112
T * ptr
Definition: file.H:72
T * define(const std::string &vn)
Definition: file.H:231
MonoTypePtr tuple(const MonoTypes &mtys=MonoTypes())
Definition: type.H:1068
recursive< T > * type
Definition: file.H:107
void storedOffsetDetails(unsigned int o, uint64_t *offset, size_t *sz) const
Definition: file.H:188
dbseq< T > * ptr
Definition: file.H:90
Definition: tylift.H:452
fileref< typename frefty< T >::type > offsetOf(const T *x) const
Definition: file.H:144
LexicalAnnotation m(const YYLTYPE &p)
Definition: hexpr.parse.C:127
std::map< TVName, MonoTypePtr > MonoTypeSubst
Definition: type.H:143
size_t storageSizeOf(const MonoTypePtr &)
Definition: file.C:890
uint64_t unsafeLookupOffset(const std::string &, const MonoTypePtr &) const
Definition: file.C:942
std::string uniqueFilename(const std::string &prefix, const std::string &suffix)
Definition: file.C:1251
reader::PageEntries * pageEntries(reader *r)
Definition: bindings.C:1065
Definition: file.C:105
MonoTypePtr tapp(const MonoTypePtr &f, const MonoTypes &args)
Definition: type.H:1133
std::vector< size_t > StoredOffsetSizes
Definition: file.H:166