use of com.cloud.framework.async.AsyncCallFuture in project cosmic by MissionCriticalCloud.
the class StorageCacheManagerImpl method createCacheObject.
@Override
public DataObject createCacheObject(final DataObject data, final DataStore store) {
DataObject objOnCacheStore = null;
final Object lock;
final DataObjectType type = data.getType();
final String typeName;
final long storeId = store.getId();
final long dataId = data.getId();
/*
* Make sure any thread knows own lock type.
*/
if (type == DataObjectType.TEMPLATE) {
lock = templateLock;
typeName = "template";
} else if (type == DataObjectType.VOLUME) {
lock = volumeLock;
typeName = "volume";
} else if (type == DataObjectType.SNAPSHOT) {
lock = snapshotLock;
typeName = "snapshot";
} else {
final String msg = "unsupported DataObject comes, then can't acquire correct lock object";
throw new CloudRuntimeException(msg);
}
s_logger.debug("check " + typeName + " cache entry(id: " + dataId + ") on store(id: " + storeId + ")");
DataObject existingDataObj = null;
synchronized (lock) {
DataObjectInStore obj = objectInStoreMgr.findObject(data, store);
if (obj != null) {
State st = obj.getState();
final long miliSeconds = 10000;
final long timeoutSeconds = 3600;
final long timeoutMiliSeconds = timeoutSeconds * 1000;
Date now = new Date();
final long expiredEpoch = now.getTime() + timeoutMiliSeconds;
final Date expiredDate = new Date(expiredEpoch);
/*
* Waiting for completion of cache copy.
*/
while (st == ObjectInDataStoreStateMachine.State.Allocated || st == ObjectInDataStoreStateMachine.State.Creating || st == ObjectInDataStoreStateMachine.State.Copying) {
/*
* Threads must release lock within waiting for cache copy and
* must be waken up at completion.
*/
s_logger.debug("waiting cache copy completion type: " + typeName + ", id: " + obj.getObjectId() + ", lock: " + lock.hashCode());
try {
lock.wait(miliSeconds);
} catch (final InterruptedException e) {
s_logger.debug("[ignored] interupted while waiting for cache copy completion.");
}
s_logger.debug("waken up");
now = new Date();
if (now.after(expiredDate)) {
final String msg = "Waiting time exceeds timeout limit(" + timeoutSeconds + " s)";
throw new CloudRuntimeException(msg);
}
obj = objectInStoreMgr.findObject(data, store);
st = obj.getState();
}
if (st == ObjectInDataStoreStateMachine.State.Ready) {
s_logger.debug("there is already one in the cache store");
final DataObject dataObj = objectInStoreMgr.get(data, store);
dataObj.incRefCount();
existingDataObj = dataObj;
}
}
if (existingDataObj == null) {
s_logger.debug("create " + typeName + " cache entry(id: " + dataId + ") on store(id: " + storeId + ")");
objOnCacheStore = store.create(data);
}
lock.notifyAll();
}
if (existingDataObj != null) {
return existingDataObj;
}
if (objOnCacheStore == null) {
s_logger.error("create " + typeName + " cache entry(id: " + dataId + ") on store(id: " + storeId + ") failed");
return null;
}
final AsyncCallFuture<CopyCommandResult> future = new AsyncCallFuture<>();
CopyCommandResult result = null;
try {
objOnCacheStore.processEvent(Event.CreateOnlyRequested);
dataMotionSvr.copyAsync(data, objOnCacheStore, future);
result = future.get();
if (result.isFailed()) {
objOnCacheStore.processEvent(Event.OperationFailed);
} else {
objOnCacheStore.processEvent(Event.OperationSuccessed, result.getAnswer());
objOnCacheStore.incRefCount();
return objOnCacheStore;
}
} catch (final InterruptedException e) {
s_logger.debug("create cache storage failed: " + e.toString());
throw new CloudRuntimeException(e);
} catch (final ExecutionException e) {
s_logger.debug("create cache storage failed: " + e.toString());
throw new CloudRuntimeException(e);
} finally {
if (result == null) {
objOnCacheStore.processEvent(Event.OperationFailed);
}
synchronized (lock) {
/*
* Wake up all threads waiting for cache copy.
*/
s_logger.debug("wake up all waiting threads(lock: " + lock.hashCode() + ")");
lock.notifyAll();
}
}
return null;
}
Aggregations