// This is different from MR implementation where POCounter updates job counters, and that is
// copied by JobControlCompiler into the PORank job's jobconf.
// Previous operator is always POCounterTez (Vertex 1)
TezOperator counterOper = curTezOp;
POCounterTez counterTez = (POCounterTez) counterOper.plan.getLeaves().get(0);
//Construct Vertex 2
TezOperator statsOper = getTezOp();
tezPlan.add(statsOper);
POCounterStatsTez counterStatsTez = new POCounterStatsTez(OperatorKey.genOpKey(scope));
statsOper.plan.addAsLeaf(counterStatsTez);
statsOper.setRequestedParallelism(1);
statsOper.setDontEstimateParallelism(true);
//Construct Vertex 3
TezOperator rankOper = getTezOp();
tezPlan.add(rankOper);
PORankTez rankTez = new PORankTez(op);
rankOper.plan.addAsLeaf(rankTez);
curTezOp = rankOper;
// Connect counterOper vertex to rankOper vertex by 1-1 edge
rankOper.setRequestedParallelismByReference(counterOper);
TezEdgeDescriptor edge = TezCompilerUtil.connect(tezPlan, counterOper, rankOper);
rankOper.setUseMRMapSettings(counterOper.isUseMRMapSettings());
TezCompilerUtil.configureValueOnlyTupleOutput(edge, DataMovementType.ONE_TO_ONE);
counterTez.setTuplesOutputKey(rankOper.getOperatorKey().toString());
rankTez.setTuplesInputKey(counterOper.getOperatorKey().toString());
// Connect counterOper vertex to statsOper vertex by Shuffle edge
edge = TezCompilerUtil.connect(tezPlan, counterOper, statsOper);
// Task id
edge.setIntermediateOutputKeyClass(IntWritable.class.getName());
edge.partitionerClass = HashPartitioner.class;
// Number of records in that task
edge.setIntermediateOutputValueClass(LongWritable.class.getName());
counterTez.setStatsOutputKey(statsOper.getOperatorKey().toString());
counterStatsTez.setInputKey(counterOper.getOperatorKey().toString());
// Connect statsOper vertex to rankOper vertex by Broadcast edge
edge = TezCompilerUtil.connect(tezPlan, statsOper, rankOper);
// Map of task id, offset count based on total number of records is in the value