Package eu.stratosphere.nephele.services.iomanager

Source Code of eu.stratosphere.nephele.services.iomanager.IOManagerITCase$Value

/***********************************************************************************************************************
* 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.nephele.services.iomanager;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Random;

import junit.framework.Assert;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import eu.stratosphere.core.io.IOReadableWritable;
import eu.stratosphere.core.memory.MemorySegment;
import eu.stratosphere.nephele.services.memorymanager.DefaultMemoryManagerTest;
import eu.stratosphere.nephele.services.memorymanager.spi.DefaultMemoryManager;
import eu.stratosphere.nephele.template.AbstractInvokable;


/**
* Integration test case for the I/O manager.
*
*
*/
public class IOManagerITCase {
 
  private static final Log LOG = LogFactory.getLog(IOManagerITCase.class);
 
  private static final long SEED = 649180756312423613L;

  private static final int NUMBER_OF_SEGMENTS = 10; // 10

  private static final int SEGMENT_SIZE = 1024 * 1024; // 1M
 
  private final int NUM_CHANNELS = 29;
 
  private final int NUMBERS_TO_BE_WRITTEN = NUM_CHANNELS * 1000000;

  private IOManager ioManager;

  private DefaultMemoryManager memoryManager;


  @Before
  public void beforeTest() {
    memoryManager = new DefaultMemoryManager(NUMBER_OF_SEGMENTS * SEGMENT_SIZE);
    ioManager = new IOManager();
  }

  @After
  public void afterTest() throws Exception {
    ioManager.shutdown();
    Assert.assertTrue("IO Manager has not properly shut down.", ioManager.isProperlyShutDown());
   
    Assert.assertTrue("Not all memory was returned to the memory manager in the test.", memoryManager.verifyEmpty());
    memoryManager.shutdown();
    memoryManager = null;
  }

  // ------------------------------------------------------------------------
 
  /**
   * This test instantiates multiple channels and writes to them in parallel and re-reads the data in
   * parallel. It is designed to check the ability of the IO manager to correctly handle multiple threads.
   */
  @Test
  public void parallelChannelsTest() throws Exception
  {
    LOG.info("Starting parallel channels test.");
   
    final Random rnd = new Random(SEED);
    final AbstractInvokable memOwner = new DefaultMemoryManagerTest.DummyInvokable();
   
    Channel.ID[] ids = new Channel.ID[NUM_CHANNELS];
    BlockChannelWriter[] writers = new BlockChannelWriter[NUM_CHANNELS];
    BlockChannelReader[] readers = new BlockChannelReader[NUM_CHANNELS];
    ChannelWriterOutputView[] outs = new ChannelWriterOutputView[NUM_CHANNELS];
    ChannelReaderInputView[] ins = new ChannelReaderInputView[NUM_CHANNELS];
   
    int[] writingCounters = new int[NUM_CHANNELS];
    int[] readingCounters = new int[NUM_CHANNELS];
   
    // instantiate the channels and writers
    for (int i = 0; i < NUM_CHANNELS; i++)
    {
      ids[i] = this.ioManager.createChannel();
      writers[i] = this.ioManager.createBlockChannelWriter(ids[i]);
     
      List<MemorySegment> memSegs = this.memoryManager.allocatePages(memOwner, rnd.nextInt(NUMBER_OF_SEGMENTS - 2) + 2);
      outs[i] = new ChannelWriterOutputView(writers[i], memSegs, this.memoryManager.getPageSize());
    }
   
   
    Value val = new Value();
   
    // write a lot of values unevenly distributed over the channels
    int nextLogCount = 0;
    float nextLogFraction = 0.0f;
   
    LOG.info("Writing to channels...");
    for (int i = 0; i < NUMBERS_TO_BE_WRITTEN; i++) {
     
      if (i == nextLogCount) {
        LOG.info("... " + (int) (nextLogFraction * 100) + "% done.");
        nextLogFraction += 0.05;
        nextLogCount = (int) (nextLogFraction * NUMBERS_TO_BE_WRITTEN);
      }
     
      int channel = skewedSample(rnd, NUM_CHANNELS - 1);
     
      val.value = String.valueOf(writingCounters[channel]++);
      val.write(outs[channel]);
    }
    LOG.info("Writing done, flushing contents...");
   
    // close all writers
    for (int i = 0; i < NUM_CHANNELS; i++) {
      this.memoryManager.release(outs[i].close());
    }
    outs = null;
    writers = null;
   
    // instantiate the readers for sequential read
    LOG.info("Reading channels sequentially...");
    for (int i = 0; i < NUM_CHANNELS; i++)
    {
      List<MemorySegment> memSegs = this.memoryManager.allocatePages(memOwner, rnd.nextInt(NUMBER_OF_SEGMENTS - 2) + 2);
     
      LOG.info("Reading channel " + (i+1) + "/" + NUM_CHANNELS + '.');
       
      final BlockChannelReader reader = this.ioManager.createBlockChannelReader(ids[i]);
      final ChannelReaderInputView in = new ChannelReaderInputView(reader, memSegs, false);
      int nextVal = 0;
     
      try {
        while (true) {
          val.read(in);
          int intValue = 0;
          try {
            intValue = Integer.parseInt(val.value);
          }
          catch (NumberFormatException nfex) {
            Assert.fail("Invalid value read from reader. Valid decimal number expected.");
          }
          Assert.assertEquals("Written and read values do not match during sequential read.", nextVal, intValue);
          nextVal++;
        }
      } catch (EOFException eofex) {
        // expected
      }
     
      Assert.assertEquals("NUmber of written numbers differs from number of read numbers.", writingCounters[i], nextVal);
     
      this.memoryManager.release(in.close());
    }
    LOG.info("Sequential reading done.");
   
    // instantiate the readers
    LOG.info("Reading channels randomly...");
    for (int i = 0; i < NUM_CHANNELS; i++) {
     
      List<MemorySegment> memSegs = this.memoryManager.allocatePages(memOwner, rnd.nextInt(NUMBER_OF_SEGMENTS - 2) + 2);
       
      readers[i] = this.ioManager.createBlockChannelReader(ids[i]);
      ins[i] = new ChannelReaderInputView(readers[i], memSegs, false);
    }
   
    nextLogCount = 0;
    nextLogFraction = 0.0f;
   
    // read a lot of values in a mixed order from the channels
    for (int i = 0; i < NUMBERS_TO_BE_WRITTEN; i++) {
     
      if (i == nextLogCount) {
        LOG.info("... " + (int) (nextLogFraction * 100) + "% done.");
        nextLogFraction += 0.05;
        nextLogCount = (int) (nextLogFraction * NUMBERS_TO_BE_WRITTEN);
      }
     
      while (true) {
        final int channel = skewedSample(rnd, NUM_CHANNELS - 1);
        if (ins[channel] != null) {
          try {
            val.read(ins[channel]);
            int intValue;
            try {
              intValue = Integer.parseInt(val.value);
            }
            catch (NumberFormatException nfex) {
              Assert.fail("Invalid value read from reader. Valid decimal number expected.");
              return;
            }
           
            Assert.assertEquals("Written and read values do not match.", readingCounters[channel]++, intValue);
           
            break;
          } catch (EOFException eofex) {
            this.memoryManager.release(ins[channel].close());
            ins[channel] = null;
          }
        }
      }
     
    }
    LOG.info("Random reading done.");
   
    // close all readers
    for (int i = 0; i < NUM_CHANNELS; i++) {
      if (ins[i] != null) {
        this.memoryManager.release(ins[i].close());
      }
      readers[i].closeAndDelete();
    }
   
    ins = null;
    readers = null;
   
    // check that files are deleted
    for (int i = 0; i < NUM_CHANNELS; i++) {
      File f = new File(ids[i].getPath());
      Assert.assertFalse("Channel file has not been deleted.", f.exists());
    }
  }
 
  private static final int skewedSample(Random rnd, int max) {
    double uniform = rnd.nextDouble();
    double var = Math.pow(uniform, 8.0);
    double pareto = 0.2 / var;
   
    int val = (int) pareto;
    return val > max ? val % max : val;
  }
 
 
  // ------------------------------------------------------------------------
 
  protected static class Value implements IOReadableWritable {

    String value;

    public Value() {
    }

    public Value(String val) {
      this.value = val;
    }

    @Override
    public void read(DataInput in) throws IOException {
      value = in.readUTF();
    }

    @Override
    public void write(DataOutput out) throws IOException {
      out.writeUTF(this.value);
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((value == null) ? 0 : value.hashCode());
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj) {
        return true;
      }
      if (obj == null) {
        return false;
      }
      if (getClass() != obj.getClass()) {
        return false;
      }
      Value other = (Value) obj;

      if (value == null) {
        if (other.value != null) {
          return false;
        }
      } else if (!value.equals(other.value)) {
        return false;
      }
      return true;
    }
  }

}
TOP

Related Classes of eu.stratosphere.nephele.services.iomanager.IOManagerITCase$Value

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.