use of org.apache.ignite.igfs.IgfsPath in project ignite by apache.
the class IgfsUtils method preparePathModes.
/**
* Checks, filters and sorts the modes.
*
* @param dfltMode The root mode. Must always be not null.
* @param modes The subdirectory modes.
* @param dualParentsContainingPrimaryChildren The set to store parents into.
* @return Descending list of filtered and checked modes.
* @throws IgniteCheckedException On error.
*/
public static ArrayList<T2<IgfsPath, IgfsMode>> preparePathModes(final IgfsMode dfltMode, @Nullable List<T2<IgfsPath, IgfsMode>> modes, Set<IgfsPath> dualParentsContainingPrimaryChildren) throws IgniteCheckedException {
if (modes == null)
return null;
// Sort by depth, shallow first.
Collections.sort(modes, new Comparator<Map.Entry<IgfsPath, IgfsMode>>() {
@Override
public int compare(Map.Entry<IgfsPath, IgfsMode> o1, Map.Entry<IgfsPath, IgfsMode> o2) {
return o1.getKey().depth() - o2.getKey().depth();
}
});
ArrayList<T2<IgfsPath, IgfsMode>> resModes = new ArrayList<>(modes.size() + 1);
resModes.add(new T2<>(IgfsPath.ROOT, dfltMode));
for (T2<IgfsPath, IgfsMode> mode : modes) {
assert mode.getKey() != null;
for (T2<IgfsPath, IgfsMode> resMode : resModes) {
if (mode.getKey().isSubDirectoryOf(resMode.getKey())) {
assert resMode.getValue() != null;
if (resMode.getValue() == mode.getValue())
// No reason to add a sub-path of the same mode, ignore this pair.
break;
if (!canContain(resMode.getValue(), mode.getValue()))
throw new IgniteCheckedException("Subdirectory " + mode.getKey() + " mode " + mode.getValue() + " is not compatible with upper level " + resMode.getKey() + " directory mode " + resMode.getValue() + ".");
// Add to the 1st position (deep first).
resModes.add(0, mode);
// Store primary paths inside dual paths in separate collection:
if (mode.getValue() == PRIMARY)
dualParentsContainingPrimaryChildren.add(mode.getKey().parent());
break;
}
}
}
// Remove root, because this class contract is that root mode is not contained in the list.
resModes.remove(resModes.size() - 1);
return resModes;
}
use of org.apache.ignite.igfs.IgfsPath in project ignite by apache.
the class IgfsUtils method readPath.
/**
* Read IGFS path.
*
* @param reader Reader.
* @return Path.
*/
@Nullable
public static IgfsPath readPath(BinaryRawReader reader) {
if (reader.readBoolean()) {
IgfsPath path = new IgfsPath();
path.readRawBinary(reader);
return path;
} else
return null;
}
use of org.apache.ignite.igfs.IgfsPath in project ignite by apache.
the class IgfsDeleteWorker method delete.
/**
* Remove particular entry from the TRASH directory.
*
* @param trashId ID of the trash directory.
* @param name Entry name.
* @param id Entry ID.
* @return {@code True} in case the entry really was deleted form the file system by this call.
* @throws IgniteCheckedException If failed.
*/
private boolean delete(IgniteUuid trashId, String name, IgniteUuid id) throws IgniteCheckedException {
assert name != null;
assert id != null;
while (true) {
IgfsEntryInfo info = meta.info(id);
if (info != null) {
if (info.isDirectory()) {
if (!deleteDirectoryContents(trashId, id))
return false;
if (meta.delete(trashId, name, id))
return true;
} else {
assert info.isFile();
// Lock the file with special lock Id to prevent concurrent writing:
IgfsEntryInfo lockedInfo = meta.lock(id, true);
if (lockedInfo == null)
// File is locked, we cannot delete it.
return false;
assert id.equals(lockedInfo.id());
// Delete file content first.
// In case this node crashes, other node will re-delete the file.
data.delete(lockedInfo).get();
boolean ret = meta.delete(trashId, name, id);
if (ret) {
IgfsPath path = IgfsUtils.extractOriginalPathFromTrash(name);
assert path != null;
IgfsUtils.sendEvents(igfsCtx.kernalContext(), path, EVT_IGFS_FILE_PURGED);
}
return ret;
}
} else
// Entry was deleted concurrently.
return false;
}
}
use of org.apache.ignite.igfs.IgfsPath in project ignite by apache.
the class IgfsMetaManager method synchronizeAndExecute.
/**
* Synchronize file system structure and then execute provided task. All these actions are performed withing
* the transaction.
*
* @param task Task to execute.
* @param fs File system.
* @param strict Whether paths must be re-created strictly.
* @param extraLockIds Additional IDs to lock (optional).
* @param paths Paths to synchronize.
* @return Result of task execution.
* @throws IgniteCheckedException If failed.
*/
@SuppressWarnings({ "Contract", "ConstantConditions" })
private <T> T synchronizeAndExecute(SynchronizationTask<T> task, IgfsSecondaryFileSystem fs, boolean strict, @Nullable Collection<IgniteUuid> extraLockIds, IgfsPath... paths) throws IgniteCheckedException {
assert task != null;
assert fs != null;
assert paths != null && paths.length > 0;
// Sort paths so that we know in which order to synchronize them.
if (paths.length > 1)
Arrays.sort(paths);
boolean finished = false;
T res = null;
while (!finished) {
// Obtain existing IDs outside the transaction.
List<List<IgniteUuid>> pathIds = new ArrayList<>(paths.length);
for (IgfsPath path : paths) pathIds.add(idsForPath(path));
// Start pessimistic.
try (GridNearTxLocal tx = startTx()) {
// Lock the very first existing parents and possibly the leaf as well.
Map<IgfsPath, IgfsPath> pathToParent = new HashMap<>();
Map<IgfsPath, IgniteUuid> pathToId = new HashMap<>();
for (int i = 0; i < paths.length; i++) {
IgfsPath path = paths[i];
// Determine the very first existing parent
List<IgniteUuid> ids = pathIds.get(i);
if (ids.size() > 1) {
// The path is not root.
IgfsPath parentPath = path.parent();
IgniteUuid parentId = ids.get(ids.size() - 2);
for (int j = ids.size() - 3; j >= 0; j--) {
if (parentId != null)
break;
else {
parentPath = parentPath.parent();
parentId = ids.get(j);
}
}
assert parentPath != null && parentId != null;
pathToParent.put(path, parentPath);
pathToId.put(parentPath, parentId);
}
IgniteUuid pathId = ids.get(ids.size() - 1);
if (pathId != null)
pathToId.put(path, pathId);
}
IgniteUuid[] lockArr = new IgniteUuid[extraLockIds == null ? pathToId.size() : pathToId.size() + extraLockIds.size()];
int idx = 0;
for (IgniteUuid id : pathToId.values()) lockArr[idx++] = id;
if (extraLockIds != null) {
for (IgniteUuid id : extraLockIds) lockArr[idx++] = id;
}
Map<IgniteUuid, IgfsEntryInfo> idToInfo = lockIds(lockArr);
if (extraLockIds != null) {
for (IgniteUuid id : extraLockIds) idToInfo.remove(id);
}
// Ensure that locked IDs still point to expected paths.
IgfsPath changed = null;
for (Map.Entry<IgfsPath, IgniteUuid> entry : pathToId.entrySet()) {
if (!idToInfo.containsKey(entry.getValue()) || !F.eq(entry.getValue(), fileId(entry.getKey(), true))) {
changed = entry.getKey();
break;
}
}
if (changed != null) {
finished = true;
throw fsException(new IgfsConcurrentModificationException("File system entry has been " + "modified concurrently: " + changed));
} else {
boolean newParents = false;
// Check whether any new parents appeared before we have obtained the locks.
for (int i = 0; i < paths.length; i++) {
List<IgniteUuid> newIds = fileIds(paths[i], true);
if (!pathIds.get(i).equals(newIds)) {
newParents = true;
break;
}
}
if (newParents)
// Release all locks and try again.
continue;
else {
// Perform synchronization.
Map<IgfsPath, IgfsEntryInfo> infos = new HashMap<>();
TreeMap<IgfsPath, IgfsEntryInfo> created = new TreeMap<>();
for (IgfsPath path : paths) {
IgfsPath parentPath = path.parent();
if (pathToId.containsKey(path)) {
infos.put(path, info(pathToId.get(path)));
if (parentPath != null)
infos.put(parentPath, info(pathToId.get(parentPath)));
} else {
IgfsPath firstParentPath = pathToParent.get(path);
assert firstParentPath != null;
assert pathToId.get(firstParentPath) != null;
IgfsEntryInfo info = synchronize(fs, firstParentPath, idToInfo.get(pathToId.get(firstParentPath)), path, strict, created);
assert strict && info != null || !strict;
if (info != null)
infos.put(path, info);
if (parentPath != null) {
if (parentPath.equals(firstParentPath))
infos.put(firstParentPath, idToInfo.get(pathToId.get(firstParentPath)));
else {
assert strict && created.get(parentPath) != null || !strict;
if (created.get(parentPath) != null)
infos.put(parentPath, created.get(parentPath));
else {
// Put the last created path.
infos.put(created.lastKey(), created.get(created.lastKey()));
}
}
}
}
}
// Finally, execute the task.
finished = true;
try {
res = task.onSuccess(infos);
} catch (Exception e) {
res = task.onFailure(e);
}
}
}
tx.commit();
} catch (IgniteCheckedException e) {
if (!finished) {
finished = true;
res = task.onFailure(e);
} else
throw e;
}
}
return res;
}
use of org.apache.ignite.igfs.IgfsPath in project ignite by apache.
the class IgfsMetaManager method synchronize.
/**
* Synchronize directory structure with the secondary file system.
*
* @param fs Secondary file system.
* @param startPath Start path.
* @param startPathInfo Start path info.
* @param endPath End path.
* @param strict Whether all paths must exist in the secondary file system.
* @param created Optional map where data about all created values is put.
* @return File info of the end path.
* @throws IgniteCheckedException If failed.
*/
private IgfsEntryInfo synchronize(IgfsSecondaryFileSystem fs, IgfsPath startPath, IgfsEntryInfo startPathInfo, IgfsPath endPath, boolean strict, @Nullable Map<IgfsPath, IgfsEntryInfo> created) throws IgniteCheckedException {
assert fs != null;
assert startPath != null && startPathInfo != null && endPath != null;
validTxState(true);
IgfsEntryInfo parentInfo = startPathInfo;
List<String> components = endPath.components();
IgfsPath curPath = startPath;
for (int i = startPath.components().size(); i < components.size(); i++) {
curPath = new IgfsPath(curPath, components.get(i));
if (created != null && created.containsKey(curPath))
// Re-use already created info.
parentInfo = created.get(curPath);
else {
// Get file status from the secondary file system.
IgfsFile status;
try {
status = fs.info(curPath);
} catch (IgniteException e) {
throw new IgniteCheckedException("Failed to get path information: " + e, e);
}
if (status != null) {
if (!status.isDirectory() && !curPath.equals(endPath))
throw new IgniteCheckedException("Failed to create path the locally because secondary file " + "system directory structure was modified concurrently and the path is not a directory as " + "expected: " + curPath);
} else {
if (strict) {
throw new IgniteCheckedException("Failed to create path locally due to secondary file system " + "exception: " + curPath);
} else if (created != null)
created.put(curPath.parent(), parentInfo);
return null;
}
// Recreate the path locally.
IgfsEntryInfo curInfo = status.isDirectory() ? IgfsUtils.createDirectory(IgniteUuid.randomUuid(), null, status.properties(), status.accessTime(), status.modificationTime()) : IgfsUtils.createFile(IgniteUuid.randomUuid(), igfsCtx.configuration().getBlockSize(), status.length(), null, null, igfsCtx.igfs().evictExclude(curPath, false), status.properties(), status.accessTime(), status.modificationTime());
assert parentInfo != null;
IgniteUuid oldId = putIfAbsentNonTx(parentInfo.id(), components.get(i), curInfo);
if (oldId != null)
curInfo = info(oldId);
if (created != null)
created.put(curPath, curInfo);
parentInfo = curInfo;
}
}
return parentInfo;
}
Aggregations