case GET_FILE_NAME_ACTION:
return privGetFileName( actionIdentity, actionStub, actionErrorOK, actionTryAlternatePath);
case CREATE_CONTAINER_ACTION:
{
StorageFile file = privGetFileName( actionIdentity, false, false, false);
try {
if (file.exists()) {
// note I'm left in the no-identity state as fillInIdentity()
// hasn't been called.
throw StandardException.newException( SQLState.FILE_EXISTS, file);
}
} catch (SecurityException se) {
throw StandardException.newException( SQLState.FILE_CREATE, se, file);
}
try {
// OK not to force WAL here, in fact, this operation preceeds the
// creation of the log record to ensure sufficient space.
dataFactory.writeInProgress();
try
{
fileData = file.getRandomAccessFile( "rw");
}
finally
{
dataFactory.writeFinished();
}
// This container format specifies that the first page is an
// allocation page and the container information is stored within
// it. The allocation page needs to be somewhat formatted
// because if the system crashed after the create container log
// operation is written, it needs to be well formed enough to get
// the container information back out of it.
//
// Don't try to go thru the page cache here because the container
// object cannot be found in the container cache at this point
// yet. However, if we use the page cache to store the first
// allocation page, then in order to write itself out, it needs to
// ask the container to do so, which is going to create a
// deadlock. The allocation page cannot write itself out without
// going thru the container because it doesn't know where its
// offset is. Here we effectively hardwired page 0 at offset 0 of
// the container file to be the first allocation page.
// create an embryonic page - if this is not a temporary container,
// synchronously write out the file header.
writeRAFHeader(fileData, true,
(actionIdentity.getSegmentId() != ContainerHandle.TEMPORARY_SEGMENT));
} catch (SecurityException se) {
// only thrown by the RandomeAccessFile constructor,
// so the file won't exist
throw StandardException.newException( SQLState.FILE_CREATE, se, file);
} catch (IOException ioe) {
boolean fileDeleted;
try {
fileDeleted = privRemoveFile(file);
} catch (SecurityException se) {
throw StandardException.newException( SQLState.FILE_CREATE_NO_CLEANUP, ioe, file, se.toString());
}
if (!fileDeleted) {
throw StandardException.newException( SQLState.FILE_CREATE_NO_CLEANUP, ioe, file, ioe.toString());
}
throw StandardException.newException( SQLState.FILE_CREATE, ioe, file);
}
canUpdate = true;
return null;
} // end of case CREATE_CONTAINER_ACTION
case REMOVE_FILE_ACTION:
return privRemoveFile( actionFile) ? this : null;
case OPEN_CONTAINER_ACTION:
{
boolean isStub = false; // is this a stub?
StorageFile file = privGetFileName( actionIdentity, false, true, true);
if (file == null)
return null;
try {
if (!file.exists()) {
// file does not exist, may be it has been stubbified
file = privGetFileName( actionIdentity, true, true, true);
if (!file.exists())
return null;
isStub = true;
}
} catch (SecurityException se) {
throw StandardException.newException(
SQLState.DATA_UNEXPECTED_EXCEPTION, se);
}
canUpdate = false;
try {
if (!dataFactory.isReadOnly() && file.canWrite())
canUpdate = true;
} catch (SecurityException se) {
// just means we can't write to it.
}
try {
fileData = file.getRandomAccessFile(canUpdate ? "rw" : "r");
fileData.seek(FIRST_ALLOC_PAGE_OFFSET);
readHeader(fileData);
if (SanityManager.DEBUG)
{
if (isStub)
SanityManager.ASSERT(getDroppedState() && getCommittedDropState(),
"a stub failed to set drop state");
}
} catch (IOException ioe) {
if (isStub)
{
throw dataFactory.
markCorrupt(StandardException.
newException(SQLState.
FILE_CONTAINER_EXCEPTION,
ioe, this));
}
// maybe it is being stubbified... try that
StorageFile stub =
privGetFileName(actionIdentity, true, true, true);
if (stub.exists())
{
try
{
boolean delete_status = privRemoveFile(file);
if (SanityManager.DEBUG)
{
if (!delete_status)
{
SanityManager.THROWASSERT(
"delete of file (" + file + ") failed.");
}
}
fileData =
stub.getRandomAccessFile(canUpdate ? "rw" : "r");
readHeader(fileData);
}
catch (IOException ioe2)
{
throw dataFactory.
markCorrupt(StandardException.
newException(SQLState.
FILE_CONTAINER_EXCEPTION,
ioe2, this));
}
// RESOLVE: this is a temporary hack
}
else
throw dataFactory.
markCorrupt(StandardException.
newException(SQLState.
FILE_CONTAINER_EXCEPTION,
ioe, this));
}
return this;
} // end of case OPEN_CONTAINER_ACTION
case STUBBIFY_ACTION:
{
StorageFile file = privGetFileName( actionIdentity, false, false, true);
StorageFile stub = privGetFileName( actionIdentity, true, false, false);
StorageRandomAccessFile stubData = null;
try
{
// !!!!!
// bumpContainerVersion();
//
// do NOT bump the container version. We WANT the stubbify
// operation to get redone every time. This is because this
// operation first writes out the stub and then remove the
// container file. If we bump the version, then the stub will
// contain the new version. And if the system crashes right then,
// then we will skip the whole operation during redo even though
// the container file may not have been removed. Since we don't
// want to have the remove happen before the stub is written, we
// cannot sync it and therefore cannot be sure the remove
// happened before the system crashed.
if (!stub.exists())
{
// write the header to the stub
stubData = stub.getRandomAccessFile( "rw");
writeRAFHeader(stubData,
true, /* create */
true); /* sync */
stubData.close();
stubData = null;
}
// Force WAL and check for database corruption before removing file.
// This is one operation where the container is changed on disk
// directly without going thru the container cache, which otherwise
// would have force WAL. Take care of it here.
dataFactory.flush(actionInstant);
// try to remove the container file
// fileDate is not null only if we are redoing a removeContainer
// (stubbify) operation. Then fileData acutally is opened against
// the stub and the original container file does not exist.
// Then we need to close it here because this method is called by
// cache.remove and nobody will be able to see fileData after this.
privRemoveFile(file);
}
catch (SecurityException se)
{
throw StandardException.
newException(SQLState.FILE_CANNOT_REMOVE_FILE, se, file,
se.toString());
}
catch (IOException ioe)
{
// exception thrown while in creating the stub. Remove the
// (half-baked) stub
try
{
if (stubData != null)
{
stubData.close();
stub.delete();
stubData = null;
}
if (fileData != null)
{