BACK
JOAFIP features and usage
summary
Easy to use
Javadoc links
The object that can be persisted are POJO that do not need to
be Serializable, but there is some
conditions:
The consideration for better performance is to use collection
implementation of JOAFIP ( Sun standard interface and more )
To be able to use JOAFIP it is needed to control the
state of the objects
Notes:
- After a data access session closed, persistent object become
detached, while transient
and detached remain in same state. A call to getObject() in newly
opened session allows to obtain a reference on persistent object.
- For object not saved in one data record, it is not possible
to use a persistent object after data session
closed, you have to make a deep copy of the persistent object, then
close data acess session and work with the copy.
IFilePerstence#copy(Object object) enable to create an copy detached from persistence.
- more easy setup can be done using setup
facility
Below the basic usage is described.
Creation of the persistence manager
/*
creation of the file persitence
manager */
File directory = new
File("runtime/database");
IFilePersistence filePersistence;
try {
filePersistence = new
FilePersistence(directory);
} catch (FilePersistenceException
exception) {
final EnumFileState fileState =
FilePersistence.fileState(exception);
switch(fileState) {
case STATE_OK:
/* exception is not relative to file
state */
throw exception;
case STATE_CORRUPTED:
/* file content corrupted */
throw exception;
case STATE_RESTORED_DATA_LOST:
/* create file persistence
using file restored even data lost */
filePersistence = new
FilePersistence(directory);
break;
case STATE_RESTORED_NO_DATA_LOST:
/* create file persistence using
file restored */
filePersistence = new
FilePersistence(directory);
break;
case STATE_UNSTABLE:
/* need file maintenance */
throw exception;
}
}
First access ( the data files not exist )
/* start data access session */
DataAccessSession session =
filePersistence.createDataAccessSession();
session.open();
persistentObject =
session.getObject("name");
if( persistentObject == null ) {
/*
the first time creation */
persistentObject = new
PersistentObject(...)
session.setObject("name", persistentObject);
}
........
session.closeAndWait(EnumFilePersistenceCloseAction.SAVE);
Access cycle
/*
start data access session */
DataAccessSession session =
filePersistence.createDataAccessSession();
session.open();
......
/* get the object in memory */
persistentObject =
session.getObject("name");
/* use of persitent object */
persistentObject.setXxx(...);
......
/* close data access session ,
saving modifications, waiting save done*/
session.closeAndWait(EnumFilePersistenceCloseAction.SAVE);
Remove object
DataAccessSession
session = filePersistence.createDataAccessSession();
session.open();
..........
/* remove object from the
persitente objet pool */
session.removeObject("name");
..........
session.closeAndWait(EnumFilePersistenceCloseAction.SAVE);
read only access
/*
start data access session */
DataAccessSession session =
filePersistence.createDataAccessSession();
session.open();
......
/* get the object in memory */
persistentObject =
session.getObject("name");
/* use of persitent object */
persistentObject.getXxx(...);
......
/* no save action */
session.close();
rollback
modifications made in memory
/*
start data access session */
DataAccessSession session =
filePersistence.createDataAccessSession();
session.open();
......
/* get the object in memory */
persistentObject =
session.getObject("name");
/* use of persitent object */
persistentObject.setXxx(...);
......
/* close data access session, do not
save modifications */
session.closeAndWait(EnumFilePersistenceCloseAction.DO_NOT_SAVE);
/* start a new data access
session */
session.open();
/* persitentObject have the previous state saved on file */
persistentObject =
session.getObject("name");
enum state management
It is possible to declare field in
enum, so the state of each enum constant must be saved. FilePersistence#storedEnum,
or setup by properties file, and DataAccessSession#setEnumState are
made to manage this case.
/*
must inform file persistence manager of enum class stored
* see
also
setup facility for stored enum declaration
*/
filePersistence.storedEnum(EnumForTest.class)
final
BobContainer bob1 = new BobContainer();
bob1.setObject1(EnumForTest.VAL1);
EnumForTest.VAL1.setObject(Integer.valueOf(0));
/* save the created object*/
session.open();
/* inform that EnumForTest class instance are persisted */
session.setObject("bob1", bob1);
session.close(EnumFilePersistenceCloseAction.SAVE);
session.open();
/* reload enum state */
session.setEnumState(EnumForTest.VAL1);
serialize a class in one file data record
it is possible to force storage in one
file data record of all objects instances of a class. There is three
ways
to do that:
- annotate the class with
- setting file persistence manager invoking one of methods in IFilePersistence
- setStoreSerializeAndGZippedInOneRecord
- setStoreSerializeAndZippedInOneRecord ( objects are always
rewriten in file even if state does not change)
- setStoreSerializeInOneRecord
- use of setup
by properties file
Shown below: one data record in file per
object in memory
Below shows when object o1 and o2 are
serialized in on file data
record
Serialization in one data record side
effect.
Instance o1 references o3 and o4, and o2
references o4 and o5.
Doing a session.setObject("key1",o1) , session.setObject("key2",o2) to
save objects o1 and o2 serialized in one data record.
Objects o1 and o2 are serialized as
below in two data records.
Reading using
o1=session.getObject("key1") , o2=session.getObject("key2")
After the reading of o1 and o2, you will have 6 object in memory: o4' and
o4'' have the same state than the original o4 object, but are not the
same instance in memory.
java
serialization mechanism
Since 2.0.0, storage in joafip data
record in file can be driven by standard java serialization mechanism.
This means that joafip invokes
readObject
and
writeObject methods of
classes implementing
Serializable
interface, and also invokes
readExternal
and
writeExternal methods
of classes implementing
Externalizable
interface.
For class implementing
Serializable
interface but not implementing
readObject
and
writeObject methods,
joafip uses default read and write object.
Invoking setStoreNotUseStandardSerialization of
IFilePersistence
disables use of standard Java serialization mechanism ( or use
StoreNotUseStandardSerialization
annotation )
Multi data access session ( multi-Thread )
File persistence is thread safe and enables to open multiple data access session at the same time
in
asynchronous mode. It is also possible
to have synchronous access.
asynchronous mode:
Since object instances accessed through file persistence are the same,
there is no transaction concept like with relational data base, same object are shared.
The persisted data model should be thread-safe in multiple thread environement.
The only JOAFIP specific things is the way
of closing and saving when multiple data access sessions are opened.
In fact the save action will be done only when the last opened data
access session is closed.
Take care: in multi-thread
environment you can have the situation where all data access session
are not closed at the same time. the
DataAccessSession.closeAndWait(...) can be used to wait for
modifications saved, or a listener on data access session can be set to
be notified of save action end.
The data access session are opened
using DataAccessSession.open() ; that is asynchronous open mode.
About rollback:
It is possible to discard modifications
done, by closing the session with "do not save" action; this will cancel
all save action asked by other data access session close. The close
methods and listener allow to know if save action asked have been
done or not.
Synchronous mode:
Using
DataAccessSession.openSynchronized, that is the synchronous open mode,
no data access session shares object access with another data access
session.
save and restore all objects in
relation in file system
one heap file record by object instance
exemple of objects in relation

saving object1 will create 4 heap file record for object1, object2,
object3, and object4
Lazy loading of object
Enables to manage a large amount of
data object whithout need to load all in memory.
In the following exemple we can imagine the map has some thousands of
records.
/*
start data access session */
DataAccessSession session =
filePersistence.createDataAccessSession();
session.open();
/* get the map to update */
PTreeMap<String,ClassData>
map=(PTreeMap<String,ClassData>)session.getObject("map1");
/* do modification */
map.put("key1",data1);
/* close data access session,
saving modifications */
session.closeAndWait(EnumFilePersistenceCloseAction.SAVE);
The getObject call will not read all records from the file.
The put call will only load in memory the nodes of the tree that needs
to be read and modified for insertion.
The endUse call will commit only loaded and modified, added objects. If
objects are unreferenced by other objects ( subject to garbage ) then
they are removed from the file ( this create free space for future
storage )
It is possible to force enhance of object even if it have "public
final" method, or to force to not use lazy mode: see IFilePersistence
interface or
setup facility.
Crash safe
There is a system of replication of
data with file reconstruction to be crash tolerant.
Two data file are used, the files are never maintened opened during the
application live.
File is marked unstable before modification and marked stable
after writing and closing it.
At startup the files state are checked and if one is not in stable
state it is restored.
This guarantees that the last
successful commit in file is not lost.
FilePersistence
filePersistence=new
FilePersistence(.......);
......
try {
}
catch(FilePersistenceException exception) {
switch (.fileState(exception)) {
case STATE_RESTORED_DATA_LOST:
/*
restoration of data from backup: data lost */
case STATE_RESTORED_NO_DATA_LOST:
/*
restoration of backup from data: no data lost */
}
}
The file content stable state management is describe below.
file corruption detection
Each record in heap file have a CRC32
on record header and in data for data record.
When reading in file a FileCorruptedException is thrown if readed CRC32
do not match computed CRC32.
FilePersistence
filePersistence=new
FilePersistence(.......);
......
try {
}
catch(FilePersistenceException exception) {
switch (.fileState(exception)) {
case STATE_CORRUPTED:
/*
cause is file corruption */
................
}
}
Additional check can be done using AssertNotNull annotation on
persistence class' field that can not have a null value.
File data record garbage collector
There
is one data record in file by object in relation with the
root object, or root itself.
Each time an object is added to the object graph, a data record is
added to the file; the file size increase according to object added.
When an object is detached from the object graph the data record
remains
in file but will no more be accessed.
The data record garbage collector is needed to free space used by this
detached data record, the free space will be used to allocated new data
record.
High speed garbage: when there is no more persisted object garbage can
be done quickly by erasing the file and creating an empty one.
Two way for garbage sweeping:
- big maintenance:
Calling FilePersistence#garbageSweep
This can take a long time
- in background:
Background is disabled by default, and must be enabled. enable has a time
frequency parameter.
Make application continously running, even if not access to persisted data, enable background
garbage sweeping.
foreground garbage sweep
FilePersistence
filePersistence=new
FilePersistence(.......);
......
/* this can take a long time and block all other operation */
int numberOfSweeped=filePersistence.garbageSweep();
background garbage sweep
FilePersistence
filePersistence=new
FilePersistence(.......);
......
/* enable background garbage sweep, one pass every 100 miliSeconds */
filePersistence.enableBackgroundGarbageSweep(100);
......
/* disable background garbage sweep */
filePersistence.disableBackgroundGarbageSweep()
© 2007-2008, joafip