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