Package lupos.datastructures.simplifiedfractaltree.buffermanager

Source Code of lupos.datastructures.simplifiedfractaltree.buffermanager.BufferedList$Itr

/**
* Copyright (c) 2013, Institute of Information Systems (Sven Groppe and contributors of LUPOSDATE), University of Luebeck
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
*   - Redistributions of source code must retain the above copyright notice, this list of conditions and the following
*     disclaimer.
*   - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
*     following disclaimer in the documentation and/or other materials provided with the distribution.
*   - Neither the name of the University of Luebeck nor the names of its contributors may be used to endorse or promote
*     products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package lupos.datastructures.simplifiedfractaltree.buffermanager;

import java.awt.Point;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.RandomAccess;

import lupos.datastructures.buffermanager.BufferManager;
import lupos.datastructures.buffermanager.BufferManager.PageAddress;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;

/**
* This class is a implementation of the <tt>List</tt> interface that stores the containing elements on the hard disk by using <tt>BufferManager</tt>
* class. Implements all optional list operations, and permits all elements, including <tt>null</tt>.
*
* <p>
* To avoid memory fragmentation it uses a memory manager, that reuses abandoned regions in memory. It also offers a defragmentation method.
*
* <p>
* <strong>Note that this implementation is not synchronized.</strong> If multiple threads access an <tt>BufferedList</tt> instance concurrently, and
* at least one of the threads modifies the list structurally, it <i>must</i> be synchronized externally. (A structural modification is any operation
* that adds or deletes one or more elements, or explicitly resizes the backing array; merely setting the value of an element is not a structural
* modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the list.
*
* @author Denis Fäcke
* @see List
* @see Collection
* @see Cloneable
* @see BufferManager
* @see RandomAccess
* @see MemoryManager
*/
public class BufferedList<E> implements Collection<E>, List<E>, RandomAccess, Cloneable, Serializable {
  /**
   * Serial Version ID.
   */
  private static final long serialVersionUID = 6855248227285932133L;
  /**
   * The <tt>BufferManager</tt> that is managing the pages.
   */
  protected transient BufferManager bufferManager;
  /**
   * The size of the <tt>BufferedList</tt>.
   */
  protected int size = 0;
  /**
   * The size of one page in bytes for this buffer managers.
   */
  protected int pageSize = 0;
  /**
   * The default size of one page (8 KB).
   */
  public static int DEFAULT_PAGESIZE = 8 * 1024;
  protected File file;
  @SuppressWarnings("rawtypes")
  protected MemoryManager_NextFit memoryManager_NextFit;
  protected int sizeDiv12 = 0;
  protected String path1;
  protected String path2;
  /**
   * An instance of <tt>E</tt>.
   */
  protected Object instance = null;

  /**
   * Constructs an empty list with default page size.
   *
   * @param instance A instance of <tt>E</tt>
   */
  @SuppressWarnings("rawtypes")
  public BufferedList(final Object instance) {
    super();
    this.instance = instance;
    this.pageSize = DEFAULT_PAGESIZE;
    this.sizeDiv12 = (int) Math.floor(this.pageSize / 12);
    String path = (this.getClass().getResource(".")).toString() + "default_name";
    path = path.replaceFirst("file:/", "");
    this.file = new File(path + "/tmp/fractaltree/bufferedlist");
    if (!this.file.getParentFile().exists()) {
      this.file.getParentFile().mkdirs();
    }
    this.path1 = this.file.getPath() + "1";
    this.path2 = this.file.getPath() + "2";
    this.memoryManager_NextFit = new MemoryManager_NextFit(new File(path + "/tmp/fractaltree/fsmanager"));

    this.bufferManager = BufferManager.getBufferManager();

    if (this.size() == 0) {
      try {
        final byte[] page = this.bufferManager.getPage(this.pageSize, new BufferManager.PageAddress(0, this.path1));
        final ByteBuffer byteBuffer = ByteBuffer.wrap(page);
        byteBuffer.putInt(0, byteBuffer.getInt(0)); // size
        byteBuffer.putInt(4, 0); // rightpage
        byteBuffer.putInt(8, 11); // rightbound
        this.bufferManager.modifyPage(this.pageSize, new BufferManager.PageAddress(0, this.path1), byteBuffer.array());
        this.bufferManager.writeAllModifiedPages();
      } catch (final IOException e) {
        e.printStackTrace();
      }
    }
  }

  /**
   * Constructs an empty list with the specified page size and name.
   *
   * @param pageSize The page size (should be 2^x)
   * @param name A name
   * @param instance A instance of <tt>E</tt>
   */
  @SuppressWarnings("rawtypes")
  public BufferedList(final int pageSize, File file, final Object instance) {
    this.instance = instance;
    this.pageSize = pageSize;
    file = file.getAbsoluteFile();
    this.file = new File(file.getParentFile() + "/tmp/fractaltree/" + file.getName());
    this.sizeDiv12 = (int) Math.floor(pageSize / 12);
    this.memoryManager_NextFit = new MemoryManager_NextFit(new File(file.getAbsolutePath() + "/tmp/fractaltree/fsmanager"));
    if (!this.file.getParentFile().exists()) {
      this.file.getParentFile().mkdirs();
    }
    this.path1 = file.getParentFile() + "/tmp/fractaltree/" + file.getName() + "1";
    this.path2 = file.getParentFile() + "/tmp/fractaltree/" + file.getName() + "2";

    this.bufferManager = BufferManager.getBufferManager();

    if (this.size() == 0) {
      try {
        final byte[] page = this.bufferManager.getPage(this.pageSize, new BufferManager.PageAddress(0, this.path1));
        final ByteBuffer byteBuffer = ByteBuffer.wrap(page);
        byteBuffer.putInt(0, byteBuffer.getInt(0)); // size
        byteBuffer.putInt(4, 0); // rightpage
        byteBuffer.putInt(8, 11); // rightbound
        this.bufferManager.modifyPage(this.pageSize, new BufferManager.PageAddress(0, this.path1), byteBuffer.array());
        this.bufferManager.writeAllModifiedPages();
      } catch (final IOException e) {
        e.printStackTrace();
      }
    }
  }

  @Override
  public void clear() {
    this.bufferManager.releaseAllPages();
    this.memoryManager_NextFit.clear();
    this.size = 0;

    try {
      final byte[] page = this.bufferManager.getPage(this.pageSize, new BufferManager.PageAddress(0, this.path1));
      final ByteBuffer byteBuffer = ByteBuffer.wrap(page);
      byteBuffer.putInt(0, byteBuffer.getInt(0)); // size
      byteBuffer.putInt(4, 0); // rightpage
      byteBuffer.putInt(8, 11); // rightbound
      this.bufferManager.modifyPage(this.pageSize, new BufferManager.PageAddress(0, this.path1), byteBuffer.array());
      this.bufferManager.writeAllModifiedPages();
    } catch (final IOException e) {
      e.printStackTrace();
    }
  }

  /**
   * Checks if the specified <tt>index</tt> is valid.
   *
   * @param index A index
   * @throws IndexOutOfBoundsException
   */
  protected void rangeCheck(final int index) {
    if (index >= this.size) {
      throw new IndexOutOfBoundsException(this.outOfBoundsMsg(index));
    }
  }

  @Override
  public boolean isEmpty() {
    return this.size == 0;
  }

  @Override
  public int size() {
    return this.size;
  }

  @Override
  public boolean add(final E e) {
    this.add(this.size, e);

    return true;
  }

  /**
   * Serializes an element and returns the serialized element as a byte array.
   *
   * @param element An element
   * @return The serialized element
   */
  protected byte[] serialize(final E element) {
    final ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream out = null;
    byte[] array = null;

    try {
      out = new ObjectOutputStream(bos);
      out.writeObject(element);
      out.flush();
      out.close();
      bos.close();
      array = bos.toByteArray();
    } catch (final IOException e) {
      e.printStackTrace();
    }

    return array;
  }

  /**
   * Deserializes a byte array and the returns the deserialized element.
   *
   * @param array A byte array
   * @param instance An instance of <tt>E</tt>
   * @return The deserialized element
   */
  @SuppressWarnings("unchecked")
  protected E deserialize(final byte[] array, final Object instance) {
    final ByteArrayInputStream bis = new ByteArrayInputStream(array);
    ObjectInputStream in = null;
    Object o = null;

    try {
      in = new ObjectInputStream(bis);
      o = in.readObject();
      bis.close();
      in.close();
    } catch (final IOException e) {
      e.printStackTrace();
    } catch (final ClassNotFoundException e) {
      e.printStackTrace();
    }
    return (E) o;
  }

  private void writeObject(final java.io.ObjectOutputStream s) throws java.io.IOException {
    // Write out element count, and any hidden stuff
    s.defaultWriteObject();

    // Write out size as capacity for behavioural compatibility with clone()
    s.writeInt(this.size());

    // Write out all elements in the proper order.
    for (int i = 0; i < this.size(); i++) {
      s.writeObject(this.get(i));
    }
  }

  @SuppressWarnings("unchecked")
  private void readObject(final java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {

    // Read in size, and any hidden stuff
    s.defaultReadObject();

    // Read in the size
    final int size = s.readInt();

    for (int i = 0; i < size; i++) {
      this.add((E) s.readObject());
    }
  }

  public int getPointerPage(final int index) {
    return (int) Math.floor(index / this.sizeDiv12);
  }

  protected int getPointerBound(final int index) {
    return (index % this.sizeDiv12) * 12;
  }

  protected void setEnd(final Point end) {
    try {
      final byte[] page = this.bufferManager.getPage(this.pageSize, new BufferManager.PageAddress(0, this.path1));
      final ByteBuffer byteBuffer = ByteBuffer.wrap(page);
      byteBuffer.putInt(4, end.x);
      byteBuffer.putInt(8, end.y);
      this.bufferManager.modifyPage(this.pageSize, new BufferManager.PageAddress(0, this.path1), byteBuffer.array());
      this.bufferManager.writeAllModifiedPages();
    } catch (final IOException e) {
      e.printStackTrace();
    }
  }

  protected Point getEnd() {
    ByteBuffer byteBuffer = null;
    try {
      final byte[] page = this.bufferManager.getPage(this.pageSize, new BufferManager.PageAddress(0, this.path1));
      byteBuffer = ByteBuffer.wrap(page);
    } catch (final IOException e) {
      e.printStackTrace();
    }
    return new Point(byteBuffer.getInt(4), byteBuffer.getInt(8));
  }

  @Override
  public void add(final int index, final E e) {
    final Point end = this.getEnd();
    int leftBound = end.y + 1;
    int leftPage = end.x;
    if (end.y == this.pageSize) {
      leftBound = 0;
      leftPage++;
    }
    final byte[] serializedObject = this.serialize(e);
    final int rightPage = this.calcRightPage(leftPage, leftBound, serializedObject.length);
    final int rightBound = this.calcRightBound(leftBound, serializedObject.length);

    this.writeData(serializedObject, leftPage, rightPage, leftBound, rightBound);

    this.setEnd(new Point(rightPage, rightBound));

    for (int i = this.size - 1; i >= index;) {
      if (i % this.pageSize == 0) {
        final Pointer pointer2 = this.getPointers(i);
        this.setPointers(i + 1, pointer2.leftPage, pointer2.leftBound, pointer2.size);
        i--;
      } else {
        byte[] page = null;
        try {
          page = this.bufferManager.getPage(this.pageSize, new BufferManager.PageAddress(this.getPointerPage(i), this.path2));
        } catch (final IOException e2) {
          e2.printStackTrace();
        }
        if (this.getPointerBound(index) != this.getPointerBound(i)) {
          try {
            System.arraycopy(page, 0, page, 1, this.pageSize - 1);
            this.bufferManager.modifyPage(this.pageSize, new PageAddress(this.getPointerPage(i), this.path2), page);
          } catch (final IOException e1) {
            e1.printStackTrace();
          }
          i -= this.pageSize - 1;
        } else {
          try {
            System.arraycopy(page, index, page, index + 1, this.pageSize - index);
            this.bufferManager.modifyPage(this.pageSize, new PageAddress(this.getPointerPage(i), this.path2), page);
          } catch (final IOException e1) {
            e1.printStackTrace();
          }
          i -= this.pageSize - index;
        }
      }
    }
    try {
      this.bufferManager.writeAllModifiedPages();
    } catch (final IOException e1) {
      e1.printStackTrace();
    }
    this.setPointers(index, leftPage, leftBound, serializedObject.length);

    this.incSize(1);
  }

  /**
   * Writes a serialized object to the the specified location.
   *
   * @param serializedObject A serialized object
   * @param leftPage The left page
   * @param rightPage The right page
   * @param leftBound The left bound
   * @param rightBound The right bound
   */
  protected void writeData(final byte[] serializedObject, final int leftPage, final int rightPage, final int leftBound, final int rightBound) {
    byte[] page = null;
    int offset = 0;
    try {
      for (int i = leftPage; i <= rightPage; i++) {
        page = this.bufferManager.getPage(this.pageSize, new PageAddress(i, this.path1));
        if (leftPage == rightPage) {
          System.arraycopy(serializedObject, 0, page, leftBound, serializedObject.length);
          this.bufferManager.modifyPage(this.pageSize, new PageAddress(i, this.path1), page);
          offset += serializedObject.length;
        } else if (i == leftPage) {
          System.arraycopy(serializedObject, 0, page, leftBound, this.pageSize - leftBound);
          this.bufferManager.modifyPage(this.pageSize, new PageAddress(i, this.path1), page);
          offset += this.pageSize - leftBound;
        } else if (i != leftPage && i != rightPage) {
          System.arraycopy(serializedObject, offset, page, 0, this.pageSize);
          this.bufferManager.modifyPage(this.pageSize, new PageAddress(i, this.path1), page);
          offset += this.pageSize;
        } else if (i == rightPage) {
          System.arraycopy(serializedObject, offset, page, 0, rightBound);
          this.bufferManager.modifyPage(this.pageSize, new PageAddress(i, this.path1), page);
          offset += rightBound;
        }
      }
      this.bufferManager.writeAllModifiedPages();
    } catch (final IOException e1) {
      e1.printStackTrace();
    }
  }

  /**
   * Increments the size stored in page 0 by <tt>i</tt>.
   *
   * @param i The amount to increase the size
   */
  protected void incSize(final int i) {
    this.size += i;
    try {
      final ByteBuffer byteBuffer = ByteBuffer.wrap(this.bufferManager.getPage(this.pageSize, new PageAddress(0, this.path1)));
      byteBuffer.putInt(0, this.size() + i);
      this.bufferManager.modifyPage(this.pageSize, new PageAddress(0, this.path1), byteBuffer.array());
      this.bufferManager.writeAllModifiedPages();
    } catch (final IOException e) {
      e.printStackTrace();
    }
  }

  /**
   * Decrements the size stored in page 0 by <tt>i</tt>.
   *
   * @param i The amount to decrease the size
   */
  protected void decSize(final int i) {
    this.size -= i;
    try {
      final ByteBuffer byteBuffer = ByteBuffer.wrap(this.bufferManager.getPage(this.pageSize, new PageAddress(0, this.path1)));
      byteBuffer.putInt(0, this.size() - i);
      this.bufferManager.modifyPage(this.pageSize, new PageAddress(0, this.path1), byteBuffer.array());
      this.bufferManager.writeAllModifiedPages();
    } catch (final IOException e) {
      e.printStackTrace();
    }
  }

  @Override
  public boolean addAll(final Collection<? extends E> c) {
    return this.addAll(this.size(), c);
  }

  @Override
  public boolean addAll(int index, final Collection<? extends E> c) {
    this.rangeCheckForAdd(index);

    boolean modified = false;
    for (final E e : c) {
      this.add(index++, e);
      modified = true;
    }
    return modified;
  }

  @Override
  public int indexOf(final Object o) {
    if (o == null) {
      for (int i = 0; i < this.size; i++) {
        if (this.get(i) == null) {
          return i;
        }
      }
    } else {
      for (int i = 0; i < this.size; i++) {
        if (o.equals(this.get(i))) {
          return i;
        }
      }
    }
    return -1;
  }

  @Override
  public boolean contains(final Object o) {
    return this.indexOf(o) >= 0;
  }

  @Override
  public boolean containsAll(final Collection<?> c) {
    @SuppressWarnings("unchecked")
    final
    Iterator<? extends E> iterator = (Iterator<? extends E>) c.iterator();
    boolean modified = true;
    for (int i = 0; i < c.size(); i++) {
      if (!this.contains(iterator.next())) {
        modified = false;
      }
    }
    return modified;
  }

  @Override
  public E get(final int index) {
    this.rangeCheck(index);

    return this.getElement(this.getPointers(index));
  }

  /**
   * Returns the element specified by the <tt>pointer</tt>.
   *
   * @param pointer A <tt>pointer</tt>
   * @return A element
   */
  protected E getElement(final Pointer pointer) {
    final int leftPage = pointer.leftPage;
    final int rightPage = this.calcRightPage(pointer.leftPage, pointer.leftBound, pointer.size);
    final int leftBound = pointer.leftBound;
    final int rightBound = this.calcRightBound(pointer.leftBound, pointer.size);

    final int size = pointer.size;
    final byte[] element = new byte[size];

    int offset = 0;
    for (int i = leftPage; i <= rightPage; i++) {
      try {
        final byte[] page = this.bufferManager.getPage(this.pageSize, new PageAddress(i, this.path1));
        if (leftPage == rightPage) {
          System.arraycopy(page, leftBound, element, offset, size);
          break;
        } else if (i == leftPage) {
          if (this.pageSize < leftBound) {
            System.out.println((this.pageSize < leftBound));
          }
          System.arraycopy(page, leftBound, element, offset, this.pageSize - leftBound);
          offset += this.pageSize - leftBound;
        } else if (i != leftPage && i != rightPage) {
          System.arraycopy(page, 0, element, offset, this.pageSize);
          offset += this.pageSize;
        } else if (i == rightPage) {
          System.arraycopy(page, 0, element, offset, rightBound);
        }

        this.bufferManager.writeAllModifiedPages();
      } catch (final IOException e) {
        e.printStackTrace();
      }
    }

    return this.deserialize(element, this.instance);
  }

  @Override
  public Iterator<E> iterator() {
    return this.listIterator();
  }

  /**
   * Checks if the <tt>index</tt> is valid for the add methd.
   *
   * @param index A index
   */
  protected void rangeCheckForAdd(final int index) {
    if (index < 0 || index > this.size) {
      throw new IndexOutOfBoundsException(this.outOfBoundsMsg(index));
    }
  }

  /**
   * Returns a message for a <tt>IndexOutOfBoundException</tt>.
   *
   * @param index A index
   * @return A String
   * @see IndexOutOfBoundException
   */
  protected String outOfBoundsMsg(final int index) {
    return "Index: " + index + ", Size: " + this.size();
  }

  @Override
  public int lastIndexOf(final Object o) {
    if (o == null) {
      for (int i = this.size() - 1; i >= 0; i--) {
        if (this.get(i) == null) {
          return i;
        }
      }
    } else {
      for (int i = this.size() - 1; i >= 0; i--) {
        if (o.equals(this.get(i))) {
          return i;
        }
      }
    }
    return -1;
  }

  @Override
  public ListIterator<E> listIterator(final int index) {
    if (index < 0 || index > this.size()) {
      throw new IndexOutOfBoundsException("Index: " + index);
    }
    return new ListItr(index);
  }

  @Override
  public ListIterator<E> listIterator() {
    return new ListItr(0);
  }

  @Override
  public boolean remove(final Object o) {
    final int size = this.size();
    if (o == null) {
      for (int index = 0; index < size; index++) {
        if (this.get(index) == null) {
          this.remove(index);
          return true;
        }
      }
    } else {
      for (int index = 0; index < size; index++) {
        if (o.equals(this.get(index))) {
          this.remove(index);
          return true;
        }
      }
    }
    return false;
  }

  @Override
  public E remove(final int index) {
    final E oldValue = this.get(index);

    final Pointer pointer = this.getPointers(index);
    final int pageStart = pointer.leftPage;
    final int leftBound = pointer.leftBound;
    final int bm2LastElement = this.getPointerPage(this.size() - 1);
    final int oldSize = pointer.size;
    this.memoryManager_NextFit.release(pageStart, leftBound, oldSize);

    final int pageEndNew = 0;

    for (int i = index; i < this.size; i++) {
      final Pointer pointers = this.getPointers(i + 1);
      this.setPointers(i, pointers.leftPage, pointers.leftBound, pointers.size);
    }

    // Remove unused pages
    if (index == this.size - 1) {
      for (int l = pageEndNew + 1; l < this.size; l++) {
        this.bufferManager.releasePage(new PageAddress(l, this.path1));
      }
      if (this.getPointerPage(this.size - 1) < bm2LastElement) {
        this.bufferManager.releasePage(new PageAddress(bm2LastElement, this.path2));
      }
    }

    this.decSize(1);

    return oldValue;
  }

  @SuppressWarnings("unchecked")
  @Override
  public boolean removeAll(final Collection<?> c) {
    final Iterator<?> itr = c.iterator();
    boolean modified = false;
    for (int i = 0; i < c.size(); i++) {
      this.remove(itr.next());
      modified = true;
    }
    return modified;
  }

  @Override
  public boolean retainAll(final Collection<?> c) {
    boolean modified = false;
    for (int i = 0; i < c.size(); i++) {
      if (!c.contains(this.get(i))) {
        this.remove(i);
      }
      modified = true;
    }
    return modified;
  }

  public void setNoReturn(final int index, final E element) {
    this.rangeCheck(index);

    final Pointer pointers = this.getPointers(index);
    this.memoryManager_NextFit.release(pointers.leftPage, pointers.leftBound, pointers.size);

    final byte[] serializedObject = this.serialize(element);
    final Point end = this.getEnd();
    int leftPage = end.x;
    int leftBound = end.y + 1;
    if (end.y == this.pageSize) {
      leftBound = 0;
      leftPage++;
    }
    final int rightPage = this.calcRightPage(leftPage, leftBound, serializedObject.length);
    final int rightBound = this.calcRightBound(leftBound, serializedObject.length);

    this.writeData(serializedObject, leftPage, rightPage, leftBound, rightBound);
    this.setPointers(index, leftPage, leftBound, serializedObject.length);

    this.setEnd(new Point(rightPage, rightBound));
  }

  @Override
  public E set(final int index, final E element) {
    this.rangeCheck(index);

    final E oldValue = this.get(index);

    final Pointer pointers = this.getPointers(index);
    this.memoryManager_NextFit.release(pointers.leftPage, pointers.leftBound, pointers.size);

    final byte[] serializedObject = this.serialize(element);
    final Point end = this.getEnd();
    int leftPage = end.x;
    int leftBound = end.y + 1;
    if (end.y == this.pageSize) {
      leftBound = 0;
      leftPage++;
    }
    final int rightPage = this.calcRightPage(leftPage, leftBound, serializedObject.length);
    final int rightBound = this.calcRightBound(leftBound, serializedObject.length);

    this.writeData(serializedObject, leftPage, rightPage, leftBound, rightBound);
    this.setPointers(index, leftPage, leftBound, serializedObject.length);

    this.setEnd(new Point(rightPage, rightBound));

    return oldValue;
  }

  protected Pointer getPointers(final int index) {
    ByteBuffer byteBuffer = null;
    try {
      byteBuffer = ByteBuffer.wrap(this.bufferManager.getPage(this.pageSize, new PageAddress(this.getPointerPage(index), this.path2)));
    } catch (final IOException e) {
      e.printStackTrace();
    }

    final int pointerBound = this.getPointerBound(index);
    return new Pointer(byteBuffer.getInt(pointerBound), byteBuffer.getInt(pointerBound + 4), byteBuffer.getInt(pointerBound + 8));
  }

  protected void setPointers(final int index, final int leftPage, final int leftBound, final int size) {
    try {
      final ByteBuffer byteBuffer = ByteBuffer.wrap(this.bufferManager.getPage(this.pageSize, new PageAddress(this.getPointerPage(index), this.path2)));

      byteBuffer.putInt(this.getPointerBound(index), leftPage);
      byteBuffer.putInt(this.getPointerBound(index) + 4, leftBound);
      byteBuffer.putInt(this.getPointerBound(index) + 8, size);
      this.bufferManager.modifyPage(this.pageSize, new PageAddress(this.getPointerPage(index), this.path2), byteBuffer.array());
      this.bufferManager.writeAllModifiedPages();
    } catch (final IOException e1) {
      e1.printStackTrace();
    }
  }

  public int calcRightBound(final int leftBound, final int size) {
    final int ans = (leftBound + size) % this.pageSize;
    if (ans == 0) {
      return this.pageSize;
    } else {
      return ans;
    }
  }

  public int calcRightPage(final int leftPage, final int leftBound, final int size) {
    double ans = 0;
    if (leftBound + size <= this.pageSize) {
      ans = leftPage;
    } else {
      ans = leftPage + Math.ceil((double) ((leftBound + size) % this.pageSize) / this.pageSize);
    }

    return (int) (ans);
  }

  @Override
  public List<E> subList(final int fromIndex, final int toIndex) {
    this.subListRangeCheck(fromIndex, toIndex, this.size());

    final List<E> list = new ArrayList<E>();
    for (int i = fromIndex; i < toIndex; i++) {
      list.add(this.get(i));
    }
    return list;
  }

  @Override
  public E[] toArray() {
    @SuppressWarnings("unchecked")
    final
    E[] array = (E[]) new Object[this.size()];
    final int size = this.size();
    for (int i = 0; i < size; i++) {
      array[i] = this.get(i);
    }
    return array;
  }

  @Override
  public <T> T[] toArray(final T[] a) {
    throw new NotImplementedException();
  }

  @Override
  public Object clone() {
    try {
      @SuppressWarnings("unchecked")
      final
      BufferedList<E> v = (BufferedList<E>) super.clone();
      return v;
    } catch (final CloneNotSupportedException e) {
      // this shouldn't happen, since we are Cloneable
      throw new InternalError();
    }
  }

  private void subListRangeCheck(final int fromIndex, final int toIndex, final int size) {
    if (fromIndex < 0) {
      throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
    }
    if (toIndex > size) {
      throw new IndexOutOfBoundsException("toIndex = " + toIndex);
    }
    if (fromIndex > toIndex) {
      throw new IllegalArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
    }
  }

  /**
   * An adapted version of ArrayList.Itr
   */
  protected class Itr implements Iterator<E> {
    int cursor; // index of next element to return
    int lastRet = -1; // index of last element returned; -1 if no such

    @Override
    public boolean hasNext() {
      return this.cursor != BufferedList.this.size();
    }

    @Override
    public E next() {
      final int i = this.cursor;
      if (i >= BufferedList.this.size()) {
        throw new NoSuchElementException();
      }
      this.cursor = i + 1;
      return BufferedList.this.get(this.lastRet = i);
    }

    @Override
    public void remove() {
      if (this.lastRet < 0) {
        throw new IllegalStateException();
      }

      try {
        BufferedList.this.remove(this.lastRet);
        this.cursor = this.lastRet;
        this.lastRet = -1;
      } catch (final IndexOutOfBoundsException ex) {
        throw new ConcurrentModificationException();
      }
    }
  }

  protected class ListItr extends Itr implements ListIterator<E> {
    ListItr(final int index) {
      super();
      this.cursor = index;
    }

    @Override
    public boolean hasPrevious() {
      return this.cursor != 0;
    }

    @Override
    public int nextIndex() {
      return this.cursor;
    }

    @Override
    public int previousIndex() {
      return this.cursor - 1;
    }

    @Override
    public E previous() {
      final int i = this.cursor - 1;
      if (i < 0) {
        throw new NoSuchElementException();
      }
      this.cursor = i;
      return BufferedList.this.get(this.lastRet = i);
    }

    @Override
    public void set(final E e) {
      if (this.lastRet < 0) {
        throw new IllegalStateException();
      }

      try {
        BufferedList.this.set(this.lastRet, e);
      } catch (final IndexOutOfBoundsException ex) {
        throw new ConcurrentModificationException();
      }
    }

    @Override
    public void add(final E e) {

      try {
        final int i = this.cursor;
        BufferedList.this.add(i, e);
        this.cursor = i + 1;
        this.lastRet = -1;
      } catch (final IndexOutOfBoundsException ex) {
        throw new ConcurrentModificationException();
      }
    }
  }
}
TOP

Related Classes of lupos.datastructures.simplifiedfractaltree.buffermanager.BufferedList$Itr

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.