rtlrecord.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2016 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #ifndef rtlrecord_hpp
  14. #define rtlrecord_hpp
  15. #if defined(_WIN32)
  16. #include <malloc.h>
  17. #else
  18. #include <alloca.h>
  19. #endif
  20. #include "eclrtl_imp.hpp"
  21. #include "rtlds_imp.hpp"
  22. #include "rtlfield.hpp"
  23. //---------------------------------------------------------------------------
  24. // Record size handling.
  25. class CGlobalHelperClass : public RtlCInterface
  26. {
  27. public:
  28. inline CGlobalHelperClass(unsigned _activityId) { activityId = _activityId; ctx = NULL; }
  29. inline void onCreate(ICodeContext * _ctx) { ctx = _ctx; }
  30. protected:
  31. ICodeContext * ctx;
  32. unsigned activityId;
  33. };
  34. class COutputRowSerializer : implements IOutputRowSerializer, public CGlobalHelperClass
  35. {
  36. public:
  37. inline COutputRowSerializer(unsigned _activityId) : CGlobalHelperClass(_activityId) { }
  38. RTLIMPLEMENT_IINTERFACE
  39. virtual void serialize(IRowSerializerTarget & out, const byte * self) override = 0;
  40. };
  41. class COutputRowDeserializer : implements IOutputRowDeserializer, public RtlCInterface
  42. {
  43. public:
  44. inline COutputRowDeserializer(unsigned _activityId) { activityId = _activityId; ctx = NULL; }
  45. RTLIMPLEMENT_IINTERFACE
  46. inline void onCreate(ICodeContext * _ctx) { ctx = _ctx; }
  47. virtual size32_t deserialize(ARowBuilder & rowBuilder, IRowDeserializerSource & in) override = 0;
  48. protected:
  49. ICodeContext * ctx;
  50. unsigned activityId;
  51. };
  52. class CSourceRowPrefetcher : implements ISourceRowPrefetcher, public RtlCInterface
  53. {
  54. public:
  55. inline CSourceRowPrefetcher(unsigned _activityId) { activityId = _activityId; ctx = NULL; }
  56. RTLIMPLEMENT_IINTERFACE
  57. inline void onCreate(ICodeContext * _ctx) { ctx = _ctx; }
  58. virtual void readAhead(IRowDeserializerSource & in) override = 0;
  59. protected:
  60. ICodeContext * ctx;
  61. unsigned activityId;
  62. };
  63. class CFixedOutputRowSerializer : public COutputRowSerializer
  64. {
  65. public:
  66. inline CFixedOutputRowSerializer(unsigned _activityId, unsigned _fixedSize) : COutputRowSerializer(_activityId) { fixedSize = _fixedSize; }
  67. virtual void serialize(IRowSerializerTarget & out, const byte * self) { out.put(fixedSize, self); }
  68. protected:
  69. size32_t fixedSize;
  70. };
  71. class CFixedOutputRowDeserializer : public COutputRowDeserializer
  72. {
  73. public:
  74. inline CFixedOutputRowDeserializer(unsigned _activityId, unsigned _fixedSize) : COutputRowDeserializer(_activityId) { fixedSize = _fixedSize; }
  75. virtual size32_t deserialize(ARowBuilder & rowBuilder, IRowDeserializerSource & in) { in.read(fixedSize, rowBuilder.getSelf()); return fixedSize; }
  76. protected:
  77. size32_t fixedSize;
  78. };
  79. class CFixedSourceRowPrefetcher : public CSourceRowPrefetcher
  80. {
  81. public:
  82. inline CFixedSourceRowPrefetcher(unsigned _activityId, unsigned _fixedSize) : CSourceRowPrefetcher(_activityId) { fixedSize = _fixedSize; }
  83. virtual void readAhead(IRowDeserializerSource & in) { in.skip(fixedSize); }
  84. protected:
  85. size32_t fixedSize;
  86. };
  87. //---------------------------------------------------------------------------
  88. class CXmlToRowTransformer : implements IXmlToRowTransformer, public CGlobalHelperClass
  89. {
  90. public:
  91. inline CXmlToRowTransformer(unsigned _activityId) : CGlobalHelperClass(_activityId) {}
  92. RTLIMPLEMENT_IINTERFACE
  93. };
  94. //---------------------------------------------------------------------------
  95. // Record size handling.
  96. class CNormalizeChildIterator : implements INormalizeChildIterator, public RtlCInterface
  97. {
  98. public:
  99. CNormalizeChildIterator(IOutputMetaData & _recordSize) : iter(0, NULL, _recordSize) {}
  100. RTLIMPLEMENT_IINTERFACE
  101. virtual byte * first(const void * parentRecord) override { init(parentRecord); return (byte *)iter.first(); }
  102. virtual byte * next() override { return (byte *)iter.next(); }
  103. virtual void init(const void * parentRecord) = 0;
  104. inline void setDataset(size32_t len, const void * data) { iter.setDataset(len, data); }
  105. protected:
  106. RtlVariableDatasetCursor iter;
  107. };
  108. class CNormalizeLinkedChildIterator : implements INormalizeChildIterator, public RtlCInterface
  109. {
  110. public:
  111. CNormalizeLinkedChildIterator() : iter(0, NULL) {}
  112. RTLIMPLEMENT_IINTERFACE
  113. virtual byte * first(const void * parentRecord) override { init(parentRecord); return (byte *)iter.first(); }
  114. virtual byte * next() override { return (byte *)iter.next(); }
  115. virtual void init(const void * parentRecord) = 0;
  116. inline void setDataset(unsigned _numRows, const byte * * _rows) { iter.setDataset(_numRows, _rows); }
  117. protected:
  118. RtlSafeLinkedDatasetCursor iter;
  119. };
  120. class CNormalizeStreamedChildIterator : implements INormalizeChildIterator, public RtlCInterface
  121. {
  122. public:
  123. CNormalizeStreamedChildIterator() {}
  124. RTLIMPLEMENT_IINTERFACE
  125. virtual byte * first(const void * parentRecord) override { init(parentRecord); return (byte *)iter.first(); }
  126. virtual byte * next() override { return (byte *)iter.next(); }
  127. virtual void init(const void * parentRecord) = 0;
  128. inline void setDataset(IRowStream * _streamed) { iter.init(_streamed); }
  129. protected:
  130. RtlStreamedDatasetCursor iter;
  131. };
  132. //These classes provides a relatively efficient way to access fields within a variable length record structure.
  133. // Probably convert to an interface with various concrete implementations for varying degrees of complexity
  134. //
  135. // Complications:
  136. // * ifblocks
  137. // * nested records.
  138. // * alien data types
  139. //
  140. class FieldNameToFieldNumMap;
  141. class ECLRTL_API RtlRecord
  142. {
  143. public:
  144. friend class RtlRow;
  145. RtlRecord(const RtlRecordTypeInfo & fields, bool expandFields);
  146. RtlRecord(const RtlFieldInfo * const * fields, bool expandFields);
  147. ~RtlRecord();
  148. void calcRowOffsets(size_t * variableOffsets, const void * _row, unsigned numFieldsUsed = (unsigned) -1) const;
  149. virtual size32_t getFixedSize() const
  150. {
  151. return numVarFields ? 0 : fixedOffsets[numFields];
  152. }
  153. size_t getOffset(size_t * variableOffsets, unsigned field) const
  154. {
  155. return fixedOffsets[field] + variableOffsets[whichVariableOffset[field]];
  156. }
  157. size_t getRecordSize(size_t * variableOffsets) const
  158. {
  159. return getOffset(variableOffsets, numFields);
  160. }
  161. size32_t getMinRecordSize() const;
  162. size32_t deserialize(ARowBuilder & rowBuilder, IRowDeserializerSource & in) const;
  163. void readAhead(IRowDeserializerSource & in) const;
  164. inline unsigned getNumFields() const { return numFields; }
  165. inline unsigned getNumVarFields() const { return numVarFields; }
  166. inline const RtlFieldInfo * queryField(unsigned field) const { return fields[field]; }
  167. inline const RtlTypeInfo * queryType(unsigned field) const { return fields[field]->type; }
  168. const char * queryName(unsigned field) const;
  169. unsigned getFieldNum(const char *fieldName) const;
  170. const RtlRecord *queryNested(unsigned field) const;
  171. protected:
  172. size_t * fixedOffsets; // fixed portion of the field offsets + 1 extra
  173. unsigned * whichVariableOffset;// which variable offset should be added to the fixed
  174. unsigned * variableFieldIds; // map variable field to real field id.
  175. unsigned * tableIds; // map nested table id to real field id.
  176. unsigned numFields;
  177. unsigned numVarFields;
  178. unsigned numTables;
  179. const RtlFieldInfo * const * fields;
  180. const RtlFieldInfo * const * originalFields;
  181. const RtlRecord **nestedTables;
  182. const char **names;
  183. mutable const FieldNameToFieldNumMap *nameMap;
  184. };
  185. class ECLRTL_API RtlRow
  186. {
  187. public:
  188. RtlRow(const RtlRecord & _info, const void * optRow, unsigned numOffsets, size_t * _variableOffsets);
  189. __int64 getInt(unsigned field) const;
  190. double getReal(unsigned field) const;
  191. void getString(size32_t & resultLen, char * & result, unsigned field) const;
  192. void getUtf8(size32_t & resultLen, char * & result, unsigned field) const;
  193. size_t getOffset(unsigned field) const
  194. {
  195. return info.getOffset(variableOffsets, field);
  196. }
  197. size_t getSize(unsigned field) const
  198. {
  199. return info.getOffset(variableOffsets, field+1) - info.getOffset(variableOffsets, field);
  200. }
  201. size_t getRecordSize() const
  202. {
  203. return info.getRecordSize(variableOffsets);
  204. }
  205. void setRow(const void * _row);
  206. void setRow(const void * _row, unsigned _numFields);
  207. const void *queryRow() const
  208. {
  209. return row;
  210. }
  211. protected:
  212. const RtlRecord & info;
  213. const void * row;
  214. size_t * variableOffsets; // [0 + 1 entry for each variable size field ]
  215. };
  216. struct ECLRTL_API RtlDynRow : public RtlRow
  217. {
  218. public:
  219. RtlDynRow(const RtlRecord & _info, const void * optRow = NULL);
  220. ~RtlDynRow();
  221. };
  222. //The following template class is used from the generated code to avoid allocating the offset array
  223. template <unsigned NUM_VARIABLE_FIELDS>
  224. struct ECLRTL_API RtlStaticRow : RtlRow
  225. {
  226. public:
  227. RtlStaticRow(const RtlRecord & _info, const void * optRow = NULL) : RtlRow(_info, optRow, NUM_VARIABLE_FIELDS+1, off) {}
  228. public:
  229. size_t off[NUM_VARIABLE_FIELDS+1];
  230. };
  231. class ECLRTL_API RtlRecordSize : public IRecordSize, public RtlCInterface
  232. {
  233. public:
  234. RtlRecordSize(const RtlRecordTypeInfo & fields) : offsetInformation(fields, true) {}
  235. RTLIMPLEMENT_IINTERFACE
  236. virtual size32_t getRecordSize(const void * row) override
  237. {
  238. //Allocate a temporary offset array on the stack to avoid runtime overhead.
  239. unsigned numOffsets = offsetInformation.getNumVarFields() + 1;
  240. size_t * variableOffsets = (size_t *)alloca(numOffsets * sizeof(size_t));
  241. RtlRow offsetCalculator(offsetInformation, row, numOffsets, variableOffsets);
  242. return offsetCalculator.getRecordSize();
  243. }
  244. virtual size32_t getFixedSize() const override
  245. {
  246. return offsetInformation.getFixedSize();
  247. }
  248. // returns 0 for variable row size
  249. virtual size32_t getMinRecordSize() const override
  250. {
  251. return offsetInformation.getMinRecordSize();
  252. }
  253. protected:
  254. RtlRecord offsetInformation;
  255. };
  256. class CSourceRowPrefetcher;
  257. class ECLRTL_API COutputMetaData : implements IOutputMetaData, public RtlCInterface
  258. {
  259. public:
  260. RTLIMPLEMENT_IINTERFACE
  261. COutputMetaData();
  262. ~COutputMetaData();
  263. virtual void toXML(const byte * self, IXmlWriter & out) override
  264. {
  265. const RtlTypeInfo * type = queryTypeInfo();
  266. if (type)
  267. {
  268. RtlFieldStrInfo dummyField("",NULL,type);
  269. type->toXML(self, self, &dummyField, out);
  270. }
  271. }
  272. virtual unsigned getVersion() const override { return OUTPUTMETADATA_VERSION; }
  273. virtual unsigned getMetaFlags() override { return MDFhasserialize|MDFhasxml; }
  274. virtual void destruct(byte * self) override {}
  275. virtual IOutputMetaData * querySerializedDiskMeta() override { return this; }
  276. virtual IOutputRowSerializer * createDiskSerializer(ICodeContext * ctx, unsigned activityId) override;
  277. virtual ISourceRowPrefetcher * createDiskPrefetcher(ICodeContext * ctx, unsigned activityId) override;
  278. virtual IOutputRowDeserializer * createDiskDeserializer(ICodeContext * ctx, unsigned activityId) override;
  279. //Default internal serializers are the same as the disk versions
  280. virtual IOutputRowSerializer * createInternalSerializer(ICodeContext * ctx, unsigned activityId) override
  281. {
  282. return createDiskSerializer(ctx, activityId);
  283. }
  284. virtual IOutputRowDeserializer * createInternalDeserializer(ICodeContext * ctx, unsigned activityId) override
  285. {
  286. return createDiskDeserializer(ctx, activityId);
  287. }
  288. virtual void walkIndirectMembers(const byte * self, IIndirectMemberVisitor & visitor) override{ }
  289. virtual IOutputMetaData * queryChildMeta(unsigned i) override { return NULL; }
  290. virtual const RtlRecord &queryRecordAccessor(bool expand) const override final;
  291. virtual size32_t getRecordSize(const void * data) override;
  292. virtual size32_t getFixedSize() const override
  293. {
  294. return queryRecordAccessor(true).getFixedSize();
  295. }
  296. // returns 0 for variable row size
  297. virtual size32_t getMinRecordSize() const override
  298. {
  299. return queryRecordAccessor(true).getMinRecordSize();
  300. }
  301. protected:
  302. //This is the prefetch function that is actually generated by the code generator
  303. virtual CSourceRowPrefetcher * doCreateDiskPrefetcher(unsigned activityId) { return NULL; }
  304. ISourceRowPrefetcher * defaultCreateDiskPrefetcher(ICodeContext * ctx, unsigned activityId);
  305. mutable RtlRecord *recordAccessor[2];
  306. };
  307. /**
  308. * class CDynamicOutputMetaData
  309. *
  310. * An implementation of IOutputMetaData for use with a dynamically-created record type info structure
  311. *
  312. */
  313. class ECLRTL_API CDynamicOutputMetaData : public COutputMetaData
  314. {
  315. public:
  316. CDynamicOutputMetaData(const RtlRecordTypeInfo & fields) : typeInfo(fields)
  317. {
  318. }
  319. virtual const RtlTypeInfo * queryTypeInfo() const override { return &typeInfo; }
  320. protected:
  321. const RtlTypeInfo &typeInfo;
  322. };
  323. /**
  324. * class CDeserializedOutputMetaData
  325. *
  326. * An implementation of IOutputMetaData for use with serialized rtlTypeInfo information
  327. *
  328. */
  329. class ECLRTL_API CDeserializedOutputMetaData : public COutputMetaData
  330. {
  331. public:
  332. CDeserializedOutputMetaData(MemoryBuffer &binInfo);
  333. CDeserializedOutputMetaData(IPropertyTree &jsonInfo);
  334. CDeserializedOutputMetaData(const char *json);
  335. virtual const RtlTypeInfo * queryTypeInfo() const override { return typeInfo; }
  336. protected:
  337. Owned<IRtlFieldTypeDeserializer> deserializer;
  338. const RtlTypeInfo *typeInfo = nullptr;
  339. };
  340. class ECLRTL_API CFixedOutputMetaData : public COutputMetaData
  341. {
  342. public:
  343. CFixedOutputMetaData(size32_t _fixedSize) { fixedSize = _fixedSize; }
  344. virtual size32_t getRecordSize(const void *rec) { return fixedSize; }
  345. virtual size32_t getMinRecordSize() const { return fixedSize; }
  346. virtual size32_t getFixedSize() const { return fixedSize; }
  347. virtual IOutputRowSerializer * createDiskSerializer(ICodeContext * ctx, unsigned activityId);
  348. virtual IOutputRowDeserializer * createDiskDeserializer(ICodeContext * ctx, unsigned activityId);
  349. virtual ISourceRowPrefetcher * createDiskPrefetcher(ICodeContext * ctx, unsigned activityId);
  350. protected:
  351. size32_t fixedSize;
  352. };
  353. class ECLRTL_API CVariableOutputMetaData : public COutputMetaData
  354. {
  355. public:
  356. CVariableOutputMetaData(size32_t _minSize) : minSize(_minSize) { }
  357. virtual size32_t getMinRecordSize() const { return minSize; }
  358. virtual size32_t getFixedSize() const { return 0; } // is variable
  359. protected:
  360. size32_t minSize;
  361. };
  362. class ECLRTL_API CActionOutputMetaData : public COutputMetaData
  363. {
  364. public:
  365. virtual size32_t getRecordSize(const void *) { return 0; }
  366. virtual size32_t getMinRecordSize() const { return 0; }
  367. virtual size32_t getFixedSize() const { return 0; } // is pseudo-variable
  368. virtual void toXML(const byte * self, IXmlWriter & out) { }
  369. virtual IOutputRowSerializer * createDiskSerializer(ICodeContext * ctx, unsigned activityId);
  370. virtual IOutputRowDeserializer * createDiskDeserializer(ICodeContext * ctx, unsigned activityId);
  371. virtual ISourceRowPrefetcher * createDiskPrefetcher(ICodeContext * ctx, unsigned activityId);
  372. };
  373. #endif