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

org.apache.iceberg.ksyun.ks3.Ks3LockManager Maven / Gradle / Ivy

The newest version!
/*
 * 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 org.apache.iceberg.ksyun.ks3;


import com.ksyun.ks3.dto.HeadObjectResult;
import com.ksyun.ks3.dto.ObjectMetadata;
import com.ksyun.ks3.exception.Ks3ClientException;
import com.ksyun.ks3.exception.serviceside.CallbackTimeoutException;
import com.ksyun.ks3.exception.serviceside.NoSuchKeyException;
import com.ksyun.ks3.exception.serviceside.RequestTimeoutException;
import com.ksyun.ks3.service.Ks3;
import com.ksyun.ks3.service.request.HeadObjectRequest;
import org.apache.iceberg.CatalogProperties;
import org.apache.iceberg.ksyun.KsyunClientFactories;
import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
import org.apache.iceberg.relocated.com.google.common.collect.Maps;
import org.apache.iceberg.util.LockManagers;
import org.apache.iceberg.util.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class Ks3LockManager extends LockManagers.BaseLockManager {

  private static final Logger LOG = LoggerFactory.getLogger(Ks3LockManager.class);

  private static final Map LOCKS = Maps.newConcurrentMap();
  private static final Map> HEARTBEATS = Maps.newHashMap();

  private Ks3 client;
  private String bucket;

  private static final int RELEASE_RETRY_ATTEMPTS_MAX = 5;

  @Override
  public void initialize(Map properties) {
    super.initialize(properties);
    this.client = KsyunClientFactories.from(properties).ks3Client();
    //TODO
    this.bucket = properties.get("ks3.bucket");
  }

  @Override
  public boolean acquire(String entityId, String ownerId) {
    try {
//      System.out.println("-------- acquire  lock  entityId: " + entityId + "  ownerId: " + ownerId);
      Tasks.foreach(entityId)
              .retry(Integer.MAX_VALUE - 1)
              // TODO need other exception?
              .onlyRetryOn(IllegalStateException.class)
              .throwFailureWhenFinished()
              .exponentialBackoff(acquireIntervalMs(), acquireIntervalMs(), acquireTimeoutMs(), 1)
              .run(id -> acquireOnce(id, ownerId));
      return true;
    }catch (Ks3ClientException se) {
      return false;
    }
  }

  /**
   *      1、查 entityId 是否存在
   *      2、不存在 -》 put if absent   存在 -> sleep 一会再put
   *      3、设置锁时间
   */
  void acquireOnce(String entityId, String ownerId) {
    //TODO add expire time
//    try {
//      HeadObjectResult headObjectResult = client.headObject(bucket,entityId);
//      Date lastDate = headObjectResult.getObjectMetadata().getLastModified();
//    }catch (Ks3ClientException e){
//    }
    ObjectMetadata metadata = new ObjectMetadata();
    metadata.setUserMeta("ownerId", ownerId);
    metadata.setHeader("x-kss-forbid-overwrite", true);
    try {
      client.putObject(bucket, entityId, new ByteArrayInputStream(new byte[0]), metadata);
    } catch (Ks3ClientException e) {
      throw new IllegalStateException("Unable to acquire lock " + entityId);
    }
  }



  @Override
  public boolean release(String entityId, String ownerId) {
    try {
      client.deleteObject(bucket, entityId);
    }catch (NoSuchKeyException e){
      return true;
    }catch (Ks3ClientException e){
      LOG.error("Unable to release lock {}" , entityId, e);
      return false;
    }
    return true;
  }

  @Override
  public void close() throws Exception {

  }

  private static class Ks3LockContent {
    private final String ownerId;
    private final long expireMs;

    Ks3LockContent(String ownerId, long expireMs) {
      this.ownerId = ownerId;
      this.expireMs = expireMs;
    }

    public long expireMs() {
      return expireMs;
    }

    public String ownerId() {
      return ownerId;
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy