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 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}