Package eu.stratosphere.runtime.io.api

Source Code of eu.stratosphere.runtime.io.api.AbstractUnionRecordReader

/***********************************************************************************************************************
* Copyright (C) 2010-2013 by the Stratosphere project (http://stratosphere.eu)
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
**********************************************************************************************************************/

package eu.stratosphere.runtime.io.api;

import eu.stratosphere.core.io.IOReadableWritable;
import eu.stratosphere.nephele.event.task.AbstractTaskEvent;
import eu.stratosphere.runtime.io.gates.InputChannelResult;
import eu.stratosphere.runtime.io.gates.RecordAvailabilityListener;
import eu.stratosphere.runtime.io.gates.InputGate;

import java.io.IOException;
import java.util.ArrayDeque;
import java.util.HashSet;
import java.util.Set;

public abstract class AbstractUnionRecordReader<T extends IOReadableWritable> extends AbstractRecordReader implements RecordAvailabilityListener<T> {

  /**
   * The set of all input gates.
   */
  private final InputGate<T>[] allInputGates;
 
  /**
   * The set of unclosed input gates.
   */
  private final Set<InputGate<T>> remainingInputGates;

  /**
   * Queue with indices of channels that store at least one available record.
   */
  private final ArrayDeque<InputGate<T>> availableInputGates = new ArrayDeque<InputGate<T>>();
 
  /**
   * The next input gate to read a record from.
   */
  private InputGate<T> nextInputGateToReadFrom;

 
  @Override
  public boolean isInputClosed() {
    return this.remainingInputGates.isEmpty();
  }
 
  /**
   * Constructs a new mutable union record reader.
   *
   * @param recordReaders
   *        the individual mutable record readers whose input is used to construct the union
   */
  @SuppressWarnings("unchecked")
  protected AbstractUnionRecordReader(MutableRecordReader<T>[] recordReaders) {

    if (recordReaders == null) {
      throw new IllegalArgumentException("Provided argument recordReaders is null");
    }

    if (recordReaders.length < 2) {
      throw new IllegalArgumentException(
        "The mutable union record reader must at least be initialized with two individual mutable record readers");
    }
   
    this.allInputGates = new InputGate[recordReaders.length];
    this.remainingInputGates = new HashSet<InputGate<T>>((int) (recordReaders.length * 1.6f));
   
    for (int i = 0; i < recordReaders.length; i++) {
      InputGate<T> inputGate = recordReaders[i].getInputGate();
      inputGate.registerRecordAvailabilityListener(this);
      this.allInputGates[i] = inputGate;
      this.remainingInputGates.add(inputGate);
    }
  }
 
 
  @Override
  public void publishEvent(AbstractTaskEvent event) throws IOException, InterruptedException {
    for (InputGate<T> gate : this.allInputGates) {
      gate.publishEvent(event);
    }
  }
 
  @Override
  public void reportRecordAvailability(InputGate<T> inputGate) {
    synchronized (this.availableInputGates) {
      this.availableInputGates.add(inputGate);
      this.availableInputGates.notifyAll();
    }
  }
 
  protected boolean getNextRecord(T target) throws IOException, InterruptedException {

    while (true) {
      // has the current input gate more data?
      if (this.nextInputGateToReadFrom == null) {
        if (this.remainingInputGates.isEmpty()) {
          return false;
        }
       
        this.nextInputGateToReadFrom = getNextAvailableInputGate();
      }

      InputChannelResult result = this.nextInputGateToReadFrom.readRecord(target);
      switch (result) {
        case INTERMEDIATE_RECORD_FROM_BUFFER: // record is available and we can stay on the same channel
          return true;
         
        case LAST_RECORD_FROM_BUFFER: // record is available, but we need to re-check the channels
          this.nextInputGateToReadFrom = null;
          return true;
         
        case END_OF_SUPERSTEP:
          this.nextInputGateToReadFrom = null;
          if (incrementEndOfSuperstepEventAndCheck()) {
            return false; // end of the superstep
          }
          else {
            break; // fall through and wait for next record/event
          }
         
        case TASK_EVENT:  // event for the subscribers is available
          handleEvent(this.nextInputGateToReadFrom.getCurrentEvent());
          this.nextInputGateToReadFrom = null;
          break;
         
        case END_OF_STREAM: // one gate is empty
          this.remainingInputGates.remove(this.nextInputGateToReadFrom);
          this.nextInputGateToReadFrom = null;
          break;
         
        case NONE: // gate processed an internal event and could not return a record on this call
          this.nextInputGateToReadFrom = null;
          break;
      }
    }
  }
 
  private InputGate<T> getNextAvailableInputGate() throws InterruptedException {
    synchronized (this.availableInputGates) {
      while (this.availableInputGates.isEmpty()) {
        this.availableInputGates.wait();
      }
      return this.availableInputGates.pop();
    }
  }
}
TOP

Related Classes of eu.stratosphere.runtime.io.api.AbstractUnionRecordReader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.