public boolean storeFilesUpgradeable(File neoStoreFile) {
   File storeDirectory = neoStoreFile.getParentFile();
   for (String fileName : fileNamesToExpectedVersions.keySet()) {
     String expectedVersion = fileNamesToExpectedVersions.get(fileName);
     FileChannel fileChannel = null;
     byte[] expectedVersionBytes = UTF8.encode(expectedVersion);
     try {
       File storeFile = new File(storeDirectory, fileName);
       if (!fs.fileExists(storeFile)) {
         return false;
       }
       fileChannel = fs.open(storeFile, "r");
       if (fileChannel.size() < expectedVersionBytes.length) {
         return false;
       }
       fileChannel.position(fileChannel.size() - expectedVersionBytes.length);
       byte[] foundVersionBytes = new byte[expectedVersionBytes.length];
       fileChannel.read(ByteBuffer.wrap(foundVersionBytes));
       if (!expectedVersion.equals(UTF8.decode(foundVersionBytes))) {
         return false;
       }
     } catch (IOException e) {
       throw new RuntimeException(e);
     } finally {
       if (fileChannel != null) {
         try {
           fileChannel.close();
         } catch (IOException e) {
           // Ignore exception on close
         }
       }
     }
   }
   return true;
 }
예제 #2
0
  private File fixPath(File dir, StoreFactory sf) {
    try {
      fileSystem.mkdirs(dir);
    } catch (IOException e) {
      throw new UnderlyingStorageException(
          "Unable to create directory path[" + storeDir + "] for Neo4j kernel store.");
    }

    File store = new File(dir, NeoStore.DEFAULT_NAME);
    if (!fileSystem.fileExists(store)) {
      sf.createNeoStore(store).close();
    }
    return store;
  }
예제 #3
0
 private int getFileSizeMb(String file) {
   long length = fs.getFileSize(new File(dbPath, "neostore." + file));
   int mb = (int) (length / 1024 / 1024);
   if (mb > 0) {
     return mb;
   }
   // default return 1MB if small or empty file
   return 1;
 }
예제 #4
0
 private void changeActiveLog(String newFileName) throws IOException {
   // change active log
   FileChannel fc = fileSystem.open(logSwitcherFileName, "rw");
   ByteBuffer buf = ByteBuffer.wrap(UTF8.encode(newFileName));
   fc.truncate(0);
   fc.write(buf);
   fc.force(true);
   fc.close();
   msgLog.logMessage("Active txlog set to " + newFileName, true);
 }
예제 #5
0
 private int logCount() {
   XaLogicalLog log = neoDataSource().getXaContainer().getLogicalLog();
   int count = 0;
   for (long i = log.getHighestLogVersion() - 1; i >= 0; i--) {
     if (fs.fileExists(log.getFileName(i))) {
       count++;
     } else {
       break;
     }
   }
   return count;
 }
예제 #6
0
 @Override
 public void init() {
   txThreadMap = new ArrayMap<Thread, TransactionImpl>((byte) 5, true, true);
   logSwitcherFileName = txLogDir + separator + "active_tx_log";
   txLog1FileName = "tm_tx_log.1";
   txLog2FileName = "tm_tx_log.2";
   try {
     if (fileSystem.fileExists(logSwitcherFileName)) {
       FileChannel fc = fileSystem.open(logSwitcherFileName, "rw");
       byte fileName[] = new byte[256];
       ByteBuffer buf = ByteBuffer.wrap(fileName);
       fc.read(buf);
       fc.close();
       String currentTxLog = txLogDir + separator + UTF8.decode(fileName).trim();
       if (!fileSystem.fileExists(currentTxLog)) {
         throw logAndReturn(
             "TM startup failure",
             new TransactionFailureException(
                 "Unable to start TM, " + "active tx log file[" + currentTxLog + "] not found."));
       }
       txLog = new TxLog(currentTxLog, fileSystem, msgLog);
       msgLog.logMessage("TM opening log: " + currentTxLog, true);
     } else {
       if (fileSystem.fileExists(txLogDir + separator + txLog1FileName)
           || fileSystem.fileExists(txLogDir + separator + txLog2FileName)) {
         throw logAndReturn(
             "TM startup failure",
             new TransactionFailureException(
                 "Unable to start TM, "
                     + "no active tx log file found but found either "
                     + txLog1FileName
                     + " or "
                     + txLog2FileName
                     + " file, please set one of them as active or "
                     + "remove them."));
       }
       ByteBuffer buf = ByteBuffer.wrap(txLog1FileName.getBytes("UTF-8"));
       FileChannel fc = fileSystem.open(logSwitcherFileName, "rw");
       fc.write(buf);
       txLog = new TxLog(txLogDir + separator + txLog1FileName, fileSystem, msgLog);
       msgLog.logMessage("TM new log: " + txLog1FileName, true);
       fc.force(true);
       fc.close();
     }
     tmOk = true;
   } catch (IOException e) {
     log.log(Level.SEVERE, "Unable to start TM", e);
     throw logAndReturn(
         "TM startup failure", new TransactionFailureException("Unable to start TM", e));
   }
 }
예제 #7
0
  @Test
  public void pruneByFileSize() throws Exception {
    // Given
    int size = 1050;
    newDb(size + " size");

    doTransaction();
    rotate();
    long sizeOfOneLog =
        fs.getFileSize(neoDataSource().getXaContainer().getLogicalLog().getFileName(0));
    int filesNeededToExceedPruneLimit = (int) Math.ceil((double) size / (double) sizeOfOneLog);

    // When
    for (int i = 1; i < filesNeededToExceedPruneLimit * 2; i++) {
      doTransaction();
      rotate();

      // Then
      assertEquals(Math.min(i + 1, filesNeededToExceedPruneLimit), logCount());
    }
  }
예제 #8
0
  @Test
  public void shouldNotReadExcessivelyFromTheFileChannelWhenRotatingLogWithNoOpenTransactions()
      throws Exception {
    // given
    XaTransactionFactory xaTf = mock(XaTransactionFactory.class);
    when(xaTf.getAndSetNewVersion()).thenAnswer(new TxVersion(TxVersion.UPDATE_AND_GET));
    when(xaTf.getCurrentVersion()).thenAnswer(new TxVersion(TxVersion.GET));
    // spy on the file system abstraction so that we can spy on the file channel for the logical log
    FileSystemAbstraction fs = spy(ephemeralFs.get());
    File dir = TargetDirectory.forTest(fs, XaLogicalLogTest.class).directory("log", true);
    // -- when opening the logical log, spy on the file channel we return and count invocations to
    // channel.read(*)
    when(fs.open(new File(dir, "logical.log.1"), "rw"))
        .thenAnswer(
            new Answer<FileChannel>() {
              @Override
              public FileChannel answer(InvocationOnMock invocation) throws Throwable {
                FileChannel channel = (FileChannel) invocation.callRealMethod();
                return mock(
                    channel.getClass(),
                    withSettings()
                        .spiedInstance(channel)
                        .name("channel")
                        .defaultAnswer(CALLS_REAL_METHODS)
                        .invocationListeners(
                            new InvocationListener() {
                              @Override
                              public void reportInvocation(
                                  MethodInvocationReport methodInvocationReport) {
                                if (methodInvocationReport
                                    .getInvocation()
                                    .toString()
                                    .startsWith("channel.read(")) {
                                  reads++;
                                }
                              }
                            }));
              }
            });
    XaLogicalLog xaLogicalLog =
        new XaLogicalLog(
            new File(dir, "logical.log"),
            mock(XaResourceManager.class),
            mock(XaCommandFactory.class),
            xaTf,
            new DefaultLogBufferFactory(),
            fs,
            new SingleLoggingService(StringLogger.wrap(output.writer())),
            LogPruneStrategies.NO_PRUNING,
            mock(TransactionStateFactory.class),
            25 * 1024 * 1024);
    xaLogicalLog.open();
    // -- set the log up with 10 transactions (with no commands, just start and commit)
    for (int txId = 1; txId <= 10; txId++) {
      int identifier =
          xaLogicalLog.start(new XidImpl(XidImpl.getNewGlobalId(), RESOURCE_ID), -1, 0);
      xaLogicalLog.writeStartEntry(identifier);
      xaLogicalLog.commitOnePhase(identifier, txId, ForceMode.forced);
      xaLogicalLog.done(identifier);
    }

    // when
    xaLogicalLog.rotate();

    // then
    assertThat(
        "should not read excessively from the logical log file channel", reads, lessThan(10));
  }