/**
* personium.io
* Copyright 2014 FUJITSU LIMITED
*
* 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 com.fujitsu.dc.core.model.lock;
import java.util.Date;
import com.fujitsu.dc.core.DcCoreConfig;
import com.fujitsu.dc.core.DcCoreException;
import com.fujitsu.dc.core.utils.MemcachedClient;
import com.fujitsu.dc.core.utils.MemcachedClient.MemcachedClientException;
/**
* Lockを管理するユーティリティ.
*/
public abstract class LockManager {
static volatile LockManager singleton;
static volatile String lockType = DcCoreConfig.getLockType();
static volatile long lockRetryInterval = Long.valueOf(DcCoreConfig.getLockRetryInterval());
static volatile int lockRetryTimes = Integer.valueOf(DcCoreConfig.getLockRetryTimes());
static volatile String lockMemcachedHost = DcCoreConfig.getLockMemcachedHost();
static volatile String lockMemcachedPort = DcCoreConfig.getLockMemcachedPort();
static volatile int accountLockLifeTime = Integer.valueOf(DcCoreConfig.getAccountLockLifetime());
/**
* Memcached タイプ.
*/
public static final String TYPE_MEMCACHED = "memcached";
/**
* InProcess タイプ.
*/
public static final String TYPE_IN_PROCESS = "inProcess";
abstract Lock doGetLock(String fullKey);
abstract Boolean doPutLock(String fullKey, Lock lock);
abstract void doReleaseLock(String fullKey);
abstract void doDeleteAllLocks();
abstract String doGetReferenceOnlyLock(String fullKey);
abstract Boolean doPutReferenceOnlyLock(String fullKey, String value);
abstract String doGetAccountLock(String fullKey);
abstract Boolean doPutAccountLock(String fullKey, String value, int expired);
abstract String doGetUnituserLock(String fullKey);
abstract Boolean doPutUnituserLock(String fullKey, String value, int expired);
abstract long doGetReferenceCount(String fullKey);
abstract long doIncrementReferenceCount(String fullKey);
abstract long doDecrementReferenceCount(String fullKey);
abstract long doGetCellStatus(String fullKey);
abstract Boolean doSetCellStatus(String fullKey, long status);
abstract void doDeleteCellStatus(String fullKey);
abstract String doGetReadDeleteOnlyMode(String fullKey);
static {
if (TYPE_MEMCACHED.equals(lockType)) {
singleton = new MemcachedLockManager();
} else if (TYPE_IN_PROCESS.equals(lockType)) {
singleton = new InProcessLockManager();
}
}
/**
* ロックを取得します.
* @param category ロックのカテゴリ
* @param cellId CellのID
* @param boxId BoxのID
* @param nodeId NodeのID
* @return Lock
*/
public static Lock getLock(String category, String cellId, String boxId, String nodeId) {
Long createdAt = (new Date()).getTime();
// memcached にキーが存在するか調べる
// なければmemcached に書きに行く
// あったら、リトライする。
int timesRetry = 0;
while (timesRetry <= lockRetryTimes) {
String fullKey = LockKeyComposer.fullKeyFromCategoryAndKey(category, cellId, boxId, nodeId);
Lock lock = null;
try {
lock = singleton.doGetLock(fullKey);
} catch (MemcachedClientException e) {
MemcachedClient.reportError();
throw DcCoreException.Server.GET_LOCK_STATE_ERROR;
}
if (lock == null) {
lock = new Lock(fullKey, createdAt);
Boolean success = singleton.doPutLock(fullKey, lock);
if (success) {
return lock;
}
}
try {
Thread.sleep(lockRetryInterval);
} catch (InterruptedException e) {
throw DcCoreException.Server.DATA_STORE_UNKNOWN_ERROR.reason(e);
}
timesRetry++;
}
throw DcCoreException.Misc.TOO_MANY_CONCURRENT_REQUESTS;
}
/*
* ロックのリリース処理
*/
static void releaseLock(String fullKey) {
singleton.doReleaseLock(fullKey);
}
/**
* ロックをすべて消します.
*/
public static void deleteAllLocks() {
singleton.doDeleteAllLocks();
}
/**
* @return the lockType
*/
public static final String getLockType() {
return lockType;
}
/**
* @param lockType the lockType to set
*/
public static final void setLockType(String lockType) {
LockManager.lockType = lockType;
}
/**
* @return the lockRetryInterval
*/
public static final long getLockRetryInterval() {
return lockRetryInterval;
}
/**
* @param lockRetryInterval the lockRetryInterval to set
*/
public static final void setLockRetryInterval(long lockRetryInterval) {
LockManager.lockRetryInterval = lockRetryInterval;
}
/**
* @return the lockRetryTimes
*/
public static final int getLockRetryTimes() {
return lockRetryTimes;
}
/**
* @param lockRetryTimes the lockRetryTimes to set
*/
public static final void setLockRetryTimes(int lockRetryTimes) {
LockManager.lockRetryTimes = lockRetryTimes;
}
/**
* @return the lockMemcachedHost
*/
public static final String getLockMemcachedHost() {
return lockMemcachedHost;
}
/**
* @param lockMemcachedHost the lockMemcachedHost to set
*/
public static final void setLockMemcachedHost(String lockMemcachedHost) {
LockManager.lockMemcachedHost = lockMemcachedHost;
}
/**
* @return the lockMemcachedPort
*/
public static final String getLockMemcachedPort() {
return lockMemcachedPort;
}
/**
* @param lockMemcachedPort the lockMemcachedPort to set
*/
public static final void setLockMemcachedPort(String lockMemcachedPort) {
LockManager.lockMemcachedPort = lockMemcachedPort;
}
}