/// <summary>
        /// Register an activated (has reconstituted object) surrogate from the data store.
        /// </summary>
        internal void RegisterActivatedSurrogate(ICmObjectSurrogate surrogate)
        {
            if (surrogate == null)
            {
                throw new ArgumentNullException("surrogate");
            }
            if (!surrogate.HasObject)
            {
                throw new InvalidOperationException("Has not been reconstituted.");
            }

            ICmObject obj     = surrogate.Object;
            var       realObj = (ICmObjectOrSurrogate)obj;

            lock (SyncRoot)
            {
                if (!m_IdentityMap.ContainsKey(surrogate.Id))
                {
                    throw new InvalidOperationException("Has not been registered.");
                }

                // Replace the surrogate with the real object in all the places that we store it so it can be
                // garbage collected.
                m_IdentityMap[surrogate.Id] = realObj;
                var occurrenceSet = m_clsid2Surrogates[m_mdc.GetClassId(surrogate.Classname)];
                // These objects are considered equal by the set Equater; but calling Add on a set
                // does not replace the existing object with an equal one. So we must remove and re-add.
                occurrenceSet.Remove(surrogate);
                occurrenceSet.Add(realObj);

                RegisterObjectHvo(obj);
            }
        }
Example #2
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <remarks>
        /// This Constructor is used for porting from one BEP to another.
        /// It's faster than getting all the stuff from the xml string.
        /// </remarks>
        internal CmObjectSurrogate(LcmCache cache, ICmObjectSurrogate sourceSurrogate)
        {
            if (cache == null)
            {
                throw new ArgumentNullException("cache");
            }
            if (sourceSurrogate == null)
            {
                throw new ArgumentNullException("sourceSurrogate");
            }

            var surr = (CmObjectSurrogate)sourceSurrogate;

            m_cache  = cache;
            m_object = null;
            if (surr.RawXmlBytes != null)
            {
                RawXmlBytes = surr.RawXmlBytes;
            }
            else
            {
                Xml = sourceSurrogate.XML;
            }
            ICmObjectId objId = surr.Id;

            m_guid = objId is CmObjectIdWithHvo ? objId
                                : ((IServiceLocatorInternal)cache.ServiceLocator).IdentityMap.CreateObjectIdWithHvo(objId.Guid);
            SetClassName(surr.m_classname);
        }
        /// <summary>
        /// Register an inactive (as no object) surrogate from the data store.
        /// The data needs to be converted, so do the bare minimum registration.
        /// </summary>
        internal void RegisterSurrogateForConversion(ICmObjectSurrogate surrogate)
        {
            if (surrogate == null)
            {
                throw new ArgumentNullException("surrogate");
            }
            if (surrogate.HasObject)
            {
                throw new InvalidOperationException("Has already been reconstituted.");
            }

            m_IdentityMap[surrogate.Id] = surrogate;
        }
        /// <summary>
        /// Register an inactive (as no object) surrogate from the data store.
        /// </summary>
        internal void RegisterInactiveSurrogate(ICmObjectSurrogate surrogate)
        {
            if (surrogate == null)
            {
                throw new ArgumentNullException("surrogate");
            }
            if (surrogate.HasObject)
            {
                throw new InvalidOperationException("Has already been reconstituted.");
            }

            RegisterSurrogate(surrogate);
        }
 private void RegisterSurrogate(ICmObjectSurrogate surrogate)
 {
     m_IdentityMap[surrogate.Id] = surrogate;
     m_clsid2Surrogates[m_mdc.GetClassId(surrogate.Classname)].Add(surrogate);
 }
        /// <summary>
        /// Gets all unseen foreign changes from the commit log. The metadata should be saved after calling this method,
        /// because inactive records might have been purged.
        /// </summary>
        private bool GetUnseenForeignChanges(CommitLogMetadata metadata,
                                             out List <ICmObjectSurrogate> foreignNewbies,
                                             out List <ICmObjectSurrogate> foreignDirtballs,
                                             out List <ICmObjectId> foreignGoners)
        {
            foreignNewbies   = new List <ICmObjectSurrogate>();
            foreignDirtballs = new List <ICmObjectSurrogate>();
            foreignGoners    = new List <ICmObjectId>();

            int minPeerGeneration = metadata.Peers.Select(p => p.Key == m_peerID ? metadata.CurrentGeneration : p.Value.Generation).Min();
            var unseenCommitRecs  = new List <CommitLogRecord>();

            int bytesRemaining = metadata.LogLength;
            // read all records up to the end of the file or the end of the log, whichever comes first
            int length = Math.Min(metadata.LogLength, m_settings.SharedXMLBackendCommitLogSize - metadata.LogOffset - metadata.Padding);

            bytesRemaining -= ReadUnseenCommitRecords(metadata, minPeerGeneration, metadata.LogOffset, length, unseenCommitRecs);
            // if there are bytes remaining, it means that we hit the end of the file, so we need to wrap around to the beginning
            if (bytesRemaining > 0)
            {
                bytesRemaining -= ReadUnseenCommitRecords(metadata, minPeerGeneration, 0, bytesRemaining, unseenCommitRecs);
            }
            Debug.Assert(bytesRemaining == 0);

            if (unseenCommitRecs.Count == 0)
            {
                return(false);
            }

            // check if there was enough room in the commit log for the last peer to write its commit
            // if it was not able, then we cannot continue, because we will be out-of-sync
            if (unseenCommitRecs[unseenCommitRecs.Count - 1].WriteGeneration < metadata.CurrentGeneration)
            {
                throw new InvalidOperationException("The most recent unseen commit could not be found.");
            }

            var idFactory = m_cache.ServiceLocator.GetInstance <ICmObjectIdFactory>();

            var newbies   = new Dictionary <Guid, ICmObjectSurrogate>();
            var dirtballs = new Dictionary <Guid, ICmObjectSurrogate>();
            var goners    = new HashSet <Guid>();

            var surrogateFactory = m_cache.ServiceLocator.GetInstance <ICmObjectSurrogateFactory>();

            foreach (CommitLogRecord commitRec in unseenCommitRecs)
            {
                if (commitRec.ObjectsDeleted != null)
                {
                    foreach (Guid goner in commitRec.ObjectsDeleted)
                    {
                        // If it was created by a previous foreign change we haven't seen, we can just forget it.
                        if (newbies.Remove(goner))
                        {
                            continue;
                        }
                        // If it was modified by a previous foreign change we haven't seen, we can forget the modification.
                        // (but we still need to know it's gone).
                        dirtballs.Remove(goner);
                        goners.Add(goner);
                    }
                }
                if (commitRec.ObjectsUpdated != null)
                {
                    foreach (byte[] dirtballXml in commitRec.ObjectsUpdated)
                    {
                        ICmObjectSurrogate dirtballSurrogate = surrogateFactory.Create(dirtballXml);
                        // This shouldn't be necessary; if a previous foreign transaction deleted it, it
                        // should not show up as a dirtball in a later transaction until it has shown up as a newby.
                        // goners.Remove(dirtball);
                        // If this was previously known as a newby or modified, then to us it still is.
                        if (newbies.ContainsKey(dirtballSurrogate.Guid) || dirtballs.ContainsKey(dirtballSurrogate.Guid))
                        {
                            continue;
                        }
                        dirtballs[dirtballSurrogate.Guid] = dirtballSurrogate;
                    }
                }
                if (commitRec.ObjectsAdded != null)
                {
                    foreach (byte[] newbyXml in commitRec.ObjectsAdded)
                    {
                        ICmObjectSurrogate newObj = surrogateFactory.Create(newbyXml);
                        if (goners.Remove(newObj.Guid))
                        {
                            // an object which an earlier transaction deleted is being re-created.
                            // This means that to us, it is a dirtball.
                            dirtballs[newObj.Guid] = newObj;
                            continue;
                        }
                        // It shouldn't be in dirtballs; can't be new in one transaction without having been deleted previously.
                        // So it really is new.
                        newbies[newObj.Guid] = newObj;
                    }
                }
                foreignNewbies.AddRange(newbies.Values);
                foreignDirtballs.AddRange(dirtballs.Values);
                foreignGoners.AddRange(from guid in goners select idFactory.FromGuid(guid));
            }
            return(true);
        }
Example #7
0
		/// <summary>
		/// Constructor.
		/// </summary>
		/// <remarks>
		/// This Constructor is used for porting from one BEP to another.
		/// It's faster than getting all the stuff from the xml string.
		/// </remarks>
		internal CmObjectSurrogate(FdoCache cache, ICmObjectSurrogate sourceSurrogate)
		{
			if (cache == null) throw new ArgumentNullException("cache");
			if (sourceSurrogate == null) throw new ArgumentNullException("sourceSurrogate");

			var surr = (CmObjectSurrogate) sourceSurrogate;
			m_cache = cache;
			m_object = null;
			if (surr.RawXmlBytes != null)
				RawXmlBytes = surr.RawXmlBytes;
			else
				Xml = sourceSurrogate.XML;
			ICmObjectId objId = surr.Id;
			m_guid = objId is CmObjectIdWithHvo ? objId
				: ((IServiceLocatorInternal)cache.ServiceLocator).IdentityMap.CreateObjectIdWithHvo(objId.Guid);
			SetClassName(surr.m_classname);
		}