[Opensim-dev] [Opensim-commits] r8236 - in trunk/OpenSim: ApplicationPlugins/Rest/Inventory Data/MSSQL Data/MySQL Data/NHibernate Data/SQLite Data/Tests Framework Framework/AssetLoader/Filesystem Framework/Communications/Cache Framework/Communications/Capabilities Grid/AssetServer Region/ClientStack/LindenUDP Region/Communications/Hypergrid Region/Environment/Modules/Agent/AssetTransaction Region/Environment/Modules/Agent/TextureSender Region/Environment/Modules/Avatar/Inventory/Archiver Region/Environment/Modules/Scripting/DynamicTexture Region/Environment/Modules/World/Archiver Region/Environment/Modules/World/Estate Region/Environment/Scenes Region/Environment/Scenes/Hypergrid Region/ScriptEngine/Shared/Api/Implementation

Mike Mazur mmazur at gmail.com
Thu Feb 5 00:27:06 UTC 2009


Hello,

I hoped this email wouldn't get too long, but I'm not sure I succeeded.
Hopefully it's clear and reads quick.

On Wed, 04 Feb 2009 07:41:03 -0500
Sean Dague <sdague at gmail.com> wrote:

> mikem at opensimulator.org wrote:
> > Author: mikem
> > Date: 2009-02-03 16:01:36 -0800 (Tue, 03 Feb 2009)
> > New Revision: 8236
> 
> Ok, I'm reading through this patch, and it makes everything far more
> confusing.  Now we are flattening and unflattening between 1 and 2
> objects when we touch xml and the database.

Which XML are you referring to? Is it the NHibernate AssetBase mapping
XML (OpenSim/Data/NHibernate/Resources/AssetBase.hbm.xml)?

> We need to either decide the Metadata is really seperate, in which
> case it's a 2nd level entity in the database and the xml (i.e. new
> table and nested xml), or it isn't, and we got back.  This midway
> point is madness.

Currently in the database the assets table contains the following
columns:

- id (primary key)
- data
- name
- description
- assetType
- local
- temporary
- create_time
- access_time

Of these columns, everything except data (and probably id) is actually
metadata that describes the asset. In the database it makes sense to
store all this information in the same table since there's a tight
coupling between the data and its metadata.

In the code the AssetBase class is mapped directly to the assets
database table, with class properties mapping directly to columns (ie:
AssetBase.Name <=> assets.name). In order to retrieve asset metadata
from the database, all information is retrieved, including the
potentially large data. This is undesirable if the application is
simply listing assets, for instance.

My commit introduced an AssetMetadata class which represents all the
columns in the assets table except data. This class can be used when
only the metadata is needed in the application, while the AssetBase
class, which is composed of the AssetMetadata class, can be used when
the asset in its entirety is required.

> 1 object per database table please.  Anything else is insanity for a
> datamodel.

So yes, there are two classes in the code, and one table in the
database. In this case I think it makes sense and it doesn't make the
datamodel very much more complicated.

The 1 object per database table rule is a good one, but like all rules
it's important to remember there are exceptions.

If we decide to go back to the single AssetBase class to represent an
asset and its metadata, we could represent the asset metadata in the
code with an AssetBase instance with its data field set to null:

  AssetBase asset = new AssetBase();
  asset.FullID = dbresult.ID;
  asset.Name = dbresult.Name;
  asset.Data = null;

I can see the resulting code throughout OpenSim becoming more
complicated, because each use of an AssetBase instance requires a
null-check on the Data property to see whether we have a complete asset
or only its metadata.

Having two DB tables, assets and assetmetada, means retrieving all
information requires a join across two tables. Also, potentially three
classes may be required to represent asset metadata, asset data only,
and asset data and metadata together (I haven't through this through so
there's probably a cleaner way).

Another option I see is for the AssetMetadata class to be defined as a
nested class of the AssetBase class. For example:

  public class AssetBase
  {
    public class Metadata
    {
      public string Name;
      public string Description;
      // etc
    }

    private byte[] _data;
    private Metadata _metadata = new Metadata();

    public string Name
    {
      get { return _metadata.Name; }
      set { _metadata.Name = value; }
    }
    // etc
  }

Then the metadata class could be instantiated alone as well (I think):

  AssetBase.Metadata some_metadata = new AssetBase.Metadata();
  some_metadata.Name = "blah";

In my opinion the current mapping of two classes to one table is a
reasonable departure from the one-class-one-table rule of thumb.

If the decision is made to stick to this rule, though, then my vote is
to split the assets table into two tables, as I see benefits to
naturally support retrieving asset metadata only.

Thanks,
Mike



More information about the Opensim-dev mailing list