use of org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal in project ignite by apache.
the class GridCacheAtomicSequenceImpl method internalUpdate.
/**
* Method returns callable for execution all update operations in async and sync mode.
*
* @param l Value will be added to sequence.
* @param updated If {@code true}, will return updated value, if {@code false}, will return previous value.
* @return Callable for execution in async and sync mode.
*/
@SuppressWarnings("TooBroadScope")
private Callable<Long> internalUpdate(final long l, final boolean updated) {
return new Callable<Long>() {
@Override
public Long call() throws Exception {
assert distUpdateFreeTop.isHeldByCurrentThread() || distUpdateLockedTop.isHeldByCurrentThread();
try (GridNearTxLocal tx = CU.txStartInternal(ctx, cacheView, PESSIMISTIC, REPEATABLE_READ)) {
GridCacheAtomicSequenceValue seq = cacheView.get(key);
checkRemoved();
assert seq != null;
long curLocVal;
long newUpBound;
// Even though we hold a transaction lock here, we must hold the local update lock here as well
// because we mutate multipe variables (locVal and upBound).
localUpdate.lock();
try {
curLocVal = locVal;
// If local range was already reserved in another thread.
if (curLocVal + l <= upBound) {
locVal = curLocVal + l;
return updated ? curLocVal + l : curLocVal;
}
long curGlobalVal = seq.get();
long newLocVal;
/* We should use offset because we already reserved left side of range.*/
long off = batchSize > 1 ? batchSize - 1 : 1;
// Calculate new values for local counter, global counter and upper bound.
if (curLocVal + l >= curGlobalVal) {
newLocVal = curLocVal + l;
newUpBound = newLocVal + off;
} else {
newLocVal = curGlobalVal;
newUpBound = newLocVal + off;
}
locVal = newLocVal;
upBound = newUpBound;
if (updated)
curLocVal = newLocVal;
} finally {
localUpdate.unlock();
}
// Global counter must be more than reserved upper bound.
seq.set(newUpBound + 1);
cacheView.put(key, seq);
tx.commit();
return curLocVal;
} catch (Error | Exception e) {
U.error(log, "Failed to get and add: " + this, e);
throw e;
}
}
};
}
use of org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal in project ignite by apache.
the class IgfsMetaManager method reserveSpace.
/**
* Reserve space for file.
*
* @param fileId File ID.
* @param space Space.
* @param affRange Affinity range.
* @return New file info.
*/
public IgfsEntryInfo reserveSpace(IgniteUuid fileId, long space, IgfsFileAffinityRange affRange) throws IgniteCheckedException {
validTxState(false);
if (busyLock.enterBusy()) {
try {
if (log.isDebugEnabled())
log.debug("Reserve file space: " + fileId);
try (GridNearTxLocal tx = startTx()) {
// Lock file ID for this transaction.
IgfsEntryInfo oldInfo = info(fileId);
if (oldInfo == null)
throw fsException("File has been deleted concurrently: " + fileId);
IgfsEntryInfo newInfo = invokeAndGet(fileId, new IgfsMetaFileReserveSpaceProcessor(space, affRange));
tx.commit();
return newInfo;
} catch (GridClosureException e) {
throw U.cast(e);
}
} finally {
busyLock.leaveBusy();
}
} else
throw new IllegalStateException("Failed to reserve file space because Grid is stopping:" + fileId);
}
use of org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal in project ignite by apache.
the class IgfsMetaManager method delete.
/**
* Remove listing entries of the given parent.
* This operation actually deletes directories from TRASH, is used solely by IgfsDeleteWorker.
*
* @param parentId Parent ID.
* @param listing Listing entries.
* @return Collection of really deleted entries.
* @throws IgniteCheckedException If failed.
*/
Collection<IgniteUuid> delete(IgniteUuid parentId, Map<String, IgfsListingEntry> listing) throws IgniteCheckedException {
if (busyLock.enterBusy()) {
try {
assert parentId != null;
assert listing != null;
validTxState(false);
try (GridNearTxLocal tx = startTx()) {
Collection<IgniteUuid> res = new HashSet<>();
// Obtain all necessary locks in one hop.
IgniteUuid[] allIds = new IgniteUuid[listing.size() + 1];
allIds[0] = parentId;
int i = 1;
for (IgfsListingEntry childEntry : listing.values()) allIds[i++] = childEntry.fileId();
Map<IgniteUuid, IgfsEntryInfo> locks = lockIds(allIds);
IgfsEntryInfo parentInfo = locks.get(parentId);
// Ensure parent is still in place.
if (parentInfo != null) {
Map<String, IgfsListingEntry> parentListing = parentInfo.listing();
Map<String, IgfsListingEntry> newListing = new HashMap<>(parentListing.size(), 1.0f);
newListing.putAll(parentListing);
// Remove child entries if possible.
for (Map.Entry<String, IgfsListingEntry> entry : listing.entrySet()) {
String childName = entry.getKey();
IgniteUuid childId = entry.getValue().fileId();
IgfsEntryInfo entryInfo = locks.get(childId);
if (entryInfo != null) {
// File must be locked for deletion:
assert entryInfo.isDirectory() || IgfsUtils.DELETE_LOCK_ID.equals(entryInfo.lockId());
// Delete only files or empty folders.
if (!entryInfo.hasChildren()) {
id2InfoPrj.remove(childId);
newListing.remove(childName);
res.add(childId);
}
} else {
// Entry was deleted concurrently.
newListing.remove(childName);
res.add(childId);
}
}
// Update parent listing.
id2InfoPrj.put(parentId, parentInfo.listing(newListing));
}
tx.commit();
return res;
}
} finally {
busyLock.leaveBusy();
}
} else
throw new IllegalStateException("Failed to perform delete because Grid is stopping [parentId=" + parentId + ", listing=" + listing + ']');
}
use of org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal in project ignite by apache.
the class IgfsMetaManager method move.
/**
* Move routine.
*
* @param srcPath Source path.
* @param dstPath Destination path.
* @throws IgniteCheckedException In case of exception.
*/
public void move(IgfsPath srcPath, IgfsPath dstPath) throws IgniteCheckedException {
if (busyLock.enterBusy()) {
try {
validTxState(false);
// Prepare path IDs.
IgfsPathIds srcPathIds = pathIds(srcPath);
IgfsPathIds dstPathIds = pathIds(dstPath);
// Source path must exists.
if (!srcPathIds.allExists())
throw new IgfsPathNotFoundException("Failed to perform move because source path is not " + "found: " + srcPath);
// At this point we need to understand name of resulting entry. It will be either destination leaf
// or source leaf depending on existence.
String dstName;
if (dstPathIds.lastExists())
// Full destination path exists -> use source name.
dstName = srcPathIds.lastPart();
else {
if (dstPathIds.lastParentExists()) {
// Destination path doesn't exists -> use destination name.
dstName = dstPathIds.lastPart();
dstPathIds = dstPathIds.parent();
} else
// Destination parent is not found either -> exception.
throw new IgfsPathNotFoundException("Failed to perform move because destination path is not " + "found: " + dstPath.parent());
}
// Lock participating IDs.
final Set<IgniteUuid> lockIds = new TreeSet<>(PATH_ID_SORTING_COMPARATOR);
srcPathIds.addExistingIds(lockIds, relaxed);
dstPathIds.addExistingIds(lockIds, relaxed);
try (GridNearTxLocal tx = startTx()) {
// Obtain the locks.
final Map<IgniteUuid, IgfsEntryInfo> lockInfos = lockIds(lockIds);
// Verify integrity of source and destination paths.
if (!srcPathIds.verifyIntegrity(lockInfos, relaxed))
throw new IgfsPathNotFoundException("Failed to perform move because source directory " + "structure changed concurrently [src=" + srcPath + ", dst=" + dstPath + ']');
if (!dstPathIds.verifyIntegrity(lockInfos, relaxed))
throw new IgfsPathNotFoundException("Failed to perform move because destination directory " + "structure changed concurrently [src=" + srcPath + ", dst=" + dstPath + ']');
// Addiional check: is destination directory?
IgfsEntryInfo dstParentInfo = lockInfos.get(dstPathIds.lastId());
if (dstParentInfo.isFile())
throw new IgfsPathAlreadyExistsException("Failed to perform move because destination points " + "to existing file [src=" + srcPath + ", dst=" + dstPath + ']');
// Additional check: does destination already has child with the same name?
if (dstParentInfo.hasChild(dstName))
throw new IgfsPathAlreadyExistsException("Failed to perform move because destination already " + "contains entry with the same name existing file [src=" + srcPath + ", dst=" + dstPath + ']');
// Actual move: remove from source parent and add to destination target.
IgfsEntryInfo srcParentInfo = lockInfos.get(srcPathIds.lastParentId());
IgfsEntryInfo srcInfo = lockInfos.get(srcPathIds.lastId());
String srcName = srcPathIds.lastPart();
IgfsListingEntry srcEntry = srcParentInfo.listing().get(srcName);
transferEntry(srcEntry, srcParentInfo.id(), srcName, dstParentInfo.id(), dstName);
tx.commit();
// Fire events.
IgfsPath newPath = new IgfsPath(dstPathIds.path(), dstName);
IgfsUtils.sendEvents(igfsCtx.kernalContext(), srcPath, newPath, srcInfo.isFile() ? EVT_IGFS_FILE_RENAMED : EVT_IGFS_DIR_RENAMED);
}
} finally {
busyLock.leaveBusy();
}
} else
throw new IllegalStateException("Failed to perform move because Grid is stopping [srcPath=" + srcPath + ", dstPath=" + dstPath + ']');
}
use of org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal in project ignite by apache.
the class IgfsMetaManager method delete.
/**
* Remove entry from the metadata listing.
* Used solely by IgfsDeleteWorker.
*
* @param parentId Parent ID.
* @param name Name.
* @param id ID.
* @return {@code True} in case the entry really was removed from the cache by this call.
* @throws IgniteCheckedException If failed.
*/
boolean delete(IgniteUuid parentId, String name, IgniteUuid id) throws IgniteCheckedException {
if (busyLock.enterBusy()) {
try {
validTxState(false);
try (GridNearTxLocal tx = startTx()) {
Map<IgniteUuid, IgfsEntryInfo> infos = lockIds(parentId, id);
IgfsEntryInfo victim = infos.get(id);
if (victim == null)
return false;
assert victim.isDirectory() || IgfsUtils.DELETE_LOCK_ID.equals(victim.lockId()) : " isDir: " + victim.isDirectory() + ", lockId: " + victim.lockId();
// Proceed only in case both parent and child exist.
if (infos.containsKey(parentId) && infos.containsKey(id)) {
IgfsEntryInfo parentInfo = infos.get(parentId);
assert parentInfo != null;
IgfsListingEntry childEntry = parentInfo.listing().get(name);
if (childEntry != null)
id2InfoPrj.invoke(parentId, new IgfsMetaDirectoryListingRemoveProcessor(name, id));
id2InfoPrj.remove(id);
tx.commit();
return true;
}
return false;
}
} finally {
busyLock.leaveBusy();
}
} else
throw new IllegalStateException("Failed to perform delete because Grid is stopping [parentId=" + parentId + ", name=" + name + ", id=" + id + ']');
}
Aggregations