protected override void LoadInternal(ref ObjectModel objectModel) { FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel); if (fsom == null) { throw new ObjectModelNotSupportedException(); } Reader reader = Accessor.Reader; string signature = reader.ReadFixedLengthString(8); if (!signature.Equals("slick!\0\0")) { Console.Error.WriteLine("expected 'slick!\\0\\0', got '{0}'", signature); throw new InvalidDataFormatException(); } float version = reader.ReadSingle(); if (version != 1.0f) { throw new InvalidDataFormatException(); } FileNameSize = reader.ReadInt32(); int fileCount = reader.ReadInt32(); for (int i = 0; i < fileCount; i++) { string fileName = reader.ReadFixedLengthString(FileNameSize).TrimNull(); int offset = reader.ReadInt32(); int length = reader.ReadInt32(); File file = fsom.AddFile(fileName); file.Properties["reader"] = reader; file.Properties["offset"] = offset; file.Properties["length"] = length; file.DataRequest += File_DataRequest; } }
protected override void BeforeSaveInternal(Stack <ObjectModel> objectModels) { base.BeforeSaveInternal(objectModels); FileNameSize = 32; ObjectModel om = objectModels.Pop(); MochaClassLibraryObjectModel mcl = (om as MochaClassLibraryObjectModel); MochaSnapshotObjectModel mcx = (om as MochaSnapshotObjectModel); if (mcl == null && mcx == null) { throw new ObjectModelNotSupportedException(); } FileSystemObjectModel fsom = new FileSystemObjectModel(); List <Guid> _instanceIndices = new List <Guid>(); List <string> _stringTable = new List <string>(); if (mcl != null) { #region Libraries { File f = fsom.AddFile("Libraries"); MemoryAccessor ma = new MemoryAccessor(); ma.Writer.WriteInt32(mcl.Libraries.Count); for (int i = 0; i < mcl.Libraries.Count; i++) { ma.Writer.WriteGuid(mcl.Libraries[i].ID); ma.Writer.WriteInt32(mcl.Libraries[i].Instances.Count); ma.Writer.WriteInt32(mcl.Libraries[i].Relationships.Count); } ma.Close(); f.SetData(ma.ToArray()); } #endregion #region Instances { File f = fsom.AddFile("Instances"); MemoryAccessor ma = new MemoryAccessor(); for (int i = 0; i < mcl.Libraries.Count; i++) { ma.Writer.WriteInt32(mcl.Libraries[i].Instances.Count); for (int j = 0; j < mcl.Libraries[i].Instances.Count; j++) { ma.Writer.WriteInt32(AddOrUpdateLookupTable <Guid>(_instanceIndices, mcl.Libraries[i].Instances[j].ID)); ma.Writer.WriteInt32(mcl.Libraries[i].Instances[j].AttributeValues.Count); MochaInstanceFlags flags = MochaInstanceFlags.None; if (mcl.Libraries[i].Instances[j].Index != null) { flags |= MochaInstanceFlags.HasIndex; } ma.Writer.WriteInt32((int)flags); if ((flags & MochaInstanceFlags.HasIndex) == MochaInstanceFlags.HasIndex) { ma.Writer.WriteInt32(mcl.Libraries[i].Instances[j].Index.Value); } } } ma.Close(); f.SetData(ma.ToArray()); } #endregion #region Attributes { File f = fsom.AddFile("Attributes"); MemoryAccessor ma = new MemoryAccessor(); for (int i = 0; i < mcl.Libraries.Count; i++) { /* * writer.WriteInt32(mcl.Libraries[i].Metadata.Count); * for (int j = 0; j < mcl.Libraries[i].Metadata.Count; j++) * { * writer.WriteNullTerminatedString(mcl.Libraries[i].Metadata[j].Name); * writer.WriteNullTerminatedString(mcl.Libraries[i].Metadata[j].Value); * } */ for (int j = 0; j < mcl.Libraries[i].Instances.Count; j++) { for (int k = 0; k < mcl.Libraries[i].Instances[j].AttributeValues.Count; k++) { ma.Writer.WriteInt32(AddOrUpdateLookupTable <Guid>(_instanceIndices, mcl.Libraries[i].Instances[j].AttributeValues[k].AttributeInstanceID)); if (mcl.Libraries[i].Instances[j].AttributeValues[k].Value == null) { ma.Writer.WriteInt32((int)MochaAttributeType.None); } else if (mcl.Libraries[i].Instances[j].AttributeValues[k].Value is string) { ma.Writer.WriteInt32((int)MochaAttributeType.Text); ma.Writer.WriteInt32(AddOrUpdateLookupTable <string>(_stringTable, mcl.Libraries[i].Instances[j].AttributeValues[k].Value as string)); } else { ma.Writer.WriteInt32((int)MochaAttributeType.Unknown); ma.Writer.WriteObject(mcl.Libraries[i].Instances[j].AttributeValues[k].Value); } } } } ma.Close(); f.SetData(ma.ToArray()); } #endregion #region Relationships { File f = fsom.AddFile("Relationships"); MemoryAccessor ma = new MemoryAccessor(); for (int i = 0; i < mcl.Libraries.Count; i++) { for (int j = 0; j < mcl.Libraries[i].Relationships.Count; j++) { ma.Writer.WriteInt32(AddOrUpdateLookupTable <Guid>(_instanceIndices, mcl.Libraries[i].Relationships[j].RelationshipInstanceID)); ma.Writer.WriteInt32(AddOrUpdateLookupTable <Guid>(_instanceIndices, mcl.Libraries[i].Relationships[j].SourceInstanceID)); ma.Writer.WriteInt32(mcl.Libraries[i].Relationships[j].DestinationInstanceIDs.Count); for (int k = 0; k < mcl.Libraries[i].Relationships[j].DestinationInstanceIDs.Count; k++) { ma.Writer.WriteInt32(AddOrUpdateLookupTable <Guid>(_instanceIndices, mcl.Libraries[i].Relationships[j].DestinationInstanceIDs[k])); } } } ma.Close(); f.SetData(ma.ToArray()); } #endregion #region Tenants { if (mcl.Tenants.Count > 0) { File f = fsom.AddFile("Tenants"); MemoryAccessor ma = new MemoryAccessor(); ma.Writer.WriteInt32(mcl.Tenants.Count); foreach (MochaTenant tenant in mcl.Tenants) { ma.Writer.WriteInt32(AddOrUpdateLookupTable <Guid>(_instanceIndices, tenant.ID)); ma.Writer.WriteInt32(AddOrUpdateLookupTable <string>(_stringTable, tenant.Name)); ma.Writer.WriteInt32(tenant.LibraryReferences.Count); for (int i = 0; i < tenant.LibraryReferences.Count; i++) { ma.Writer.WriteInt32(AddOrUpdateLookupTable <Guid>(_instanceIndices, tenant.LibraryReferences[i].LibraryID)); } ma.Writer.WriteInt32(tenant.Instances.Count); for (int i = 0; i < tenant.Instances.Count; i++) { ma.Writer.WriteInt32(AddOrUpdateLookupTable <Guid>(_instanceIndices, tenant.Instances[i].ID)); } ma.Writer.WriteInt32(tenant.Relationships.Count); for (int i = 0; i < tenant.Relationships.Count; i++) { ma.Writer.WriteInt32(AddOrUpdateLookupTable <Guid>(_instanceIndices, tenant.Relationships[i].SourceInstanceID)); ma.Writer.WriteInt32(AddOrUpdateLookupTable <Guid>(_instanceIndices, tenant.Relationships[i].RelationshipInstanceID)); ma.Writer.WriteInt32(tenant.Relationships[i].DestinationInstanceIDs.Count); for (int j = 0; j < tenant.Relationships[i].DestinationInstanceIDs.Count; j++) { ma.Writer.WriteInt32(AddOrUpdateLookupTable <Guid>(_instanceIndices, tenant.Relationships[i].DestinationInstanceIDs[j])); } } } ma.Close(); f.SetData(ma.ToArray()); } } #endregion } else if (mcx != null) { #region Journal { if (mcx.Transactions.Count > 0) { File f = fsom.AddFile("Journal"); MemoryAccessor ma = new MemoryAccessor(); foreach (MochaSnapshotTransaction t in mcx.Transactions) { ma.Writer.WriteByte((byte)MochaOpcode.BeginTransaction); ma.Writer.WriteInt32(AddOrUpdateLookupTable <string>(_stringTable, t.TenantName)); foreach (MochaSnapshotTransactionOperation op in t.Operations) { if (op is MochaSnapshotCreateInstanceTransactionOperation ci) { ma.Writer.WriteByte((byte)MochaOpcode.CreateInstance); ma.Writer.WriteDateTime(ci.EffectiveDate); ma.Writer.WriteInt32(AddOrUpdateLookupTable <Guid>(_instanceIndices, ci.GlobalIdentifier)); ma.Writer.WriteInt32(AddOrUpdateLookupTable <Guid>(_instanceIndices, ci.ClassGlobalIdentifier)); } else if (op is MochaSnapshotAssignAttributeTransactionOperation aa) { ma.Writer.WriteByte((byte)MochaOpcode.AssignAttribute); ma.Writer.WriteDateTime(aa.EffectiveDate); ma.Writer.WriteInt32(AddOrUpdateLookupTable <Guid>(_instanceIndices, aa.SourceInstanceID)); ma.Writer.WriteInt32(AddOrUpdateLookupTable <Guid>(_instanceIndices, aa.AttributeInstanceID)); WriteMochaValue(ma.Writer, aa.Value, _stringTable); } else if (op is MochaSnapshotAssociateRelationshipTransactionOperation ar) { ma.Writer.WriteByte((byte)MochaOpcode.CreateRelationship); ma.Writer.WriteDateTime(ar.EffectiveDate); ma.Writer.WriteInt32(AddOrUpdateLookupTable <Guid>(_instanceIndices, ar.SourceInstanceID)); ma.Writer.WriteInt32(AddOrUpdateLookupTable <Guid>(_instanceIndices, ar.RelationshipInstanceID)); ma.Writer.WriteInt32(ar.TargetInstanceIDs.Count); foreach (Guid id in ar.TargetInstanceIDs) { ma.Writer.WriteInt32(AddOrUpdateLookupTable <Guid>(_instanceIndices, id)); } } } ma.Writer.WriteByte((byte)MochaOpcode.EndTransaction); } ma.Close(); f.SetData(ma.ToArray()); } } #endregion } #region Guid Table { File f = fsom.AddFile("GlobalIdentifiers"); MemoryAccessor ma = new MemoryAccessor(); ma.Writer.WriteInt32(_instanceIndices.Count); foreach (Guid id in _instanceIndices) { ma.Writer.WriteGuid(id); } ma.Close(); f.SetData(ma.ToArray()); } #endregion #region String Table { File f = fsom.AddFile("StringTable"); MemoryAccessor ma = new MemoryAccessor(); ma.Writer.WriteInt32(_stringTable.Count); foreach (string id in _stringTable) { ma.Writer.WriteNullTerminatedString(id); } ma.Close(); f.SetData(ma.ToArray()); } #endregion objectModels.Push(fsom); }