Package com.orientechnologies.orient.core.storage.impl.local.paginated.base

Source Code of com.orientechnologies.orient.core.storage.impl.local.paginated.base.ODurablePage

/*
  *
  *  *  Copyright 2014 Orient Technologies LTD (info(at)orientechnologies.com)
  *  *
  *  *  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.
  *  *
  *  * For more information: http://www.orientechnologies.com
  *
  */

package com.orientechnologies.orient.core.storage.impl.local.paginated.base;

import com.orientechnologies.common.directmemory.ODirectMemoryPointer;
import com.orientechnologies.common.serialization.types.OBinarySerializer;
import com.orientechnologies.common.serialization.types.OByteSerializer;
import com.orientechnologies.common.serialization.types.OIntegerSerializer;
import com.orientechnologies.common.serialization.types.OLongSerializer;
import com.orientechnologies.orient.core.config.OGlobalConfiguration;
import com.orientechnologies.orient.core.index.hashindex.local.cache.OCacheEntry;
import com.orientechnologies.orient.core.index.hashindex.local.cache.OCachePointer;
import com.orientechnologies.orient.core.index.hashindex.local.cache.OWOWCache;
import com.orientechnologies.orient.core.storage.impl.local.paginated.wal.OLogSequenceNumber;
import com.orientechnologies.orient.core.storage.impl.local.paginated.wal.OPageChanges;

import java.io.IOException;

/**
* Base page class for all durable data structures, that is data structures state of which can be consistently restored after system
* crash but results of last operations in small interval before crash may be lost.
*
* This page has several booked memory areas with following offsets at the beginning:
* <ol>
* <li>from 0 to 7 - Magic number</li>
* <li>from 8 to 11 - crc32 of all page content, which is calculated by cache system just before save</li>
* <li>from 12 to 23 - LSN of last operation which was stored for given page</li>
* </ol>
*
* Developer which will extend this class should use all page memory starting from {@link #NEXT_FREE_POSITION} offset.
*
* To make page changes durable method {@link ODurableComponent#logPageChanges(ODurablePage, long, long, boolean)} should be called
* just before release of page
* {@link com.orientechnologies.orient.core.index.hashindex.local.cache.ODiskCache#release(com.orientechnologies.orient.core.index.hashindex.local.cache.OCacheEntry)}
* back to the cache.
*
* All data structures which use this kind of pages should be derived from
* {@link com.orientechnologies.orient.core.storage.impl.local.paginated.base.ODurableComponent} class.
*
* @author Andrey Lomakin
* @since 16.08.13
*/
public class ODurablePage {
  public static final int         PAGE_PADDING        = OWOWCache.PAGE_PADDING;

  protected static final int         MAGIC_NUMBER_OFFSET = 0;
  protected static final int         CRC32_OFFSET        = MAGIC_NUMBER_OFFSET + OLongSerializer.LONG_SIZE;

  public static final int            WAL_SEGMENT_OFFSET  = CRC32_OFFSET + OIntegerSerializer.INT_SIZE;
  public static final int            WAL_POSITION_OFFSET = WAL_SEGMENT_OFFSET + OLongSerializer.LONG_SIZE;
  public static final int            MAX_PAGE_SIZE_BYTES = OGlobalConfiguration.DISK_CACHE_PAGE_SIZE.getValueAsInteger() * 1024;

  protected static final int         NEXT_FREE_POSITION  = WAL_POSITION_OFFSET + OLongSerializer.LONG_SIZE;

  protected OPageChanges             pageChanges         = new OPageChanges();

  private final OCacheEntry          cacheEntry;
  private final ODirectMemoryPointer pagePointer;

  protected final TrackMode          trackMode;

  public ODurablePage(OCacheEntry cacheEntry, TrackMode trackMode) {
    this.cacheEntry = cacheEntry;

    final OCachePointer cachePointer = cacheEntry.getCachePointer();
    this.pagePointer = cachePointer.getDataPointer();

    this.trackMode = trackMode;
  }

  public static OLogSequenceNumber getLogSequenceNumberFromPage(ODirectMemoryPointer dataPointer) {
    final long segment = OLongSerializer.INSTANCE.deserializeFromDirectMemory(dataPointer, WAL_SEGMENT_OFFSET + PAGE_PADDING);
    final long position = OLongSerializer.INSTANCE.deserializeFromDirectMemory(dataPointer, WAL_POSITION_OFFSET + PAGE_PADDING);

    return new OLogSequenceNumber(segment, position);
  }

  public static enum TrackMode {
    NONE, FULL, ROLLBACK_ONLY
  }

  protected int getIntValue(int pageOffset) {
    return OIntegerSerializer.INSTANCE.deserializeFromDirectMemory(pagePointer, pageOffset + PAGE_PADDING);
  }

  protected long getLongValue(int pageOffset) {
    return OLongSerializer.INSTANCE.deserializeFromDirectMemory(pagePointer, pageOffset + PAGE_PADDING);
  }

  protected byte[] getBinaryValue(int pageOffset, int valLen) {
    return pagePointer.get(pageOffset + PAGE_PADDING, valLen);
  }

  protected int getObjectSizeInDirectMemory(OBinarySerializer binarySerializer, long offset) {
    return binarySerializer.getObjectSizeInDirectMemory(pagePointer, offset + PAGE_PADDING);
  }

  protected <T> T deserializeFromDirectMemory(OBinarySerializer<T> binarySerializer, long offset) {
    return binarySerializer.deserializeFromDirectMemoryObject(pagePointer, offset + PAGE_PADDING);
  }

  protected byte getByteValue(int pageOffset) {
    return pagePointer.getByte(pageOffset + PAGE_PADDING);
  }

  protected int setIntValue(int pageOffset, int value) throws IOException {
    if (trackMode.equals(TrackMode.FULL)) {
      byte[] oldValues = pagePointer.get(pageOffset + PAGE_PADDING, OIntegerSerializer.INT_SIZE);
      OIntegerSerializer.INSTANCE.serializeInDirectMemory(value, pagePointer, pageOffset + PAGE_PADDING);
      byte[] newValues = pagePointer.get(pageOffset + PAGE_PADDING, OIntegerSerializer.INT_SIZE);

      pageChanges.addChanges(pageOffset, newValues, oldValues);
    } else if (trackMode.equals(TrackMode.ROLLBACK_ONLY)) {
      byte[] oldValues = pagePointer.get(pageOffset + PAGE_PADDING, OIntegerSerializer.INT_SIZE);
      OIntegerSerializer.INSTANCE.serializeInDirectMemory(value, pagePointer, pageOffset + PAGE_PADDING);

      pageChanges.addChanges(pageOffset, null, oldValues);
    } else
      OIntegerSerializer.INSTANCE.serializeInDirectMemory(value, pagePointer, pageOffset + PAGE_PADDING);

    cacheEntry.markDirty();

    return OIntegerSerializer.INT_SIZE;

  }

  protected int setByteValue(int pageOffset, byte value) {
    if (trackMode.equals(TrackMode.FULL)) {
      byte[] oldValues = new byte[] { pagePointer.getByte(pageOffset + PAGE_PADDING) };
      pagePointer.setByte(pageOffset + PAGE_PADDING, value);
      byte[] newValues = new byte[] { pagePointer.getByte(pageOffset + PAGE_PADDING) };

      pageChanges.addChanges(pageOffset, newValues, oldValues);
    } else if (trackMode.equals(TrackMode.ROLLBACK_ONLY)) {
      byte[] oldValues = new byte[] { pagePointer.getByte(pageOffset + PAGE_PADDING) };
      pagePointer.setByte(pageOffset + PAGE_PADDING, value);

      pageChanges.addChanges(pageOffset, null, oldValues);
    } else
      pagePointer.setByte(pageOffset + PAGE_PADDING, value);

    cacheEntry.markDirty();

    return OByteSerializer.BYTE_SIZE;
  }

  protected int setLongValue(int pageOffset, long value) throws IOException {
    if (trackMode.equals(TrackMode.FULL)) {
      byte[] oldValues = pagePointer.get(pageOffset + PAGE_PADDING, OLongSerializer.LONG_SIZE);
      OLongSerializer.INSTANCE.serializeInDirectMemory(value, pagePointer, pageOffset + PAGE_PADDING);
      byte[] newValues = pagePointer.get(pageOffset + PAGE_PADDING, OLongSerializer.LONG_SIZE);

      pageChanges.addChanges(pageOffset, newValues, oldValues);
    } else if (trackMode.equals(TrackMode.ROLLBACK_ONLY)) {
      byte[] oldValues = pagePointer.get(pageOffset + PAGE_PADDING, OLongSerializer.LONG_SIZE);
      OLongSerializer.INSTANCE.serializeInDirectMemory(value, pagePointer, pageOffset + PAGE_PADDING);

      pageChanges.addChanges(pageOffset, null, oldValues);
    } else
      OLongSerializer.INSTANCE.serializeInDirectMemory(value, pagePointer, pageOffset + PAGE_PADDING);

    cacheEntry.markDirty();

    return OLongSerializer.LONG_SIZE;
  }

  protected int setBinaryValue(int pageOffset, byte[] value) throws IOException {
    if (value.length == 0)
      return 0;

    if (trackMode.equals(TrackMode.FULL)) {
      byte[] oldValues = pagePointer.get(pageOffset + PAGE_PADDING, value.length);
      pagePointer.set(pageOffset + PAGE_PADDING, value, 0, value.length);

      pageChanges.addChanges(pageOffset, value, oldValues);
    } else if (trackMode.equals(TrackMode.ROLLBACK_ONLY)) {
      byte[] oldValues = pagePointer.get(pageOffset + PAGE_PADDING, value.length);
      pagePointer.set(pageOffset + PAGE_PADDING, value, 0, value.length);

      pageChanges.addChanges(pageOffset, null, oldValues);
    } else
      pagePointer.set(pageOffset + PAGE_PADDING, value, 0, value.length);

    cacheEntry.markDirty();

    return value.length;
  }

  protected void moveData(int from, int to, int len) throws IOException {
    if (len == 0)
      return;

    if (trackMode.equals(TrackMode.FULL)) {
      byte[] content = pagePointer.get(from + PAGE_PADDING, len);
      byte[] oldContent = pagePointer.get(to + PAGE_PADDING, len);

      pagePointer.moveData(from + PAGE_PADDING, pagePointer, to + PAGE_PADDING, len);

      pageChanges.addChanges(to, content, oldContent);
    } else if (trackMode.equals(TrackMode.ROLLBACK_ONLY)) {
      byte[] oldContent = pagePointer.get(to + PAGE_PADDING, len);

      pagePointer.moveData(from + PAGE_PADDING, pagePointer, to + PAGE_PADDING, len);

      pageChanges.addChanges(to, null, oldContent);

    } else
      pagePointer.moveData(from + PAGE_PADDING, pagePointer, to + PAGE_PADDING, len);

    cacheEntry.markDirty();
  }

  public OPageChanges getPageChanges() {
    return pageChanges;
  }

  public void restoreChanges(OPageChanges pageChanges) {
    pageChanges.applyChanges(pagePointer);
    cacheEntry.markDirty();
  }

  public void revertChanges(OPageChanges pageChanges) {
    pageChanges.revertChanges(pagePointer);
    cacheEntry.markDirty();
  }

  public OLogSequenceNumber getLsn() {
    final long segment = getLongValue(WAL_SEGMENT_OFFSET);
    final long position = getLongValue(WAL_POSITION_OFFSET);

    return new OLogSequenceNumber(segment, position);
  }

  public void setLsn(OLogSequenceNumber lsn) {
    OLongSerializer.INSTANCE.serializeInDirectMemory(lsn.getSegment(), pagePointer, WAL_SEGMENT_OFFSET + PAGE_PADDING);
    OLongSerializer.INSTANCE.serializeInDirectMemory(lsn.getPosition(), pagePointer, WAL_POSITION_OFFSET + PAGE_PADDING);

    cacheEntry.markDirty();
  }
}
TOP

Related Classes of com.orientechnologies.orient.core.storage.impl.local.paginated.base.ODurablePage

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.