use of org.apache.ignite.internal.util.typedef.T1 in project ignite by apache.
the class IgfsMetaManager method create.
/**
* Create a file.
*
* @param path Path.
* @param dirProps Directory properties.
* @param overwrite Overwrite flag.
* @param blockSize Block size.
* @param affKey Affinity key.
* @param evictExclude Evict exclude flag.
* @param fileProps File properties.
* @param secondaryCtx Secondary file system create context.
* @return @return Operation result.
* @throws IgniteCheckedException If failed.
*/
IgfsCreateResult create(final IgfsPath path, Map<String, String> dirProps, final boolean overwrite, final int blockSize, @Nullable final IgniteUuid affKey, final boolean evictExclude, @Nullable Map<String, String> fileProps, @Nullable IgfsSecondaryFileSystemCreateContext secondaryCtx) throws IgniteCheckedException {
validTxState(false);
while (true) {
if (busyLock.enterBusy()) {
OutputStream secondaryOut = null;
try {
// Prepare path IDs.
IgfsPathIds pathIds = pathIds(path);
// Prepare lock IDs.
Set<IgniteUuid> lockIds = new TreeSet<>(PATH_ID_SORTING_COMPARATOR);
pathIds.addExistingIds(lockIds, relaxed);
pathIds.addSurrogateIds(lockIds);
// In overwrite mode we also lock ID of potential replacement as well as trash ID.
IgniteUuid overwriteId = IgniteUuid.randomUuid();
IgniteUuid trashId = IgfsUtils.randomTrashId();
if (overwrite) {
lockIds.add(overwriteId);
// Trash ID is only added if we suspect conflict.
if (pathIds.allExists())
lockIds.add(trashId);
}
// Start TX.
try (GridNearTxLocal tx = startTx()) {
Map<IgniteUuid, IgfsEntryInfo> lockInfos = lockIds(lockIds);
if (secondaryCtx != null && isRetryForSecondary(pathIds, lockInfos))
continue;
if (!pathIds.verifyIntegrity(lockInfos, relaxed))
// Directory structure changed concurrently. So we simply re-try.
continue;
if (pathIds.allExists()) {
// All participants found.
IgfsEntryInfo oldInfo = lockInfos.get(pathIds.lastId());
// Check: is it a file?
if (!oldInfo.isFile())
throw new IgfsPathIsDirectoryException("Failed to create a file: " + path);
// Check: can we overwrite it?
if (!overwrite)
throw new IgfsPathAlreadyExistsException("Failed to create a file: " + path);
// Check if file already opened for write.
if (oldInfo.lockId() != null)
throw new IgfsException("File is already opened for write: " + path);
// At this point file can be re-created safely.
// Add existing to trash listing.
IgniteUuid oldId = pathIds.lastId();
id2InfoPrj.invoke(trashId, new IgfsMetaDirectoryListingAddProcessor(IgfsUtils.composeNameForTrash(path, oldId), new IgfsListingEntry(oldInfo)));
// Replace ID in parent directory.
String name = pathIds.lastPart();
IgniteUuid parentId = pathIds.lastParentId();
id2InfoPrj.invoke(parentId, new IgfsMetaDirectoryListingReplaceProcessor(name, overwriteId));
// Create the file.
IgniteUuid newLockId = createFileLockId(false);
long newAccessTime;
long newModificationTime;
Map<String, String> newProps;
long newLen;
int newBlockSize;
if (secondaryCtx != null) {
secondaryOut = secondaryCtx.create();
newAccessTime = 0L;
newModificationTime = 0L;
newProps = null;
} else {
newAccessTime = System.currentTimeMillis();
newModificationTime = newAccessTime;
newProps = fileProps;
}
newLen = 0L;
newBlockSize = blockSize;
IgfsEntryInfo newInfo = invokeAndGet(overwriteId, new IgfsMetaFileCreateProcessor(newAccessTime, newModificationTime, newProps, newBlockSize, affKey, newLockId, evictExclude, newLen));
// Prepare result and commit.
tx.commit();
IgfsUtils.sendEvents(igfsCtx.kernalContext(), path, EventType.EVT_IGFS_FILE_OPENED_WRITE);
return new IgfsCreateResult(newInfo, secondaryOut);
} else {
// Create file and parent folders.
T1<OutputStream> secondaryOutHolder = null;
if (secondaryCtx != null)
secondaryOutHolder = new T1<>();
IgfsPathsCreateResult res;
try {
res = createFile(pathIds, lockInfos, dirProps, fileProps, blockSize, affKey, evictExclude, secondaryCtx, secondaryOutHolder);
} finally {
if (secondaryOutHolder != null)
secondaryOut = secondaryOutHolder.get();
}
if (res == null)
continue;
// Commit.
tx.commit();
// Generate events.
generateCreateEvents(res.createdPaths(), true);
return new IgfsCreateResult(res.info(), secondaryOut);
}
}
} catch (IgniteException | IgniteCheckedException e) {
U.closeQuiet(secondaryOut);
throw e;
} catch (Exception e) {
U.closeQuiet(secondaryOut);
throw new IgniteCheckedException("Create failed due to unexpected exception: " + path, e);
} finally {
busyLock.leaveBusy();
}
} else
throw new IllegalStateException("Failed to mkdir because Grid is stopping. [path=" + path + ']');
}
}
use of org.apache.ignite.internal.util.typedef.T1 in project ignite by apache.
the class CacheObjectBinaryProcessorImpl method affinityKey.
/**
* @param po Binary object.
* @return Affinity key.
*/
public Object affinityKey(BinaryObject po) {
// Fast path for already cached field.
if (po instanceof BinaryObjectEx) {
int typeId = ((BinaryObjectEx) po).typeId();
T1<BinaryField> fieldHolder = affKeyFields.get(typeId);
if (fieldHolder != null) {
BinaryField field = fieldHolder.get();
return field != null ? field.value(po) : po;
}
}
// Slow path if affinity field is not cached yet.
try {
BinaryType meta = po instanceof BinaryObjectEx ? ((BinaryObjectEx) po).rawType() : po.type();
if (meta != null) {
String name = meta.affinityKeyFieldName();
if (name != null) {
BinaryField field = meta.field(name);
affKeyFields.putIfAbsent(meta.typeId(), new T1<>(field));
return field.value(po);
} else
affKeyFields.putIfAbsent(meta.typeId(), new T1<BinaryField>(null));
} else if (po instanceof BinaryObjectEx) {
int typeId = ((BinaryObjectEx) po).typeId();
String name = binaryCtx.affinityKeyFieldName(typeId);
if (name != null)
return po.field(name);
}
} catch (BinaryObjectException e) {
U.error(log, "Failed to get affinity field from binary object: " + po, e);
}
return po;
}
use of org.apache.ignite.internal.util.typedef.T1 in project ignite by apache.
the class IgfsMetaManager method appendDual.
/**
* Append to a file in DUAL mode.
*
* @param fs File system.
* @param path Path.
* @param bufSize Buffer size.
* @param create Create flag.
* @return Output stream descriptor.
* @throws IgniteCheckedException If output stream open for append has failed.
*/
public IgfsCreateResult appendDual(final IgfsSecondaryFileSystem fs, final IgfsPath path, final int bufSize, final boolean create) throws IgniteCheckedException {
if (busyLock.enterBusy()) {
try {
assert fs != null;
assert path != null;
// Events to fire (can be done outside of a transaction).
final Deque<IgfsEvent> pendingEvts = new LinkedList<>();
SynchronizationTask<IgfsCreateResult> task = new SynchronizationTask<IgfsCreateResult>() {
/** Container for the secondary file system output stream. */
private final T1<OutputStream> outT1 = new T1<>(null);
@Override
public IgfsCreateResult onSuccess(Map<IgfsPath, IgfsEntryInfo> infos) throws Exception {
validTxState(true);
final IgfsEntryInfo info = infos.get(path);
final IgfsEntryInfo lockedInfo;
if (info == null)
return onSuccessCreate(fs, path, true, /*simpleCreate*/
null, false, /*overwrite*/
bufSize, (short) 0, 0, null, infos, pendingEvts, outT1);
else {
if (info.isDirectory())
throw fsException("Failed to open output stream to the file in the " + "secondary file system because the path points to a directory: " + path);
outT1.set(fs.append(path, bufSize, false, null));
// Synchronize file ending.
long len = info.length();
int blockSize = info.blockSize();
int remainder = (int) (len % blockSize);
if (remainder > 0) {
int blockIdx = (int) (len / blockSize);
try (IgfsSecondaryFileSystemPositionedReadable reader = fs.open(path, bufSize)) {
IgniteInternalFuture<byte[]> fut = igfsCtx.data().dataBlock(info, path, blockIdx, reader);
assert fut != null;
fut.get();
}
}
if (info.lockId() != null) {
throw fsException("Failed to open file (file is opened for writing) [path=" + path + ", fileId=" + info.id() + ", lockId=" + info.lockId() + ']');
}
// Set lock and return.
lockedInfo = invokeLock(info.id(), false);
}
if (evts.isRecordable(EventType.EVT_IGFS_FILE_OPENED_WRITE))
pendingEvts.add(new IgfsEvent(path, locNode, EventType.EVT_IGFS_FILE_OPENED_WRITE));
return new IgfsCreateResult(lockedInfo, outT1.get());
}
@Override
public IgfsCreateResult onFailure(@Nullable Exception err) throws IgniteCheckedException {
U.closeQuiet(outT1.get());
U.error(log, "File append in DUAL mode failed [path=" + path + ", bufferSize=" + bufSize + ']', err);
throw new IgniteCheckedException("Failed to append to the file due to secondary file " + "system exception: " + path, err);
}
};
try {
return synchronizeAndExecute(task, fs, !create, /*strict*/
path);
} finally {
for (IgfsEvent evt : pendingEvts) evts.record(evt);
}
} finally {
busyLock.leaveBusy();
}
} else
throw new IllegalStateException("Failed to append to file in DUAL mode because Grid is stopping: " + path);
}
Aggregations