MemoryIoAdapter

One of the built-in db4o IoAdapters is MemoryIoAdapter. This adapter keeps the whole database in RAM instead of a hard-drive. Obviously such in-memory database has both advantages and disadvantages:

Pros:

Cons:

You can achieve the best results combining the usage of MemoryIoAdapter with the normal file adapter. Let's look, how MemoryIoAdapter should be used in your application.

First of all MemoryIoAdapter should be configured. The API gives you control over memory consumption with

c#: MemoryIoAdapter#GrowBy(length)

VB: MemoryIoAdapter#GrowBy(length)

method. Length defines the amount of bytes in memory that should be allocated, when no more free slots are found within the allocated file. Large value (100,000) will assure the best performance; small value (100) will keep the memory consumption at the lowest level. The default setting is 10,000.

MemoryIoAdaptor supplies methods to exchange data with the database from the filesystem.

c#: MemoryIoAdapter#Put(filename, byte[])

VB: MemoryIoAdapter#Put(String, byte())

This method allows you to put the contents of the stored database file (byte[]) into the memory database.

The opposite method:

c#: MemoryIoAdapter#Get(filename)

VB: MemoryIoAdapter#Get(filename)

returns the updated byte[] array of the database in memory, which can be saved to disc as a normal database file.

The filename can be used for all further access (#openFile, #openServer methods) like normal file name. Make sure that you close the database file on the disc after reading its contents into memory and writing it back.

The configured adapter should be assigned as db4o IO system:

c#: Db4o.Configure().Io(MemoryIoAdapter)

VB: Db4o.Configure().Io(MemoryIoAdapter)

Let's create sample database on the disc:

IOExample.cs: SetObjects
01public static void SetObjects() 02 { 03 File.Delete(YapFileName); 04 IObjectContainer db = Db4oFactory.OpenFile(YapFileName); 05 try 06 { 07 Pilot pilot = new Pilot("Rubens Barrichello"); 08 db.Set(pilot); 09 } 10 finally 11 { 12 db.Close(); 13 } 14 }

IOExample.vb: SetObjects
01Public Shared Sub SetObjects() 02 File.Delete(YapFileName) 03 Dim db As IObjectContainer = Db4oFactory.OpenFile(YapFileName) 04 Try 05 Dim pilot As Pilot = New Pilot("Rubens Barrichello") 06 db.Set(pilot) 07 Finally 08 db.Close() 09 End Try 10 End Sub

Now we can read the database into the memory file and work in the memory using MemoryIoAdapter:

IOExample.cs: GetObjectsInMem
01public static void GetObjectsInMem() 02 { 03 System.Console.WriteLine("Setting up in-memory database"); 04 MemoryIoAdapter adapter = new MemoryIoAdapter(); 05 try 06 { 07 Sharpen.IO.RandomAccessFile raf = new Sharpen.IO.RandomAccessFile(YapFileName,"r"); 08 adapter.GrowBy(100); 09 10 int len = (int)raf.Length(); 11 byte[] b = new byte[len]; 12 raf.Read(b,0,len); 13 adapter.Put(YapFileName, b); 14 raf.Close(); 15 } 16 catch (Exception ex) 17 { 18 System.Console.WriteLine("Exception: " + ex.Message); 19 } 20 21 Db4oFactory.Configure().Io(adapter); 22 IObjectContainer db = Db4oFactory.OpenFile(YapFileName); 23 try 24 { 25 IObjectSet result=db.Get(typeof(Pilot)); 26 System.Console.WriteLine("Read stored results through memory file"); 27 ListResult(result); 28 Pilot pilotNew = new Pilot("Michael Schumacher"); 29 db.Set(pilotNew); 30 System.Console.WriteLine("New pilot added"); 31 } 32 finally 33 { 34 db.Close(); 35 } 36 System.Console.WriteLine("Writing the database back to disc"); 37 byte[] dbstream = adapter.Get(YapFileName); 38 try 39 { 40 Sharpen.IO.RandomAccessFile file = new Sharpen.IO.RandomAccessFile(YapFileName, "rw"); 41 file.Write(dbstream); 42 file.Close(); 43 } 44 catch (IOException ioex) 45 { 46 System.Console.WriteLine("Exception: " + ioex.Message); 47 } 48 }

IOExample.vb: GetObjectsInMem
01Public Shared Sub GetObjectsInMem() 02 System.Console.WriteLine("Setting up in-memory database") 03 Dim adapter As MemoryIoAdapter = New MemoryIoAdapter() 04 Try 05 Dim raf As Sharpen.IO.RandomAccessFile = New Sharpen.IO.RandomAccessFile(YapFileName, "r") 06 adapter.GrowBy(100) 07 08 Dim len As Integer = CType(raf.Length(), Integer) 09 Dim b() As Byte = New Byte(len) {} 10 raf.Read(b, 0, len) 11 adapter.Put(YapFileName, b) 12 raf.Close() 13 Catch ex As Exception 14 System.Console.WriteLine("Exception: " + ex.Message) 15 End Try 16 17 Db4oFactory.Configure().Io(adapter) 18 Dim db As IObjectContainer = Db4oFactory.OpenFile(YapFileName) 19 Try 20 Dim result As IObjectSet = db.Get(GetType(Pilot)) 21 System.Console.WriteLine("Read stored results through memory file") 22 ListResult(result) 23 Dim pilotNew As Pilot = New Pilot("Michael Schumacher") 24 db.Set(pilotNew) 25 System.Console.WriteLine("New pilot added") 26 Finally 27 db.Close() 28 End Try 29 System.Console.WriteLine("Writing the database back to disc") 30 Dim dbstream() As Byte = adapter.Get(YapFileName) 31 Try 32 Dim file As Sharpen.IO.RandomAccessFile = New Sharpen.IO.RandomAccessFile(YapFileName, "rw") 33 file.Write(dbstream) 34 file.Close() 35 Catch ioex As IOException 36 System.Console.WriteLine("Exception: " + ioex.Message) 37 End Try 38 End Sub

Well, the changes are made and written to the disc. Let's check, if all the data are in place. We will need to switch back to the normal RandomAccessFileAdapter:

IOExample.cs: GetObjects
01public static void GetObjects() 02 { 03 Db4oFactory.Configure().Io(new RandomAccessFileAdapter()); 04 IObjectContainer db = Db4oFactory.OpenFile(YapFileName); 05 try 06 { 07 IObjectSet result=db.Get(typeof(Pilot)); 08 System.Console.WriteLine("Read stored results through disc file"); 09 ListResult(result); 10 } 11 finally 12 { 13 db.Close(); 14 } 15 }

IOExample.vb: GetObjects
01Public Shared Sub GetObjects() 02 Db4oFactory.Configure().Io(New RandomAccessFileAdapter()) 03 Dim db As IObjectContainer = Db4oFactory.OpenFile(YapFileName) 04 Try 05 Dim result As IObjectSet = db.Get(GetType(Pilot)) 06 System.Console.WriteLine("Read stored results through disc file") 07 ListResult(result) 08 Finally 09 db.Close() 10 End Try 11 End Sub

So, switching between disc and memory database is quite easy. It can be used to increase performance on certain operations. More flexibility can be reached writing your own IoAdapter implementation.