layouttrans.ipp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 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. #include "layouttrans.hpp"
  14. typedef UnsignedArray Size32Array;
  15. class RLTFailure : public IRecordLayoutTranslator::Failure
  16. {
  17. public:
  18. RLTFailure(Code _code) : code(_code) {}
  19. virtual Code queryCode() const { return code; }
  20. virtual StringBuffer & getDetail(StringBuffer & out) const { return out.append(detail); }
  21. RLTFailure * append(char const * str) { detail.append(str); return this; }
  22. RLTFailure * append(unsigned n) { detail.append(n); return this; }
  23. RLTFailure * appendScopeDesc(char const * scope);
  24. RLTFailure * appendFieldName(char const * scope, IDefRecordElement const * field);
  25. private:
  26. Code code;
  27. StringBuffer detail;
  28. };
  29. class FieldSearcher
  30. {
  31. public:
  32. FieldSearcher(IDefRecordElement const * elem);
  33. bool search(IAtom * search, unsigned & pos) const;
  34. private:
  35. MapBetween<IAtom *, IAtom *, unsigned, unsigned> tab;
  36. };
  37. class FieldMapping : public CInterface
  38. {
  39. public:
  40. typedef enum { None, Simple, ChildDataset } Type;
  41. typedef CIArrayOf<FieldMapping> List;
  42. FieldMapping(Type _type, IDefRecordElement const * _diskRecord, unsigned _diskFieldNum, bool _diskFieldKeyed, IDefRecordElement const * _activityRecord, unsigned _activityFieldNum, bool _activityFieldKeyed)
  43. : type(_type), diskRecord(_diskRecord), diskFieldNum(_diskFieldNum), activityRecord(_activityRecord), activityFieldNum(_activityFieldNum), diskFieldKeyed(_diskFieldKeyed), activityFieldKeyed(_activityFieldKeyed) {}
  44. List & queryChildMappings() { return childMappings; }
  45. Type queryType() const { return type; }
  46. char const * queryDiskFieldName() const { return diskRecord->queryChild(diskFieldNum)->queryName()->str(); }
  47. unsigned queryDiskFieldNum() const { return diskFieldNum; }
  48. size32_t queryDiskFieldSize() const { return diskRecord->queryChild(diskFieldNum)->queryType()->getSize(); }
  49. bool isDiskFieldFpos() const { return ((type != ChildDataset) && !diskFieldKeyed && (diskFieldNum == diskRecord->numChildren()-1) && diskRecord->queryChild(diskFieldNum)->queryType()->isInteger()); }
  50. bool isDiskFieldSet() const { return (diskRecord->queryChild(diskFieldNum)->queryType()->getTypeCode() == type_set); }
  51. char const * queryActivityFieldName() const { return activityRecord->queryChild(activityFieldNum)->queryName()->str(); }
  52. unsigned queryActivityFieldNum() const { return activityFieldNum; }
  53. size32_t queryActivityFieldSize() const { return activityRecord->queryChild(activityFieldNum)->queryType()->getSize(); }
  54. bool isActivityFieldFpos() const { return ((type == Simple) && !activityFieldKeyed && (activityFieldNum == activityRecord->numChildren()-1) && activityRecord->queryChild(activityFieldNum)->queryType()->isInteger()); }
  55. List const & queryChildMappings() const { return childMappings; }
  56. private:
  57. Type type;
  58. IDefRecordElement const * diskRecord;
  59. IDefRecordElement const * activityRecord;
  60. unsigned diskFieldNum;
  61. unsigned activityFieldNum;
  62. bool diskFieldKeyed;
  63. bool activityFieldKeyed;
  64. List childMappings;
  65. };
  66. class MappingLevel
  67. {
  68. public:
  69. MappingLevel(FieldMapping::List & _mappings);
  70. MappingLevel(MappingLevel * parent, char const * name, FieldMapping::List & _mappings);
  71. void calculateMappings(IDefRecordElement const * diskRecord, unsigned numKeyedDisk, IDefRecordElement const * activityRecord, unsigned numKeyedActivity);
  72. void attemptMapping(IDefRecordElement const * diskRecord, unsigned diskFieldNum, bool diskFieldKeyed, IDefRecordElement const * activityRecord, unsigned activityFieldNum, bool activityFieldKeyed);
  73. private:
  74. void checkField(IDefRecordElement const * record, unsigned num, char const * label);
  75. void queryCheckFieldChild(IDefRecordElement const * field, char const * label, IDefRecordElement const * & child, IDefRecordElement const * & blob);
  76. private:
  77. bool topLevel;
  78. StringBuffer scope;
  79. FieldMapping::List & mappings;
  80. };
  81. class CRecordLayoutTranslator;
  82. class ExpandedSegmentMonitorList : public CInterface, public IRecordLayoutTranslator::SegmentMonitorContext
  83. {
  84. public:
  85. ExpandedSegmentMonitorList(CRecordLayoutTranslator * _owner) : owner(_owner) {}
  86. IMPLEMENT_IINTERFACE;
  87. virtual void setMergeBarrier(unsigned barrierOffset);
  88. virtual void append(IKeySegmentMonitor * monitor);
  89. virtual bool isLastSegmentWild() const { return false; }
  90. virtual unsigned ordinality() const { return monitors.ordinality(); }
  91. virtual IKeySegmentMonitor * item(unsigned i) const { return &monitors.item(i); }
  92. virtual void reset() { monitors.kill(); }
  93. private:
  94. CRecordLayoutTranslator * owner;
  95. IArrayOf<IKeySegmentMonitor> monitors;
  96. };
  97. class FieldCopy;
  98. class RowTransformer : public CInterface
  99. {
  100. public:
  101. RowTransformer() {}
  102. RowTransformer(unsigned & seq, FieldMapping::List const & mappings) { build(seq, mappings); }
  103. void build(unsigned & seq, FieldMapping::List const & mappings);
  104. void transform(IRecordLayoutTranslator::RowTransformContext * ctx, byte const * in, size32_t inSize, size32_t & inOffset, byte * out, size32_t outBuffSize, size32_t & outOffset) const;
  105. void getFposOut(IRecordLayoutTranslator::RowTransformContext const * ctx, offset_t & fpos) const;
  106. void createRowTransformContext(IRecordLayoutTranslator::RowTransformContext * ctx) const;
  107. private:
  108. class RowRecord : public CInterface
  109. {
  110. public:
  111. RowRecord() : relOffset(0), relBase(0), size(0), followOn(false), childMappings(NULL), toFpos(false), fromFpos(false) {}
  112. RowRecord & setVals(size32_t _relOffset, unsigned _relBase, size32_t _size, bool _followOn) { relOffset = _relOffset; relBase = _relBase; size = _size; followOn = _followOn; return *this; }
  113. RowRecord & setChildMappings(FieldMapping::List const * _mappings) { childMappings = _mappings; return *this; }
  114. RowRecord & setFpos(bool to, bool from) { toFpos = to; fromFpos = from; return *this; }
  115. size32_t queryRelOffset() const { return relOffset; }
  116. unsigned queryRelBase() const { return relBase; }
  117. size32_t querySize() const { return size; }
  118. bool queryFollowOn() const { return followOn; }
  119. bool isToFpos() const { return toFpos; }
  120. bool isFromFpos() const { return fromFpos; }
  121. FieldMapping::List const * queryChildMappings() const { return childMappings; }
  122. private:
  123. size32_t relOffset;
  124. unsigned relBase;
  125. size32_t size;
  126. bool followOn;
  127. FieldMapping::List const * childMappings;
  128. bool toFpos;
  129. bool fromFpos;
  130. };
  131. RowRecord & ensureItem(CIArrayOf<RowRecord> & arr, unsigned pos);
  132. void createRowRecord(FieldMapping const & mapping, CIArrayOf<RowRecord> & records, size32_t diskOffset, unsigned numVarFields, bool & prevActivityField, unsigned & prevActivityFieldNum);
  133. void analyseMappings(FieldMapping::List const & mappings, CIArrayOf<RowRecord> & records);
  134. void generateSimpleCopy(unsigned & seq, RowRecord const & record);
  135. void generateCopyToFpos(RowRecord const & record);
  136. void generateCopyFromFpos(RowRecord const & record);
  137. void generateCopies(unsigned & seq, CIArrayOf<RowRecord> const & records);
  138. private:
  139. unsigned sequence;
  140. size32_t finalFixedSize;
  141. Size32Array diskVarFieldRelOffsets;
  142. Size32Array diskVarFieldLenDisplacements;
  143. CIArrayOf<FieldCopy> copies;
  144. bool keepFpos;
  145. bool copyToFpos;
  146. size32_t copyToFposRelOffset;
  147. unsigned copyToFposRelBase;
  148. size32_t copyToFposSize;
  149. };
  150. class FieldCopy : public CInterface
  151. {
  152. public:
  153. FieldCopy(unsigned seq, size32_t _relOffset, unsigned _relBase) : sequence(seq), relOffset(_relOffset), relBase(_relBase), fixedSize(0) {}
  154. void addFixedSize(size32_t size) { fixedSize += size; }
  155. void addVarField(unsigned base) { varFields.append(base); }
  156. void setChildTransformer(RowTransformer * _transformer) { assertex(!childTransformer); childTransformer.setown(_transformer); }
  157. RowTransformer const * queryChildTransformer() const { return childTransformer; }
  158. void copy(IRecordLayoutTranslator::RowTransformContext * ctx, byte * out, size32_t outBuffSize, size32_t & outOffset) const;
  159. private:
  160. unsigned sequence;
  161. size32_t relOffset;
  162. unsigned relBase;
  163. size32_t fixedSize;
  164. UnsignedArray varFields;
  165. Owned<RowTransformer> childTransformer;
  166. };
  167. class CRecordLayoutTranslator : public IRecordLayoutTranslator, public CInterface
  168. {
  169. public:
  170. CRecordLayoutTranslator(IDefRecordMeta const * _diskMeta, IDefRecordMeta const * _activityMeta);
  171. ~CRecordLayoutTranslator() { delete [] activityKeySizes; }
  172. IMPLEMENT_IINTERFACE;
  173. virtual bool querySuccess() const { return !failure; }
  174. virtual Failure const & queryFailure() const { return *failure; }
  175. virtual size32_t queryActivityKeySize() const { return activityMetaSize; }
  176. virtual size32_t queryDiskKeySize() const { return diskMetaSize; }
  177. virtual void checkSizes(char const * filename, size32_t activitySize, size32_t diskSize) const;
  178. virtual bool queryKeysTransformed() const { return keysTransformed; }
  179. virtual SegmentMonitorContext * getSegmentMonitorContext() { return new ExpandedSegmentMonitorList(this); }
  180. virtual void createDiskSegmentMonitors(SegmentMonitorContext const & in, IIndexReadContext & out);
  181. virtual RowTransformContext * getRowTransformContext();
  182. virtual size32_t transformRow(RowTransformContext * ctx, byte const * in, size32_t inSize, byte * out, size32_t outBuffSize, offset_t & fpos) const;
  183. #ifdef DEBUG_HELPERS_REQUIRED
  184. virtual StringBuffer & getMappingsAsString(StringBuffer & out) const;
  185. #endif
  186. private:
  187. void calculateActivityKeySizes();
  188. void calculateKeysTransformed();
  189. private:
  190. friend class ExpandedSegmentMonitorList;
  191. Linked<IDefRecordMeta> diskMeta;
  192. Linked<IDefRecordMeta> activityMeta;
  193. size32_t activityMetaSize;
  194. size32_t diskMetaSize;
  195. bool success;
  196. Owned<Failure> failure;
  197. FieldMapping::List mappings;
  198. size32_t * activityKeySizes;
  199. unsigned numKeyedDisk;
  200. unsigned numKeyedActivity;
  201. RowTransformer transformer;
  202. unsigned numTransformers;
  203. bool keysTransformed;
  204. };
  205. class CacheKey
  206. {
  207. public:
  208. CacheKey(size32_t _s1, void const * _d1, size32_t _s2, void const * _d2);
  209. unsigned getHash() const { return hashval; }
  210. bool operator==(CacheKey const & other) const { return((s1 == other.s1) && (s2 == other.s2) && (memcmp(d1, other.d1, s1) == 0) && (memcmp(d2, other.d2, s2) == 0)); }
  211. private:
  212. size32_t s1;
  213. byte const * d1;
  214. size32_t s2;
  215. byte const * d2;
  216. unsigned hashval;
  217. };
  218. class CacheValue
  219. {
  220. public:
  221. CacheValue(size32_t s1, void const * d1, size32_t s2, void const * d2, IRecordLayoutTranslator * _trans);
  222. CacheKey const & queryKey() const { return key; }
  223. IRecordLayoutTranslator * getTranslator() const { return trans.getLink(); }
  224. private:
  225. MemoryAttr b1;
  226. MemoryAttr b2;
  227. CacheKey key;
  228. Owned<IRecordLayoutTranslator> trans;
  229. };
  230. typedef SuperHashTableOf<CacheValue, CacheKey> CacheTable;
  231. class CRecordLayoutTranslatorCache : public CacheTable, public IRecordLayoutTranslatorCache
  232. {
  233. public:
  234. IMPLEMENT_IINTERFACE;
  235. virtual ~CRecordLayoutTranslatorCache() { releaseAll(); }
  236. virtual IRecordLayoutTranslator * get(size32_t diskMetaSize, void const * diskMetaData, size32_t activityMetaSize, void const * activityMetaData, IDefRecordMeta const * activityMeta = NULL);
  237. virtual unsigned count() const { return CacheTable::count(); }
  238. private:
  239. virtual void onAdd(void * et) {}
  240. virtual void onRemove(void * et) { delete static_cast<CacheValue *>(et); }
  241. virtual unsigned getHashFromElement(const void * et) const { return static_cast<CacheValue const *>(et)->queryKey().getHash(); }
  242. virtual unsigned getHashFromFindParam(const void * fp) const { return static_cast<CacheKey const *>(fp)->getHash(); }
  243. virtual const void * getFindParam(const void * et) const { return &(static_cast<CacheValue const *>(et)->queryKey()); }
  244. virtual bool matchesFindParam(const void * et, const void *key, unsigned fphash) const { return static_cast<CacheValue const *>(et)->queryKey() == *static_cast<CacheKey const *>(key); }
  245. virtual bool matchesElement(const void *et, const void *searchET) const { return static_cast<CacheValue const *>(et)->queryKey() == static_cast<CacheValue const *>(searchET)->queryKey(); }
  246. };