Skip to content

Commit

Permalink
File version display - issue #115
Browse files Browse the repository at this point in the history
  • Loading branch information
tzaeschke committed Jan 19, 2020
1 parent 2e726b7 commit d43f08c
Show file tree
Hide file tree
Showing 9 changed files with 280 additions and 29 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG
Expand Up @@ -24,7 +24,8 @@ CHANGELOG
2020-Jan-05
===========
- T.Zaeschke
- Fixed missing cleanup for exmpty transactions. Tighter control over open iterators in FSM.
- Issue #115: Extend ZooCheckDb tool to show file format versions, even when not compatible.
- Fixed missing cleanup for empty transactions. Tighter control over open iterators in FSM.

2018-Dec-18
===========
Expand Down
4 changes: 4 additions & 0 deletions src/org/zoodb/internal/server/SessionFactory.java
Expand Up @@ -146,4 +146,8 @@ public static void cleanUp(File dbFile) {
throw DBLogger.newFatal("Failed while acessing path: " + dbFile, e);
}
}

public static FileHeader readHeader(Path path) {
return SessionManager.readHeader(path);
}
}
42 changes: 15 additions & 27 deletions src/org/zoodb/internal/server/SessionManager.java
Expand Up @@ -75,35 +75,14 @@ public SessionManager(Path path) {
StorageChannelInput in = rootChannel.createReader(false);

//read header
in.seekPageForRead(PAGE_TYPE.DB_HEADER, 0);
int fid = in.readInt();
if (fid != DiskIO.DB_FILE_TYPE_ID) {
throw DBLogger.newFatal("This is not a ZooDB file (illegal file ID: " + fid + ")");
FileHeader header = FileHeader.read(in);
if (!header.successfulRead()) {
file.close();
throw DBLogger.newFatal(header.errorMsg().get(0));
}
int maj = in.readInt();
int min = in.readInt();
if (maj != DiskIO.DB_FILE_VERSION_MAJ) {
throw DBLogger.newFatal("Illegal major file version: " + maj + "." + min +
"; Software version: " +
DiskIO.DB_FILE_VERSION_MAJ + "." + DiskIO.DB_FILE_VERSION_MIN);
}
if (min != DiskIO.DB_FILE_VERSION_MIN) {
throw DBLogger.newFatal("Illegal minor file version: " + maj + "." + min +
"; Software version: " +
DiskIO.DB_FILE_VERSION_MAJ + "." + DiskIO.DB_FILE_VERSION_MIN);
}

int pageSize = in.readInt();
if (pageSize != ZooConfig.getFilePageSize()) {
//TODO actually, in this case would should just close the file and reopen it with the
//correct page size.
throw DBLogger.newFatal("Incompatible page size: " + pageSize);
}

//main directory
rootPages[0] = header.getRootPages()[0];
rootPages[1] = header.getRootPages()[1];
rootPage = new RootPage();
rootPages[0] = in.readInt();
rootPages[1] = in.readInt();

//check root pages
//we have two root pages. They are used alternatingly.
Expand Down Expand Up @@ -158,6 +137,15 @@ public SessionManager(Path path) {
fileOut = rootChannel.createWriter(false);
}

static FileHeader readHeader(Path path) {
StorageRoot file = createPageAccessFile(path, "rw", new FreeSpaceManager());
IOResourceProvider rootChannel = file.getIndexChannel();
StorageChannelInput in = rootChannel.createReader(false);
FileHeader header = FileHeader.read(in);
file.close();
return header;
}

/**
* Writes the main page.
* @param pageCount
Expand Down
30 changes: 29 additions & 1 deletion src/org/zoodb/tools/ZooCheckDb.java
Expand Up @@ -20,11 +20,16 @@
*/
package org.zoodb.tools;

import java.nio.file.Path;
import java.nio.file.Paths;

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;

import org.zoodb.internal.Session;
import org.zoodb.internal.server.FileHeader;
import org.zoodb.internal.server.SessionFactory;
import org.zoodb.jdo.ZooJdoProperties;
import org.zoodb.tools.internal.ZooCommandLineTool;

Expand All @@ -37,7 +42,7 @@ public class ZooCheckDb extends ZooCommandLineTool {
//private static final String DB_NAME = "StackBicycles";
//private static final String DB_NAME = "StackServerFault";

public static void main(String[] args) {
public static void main(String ... args) {
String dbName;
if (args.length == 0) {
dbName = DB_NAME;
Expand All @@ -50,6 +55,29 @@ public static void main(String[] args) {
return;
}

//read header
out.println("Database file info: " + dbName);
Path path = Paths.get(ZooHelper.getDataStoreManager().getDbPath(dbName));
FileHeader header = SessionFactory.readHeader(path);
if (!header.successfulRead()) {
out.println("ERROR reading file: " + header.errorMsg());
}
out.println("magic number: " + Integer.toHexString(header.getFileID()));
out.println("format version: " + header.getVersionMajor() + "." + header.getVersionMinor());
out.println("page size: " + header.getPageSize());
out.print("root page IDs: ");
for (int id : header.getRootPages()) {
out.print(id + ", ");
}
out.println();
out.println();

if (!header.successfulRead()) {
out.println("Aborting due to error.");
return;
}


out.println("Checking database: " + dbName);

ZooJdoProperties props = new ZooJdoProperties(dbName);
Expand Down
230 changes: 230 additions & 0 deletions tst/org/zoodb/test/jdo/Test_017_DatabaseVersioning.java
@@ -0,0 +1,230 @@
/*
* Copyright 2009-2016 Tilmann Zaeschke. All rights reserved.
*
* This file is part of ZooDB.
*
* ZooDB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ZooDB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ZooDB. If not, see <http://www.gnu.org/licenses/>.
*
* See the README and COPYING files for further information.
*/
package org.zoodb.test.jdo;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.zoodb.internal.util.DBLogger;
import org.zoodb.test.testutil.TestTools;
import org.zoodb.tools.ZooCheckDb;
import org.zoodb.tools.ZooCompareDb;

public class Test_017_DatabaseVersioning {

private static final String DB2 = TestTools.getDbName() + "2";
private static final String DB_0_5_2 = "TestDb_0.5.2.zdb";
private static final String DB_0_0_0 = "TestDb_0.0.0.zdb";
private static final String DB_999_999_999 = "TestDb_999.999.999.zdb";
private static final String DB_0_5_2_wrecked = "TestDb_0.5.2.wrecked.zdb";


@Before
public void before() {
TestTools.createDb();
ZooCompareDb.logToConsole = false;
}

@After
public void after() {
ZooCompareDb.logToConsole = true;
TestTools.closePM();
TestTools.removeDb();
TestTools.removeDb(DB2);
removeFile( FileSystems.getDefault().getPath(TestTools.getDbFileName() + "2") );
removeFile( FileSystems.getDefault().getPath(TestTools.getDbFileName()) );
}

private void removeFile(Path p) {
if (Files.exists(p)) {
try {
Files.delete(p);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

private String copyDB(String orig) {
String origPath =
Test_017_DatabaseVersioning.class.getResource(orig).getPath().substring(1);
try {
Path p2 = FileSystems.getDefault().getPath(TestTools.getDbFileName() + "2");
removeFile(p2);
Path pOrig = Paths.get(origPath);
Files.copy(pOrig, p2);
} catch (IOException e) {
throw new RuntimeException(e);
}
return origPath;
}

private void populateSimple() {
TestTools.defineSchema(TestClass.class);
TestTools.defineIndex(TestClass.class, "_int", true);
TestTools.defineIndex(TestClass.class, "_long", false);
TestTools.defineIndex(TestClass.class, "_string", false);
TestTools.defineIndex(TestClass.class, "_double", true);
PersistenceManager pm = TestTools.openPM();
pm.currentTransaction().begin();

pm.newQuery(TestClass.class).deletePersistentAll();

TestClass tc1 = new TestClass();
tc1.setData(1, false, 'c', (byte)127, (short)32000, 1234567890L, "xyz", new byte[]{1,2},
-1.1f, 35);
pm.makePersistent(tc1);
tc1 = new TestClass();
tc1.setData(12, false, 'd', (byte)127, (short)32000, 1234567890L, "xyz", new byte[]{1,2},
-0.1f, 34);
pm.makePersistent(tc1);
tc1 = new TestClass();
tc1.setData(123, false, 'e', (byte)127, (short)32000, 1234567890L, "xyz", new byte[]{1,2},
0.1f, 3.0);
pm.makePersistent(tc1);
tc1 = new TestClass();
tc1.setData(1234, false, 'f', (byte)127, (short)32000, 1234567890L, "xyz", new byte[]{1,2},
1.1f, -0.01);
pm.makePersistent(tc1);
tc1 = new TestClass();
tc1.setData(12345, false, 'g', (byte)127, (short)32000, 1234567890L, "xyz", new byte[]{1,2},
11.1f, -35);
pm.makePersistent(tc1);

pm.currentTransaction().commit();
TestTools.closePM();
}


@SuppressWarnings("unchecked")
@Test
public void testSimpleClasses_0_5_2() {
// populate DB
populateSimple();

// Copy DB_0_5_2 to DB2
String db2Path = copyDB(DB_0_5_2);

// Check DB2 file version
ZooCheckDb.enableStringOutput();
ZooCheckDb.main(db2Path);
String output = ZooCheckDb.getStringOutput();
assertTrue(output.contains("format version: 1.5"));

// Compare TODO this should fail in future unless we evolve the DB
String result = ZooCompareDb.run(TestTools.getDbName(), DB2);
assertEquals("", result);

// Run some tests
PersistenceManager pm = TestTools.openPM(DB2);
pm.currentTransaction().begin();
// Test index query
Query q = pm.newQuery(TestClass.class, "_int == 12 || _int == 123");
List<TestClass> c = (List<TestClass>) q.execute();
assertTrue(c.get(0).getInt() == 12);
assertTrue(c.get(1).getInt() == 123);
assertEquals(2, c.size());
q.close(c);

pm.currentTransaction().commit();
pm.close();
}


@Test
public void testFailure_0_0_0() {
// Copy DB_0_5_2 to DB2
String db2Path = copyDB(DB_0_0_0);

// Check DB2 file version
ZooCheckDb.enableStringOutput();
ZooCheckDb.main(db2Path);
String output = ZooCheckDb.getStringOutput();
assertTrue(output.contains("format version: 0.0"));
assertTrue(output.contains("Illegal major file version: "));

try {
TestTools.openPM(DB2);
fail();
} catch (RuntimeException e) {
DBLogger.isFatalDataStoreException(e);
assertTrue(e.getMessage().contains("Illegal major file version: "));
}
}

@Test
public void testFailure_999_999_999() {
// Copy DB_0_5_2 to DB2
String db2Path = copyDB(DB_999_999_999);

// Check DB2 file version
ZooCheckDb.enableStringOutput();
ZooCheckDb.main(db2Path);
String output = ZooCheckDb.getStringOutput();
assertTrue(output.contains("format version: 999.999"));
assertTrue(output.contains("Illegal major file version: "));

try {
TestTools.openPM(DB2);
fail();
} catch (RuntimeException e) {
DBLogger.isFatalDataStoreException(e);
assertTrue(e.getMessage().contains("Illegal major file version: "));
}
}

@Test
public void testFailure_0_5_2_wrecked() {
// Copy DB_0_5_2_wrecked to DB2
String db2Path = copyDB(DB_0_5_2_wrecked);

// Check DB2 file version
ZooCheckDb.enableStringOutput();
ZooCheckDb.main(db2Path);
String output = ZooCheckDb.getStringOutput();
assertTrue(output.contains("This is not a ZooDB file (illegal file ID:"));

// try to open DB
try {
TestTools.openPM(DB2);
fail();
} catch (RuntimeException e) {
DBLogger.isFatalDataStoreException(e);
assertTrue(e.getMessage().contains("This is not a ZooDB file (illegal file ID:"));
}
TestTools.closePM();
}

}
Binary file added tstresources/org/zoodb/test/jdo/TestDb_0.0.0.zdb
Binary file not shown.
Binary file not shown.
Binary file added tstresources/org/zoodb/test/jdo/TestDb_0.5.2.zdb
Binary file not shown.
Binary file not shown.

0 comments on commit d43f08c

Please sign in to comment.