rtlrecord.hpp 16 KB

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