use of org.apache.jackrabbit.core.util.db.StreamWrapper in project jackrabbit by apache.
the class DatabaseFileSystem method getOutputStream.
/**
* {@inheritDoc}
*/
public OutputStream getOutputStream(final String filePath) throws FileSystemException {
if (!initialized) {
throw new IllegalStateException("not initialized");
}
FileSystemPathUtil.checkFormat(filePath);
final String parentDir = FileSystemPathUtil.getParentDir(filePath);
final String name = FileSystemPathUtil.getName(filePath);
if (!isFolder(parentDir)) {
throw new FileSystemException("path not found: " + parentDir);
}
if (isFolder(filePath)) {
throw new FileSystemException("path denotes folder: " + filePath);
}
try {
TransientFileFactory fileFactory = TransientFileFactory.getInstance();
final File tmpFile = fileFactory.createTransientFile("bin", null, null);
return new FilterOutputStream(new FileOutputStream(tmpFile)) {
public void write(byte[] bytes, int off, int len) throws IOException {
out.write(bytes, off, len);
}
public void close() throws IOException {
out.flush();
((FileOutputStream) out).getFD().sync();
out.close();
InputStream in = null;
try {
if (isFile(filePath)) {
synchronized (updateDataSQL) {
long length = tmpFile.length();
in = new FileInputStream(tmpFile);
conHelper.exec(updateDataSQL, new Object[] { new StreamWrapper(in, length), new Long(System.currentTimeMillis()), new Long(length), parentDir, name });
}
} else {
synchronized (insertFileSQL) {
long length = tmpFile.length();
in = new FileInputStream(tmpFile);
conHelper.exec(insertFileSQL, new Object[] { parentDir, name, new StreamWrapper(in, length), new Long(System.currentTimeMillis()), new Long(length) });
}
}
} catch (Exception e) {
IOException ioe = new IOException(e.getMessage());
ioe.initCause(e);
throw ioe;
} finally {
if (in != null) {
in.close();
}
// temp file can now safely be removed
tmpFile.delete();
}
}
};
} catch (Exception e) {
String msg = "failed to open output stream to file: " + filePath;
log.error(msg, e);
throw new FileSystemException(msg, e);
}
}
use of org.apache.jackrabbit.core.util.db.StreamWrapper in project jackrabbit by apache.
the class DbDataStore method addRecord.
public DataRecord addRecord(InputStream stream) throws DataStoreException {
InputStream fileInput = null;
String tempId = null;
ResultSet rs = null;
try {
long tempModified;
while (true) {
try {
tempModified = System.currentTimeMillis();
String id = UUID.randomUUID().toString();
tempId = TEMP_PREFIX + id;
temporaryInUse.add(tempId);
// SELECT LENGTH, LAST_MODIFIED FROM DATASTORE WHERE ID=?
rs = conHelper.query(selectMetaSQL, tempId);
boolean hasNext = rs.next();
DbUtility.close(rs);
rs = null;
if (hasNext) {
// re-try in the very, very unlikely event that the row already exists
continue;
}
// INSERT INTO DATASTORE VALUES(?, 0, ?, NULL)
conHelper.exec(insertTempSQL, tempId, tempModified);
break;
} catch (Exception e) {
throw convert("Can not insert new record", e);
} finally {
DbUtility.close(rs);
// prevent that rs.close() is called again
rs = null;
}
}
MessageDigest digest = getDigest();
DigestInputStream dIn = new DigestInputStream(stream, digest);
CountingInputStream in = new CountingInputStream(dIn);
StreamWrapper wrapper;
if (STORE_SIZE_MINUS_ONE.equals(storeStream)) {
wrapper = new StreamWrapper(in, -1);
} else if (STORE_SIZE_MAX.equals(storeStream)) {
wrapper = new StreamWrapper(in, Integer.MAX_VALUE);
} else if (STORE_TEMP_FILE.equals(storeStream)) {
File temp = moveToTempFile(in);
long length = temp.length();
wrapper = new StreamWrapper(new ResettableTempFileInputStream(temp), length);
} else {
throw new DataStoreException("Unsupported stream store algorithm: " + storeStream);
}
// UPDATE DATASTORE SET DATA=? WHERE ID=?
conHelper.exec(updateDataSQL, wrapper, tempId);
long length = in.getByteCount();
DataIdentifier identifier = new DataIdentifier(encodeHexString(digest.digest()));
usesIdentifier(identifier);
String id = identifier.toString();
long newModified;
while (true) {
newModified = System.currentTimeMillis();
if (checkExisting(tempId, length, identifier)) {
touch(identifier, newModified);
conHelper.exec(deleteSQL, tempId);
break;
}
try {
// UPDATE DATASTORE SET ID=?, LENGTH=?, LAST_MODIFIED=?
// WHERE ID=? AND LAST_MODIFIED=?
int count = conHelper.update(updateSQL, id, length, newModified, tempId, tempModified);
// collection could delete rows)
if (count != 0) {
// update was successful
break;
}
} catch (SQLException e) {
// duplicate key (the row already exists) - repeat
// we use exception handling for flow control here, which is bad,
// but the alternative is to use UPDATE ... WHERE ... (SELECT ...)
// which could cause a deadlock in some databases - also,
// duplicate key will only occur if somebody else concurrently
// added the same record (which is very unlikely)
}
// SELECT LENGTH, LAST_MODIFIED FROM DATASTORE WHERE ID=?
rs = conHelper.query(selectMetaSQL, tempId);
if (!rs.next()) {
// the row was deleted, which is unexpected / not allowed
String msg = DIGEST + " temporary entry deleted: " + " id=" + tempId + " length=" + length;
log.error(msg);
throw new DataStoreException(msg);
}
tempModified = rs.getLong(2);
DbUtility.close(rs);
rs = null;
}
usesIdentifier(identifier);
DbDataRecord record = new DbDataRecord(this, identifier, length, newModified);
return record;
} catch (Exception e) {
throw convert("Can not insert new record", e);
} finally {
if (tempId != null) {
temporaryInUse.remove(tempId);
}
DbUtility.close(rs);
if (fileInput != null) {
try {
fileInput.close();
} catch (IOException e) {
throw convert("Can not close temporary file", e);
}
}
}
}
Aggregations