rtlrecord.hpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  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. bool isFixedOffset(unsigned field) const;
  158. size_t getRecordSize(size_t * variableOffsets) const
  159. {
  160. return getOffset(variableOffsets, numFields);
  161. }
  162. size32_t getRecordSize(const void *data) const;
  163. size32_t calculateOffset(const void *_row, unsigned field) const;
  164. size32_t getMinRecordSize() const;
  165. size32_t deserialize(ARowBuilder & rowBuilder, IRowDeserializerSource & in) const;
  166. void readAhead(IRowPrefetcherSource & in) const;
  167. int compare(const byte * left, const byte * right) const;
  168. unsigned queryIfBlockLimit(const RtlIfBlockTypeInfo * ifblock) const;
  169. inline unsigned getNumFields() const { return numFields; }
  170. unsigned getNumKeyedFields() const;
  171. inline unsigned getNumVarFields() const { return numVarFields; }
  172. inline unsigned getNumIfBlocks() const { return numIfBlocks; }
  173. inline const RtlFieldInfo * queryField(unsigned field) const { return fields[field]; }
  174. const RtlFieldInfo * queryOriginalField(unsigned field) const;
  175. inline const RtlTypeInfo * queryType(unsigned field) const { return fields[field]->type; }
  176. const char * queryName(unsigned field) const;
  177. const char * queryXPath(unsigned field) const; // NB: returns name if no xpath
  178. unsigned getFieldNum(const char *fieldName) const;
  179. const RtlRecord *queryNested(unsigned field) const;
  180. bool excluded(const RtlFieldInfo *field, const byte *row, byte *conditions) const;
  181. bool hasNested() const;
  182. const RtlFieldInfo * queryOriginalField(const char *fieldName) const;
  183. protected:
  184. size_t * fixedOffsets; // fixed portion of the field offsets + 1 extra
  185. unsigned * whichVariableOffset;// which variable offset should be added to the fixed
  186. unsigned * variableFieldIds; // map variable field to real field id.
  187. unsigned * tableIds; // map nested table id to real field id.
  188. unsigned numFields;
  189. unsigned numVarFields;
  190. unsigned numTables;
  191. unsigned numIfBlocks;
  192. const RtlFieldInfo * const * fields;
  193. const RtlFieldInfo * const * originalFields;
  194. const RtlRecord **nestedTables;
  195. const char **names;
  196. const char **xpaths;
  197. const IfBlockInfo **ifblocks;
  198. mutable const FieldNameToFieldNumMap *nameMap;
  199. };
  200. class ECLRTL_API RtlRow
  201. {
  202. public:
  203. RtlRow(const RtlRecord & _info, const void * optRow, unsigned numOffsets, size_t * _variableOffsets);
  204. __int64 getInt(unsigned field) const;
  205. double getReal(unsigned field) const;
  206. void getString(size32_t & resultLen, char * & result, unsigned field) const;
  207. void getUtf8(size32_t & resultLen, char * & result, unsigned field) const;
  208. size_t getOffset(unsigned field) const
  209. {
  210. assert(field <= numFieldsUsed);
  211. return info.getOffset(variableOffsets, field);
  212. }
  213. size_t getSize(unsigned field) const
  214. {
  215. return getOffset(field+1) - getOffset(field);
  216. }
  217. size_t getRecordSize() const
  218. {
  219. assert(info.numFields <= numFieldsUsed);
  220. return info.getRecordSize(variableOffsets);
  221. }
  222. void setRow(const void * _row, unsigned _numFieldsUsed = (unsigned) -1);
  223. void lazyCalcOffsets(unsigned _numFieldsUsed) const;
  224. inline const byte *queryRow() const
  225. {
  226. return row;
  227. }
  228. const byte * queryField(unsigned field) const
  229. {
  230. return queryRow() + getOffset(field);
  231. }
  232. explicit operator bool() { return row != nullptr; }
  233. protected:
  234. RtlRow(const RtlRecord & _info, const void *_row); // for use by fixed-only case
  235. const RtlRecord & info;
  236. const byte * row;
  237. mutable unsigned numFieldsUsed = 0;
  238. size_t * variableOffsets; // [0 + 1 entry for each variable size field ]
  239. static size_t noVariableOffsets [1]; // Used when we are only interested in fixed offsets
  240. };
  241. struct ECLRTL_API RtlDynRow : public RtlRow
  242. {
  243. public:
  244. RtlDynRow(const RtlRecord & _info, const void * optRow = NULL);
  245. ~RtlDynRow();
  246. };
  247. // Special case for where we only want to access fields that are at fixed offsets - i.e. jhtree
  248. // Note that the RecInfo passed in may have variable fields, but we should not (and must not) try to resolve them
  249. struct ECLRTL_API RtlFixedRow : public RtlRow
  250. {
  251. public:
  252. RtlFixedRow(const RtlRecord & _info, const void *_row, unsigned numFieldsUsed);
  253. };
  254. //The following template class is used from the generated code to avoid allocating the offset array
  255. template <unsigned NUM_VARIABLE_FIELDS>
  256. struct ECLRTL_API RtlStaticRow : RtlRow
  257. {
  258. public:
  259. RtlStaticRow(const RtlRecord & _info, const void * optRow = NULL) : RtlRow(_info, optRow, NUM_VARIABLE_FIELDS+1, off) {}
  260. public:
  261. size_t off[NUM_VARIABLE_FIELDS+1];
  262. };
  263. class ECLRTL_API RtlRecordSize : public IRecordSize, public RtlCInterface
  264. {
  265. public:
  266. RtlRecordSize(const RtlRecordTypeInfo & fields) : offsetInformation(fields, true) {}
  267. RTLIMPLEMENT_IINTERFACE
  268. virtual size32_t getRecordSize(const void * row) override
  269. {
  270. //Allocate a temporary offset array on the stack to avoid runtime overhead.
  271. unsigned numOffsets = offsetInformation.getNumVarFields() + 1;
  272. size_t * variableOffsets = (size_t *)alloca(numOffsets * sizeof(size_t));
  273. RtlRow offsetCalculator(offsetInformation, row, numOffsets, variableOffsets);
  274. return offsetCalculator.getRecordSize();
  275. }
  276. virtual size32_t getFixedSize() const override
  277. {
  278. return offsetInformation.getFixedSize();
  279. }
  280. // returns 0 for variable row size
  281. virtual size32_t getMinRecordSize() const override
  282. {
  283. return offsetInformation.getMinRecordSize();
  284. }
  285. protected:
  286. RtlRecord offsetInformation;
  287. };
  288. class CSourceRowPrefetcher;
  289. class ECLRTL_API COutputMetaData : implements IOutputMetaData, public RtlCInterface
  290. {
  291. public:
  292. RTLIMPLEMENT_IINTERFACE
  293. COutputMetaData();
  294. ~COutputMetaData();
  295. virtual void toXML(const byte * self, IXmlWriter & out) override
  296. {
  297. const RtlTypeInfo * type = queryTypeInfo();
  298. if (type)
  299. {
  300. RtlFieldStrInfo dummyField("",NULL,type);
  301. type->toXML(self, self, &dummyField, out);
  302. }
  303. }
  304. virtual unsigned getVersion() const override { return OUTPUTMETADATA_VERSION; }
  305. virtual unsigned getMetaFlags() override { return MDFhasserialize|MDFhasxml; }
  306. virtual const RtlTypeInfo * queryTypeInfo() const override { return nullptr; }
  307. virtual void destruct(byte * self) override {}
  308. virtual IOutputMetaData * querySerializedDiskMeta() override { return this; }
  309. virtual IOutputRowSerializer * createDiskSerializer(ICodeContext * ctx, unsigned activityId) override;
  310. virtual ISourceRowPrefetcher * createDiskPrefetcher() override;
  311. virtual IOutputRowDeserializer * createDiskDeserializer(ICodeContext * ctx, unsigned activityId) override;
  312. //Default internal serializers are the same as the disk versions
  313. virtual IOutputRowSerializer * createInternalSerializer(ICodeContext * ctx, unsigned activityId) override
  314. {
  315. return createDiskSerializer(ctx, activityId);
  316. }
  317. virtual IOutputRowDeserializer * createInternalDeserializer(ICodeContext * ctx, unsigned activityId) override
  318. {
  319. return createDiskDeserializer(ctx, activityId);
  320. }
  321. virtual void process(const byte * self, IFieldProcessor & target, unsigned from, unsigned to) override {}
  322. virtual void walkIndirectMembers(const byte * self, IIndirectMemberVisitor & visitor) override { }
  323. virtual IOutputMetaData * queryChildMeta(unsigned i) override { return NULL; }
  324. virtual const RtlRecord &queryRecordAccessor(bool expand) const override final;
  325. virtual size32_t getRecordSize(const void * data) override;
  326. virtual size32_t getFixedSize() const override
  327. {
  328. return queryRecordAccessor(true).getFixedSize();
  329. }
  330. // returns 0 for variable row size
  331. virtual size32_t getMinRecordSize() const override
  332. {
  333. return queryRecordAccessor(true).getMinRecordSize();
  334. }
  335. protected:
  336. //This is the prefetch function that is actually generated by the code generator
  337. virtual CSourceRowPrefetcher * doCreateDiskPrefetcher() { return NULL; }
  338. ISourceRowPrefetcher * defaultCreateDiskPrefetcher();
  339. mutable RtlRecord *recordAccessor[2];
  340. };
  341. /**
  342. * class CDynamicOutputMetaData
  343. *
  344. * An implementation of IOutputMetaData for use with a dynamically-created record type info structure
  345. *
  346. */
  347. class ECLRTL_API CDynamicOutputMetaData : public COutputMetaData
  348. {
  349. public:
  350. CDynamicOutputMetaData(const RtlRecordTypeInfo & fields) : typeInfo(fields)
  351. {
  352. }
  353. virtual const RtlTypeInfo * queryTypeInfo() const override { return &typeInfo; }
  354. protected:
  355. const RtlTypeInfo &typeInfo;
  356. };
  357. class ECLRTL_API CFixedOutputMetaData : public COutputMetaData
  358. {
  359. public:
  360. CFixedOutputMetaData(size32_t _fixedSize) { fixedSize = _fixedSize; }
  361. virtual size32_t getRecordSize(const void *rec) { return fixedSize; }
  362. virtual size32_t getMinRecordSize() const { return fixedSize; }
  363. virtual size32_t getFixedSize() const { return fixedSize; }
  364. virtual IOutputRowSerializer * createDiskSerializer(ICodeContext * ctx, unsigned activityId);
  365. virtual IOutputRowDeserializer * createDiskDeserializer(ICodeContext * ctx, unsigned activityId);
  366. virtual ISourceRowPrefetcher * createDiskPrefetcher();
  367. protected:
  368. size32_t fixedSize;
  369. };
  370. class ECLRTL_API CVariableOutputMetaData : public COutputMetaData
  371. {
  372. public:
  373. CVariableOutputMetaData(size32_t _minSize) : minSize(_minSize) { }
  374. virtual size32_t getMinRecordSize() const { return minSize; }
  375. virtual size32_t getFixedSize() const { return 0; } // is variable
  376. protected:
  377. size32_t minSize;
  378. };
  379. class ECLRTL_API CActionOutputMetaData : public COutputMetaData
  380. {
  381. public:
  382. virtual size32_t getRecordSize(const void *) { return 0; }
  383. virtual size32_t getMinRecordSize() const { return 0; }
  384. virtual size32_t getFixedSize() const { return 0; } // is pseudo-variable
  385. virtual void toXML(const byte * self, IXmlWriter & out) { }
  386. virtual IOutputRowSerializer * createDiskSerializer(ICodeContext * ctx, unsigned activityId);
  387. virtual IOutputRowDeserializer * createDiskDeserializer(ICodeContext * ctx, unsigned activityId);
  388. virtual ISourceRowPrefetcher * createDiskPrefetcher();
  389. };
  390. #endif