All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.accumulo.server.tablets.TabletTime Maven / Gradle / Ivy

There is a newer version: 3.0.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.accumulo.server.tablets;

import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.accumulo.core.client.admin.TimeType;
import org.apache.accumulo.core.data.Mutation;
import org.apache.accumulo.server.data.ServerMutation;
import org.apache.accumulo.server.util.time.RelativeTime;

public abstract class TabletTime {
  public static final char LOGICAL_TIME_ID = 'L';
  public static final char MILLIS_TIME_ID = 'M';

  public static char getTimeID(TimeType timeType) {
    switch (timeType) {
      case LOGICAL:
        return LOGICAL_TIME_ID;
      case MILLIS:
        return MILLIS_TIME_ID;
    }

    throw new IllegalArgumentException("Unknown time type " + timeType);
  }

  public abstract void useMaxTimeFromWALog(long time);

  public abstract String getMetadataValue(long time);

  public abstract String getMetadataValue();

  public abstract long setUpdateTimes(List mutations);

  public abstract long getTime();

  public abstract long getAndUpdateTime();

  protected void setSystemTimes(Mutation mutation, long lastCommitTime) {
    ServerMutation m = (ServerMutation) mutation;
    m.setSystemTimestamp(lastCommitTime);
  }

  public static TabletTime getInstance(String metadataValue) {
    if (metadataValue.charAt(0) == LOGICAL_TIME_ID) {
      return new LogicalTime(Long.parseLong(metadataValue.substring(1)));
    } else if (metadataValue.charAt(0) == MILLIS_TIME_ID) {
      return new MillisTime(Long.parseLong(metadataValue.substring(1)));
    }

    throw new IllegalArgumentException("Time type unknown : " + metadataValue);

  }

  public static String maxMetadataTime(String mv1, String mv2) {
    if (mv1 == null && mv2 == null) {
      return null;
    }

    if (mv1 == null) {
      checkType(mv2);
      return mv2;
    }

    if (mv2 == null) {
      checkType(mv1);
      return mv1;
    }

    if (mv1.charAt(0) != mv2.charAt(0))
      throw new IllegalArgumentException("Time types differ " + mv1 + " " + mv2);
    checkType(mv1);

    long t1 = Long.parseLong(mv1.substring(1));
    long t2 = Long.parseLong(mv2.substring(1));

    if (t1 < t2)
      return mv2;
    else
      return mv1;

  }

  private static void checkType(String mv1) {
    if (mv1.charAt(0) != LOGICAL_TIME_ID && mv1.charAt(0) != MILLIS_TIME_ID)
      throw new IllegalArgumentException("Invalid time type " + mv1);
  }

  static class MillisTime extends TabletTime {

    private long lastTime;
    private long lastUpdateTime = 0;

    public MillisTime(long time) {
      this.lastTime = time;
    }

    @Override
    public String getMetadataValue(long time) {
      return MILLIS_TIME_ID + "" + time;
    }

    @Override
    public String getMetadataValue() {
      return getMetadataValue(lastTime);
    }

    @Override
    public void useMaxTimeFromWALog(long time) {
      if (time > lastTime)
        lastTime = time;
    }

    @Override
    public long setUpdateTimes(List mutations) {

      long currTime = RelativeTime.currentTimeMillis();

      synchronized (this) {
        if (mutations.size() == 0)
          return lastTime;

        currTime = updateTime(currTime);
      }

      for (Mutation mutation : mutations)
        setSystemTimes(mutation, currTime);

      return currTime;
    }

    private long updateTime(long currTime) {
      if (currTime < lastTime) {
        if (currTime - lastUpdateTime > 0) {
          // not in same millisecond as last call
          // to this method so move ahead slowly
          lastTime++;
        }

        lastUpdateTime = currTime;

        currTime = lastTime;
      } else {
        lastTime = currTime;
      }
      return currTime;
    }

    @Override
    public long getTime() {
      return lastTime;
    }

    @Override
    public long getAndUpdateTime() {
      long currTime = RelativeTime.currentTimeMillis();

      synchronized (this) {
        currTime = updateTime(currTime);
      }

      return currTime;
    }

  }

  static class LogicalTime extends TabletTime {
    AtomicLong nextTime;

    private LogicalTime(Long time) {
      this.nextTime = new AtomicLong(time.longValue() + 1);
    }

    @Override
    public void useMaxTimeFromWALog(long time) {
      time++;

      if (this.nextTime.get() < time) {
        this.nextTime.set(time);
      }
    }

    @Override
    public String getMetadataValue() {
      return getMetadataValue(getTime());
    }

    @Override
    public String getMetadataValue(long time) {
      return LOGICAL_TIME_ID + "" + time;
    }

    @Override
    public long setUpdateTimes(List mutations) {
      if (mutations.size() == 0)
        return getTime();

      long time = nextTime.getAndAdd(mutations.size());
      for (Mutation mutation : mutations)
        setSystemTimes(mutation, time++);

      return time - 1;
    }

    @Override
    public long getTime() {
      return nextTime.get() - 1;
    }

    @Override
    public long getAndUpdateTime() {
      return nextTime.getAndIncrement();
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy