001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package org.apache.hadoop.record.compiler;
020
021 import java.io.File;
022 import java.io.FileWriter;
023 import java.io.IOException;
024 import java.util.*;
025
026 import org.apache.hadoop.classification.InterfaceAudience;
027 import org.apache.hadoop.classification.InterfaceStability;
028
029 /**
030 * @deprecated Replaced by <a href="http://hadoop.apache.org/avro/">Avro</a>.
031 */
032 @Deprecated
033 @InterfaceAudience.Public
034 @InterfaceStability.Stable
035 public class JRecord extends JCompType {
036
037 class JavaRecord extends JavaCompType {
038
039 private String fullName;
040 private String name;
041 private String module;
042 private ArrayList<JField<JavaType>> fields =
043 new ArrayList<JField<JavaType>>();
044
045 JavaRecord(String name, ArrayList<JField<JType>> flist) {
046 super(name, "Record", name, "TypeID.RIOType.STRUCT");
047 this.fullName = name;
048 int idx = name.lastIndexOf('.');
049 this.name = name.substring(idx+1);
050 this.module = name.substring(0, idx);
051 for (Iterator<JField<JType>> iter = flist.iterator(); iter.hasNext();) {
052 JField<JType> f = iter.next();
053 fields.add(new JField<JavaType>(f.getName(), f.getType().getJavaType()));
054 }
055 }
056
057 String getTypeIDObjectString() {
058 return "new org.apache.hadoop.record.meta.StructTypeID(" +
059 fullName + ".getTypeInfo())";
060 }
061
062 void genSetRTIFilter(CodeBuffer cb, Map<String, Integer> nestedStructMap) {
063 // ignore, if we'ev already set the type filter for this record
064 if (!nestedStructMap.containsKey(fullName)) {
065 // we set the RTI filter here
066 cb.append(fullName + ".setTypeFilter(rti.getNestedStructTypeInfo(\""+
067 name + "\"));\n");
068 nestedStructMap.put(fullName, null);
069 }
070 }
071
072 // for each typeInfo in the filter, we see if there's a similar one in the record.
073 // Since we store typeInfos in ArrayLists, thsi search is O(n squared). We do it faster
074 // if we also store a map (of TypeInfo to index), but since setupRtiFields() is called
075 // only once when deserializing, we're sticking with the former, as the code is easier.
076 void genSetupRtiFields(CodeBuffer cb) {
077 cb.append("private static void setupRtiFields()\n{\n");
078 cb.append("if (null == " + Consts.RTI_FILTER + ") return;\n");
079 cb.append("// we may already have done this\n");
080 cb.append("if (null != " + Consts.RTI_FILTER_FIELDS + ") return;\n");
081 cb.append("int " + Consts.RIO_PREFIX + "i, " + Consts.RIO_PREFIX + "j;\n");
082 cb.append(Consts.RTI_FILTER_FIELDS + " = new int [" +
083 Consts.RIO_PREFIX + "rtiFilter.getFieldTypeInfos().size()];\n");
084 cb.append("for (" + Consts.RIO_PREFIX + "i=0; " + Consts.RIO_PREFIX + "i<"+
085 Consts.RTI_FILTER_FIELDS + ".length; " + Consts.RIO_PREFIX + "i++) {\n");
086 cb.append(Consts.RTI_FILTER_FIELDS + "[" + Consts.RIO_PREFIX + "i] = 0;\n");
087 cb.append("}\n");
088 cb.append("java.util.Iterator<org.apache.hadoop.record.meta." +
089 "FieldTypeInfo> " + Consts.RIO_PREFIX + "itFilter = " +
090 Consts.RIO_PREFIX + "rtiFilter.getFieldTypeInfos().iterator();\n");
091 cb.append(Consts.RIO_PREFIX + "i=0;\n");
092 cb.append("while (" + Consts.RIO_PREFIX + "itFilter.hasNext()) {\n");
093 cb.append("org.apache.hadoop.record.meta.FieldTypeInfo " +
094 Consts.RIO_PREFIX + "tInfoFilter = " +
095 Consts.RIO_PREFIX + "itFilter.next();\n");
096 cb.append("java.util.Iterator<org.apache.hadoop.record.meta." +
097 "FieldTypeInfo> " + Consts.RIO_PREFIX + "it = " + Consts.RTI_VAR +
098 ".getFieldTypeInfos().iterator();\n");
099 cb.append(Consts.RIO_PREFIX + "j=1;\n");
100 cb.append("while (" + Consts.RIO_PREFIX + "it.hasNext()) {\n");
101 cb.append("org.apache.hadoop.record.meta.FieldTypeInfo " +
102 Consts.RIO_PREFIX + "tInfo = " + Consts.RIO_PREFIX + "it.next();\n");
103 cb.append("if (" + Consts.RIO_PREFIX + "tInfo.equals(" +
104 Consts.RIO_PREFIX + "tInfoFilter)) {\n");
105 cb.append(Consts.RTI_FILTER_FIELDS + "[" + Consts.RIO_PREFIX + "i] = " +
106 Consts.RIO_PREFIX + "j;\n");
107 cb.append("break;\n");
108 cb.append("}\n");
109 cb.append(Consts.RIO_PREFIX + "j++;\n");
110 cb.append("}\n");
111 /*int ct = 0;
112 for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
113 ct++;
114 JField<JavaType> jf = i.next();
115 JavaType type = jf.getType();
116 String name = jf.getName();
117 if (ct != 1) {
118 cb.append("else ");
119 }
120 type.genRtiFieldCondition(cb, name, ct);
121 }
122 if (ct != 0) {
123 cb.append("else {\n");
124 cb.append("rtiFilterFields[i] = 0;\n");
125 cb.append("}\n");
126 }*/
127 cb.append(Consts.RIO_PREFIX + "i++;\n");
128 cb.append("}\n");
129 cb.append("}\n");
130 }
131
132 void genReadMethod(CodeBuffer cb, String fname, String tag, boolean decl) {
133 if (decl) {
134 cb.append(fullName+" "+fname+";\n");
135 }
136 cb.append(fname+"= new "+fullName+"();\n");
137 cb.append(fname+".deserialize(" + Consts.RECORD_INPUT + ",\""+tag+"\");\n");
138 }
139
140 void genWriteMethod(CodeBuffer cb, String fname, String tag) {
141 cb.append(fname+".serialize(" + Consts.RECORD_OUTPUT + ",\""+tag+"\");\n");
142 }
143
144 void genSlurpBytes(CodeBuffer cb, String b, String s, String l) {
145 cb.append("{\n");
146 cb.append("int r = "+fullName+
147 ".Comparator.slurpRaw("+b+","+s+","+l+");\n");
148 cb.append(s+"+=r; "+l+"-=r;\n");
149 cb.append("}\n");
150 }
151
152 void genCompareBytes(CodeBuffer cb) {
153 cb.append("{\n");
154 cb.append("int r1 = "+fullName+
155 ".Comparator.compareRaw(b1,s1,l1,b2,s2,l2);\n");
156 cb.append("if (r1 <= 0) { return r1; }\n");
157 cb.append("s1+=r1; s2+=r1; l1-=r1; l2-=r1;\n");
158 cb.append("}\n");
159 }
160
161 void genCode(String destDir, ArrayList<String> options) throws IOException {
162 String pkg = module;
163 String pkgpath = pkg.replaceAll("\\.", "/");
164 File pkgdir = new File(destDir, pkgpath);
165
166 final File jfile = new File(pkgdir, name+".java");
167 if (!pkgdir.exists()) {
168 // create the pkg directory
169 boolean ret = pkgdir.mkdirs();
170 if (!ret) {
171 throw new IOException("Cannnot create directory: "+pkgpath);
172 }
173 } else if (!pkgdir.isDirectory()) {
174 // not a directory
175 throw new IOException(pkgpath+" is not a directory.");
176 }
177
178 CodeBuffer cb = new CodeBuffer();
179 cb.append("// File generated by hadoop record compiler. Do not edit.\n");
180 cb.append("package "+module+";\n\n");
181 cb.append("public class "+name+
182 " extends org.apache.hadoop.record.Record {\n");
183
184 // type information declarations
185 cb.append("private static final " +
186 "org.apache.hadoop.record.meta.RecordTypeInfo " +
187 Consts.RTI_VAR + ";\n");
188 cb.append("private static " +
189 "org.apache.hadoop.record.meta.RecordTypeInfo " +
190 Consts.RTI_FILTER + ";\n");
191 cb.append("private static int[] " + Consts.RTI_FILTER_FIELDS + ";\n");
192
193 // static init for type information
194 cb.append("static {\n");
195 cb.append(Consts.RTI_VAR + " = " +
196 "new org.apache.hadoop.record.meta.RecordTypeInfo(\"" +
197 name + "\");\n");
198 for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
199 JField<JavaType> jf = i.next();
200 String name = jf.getName();
201 JavaType type = jf.getType();
202 type.genStaticTypeInfo(cb, name);
203 }
204 cb.append("}\n\n");
205
206 // field definitions
207 for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
208 JField<JavaType> jf = i.next();
209 String name = jf.getName();
210 JavaType type = jf.getType();
211 type.genDecl(cb, name);
212 }
213
214 // default constructor
215 cb.append("public "+name+"() { }\n");
216
217 // constructor
218 cb.append("public "+name+"(\n");
219 int fIdx = 0;
220 for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext(); fIdx++) {
221 JField<JavaType> jf = i.next();
222 String name = jf.getName();
223 JavaType type = jf.getType();
224 type.genConstructorParam(cb, name);
225 cb.append((!i.hasNext())?"":",\n");
226 }
227 cb.append(") {\n");
228 fIdx = 0;
229 for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext(); fIdx++) {
230 JField<JavaType> jf = i.next();
231 String name = jf.getName();
232 JavaType type = jf.getType();
233 type.genConstructorSet(cb, name);
234 }
235 cb.append("}\n");
236
237 // getter/setter for type info
238 cb.append("public static org.apache.hadoop.record.meta.RecordTypeInfo"
239 + " getTypeInfo() {\n");
240 cb.append("return " + Consts.RTI_VAR + ";\n");
241 cb.append("}\n");
242 cb.append("public static void setTypeFilter("
243 + "org.apache.hadoop.record.meta.RecordTypeInfo rti) {\n");
244 cb.append("if (null == rti) return;\n");
245 cb.append(Consts.RTI_FILTER + " = rti;\n");
246 cb.append(Consts.RTI_FILTER_FIELDS + " = null;\n");
247 // set RTIFilter for nested structs.
248 // To prevent setting up the type filter for the same struct more than once,
249 // we use a hash map to keep track of what we've set.
250 Map<String, Integer> nestedStructMap = new HashMap<String, Integer>();
251 for (JField<JavaType> jf : fields) {
252 JavaType type = jf.getType();
253 type.genSetRTIFilter(cb, nestedStructMap);
254 }
255 cb.append("}\n");
256
257 // setupRtiFields()
258 genSetupRtiFields(cb);
259
260 // getters/setters for member variables
261 for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
262 JField<JavaType> jf = i.next();
263 String name = jf.getName();
264 JavaType type = jf.getType();
265 type.genGetSet(cb, name);
266 }
267
268 // serialize()
269 cb.append("public void serialize("+
270 "final org.apache.hadoop.record.RecordOutput " +
271 Consts.RECORD_OUTPUT + ", final String " + Consts.TAG + ")\n"+
272 "throws java.io.IOException {\n");
273 cb.append(Consts.RECORD_OUTPUT + ".startRecord(this," + Consts.TAG + ");\n");
274 for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
275 JField<JavaType> jf = i.next();
276 String name = jf.getName();
277 JavaType type = jf.getType();
278 type.genWriteMethod(cb, name, name);
279 }
280 cb.append(Consts.RECORD_OUTPUT + ".endRecord(this," + Consts.TAG+");\n");
281 cb.append("}\n");
282
283 // deserializeWithoutFilter()
284 cb.append("private void deserializeWithoutFilter("+
285 "final org.apache.hadoop.record.RecordInput " +
286 Consts.RECORD_INPUT + ", final String " + Consts.TAG + ")\n"+
287 "throws java.io.IOException {\n");
288 cb.append(Consts.RECORD_INPUT + ".startRecord(" + Consts.TAG + ");\n");
289 for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
290 JField<JavaType> jf = i.next();
291 String name = jf.getName();
292 JavaType type = jf.getType();
293 type.genReadMethod(cb, name, name, false);
294 }
295 cb.append(Consts.RECORD_INPUT + ".endRecord(" + Consts.TAG+");\n");
296 cb.append("}\n");
297
298 // deserialize()
299 cb.append("public void deserialize(final " +
300 "org.apache.hadoop.record.RecordInput " +
301 Consts.RECORD_INPUT + ", final String " + Consts.TAG + ")\n"+
302 "throws java.io.IOException {\n");
303 cb.append("if (null == " + Consts.RTI_FILTER + ") {\n");
304 cb.append("deserializeWithoutFilter(" + Consts.RECORD_INPUT + ", " +
305 Consts.TAG + ");\n");
306 cb.append("return;\n");
307 cb.append("}\n");
308 cb.append("// if we're here, we need to read based on version info\n");
309 cb.append(Consts.RECORD_INPUT + ".startRecord(" + Consts.TAG + ");\n");
310 cb.append("setupRtiFields();\n");
311 cb.append("for (int " + Consts.RIO_PREFIX + "i=0; " + Consts.RIO_PREFIX +
312 "i<" + Consts.RTI_FILTER + ".getFieldTypeInfos().size(); " +
313 Consts.RIO_PREFIX + "i++) {\n");
314 int ct = 0;
315 for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
316 JField<JavaType> jf = i.next();
317 String name = jf.getName();
318 JavaType type = jf.getType();
319 ct++;
320 if (1 != ct) {
321 cb.append("else ");
322 }
323 cb.append("if (" + ct + " == " + Consts.RTI_FILTER_FIELDS + "[" +
324 Consts.RIO_PREFIX + "i]) {\n");
325 type.genReadMethod(cb, name, name, false);
326 cb.append("}\n");
327 }
328 if (0 != ct) {
329 cb.append("else {\n");
330 cb.append("java.util.ArrayList<"
331 + "org.apache.hadoop.record.meta.FieldTypeInfo> typeInfos = "
332 + "(java.util.ArrayList<"
333 + "org.apache.hadoop.record.meta.FieldTypeInfo>)"
334 + "(" + Consts.RTI_FILTER + ".getFieldTypeInfos());\n");
335 cb.append("org.apache.hadoop.record.meta.Utils.skip(" +
336 Consts.RECORD_INPUT + ", " + "typeInfos.get(" + Consts.RIO_PREFIX +
337 "i).getFieldID(), typeInfos.get(" +
338 Consts.RIO_PREFIX + "i).getTypeID());\n");
339 cb.append("}\n");
340 }
341 cb.append("}\n");
342 cb.append(Consts.RECORD_INPUT + ".endRecord(" + Consts.TAG+");\n");
343 cb.append("}\n");
344
345 // compareTo()
346 cb.append("public int compareTo (final Object " + Consts.RIO_PREFIX +
347 "peer_) throws ClassCastException {\n");
348 cb.append("if (!(" + Consts.RIO_PREFIX + "peer_ instanceof "+name+")) {\n");
349 cb.append("throw new ClassCastException(\"Comparing different types of records.\");\n");
350 cb.append("}\n");
351 cb.append(name+" " + Consts.RIO_PREFIX + "peer = ("+name+") " +
352 Consts.RIO_PREFIX + "peer_;\n");
353 cb.append("int " + Consts.RIO_PREFIX + "ret = 0;\n");
354 for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
355 JField<JavaType> jf = i.next();
356 String name = jf.getName();
357 JavaType type = jf.getType();
358 type.genCompareTo(cb, name, Consts.RIO_PREFIX + "peer."+name);
359 cb.append("if (" + Consts.RIO_PREFIX + "ret != 0) return " +
360 Consts.RIO_PREFIX + "ret;\n");
361 }
362 cb.append("return " + Consts.RIO_PREFIX + "ret;\n");
363 cb.append("}\n");
364
365 // equals()
366 cb.append("public boolean equals(final Object " + Consts.RIO_PREFIX +
367 "peer_) {\n");
368 cb.append("if (!(" + Consts.RIO_PREFIX + "peer_ instanceof "+name+")) {\n");
369 cb.append("return false;\n");
370 cb.append("}\n");
371 cb.append("if (" + Consts.RIO_PREFIX + "peer_ == this) {\n");
372 cb.append("return true;\n");
373 cb.append("}\n");
374 cb.append(name+" " + Consts.RIO_PREFIX + "peer = ("+name+") " +
375 Consts.RIO_PREFIX + "peer_;\n");
376 cb.append("boolean " + Consts.RIO_PREFIX + "ret = false;\n");
377 for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
378 JField<JavaType> jf = i.next();
379 String name = jf.getName();
380 JavaType type = jf.getType();
381 type.genEquals(cb, name, Consts.RIO_PREFIX + "peer."+name);
382 cb.append("if (!" + Consts.RIO_PREFIX + "ret) return " +
383 Consts.RIO_PREFIX + "ret;\n");
384 }
385 cb.append("return " + Consts.RIO_PREFIX + "ret;\n");
386 cb.append("}\n");
387
388 // clone()
389 cb.append("public Object clone() throws CloneNotSupportedException {\n");
390 cb.append(name+" " + Consts.RIO_PREFIX + "other = new "+name+"();\n");
391 for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
392 JField<JavaType> jf = i.next();
393 String name = jf.getName();
394 JavaType type = jf.getType();
395 type.genClone(cb, name);
396 }
397 cb.append("return " + Consts.RIO_PREFIX + "other;\n");
398 cb.append("}\n");
399
400 cb.append("public int hashCode() {\n");
401 cb.append("int " + Consts.RIO_PREFIX + "result = 17;\n");
402 cb.append("int " + Consts.RIO_PREFIX + "ret;\n");
403 for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
404 JField<JavaType> jf = i.next();
405 String name = jf.getName();
406 JavaType type = jf.getType();
407 type.genHashCode(cb, name);
408 cb.append(Consts.RIO_PREFIX + "result = 37*" + Consts.RIO_PREFIX +
409 "result + " + Consts.RIO_PREFIX + "ret;\n");
410 }
411 cb.append("return " + Consts.RIO_PREFIX + "result;\n");
412 cb.append("}\n");
413
414 cb.append("public static String signature() {\n");
415 cb.append("return \""+getSignature()+"\";\n");
416 cb.append("}\n");
417
418 cb.append("public static class Comparator extends"+
419 " org.apache.hadoop.record.RecordComparator {\n");
420 cb.append("public Comparator() {\n");
421 cb.append("super("+name+".class);\n");
422 cb.append("}\n");
423
424 cb.append("static public int slurpRaw(byte[] b, int s, int l) {\n");
425 cb.append("try {\n");
426 cb.append("int os = s;\n");
427 for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
428 JField<JavaType> jf = i.next();
429 String name = jf.getName();
430 JavaType type = jf.getType();
431 type.genSlurpBytes(cb, "b","s","l");
432 }
433 cb.append("return (os - s);\n");
434 cb.append("} catch(java.io.IOException e) {\n");
435 cb.append("throw new RuntimeException(e);\n");
436 cb.append("}\n");
437 cb.append("}\n");
438
439 cb.append("static public int compareRaw(byte[] b1, int s1, int l1,\n");
440 cb.append(" byte[] b2, int s2, int l2) {\n");
441 cb.append("try {\n");
442 cb.append("int os1 = s1;\n");
443 for (Iterator<JField<JavaType>> i = fields.iterator(); i.hasNext();) {
444 JField<JavaType> jf = i.next();
445 String name = jf.getName();
446 JavaType type = jf.getType();
447 type.genCompareBytes(cb);
448 }
449 cb.append("return (os1 - s1);\n");
450 cb.append("} catch(java.io.IOException e) {\n");
451 cb.append("throw new RuntimeException(e);\n");
452 cb.append("}\n");
453 cb.append("}\n");
454 cb.append("public int compare(byte[] b1, int s1, int l1,\n");
455 cb.append(" byte[] b2, int s2, int l2) {\n");
456 cb.append("int ret = compareRaw(b1,s1,l1,b2,s2,l2);\n");
457 cb.append("return (ret == -1)? -1 : ((ret==0)? 1 : 0);");
458 cb.append("}\n");
459 cb.append("}\n\n");
460 cb.append("static {\n");
461 cb.append("org.apache.hadoop.record.RecordComparator.define("
462 +name+".class, new Comparator());\n");
463 cb.append("}\n");
464 cb.append("}\n");
465
466 FileWriter jj = new FileWriter(jfile);
467 try {
468 jj.write(cb.toString());
469 } finally {
470 jj.close();
471 }
472 }
473 }
474
475 class CppRecord extends CppCompType {
476
477 private String fullName;
478 private String name;
479 private String module;
480 private ArrayList<JField<CppType>> fields =
481 new ArrayList<JField<CppType>>();
482
483 CppRecord(String name, ArrayList<JField<JType>> flist) {
484 super(name.replaceAll("\\.","::"));
485 this.fullName = name.replaceAll("\\.", "::");
486 int idx = name.lastIndexOf('.');
487 this.name = name.substring(idx+1);
488 this.module = name.substring(0, idx).replaceAll("\\.", "::");
489 for (Iterator<JField<JType>> iter = flist.iterator(); iter.hasNext();) {
490 JField<JType> f = iter.next();
491 fields.add(new JField<CppType>(f.getName(), f.getType().getCppType()));
492 }
493 }
494
495 String getTypeIDObjectString() {
496 return "new ::hadoop::StructTypeID(" +
497 fullName + "::getTypeInfo().getFieldTypeInfos())";
498 }
499
500 String genDecl(String fname) {
501 return " "+name+" "+fname+";\n";
502 }
503
504 void genSetRTIFilter(CodeBuffer cb) {
505 // we set the RTI filter here
506 cb.append(fullName + "::setTypeFilter(rti.getNestedStructTypeInfo(\""+
507 name + "\"));\n");
508 }
509
510 void genSetupRTIFields(CodeBuffer cb) {
511 cb.append("void " + fullName + "::setupRtiFields() {\n");
512 cb.append("if (NULL == p" + Consts.RTI_FILTER + ") return;\n");
513 cb.append("if (NULL != p" + Consts.RTI_FILTER_FIELDS + ") return;\n");
514 cb.append("p" + Consts.RTI_FILTER_FIELDS + " = new int[p" +
515 Consts.RTI_FILTER + "->getFieldTypeInfos().size()];\n");
516 cb.append("for (unsigned int " + Consts.RIO_PREFIX + "i=0; " +
517 Consts.RIO_PREFIX + "i<p" + Consts.RTI_FILTER +
518 "->getFieldTypeInfos().size(); " + Consts.RIO_PREFIX + "i++) {\n");
519 cb.append("p" + Consts.RTI_FILTER_FIELDS + "[" + Consts.RIO_PREFIX +
520 "i] = 0;\n");
521 cb.append("}\n");
522 cb.append("for (unsigned int " + Consts.RIO_PREFIX + "i=0; " +
523 Consts.RIO_PREFIX + "i<p" + Consts.RTI_FILTER +
524 "->getFieldTypeInfos().size(); " + Consts.RIO_PREFIX + "i++) {\n");
525 cb.append("for (unsigned int " + Consts.RIO_PREFIX + "j=0; " +
526 Consts.RIO_PREFIX + "j<p" + Consts.RTI_VAR +
527 "->getFieldTypeInfos().size(); " + Consts.RIO_PREFIX + "j++) {\n");
528 cb.append("if (*(p" + Consts.RTI_FILTER + "->getFieldTypeInfos()[" +
529 Consts.RIO_PREFIX + "i]) == *(p" + Consts.RTI_VAR +
530 "->getFieldTypeInfos()[" + Consts.RIO_PREFIX + "j])) {\n");
531 cb.append("p" + Consts.RTI_FILTER_FIELDS + "[" + Consts.RIO_PREFIX +
532 "i] = " + Consts.RIO_PREFIX + "j+1;\n");
533 cb.append("break;\n");
534 cb.append("}\n");
535 cb.append("}\n");
536 cb.append("}\n");
537 cb.append("}\n");
538 }
539
540 void genCode(FileWriter hh, FileWriter cc, ArrayList<String> options)
541 throws IOException {
542 CodeBuffer hb = new CodeBuffer();
543
544 String[] ns = module.split("::");
545 for (int i = 0; i < ns.length; i++) {
546 hb.append("namespace "+ns[i]+" {\n");
547 }
548
549 hb.append("class "+name+" : public ::hadoop::Record {\n");
550 hb.append("private:\n");
551
552 for (Iterator<JField<CppType>> i = fields.iterator(); i.hasNext();) {
553 JField<CppType> jf = i.next();
554 String name = jf.getName();
555 CppType type = jf.getType();
556 type.genDecl(hb, name);
557 }
558
559 // type info vars
560 hb.append("static ::hadoop::RecordTypeInfo* p" + Consts.RTI_VAR + ";\n");
561 hb.append("static ::hadoop::RecordTypeInfo* p" + Consts.RTI_FILTER + ";\n");
562 hb.append("static int* p" + Consts.RTI_FILTER_FIELDS + ";\n");
563 hb.append("static ::hadoop::RecordTypeInfo* setupTypeInfo();\n");
564 hb.append("static void setupRtiFields();\n");
565 hb.append("virtual void deserializeWithoutFilter(::hadoop::IArchive& " +
566 Consts.RECORD_INPUT + ", const char* " + Consts.TAG + ");\n");
567 hb.append("public:\n");
568 hb.append("static const ::hadoop::RecordTypeInfo& getTypeInfo() " +
569 "{return *p" + Consts.RTI_VAR + ";}\n");
570 hb.append("static void setTypeFilter(const ::hadoop::RecordTypeInfo& rti);\n");
571 hb.append("static void setTypeFilter(const ::hadoop::RecordTypeInfo* prti);\n");
572 hb.append("virtual void serialize(::hadoop::OArchive& " +
573 Consts.RECORD_OUTPUT + ", const char* " + Consts.TAG + ") const;\n");
574 hb.append("virtual void deserialize(::hadoop::IArchive& " +
575 Consts.RECORD_INPUT + ", const char* " + Consts.TAG + ");\n");
576 hb.append("virtual const ::std::string& type() const;\n");
577 hb.append("virtual const ::std::string& signature() const;\n");
578 hb.append("virtual bool operator<(const "+name+"& peer_) const;\n");
579 hb.append("virtual bool operator==(const "+name+"& peer_) const;\n");
580 hb.append("virtual ~"+name+"() {};\n");
581 for (Iterator<JField<CppType>> i = fields.iterator(); i.hasNext();) {
582 JField<CppType> jf = i.next();
583 String name = jf.getName();
584 CppType type = jf.getType();
585 type.genGetSet(hb, name);
586 }
587 hb.append("}; // end record "+name+"\n");
588 for (int i=ns.length-1; i>=0; i--) {
589 hb.append("} // end namespace "+ns[i]+"\n");
590 }
591
592 hh.write(hb.toString());
593
594 CodeBuffer cb = new CodeBuffer();
595
596 // initialize type info vars
597 cb.append("::hadoop::RecordTypeInfo* " + fullName + "::p" +
598 Consts.RTI_VAR + " = " + fullName + "::setupTypeInfo();\n");
599 cb.append("::hadoop::RecordTypeInfo* " + fullName + "::p" +
600 Consts.RTI_FILTER + " = NULL;\n");
601 cb.append("int* " + fullName + "::p" +
602 Consts.RTI_FILTER_FIELDS + " = NULL;\n\n");
603
604 // setupTypeInfo()
605 cb.append("::hadoop::RecordTypeInfo* "+fullName+"::setupTypeInfo() {\n");
606 cb.append("::hadoop::RecordTypeInfo* p = new ::hadoop::RecordTypeInfo(\"" +
607 name + "\");\n");
608 for (Iterator<JField<CppType>> i = fields.iterator(); i.hasNext();) {
609 JField<CppType> jf = i.next();
610 String name = jf.getName();
611 CppType type = jf.getType();
612 type.genStaticTypeInfo(cb, name);
613 }
614 cb.append("return p;\n");
615 cb.append("}\n");
616
617 // setTypeFilter()
618 cb.append("void "+fullName+"::setTypeFilter(const " +
619 "::hadoop::RecordTypeInfo& rti) {\n");
620 cb.append("if (NULL != p" + Consts.RTI_FILTER + ") {\n");
621 cb.append("delete p" + Consts.RTI_FILTER + ";\n");
622 cb.append("}\n");
623 cb.append("p" + Consts.RTI_FILTER + " = new ::hadoop::RecordTypeInfo(rti);\n");
624 cb.append("if (NULL != p" + Consts.RTI_FILTER_FIELDS + ") {\n");
625 cb.append("delete p" + Consts.RTI_FILTER_FIELDS + ";\n");
626 cb.append("}\n");
627 cb.append("p" + Consts.RTI_FILTER_FIELDS + " = NULL;\n");
628 // set RTIFilter for nested structs. We may end up with multiple lines that
629 // do the same thing, if the same struct is nested in more than one field,
630 // but that's OK.
631 for (Iterator<JField<CppType>> i = fields.iterator(); i.hasNext();) {
632 JField<CppType> jf = i.next();
633 CppType type = jf.getType();
634 type.genSetRTIFilter(cb);
635 }
636 cb.append("}\n");
637
638 // setTypeFilter()
639 cb.append("void "+fullName+"::setTypeFilter(const " +
640 "::hadoop::RecordTypeInfo* prti) {\n");
641 cb.append("if (NULL != prti) {\n");
642 cb.append("setTypeFilter(*prti);\n");
643 cb.append("}\n");
644 cb.append("}\n");
645
646 // setupRtiFields()
647 genSetupRTIFields(cb);
648
649 // serialize()
650 cb.append("void "+fullName+"::serialize(::hadoop::OArchive& " +
651 Consts.RECORD_OUTPUT + ", const char* " + Consts.TAG + ") const {\n");
652 cb.append(Consts.RECORD_OUTPUT + ".startRecord(*this," +
653 Consts.TAG + ");\n");
654 for (Iterator<JField<CppType>> i = fields.iterator(); i.hasNext();) {
655 JField<CppType> jf = i.next();
656 String name = jf.getName();
657 CppType type = jf.getType();
658 if (type instanceof JBuffer.CppBuffer) {
659 cb.append(Consts.RECORD_OUTPUT + ".serialize("+name+","+name+
660 ".length(),\""+name+"\");\n");
661 } else {
662 cb.append(Consts.RECORD_OUTPUT + ".serialize("+name+",\""+
663 name+"\");\n");
664 }
665 }
666 cb.append(Consts.RECORD_OUTPUT + ".endRecord(*this," + Consts.TAG + ");\n");
667 cb.append("return;\n");
668 cb.append("}\n");
669
670 // deserializeWithoutFilter()
671 cb.append("void "+fullName+"::deserializeWithoutFilter(::hadoop::IArchive& " +
672 Consts.RECORD_INPUT + ", const char* " + Consts.TAG + ") {\n");
673 cb.append(Consts.RECORD_INPUT + ".startRecord(*this," +
674 Consts.TAG + ");\n");
675 for (Iterator<JField<CppType>> i = fields.iterator(); i.hasNext();) {
676 JField<CppType> jf = i.next();
677 String name = jf.getName();
678 CppType type = jf.getType();
679 if (type instanceof JBuffer.CppBuffer) {
680 cb.append("{\nsize_t len=0; " + Consts.RECORD_INPUT + ".deserialize("+
681 name+",len,\""+name+"\");\n}\n");
682 } else {
683 cb.append(Consts.RECORD_INPUT + ".deserialize("+name+",\""+
684 name+"\");\n");
685 }
686 }
687 cb.append(Consts.RECORD_INPUT + ".endRecord(*this," + Consts.TAG + ");\n");
688 cb.append("return;\n");
689 cb.append("}\n");
690
691 // deserialize()
692 cb.append("void "+fullName+"::deserialize(::hadoop::IArchive& " +
693 Consts.RECORD_INPUT + ", const char* " + Consts.TAG + ") {\n");
694 cb.append("if (NULL == p" + Consts.RTI_FILTER + ") {\n");
695 cb.append("deserializeWithoutFilter(" + Consts.RECORD_INPUT + ", " +
696 Consts.TAG + ");\n");
697 cb.append("return;\n");
698 cb.append("}\n");
699 cb.append("// if we're here, we need to read based on version info\n");
700 cb.append(Consts.RECORD_INPUT + ".startRecord(*this," +
701 Consts.TAG + ");\n");
702 cb.append("setupRtiFields();\n");
703 cb.append("for (unsigned int " + Consts.RIO_PREFIX + "i=0; " +
704 Consts.RIO_PREFIX + "i<p" + Consts.RTI_FILTER +
705 "->getFieldTypeInfos().size(); " + Consts.RIO_PREFIX + "i++) {\n");
706 int ct = 0;
707 for (Iterator<JField<CppType>> i = fields.iterator(); i.hasNext();) {
708 JField<CppType> jf = i.next();
709 String name = jf.getName();
710 CppType type = jf.getType();
711 ct++;
712 if (1 != ct) {
713 cb.append("else ");
714 }
715 cb.append("if (" + ct + " == p" + Consts.RTI_FILTER_FIELDS + "[" +
716 Consts.RIO_PREFIX + "i]) {\n");
717 if (type instanceof JBuffer.CppBuffer) {
718 cb.append("{\nsize_t len=0; " + Consts.RECORD_INPUT + ".deserialize("+
719 name+",len,\""+name+"\");\n}\n");
720 } else {
721 cb.append(Consts.RECORD_INPUT + ".deserialize("+name+",\""+
722 name+"\");\n");
723 }
724 cb.append("}\n");
725 }
726 if (0 != ct) {
727 cb.append("else {\n");
728 cb.append("const std::vector< ::hadoop::FieldTypeInfo* >& typeInfos = p" +
729 Consts.RTI_FILTER + "->getFieldTypeInfos();\n");
730 cb.append("::hadoop::Utils::skip(" + Consts.RECORD_INPUT +
731 ", typeInfos[" + Consts.RIO_PREFIX + "i]->getFieldID()->c_str()" +
732 ", *(typeInfos[" + Consts.RIO_PREFIX + "i]->getTypeID()));\n");
733 cb.append("}\n");
734 }
735 cb.append("}\n");
736 cb.append(Consts.RECORD_INPUT + ".endRecord(*this, " + Consts.TAG+");\n");
737 cb.append("}\n");
738
739 // operator <
740 cb.append("bool "+fullName+"::operator< (const "+fullName+"& peer_) const {\n");
741 cb.append("return (1\n");
742 for (Iterator<JField<CppType>> i = fields.iterator(); i.hasNext();) {
743 JField<CppType> jf = i.next();
744 String name = jf.getName();
745 cb.append("&& ("+name+" < peer_."+name+")\n");
746 }
747 cb.append(");\n");
748 cb.append("}\n");
749
750 cb.append("bool "+fullName+"::operator== (const "+fullName+"& peer_) const {\n");
751 cb.append("return (1\n");
752 for (Iterator<JField<CppType>> i = fields.iterator(); i.hasNext();) {
753 JField<CppType> jf = i.next();
754 String name = jf.getName();
755 cb.append("&& ("+name+" == peer_."+name+")\n");
756 }
757 cb.append(");\n");
758 cb.append("}\n");
759
760 cb.append("const ::std::string&"+fullName+"::type() const {\n");
761 cb.append("static const ::std::string type_(\""+name+"\");\n");
762 cb.append("return type_;\n");
763 cb.append("}\n");
764
765 cb.append("const ::std::string&"+fullName+"::signature() const {\n");
766 cb.append("static const ::std::string sig_(\""+getSignature()+"\");\n");
767 cb.append("return sig_;\n");
768 cb.append("}\n");
769
770 cc.write(cb.toString());
771 }
772 }
773
774 class CRecord extends CCompType {
775
776 }
777
778 private String signature;
779
780 /**
781 * Creates a new instance of JRecord
782 */
783 public JRecord(String name, ArrayList<JField<JType>> flist) {
784 setJavaType(new JavaRecord(name, flist));
785 setCppType(new CppRecord(name, flist));
786 setCType(new CRecord());
787 // precompute signature
788 int idx = name.lastIndexOf('.');
789 String recName = name.substring(idx+1);
790 StringBuilder sb = new StringBuilder();
791 sb.append("L").append(recName).append("(");
792 for (Iterator<JField<JType>> i = flist.iterator(); i.hasNext();) {
793 String s = i.next().getType().getSignature();
794 sb.append(s);
795 }
796 sb.append(")");
797 signature = sb.toString();
798 }
799
800 String getSignature() {
801 return signature;
802 }
803
804 void genCppCode(FileWriter hh, FileWriter cc, ArrayList<String> options)
805 throws IOException {
806 ((CppRecord)getCppType()).genCode(hh, cc, options);
807 }
808
809 void genJavaCode(String destDir, ArrayList<String> options)
810 throws IOException {
811 ((JavaRecord)getJavaType()).genCode(destDir, options);
812 }
813 }