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