use of org.neo4j.exceptions.UnderlyingStorageException in project neo4j by neo4j.
the class CheckPointSchedulerTest method shouldCausePanicAfterSomeFailures.
@Test
void shouldCausePanicAfterSomeFailures() throws Throwable {
// GIVEN
RuntimeException[] failures = new RuntimeException[] { new RuntimeException("First"), new RuntimeException("Second"), new RuntimeException("Third") };
when(checkPointer.checkPointIfNeeded(any(TriggerInfo.class))).thenThrow(failures);
CheckPointScheduler scheduler = new CheckPointScheduler(checkPointer, ioController, jobScheduler, 1, health, "test db");
scheduler.start();
// WHEN
for (int i = 0; i < CheckPointScheduler.MAX_CONSECUTIVE_FAILURES_TOLERANCE - 1; i++) {
jobScheduler.runJob();
verifyNoInteractions(health);
}
UnderlyingStorageException error = assertThrows(UnderlyingStorageException.class, jobScheduler::runJob);
// THEN
assertEquals(Iterators.asSet(failures), Iterators.asSet(error.getSuppressed()));
verify(health).panic(error);
}
use of org.neo4j.exceptions.UnderlyingStorageException in project neo4j by neo4j.
the class NeoStores method verifyRecordFormat.
private void verifyRecordFormat(StoreType[] storeTypes, CursorContext cursorContext) {
String expectedStoreVersion = recordFormats.storeVersion();
long existingFormat;
if (!fileSystem.fileExists(layout.metadataStore())) {
// If the meta data store doesn't even exist then look no further, there's nothing to verify
return;
}
if (contains(storeTypes, StoreType.META_DATA)) {
// We're going to open this store anyway so might as well do it here, like we open the others
MetaDataStore metaDataStore = (MetaDataStore) getOrOpenStore(StoreType.META_DATA, cursorContext);
existingFormat = metaDataStore.getRecord(STORE_VERSION.id(), metaDataStore.newRecord(), RecordLoad.CHECK, cursorContext).getValue();
} else {
// if we have createIfNotExists set, but don't have the meta data store in the list of stores to open
try {
existingFormat = MetaDataStore.getRecord(pageCache, layout.metadataStore(), STORE_VERSION, layout.getDatabaseName(), cursorContext);
} catch (NoSuchFileException e) {
// Weird that the file isn't here after we passed the exists check above. Regardless, treat this the same way as above.
return;
} catch (IOException e) {
throw new UnderlyingStorageException(e);
}
}
if (existingFormat != MetaDataRecordFormat.FIELD_NOT_PRESENT) {
String actualStoreVersion = versionLongToString(existingFormat);
RecordFormats actualStoreFormat = RecordFormatSelector.selectForVersion(actualStoreVersion);
if (!isCompatibleFormats(actualStoreFormat)) {
throw new UnexpectedStoreVersionException(actualStoreVersion, expectedStoreVersion);
}
}
}
use of org.neo4j.exceptions.UnderlyingStorageException in project neo4j by neo4j.
the class CommonAbstractStore method checkAndLoadStorage.
/**
* This method is called by constructors. Checks the header record and loads the store.
* <p>
* Note: This method will map the file with the page cache. The store file must not
* be accessed directly until it has been unmapped - the store file must only be
* accessed through the page cache.
* @param createIfNotExists If true, creates and initialises the store file if it does not exist already. If false,
* this method will instead throw an exception in that situation.
* @return {@code true} if the store was created as part of this call, otherwise {@code false} if it already existed.
*/
private boolean checkAndLoadStorage(boolean createIfNotExists, CursorContext cursorContext) {
try {
determineRecordSize(storeHeaderFormat.generateHeader());
if (getNumberOfReservedLowIds() > 0) {
// This store has a store-specific header so we have read it before we can be sure that we can map it with correct page size.
// Try to open the store file (w/o creating if it doesn't exist), with page size for the configured header value.
HEADER defaultHeader = storeHeaderFormat.generateHeader();
pagedFile = pageCache.map(storageFile, filePageSize, databaseName, openOptions.newWith(ANY_PAGE_SIZE));
HEADER readHeader = readStoreHeaderAndDetermineRecordSize(pagedFile, cursorContext);
if (!defaultHeader.equals(readHeader)) {
// The header that we read was different from the default one so unmap
pagedFile.close();
pagedFile = null;
}
}
if (pagedFile == null) {
// Map the file with the correct page size
pagedFile = pageCache.map(storageFile, filePageSize, databaseName, openOptions);
}
} catch (NoSuchFileException | StoreNotFoundException e) {
if (pagedFile != null) {
pagedFile.close();
pagedFile = null;
}
if (createIfNotExists) {
try {
// Generate the header and determine correct page size
determineRecordSize(storeHeaderFormat.generateHeader());
// Create the id generator, and also open it because some stores may need the id generator when initializing their store
idGenerator = idGeneratorFactory.create(pageCache, idFile, idType, getNumberOfReservedLowIds(), false, recordFormat.getMaxId(), readOnlyChecker, configuration, cursorContext, openOptions);
// Map the file (w/ the CREATE flag) and initialize the header
pagedFile = pageCache.map(storageFile, filePageSize, databaseName, openOptions.newWith(CREATE));
initialiseNewStoreFile(cursorContext);
// <-- successfully created and initialized
return true;
} catch (IOException e1) {
e.addSuppressed(e1);
}
}
if (e instanceof StoreNotFoundException) {
throw (StoreNotFoundException) e;
}
throw new StoreNotFoundException("Store file not found: " + storageFile, e);
} catch (IOException e) {
throw new UnderlyingStorageException("Unable to open store file: " + storageFile, e);
}
return false;
}
use of org.neo4j.exceptions.UnderlyingStorageException in project neo4j by neo4j.
the class CommonAbstractStore method scanForHighId.
/**
* Starts from the end of the file and scans backwards to find the highest in use record.
* Can be used even if {@link #start(CursorContext)} hasn't been called. Basically this method should be used
* over {@link #getHighestPossibleIdInUse(CursorContext)} and {@link #getHighId()} in cases where a store has been opened
* but is in a scenario where recovery isn't possible, like some tooling or migration.
*
* @return the id of the highest in use record + 1, i.e. highId.
*/
protected long scanForHighId(CursorContext cursorContext) {
try (PageCursor cursor = pagedFile.io(0, PF_SHARED_READ_LOCK | PF_READ_AHEAD, cursorContext)) {
int recordsPerPage = getRecordsPerPage();
int recordSize = getRecordSize();
// Scan pages backwards in the chunk using page cache prefetch (PF_READ_AHEAD)
for (long currentId = pagedFile.getLastPageId(); currentId >= 0 && cursor.next(currentId); currentId--) {
long highestId = 0;
boolean found;
do {
found = false;
long basePageId = cursor.getCurrentPageId() * recordsPerPage;
for (int record = 0; record < recordsPerPage; record++) {
cursor.setOffset(record * recordSize);
if (isInUse(cursor)) {
// We've found the highest id in use
highestId = basePageId + record + 1;
found = true;
}
}
} while (cursor.shouldRetry());
checkIdScanCursorBounds(cursor);
if (found) {
return highestId;
}
}
return getNumberOfReservedLowIds();
} catch (IOException e) {
throw new UnderlyingStorageException("Unable to find high id by scanning backwards " + getStorageFile(), e);
}
}
use of org.neo4j.exceptions.UnderlyingStorageException in project neo4j by neo4j.
the class MetaDataStore method setUpgradeTransaction.
public void setUpgradeTransaction(long id, int checksum, long timestamp, CursorContext cursorContext) {
long pageId = pageIdForRecord(Position.UPGRADE_TRANSACTION_ID.id);
assert pageId == pageIdForRecord(Position.UPGRADE_TRANSACTION_CHECKSUM.id);
synchronized (upgradeTransactionLock) {
try (PageCursor cursor = pagedFile.io(pageId, PF_SHARED_WRITE_LOCK, cursorContext)) {
if (!cursor.next()) {
throw new UnderlyingStorageException("Could not access MetaDataStore page " + pageId);
}
setRecord(cursor, Position.UPGRADE_TRANSACTION_ID, id);
setRecord(cursor, Position.UPGRADE_TRANSACTION_CHECKSUM, checksum);
setRecord(cursor, Position.UPGRADE_TRANSACTION_COMMIT_TIMESTAMP, timestamp);
upgradeTxIdField = id;
upgradeTxChecksumField = checksum;
upgradeCommitTimestampField = timestamp;
upgradeTransaction = new TransactionId(id, checksum, timestamp);
} catch (IOException e) {
throw new UnderlyingStorageException(e);
}
}
}
Aggregations