History | Log In     View a printable version of the current page.  
Issue Details (XML | Word | Printable)

Key: COR-739
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Priority: Critical Critical
Assignee: Unassigned
Reporter: Maik Jablonski
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
db4o Core

Removing array-reference in schema evolution corrupts database

Created: 25/Jul/07 06:52 AM   Updated: 22/Aug/07 07:45 PM
Component/s: Local
Affects Version/s: Hammerfest - v6.1
Fix Version/s: Denmark - v6.3

Time Tracking:
Original Estimate: Not Specified
Remaining Estimate: 0h
Time Spent - 5h
Time Spent: 5h
Time Spent - 5h

File Attachments: 1. Zip Archive SchemaEvolutionTest.zip (2 kb)

Environment:
Linux
Java 1.5.12

Order: 3
Original IDS Estimate: 2
Resolution Date: 22/Aug/07 07:45 PM
First Response Date: 07/Aug/07 01:07 PM
Labels:
Participants: Maik Jablonski, Patrick Roemer and Rodrigo B. de Oliveira
Number of Attachments: 1
Number of Comments: 5


 Description  « Hide
Removing a reference to an array in a schema evolution results in a corrupted database. Please follow these steps to reproduce the problem. Sample output of corrupted data is attached below.

// Needed just as a simple value holder, not relevant any further
public class SimpleObject {

String name;

public SimpleObject(String name) {
this.name = name;
}

public String toString() {
return name;
}
}


// Base-Class storing a date which gets corrupted later on
import java.util.Date;

public class Base {
Date date;
}


// Main Class (extending Base) which holds the array and is going to be schema evoluted... later on the status field gets corrupted.
import java.util.Date;

public class ExtendedBase extends Base {

String name;

// Please comment out for schema-evolution test after first run
SimpleObject[] array;

boolean status;

public ExtendedBase() {

}

public ExtendedBase(String name, boolean status, SimpleObject[] array) {
this.date = new Date();
this.name = name;
this.status = status;
// Please comment out for schema-evolution after first run
this.array = array;
}

public String toString() {
return new StringBuilder().append(name).append("\t").append(status)
.append("\t").append(date).toString();
}
}


// And here's the TestRun
// 1. Run it the first time without any changes to ExtendedBase, so a database is populated.
// 2. Simulate the schema evolution: Comment out all references to the array in ExtendedBase (see comments) and rerun TestRun (database is reused if it exists).

import java.io.File;

import com.db4o.Db4o;
import com.db4o.ObjectContainer;

public class TestRun {

static String YAP_FILE = "test.yap";

public static void createDb() {
if (!new File(YAP_FILE).exists()) {
System.out.println("Creating database: " + Db4o.version());
ObjectContainer oc = Db4o.openFile(YAP_FILE);
for (int i = 0; i < 1000; i++) {
SimpleObject[] array = new SimpleObject[10];
for (int j = 0; j < 10; j++) {
array[j] = new SimpleObject("" + j + i);
}
oc.set(new ExtendedBase("" + i, i % 2 == 0, array));
}
oc.commit();
oc.close();
}
}

public static void logDb() {
ObjectContainer oc = Db4o.openFile(YAP_FILE);
for (Object obj : oc.get(ExtendedBase.class)) {
System.out.println(obj);
}
oc.close();
}

public static void main(String[] args) {
createDb();
logDb();
}
}


---------------------------------------
Output of TestRun (first time)
---------------------------------------

Creating database: db4o 6.1.602
0 true Wed Jul 25 08:47:00 CEST 2007
1 false Wed Jul 25 08:47:00 CEST 2007
2 true Wed Jul 25 08:47:00 CEST 2007
3 false Wed Jul 25 08:47:00 CEST 2007
...

After schema evolution (removing array reference in ExtendedBase):


--------------------------------------------
Output of TestRun (second time)
---------------------------------------------

0 false Thu Feb 19 18:02:47 CET 1970
1 false Thu Feb 19 18:02:47 CET 1970
2 false Thu Feb 19 18:02:47 CET 1970
3 false Thu Feb 19 18:02:47 CET 1970
...

 All   Comments   Work Log   Change History      Sort Order: Ascending order - Click to sort in descending order
Maik Jablonski - 25/Jul/07 06:57 AM
Java-Sources for Test attached

Rodrigo B. de Oliveira - 07/Aug/07 01:07 PM
* must be backported to 6.3

Patrick Roemer - 08/Aug/07 03:24 PM
The issue seems to be unrelated to inheritance and the use of custom classes (and Date). A simplified version of the test case that still reproduces the faulty behavior can use this instead of Base/ExtendedBase/SimpleObject:

public class Data {

String name;
// Please comment out for schema-evolution test after first run
Object[] array;
boolean status;

public Data(String name, boolean status, Object[] array) {
this.name = name;
this.status = status;
// Please comment out for schema-evolution after first run
this.array = array;
}

public String toString() {
return new StringBuilder().append(name).append("\t").append(status).append("\t").toString();
}
}

So the issue seems to be directly related to removing reference typed arrays.

Patrick Roemer - 08/Aug/07 04:23 PM
The inactive field is equipped with the wrong handler in the second pass - UntypedFieldHandler instead of ArrayHandler. This results in a wrong link length used for skipping the field during unmarshalling.

Patrick Roemer - 08/Aug/07 07:25 PM
Fixed, but no test case, yet.