1

I have a server running .net 4.0 which is creating a db4o database and sending it to a client. The client is running .net 3.5, and cannot open the database (This used to work when the server was also 3.5).

The client throws a Db4oIOException with a stack trace that looks like this:

at Db4objects.Db4o.IO.ReadOnlyBin.Write(Int64 position, Byte[] bytes, Int32 bytesToWrite)
at Db4objects.Db4o.IO.BinDecorator.Write(Int64 position, Byte[] bytes, Int32 bytesToWrite)
at Db4objects.Db4o.IO.BlockAwareBin.BlockWrite(Int32 address, Int32 offset, Byte[] bytes, Int32 length)
at Db4objects.Db4o.Internal.IoAdaptedObjectContainer.WriteBytes(ByteArrayBuffer buffer, Int32 blockedAddress, Int32 addressOffset)
at Db4objects.Db4o.Internal.LocalObjectContainer.WritePointer(Int32 id, Slot slot)
at Db4objects.Db4o.Internal.LocalObjectContainer.AllocatePointerSlot()
at Db4objects.Db4o.Internal.Ids.PointerBasedIdSystem.NewId()
at Db4objects.Db4o.Internal.Ids.TransactionalIdSystemImpl.AcquireId()
at Db4objects.Db4o.Internal.Ids.TransactionalIdSystemImpl.NewId(SlotChangeFactory slotChangeFactory)
at Db4objects.Db4o.Internal.PersistentBase.Write(Transaction trans)
...

Any ideas on how to either save the database in a compatible format, or load without errors?

Additional information

I don't seem to be storing any .net 4.0 specific data. Opening the database in LINQPad and just browsing it shows only my own custom classes (which were all built under 3.5).

It seems that the object / type that db4o is trying to write is System.Reflection.Cache.InternalCache. There is an issue on db4o's Jira that might be related (or might not).

There is also a bug filed with an eerily similar stack trace.

Using Db4oEmbedded.OpenFile(Db4oConfiguration.Default(), path) causes this exception. If I use Db4oEmbedded.OpenFile(path) instead, then an exception is not thrown, but some objects are missing from the restored data.

andypaxo
  • 6,171
  • 3
  • 38
  • 53

1 Answers1

1

Looks like db4o is trying to create metadata on a read only db (ReadOnlyBin).

Are you opening the db in readonly mode?

I could reproduce your issue with the following code (you don't even need to have different versions of the framework):

  • Run the application with ProxyTuple = System.Tuple (to create the database)
  • Run it again with ProxyTyple = Db4objects.Db4o.Foundation.Tuple

The problem in this case is that I'm creating the db with System.Tuple (available on .Net 4.0) and trying to open the db on .Net 3.5 using Db4o tuple implementation (since Tuple type does not exist on .Net 3.5).

You may be running into a similar situation.

using System;
using System.IO;
using Db4objects.Db4o;
using Db4objects.Db4o.Config;

using ProxyTuple = Db4objects.Db4o.Foundation.Tuple<int, string>;
//using ProxyTuple = System.Tuple<int, string>;

namespace db4oVersionTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var databaseFileName = "test.odb";
            if (!typeof(ProxyTuple).FullName.Contains("Db4o"))
            {
                File.Delete(databaseFileName);

                using (var db = Db4oEmbedded.OpenFile(databaseFileName))
                {
                    db.Store(new Item { value = 42, tuple = new ProxyTuple(42, "forty two")});
                }
            }
            else
            {
                using (var db = Db4oEmbedded.OpenFile(NewConfiguration(), databaseFileName))
                {
                    foreach (var item in db.Query<Item>())
                    {
                        Console.WriteLine(item);
                    }
                }
            }
        }

        private static IEmbeddedConfiguration NewConfiguration()
        {
            var configuration = Db4oEmbedded.NewConfiguration();
            configuration.File.ReadOnly = true;

            return configuration;
        }
    }

    class Item
    {
        public int value;
        public ProxyTuple tuple;

        public override string ToString()
        {
            return value + " " + tuple;
        }
    }
}
Vagaus
  • 4,174
  • 20
  • 31
  • Okay, turning off read only does get rid of the exception. Now some objects are missing from the restored data. Odd thing is, I'm only saving my own (3.5 compatible) objects into the database, and not using any type aliases as far as I know. Thanks for detailing how to configure the connection, didn't have a clue how to do that! – andypaxo Apr 02 '13 at 14:13
  • If you can reproduce this issue with a realy simple assembly (with the simplest object model that causes the issue) I can debug it and try to understand. – Vagaus Apr 02 '13 at 15:05
  • In the end, I have decided that db4o is too heavyweight for what we're trying to achieve here, and have switched to .net serialization. Thanks for your answer, though... definitely learned something about db4o and I'm sure it will help others with the same issue. – andypaxo Apr 03 '13 at 15:28