Ejemplo n.º 1
0
        public Factory <ExampleClass> .MessagePacket ReceiveMessage(Factory <ExampleClass> .MessagePacket clientMsg)
        {
            if (!ExampleSyncers.ContainsKey(clientMsg.ObjectGuid))
            {
                ExampleSyncers.Add(clientMsg.ObjectGuid, new Dictionary <Guid, Factory <ExampleClass> .Syncer>());
            }

            ExampleClass live, shadow = new ExampleClass()
            {
                Guid = clientMsg.ObjectGuid
            };

            if (ExampleDB.ContainsKey(clientMsg.ObjectGuid))
            {
                var itemRevs  = ExampleDB[clientMsg.ObjectGuid];
                var maxRev    = itemRevs.Keys.Max();
                var latestRev = itemRevs[maxRev];

                // Revision = 0 means it's the first upload, yet we have the item. This can happen if a message gets lost; the client doesn't know the server got the message
                if (clientMsg.Revision != 0)
                {
                    if (!ExampleDBByRevision.ContainsKey(clientMsg.Revision))
                    {
                        return new Factory <ExampleClass> .MessagePacket(clientMsg.SessionGuid, clientMsg.ObjectGuid, null)
                               {
                                   ClientCompleted = true, ServerError = new Exception("Could not find the given revision #")
                               }
                    }
                    ;

                    // We don't need to start from an existing shadow if the client's base version is empty (and it is likely we have a session with a good shadow already)
                    var baseRev = ExampleDBByRevision[clientMsg.Revision]; // Very important to use this as the common start point
                    shadow = baseRev;
                }

                live = latestRev;
            }
            else
            {
                // No syncer, no item; new item
                live = new ExampleClass()
                {
                    Guid = clientMsg.ObjectGuid
                };
            }

            if (!ExampleSyncers[clientMsg.ObjectGuid].ContainsKey(clientMsg.SessionGuid))
            {
                // No syncer
                if (clientMsg.Message.SenderPeerVersion != 0) // This could be because of a very old syncer that we discarded? May need to account for obsolete syncers here.
                {
                    return new Factory <ExampleClass> .MessagePacket(clientMsg.SessionGuid, clientMsg.ObjectGuid, null)
                           {
                               ClientCompleted = true, ServerError = new Exception("The SenderPeerVersion for a new syncer is not 0")
                           }
                }
                ;

                var syncer = Factory <ExampleClass> .Create(clientMsg.ObjectGuid, live.Clone(), shadow.Clone());

                syncer.ObjectGuid  = clientMsg.ObjectGuid;
                syncer.SessionGuid = clientMsg.SessionGuid;
                ExampleSyncers[clientMsg.ObjectGuid].Add(clientMsg.SessionGuid, syncer);
            }

            {
                // Syncer exists (now)
                var syncer = ExampleSyncers[clientMsg.ObjectGuid][clientMsg.SessionGuid];

                syncer.Live.StateObject.SetStateData(live.Clone());

                var changed = syncer.ReadMessageCycle(clientMsg.Message);
                if (changed)
                {
                    syncer.LiveObject.Revision = NextExampleDBRevisionID++;

                    var newRec = syncer.Live.StateObject.GetStateData();

                    if (!ExampleDB.ContainsKey(clientMsg.ObjectGuid))
                    {
                        ExampleDB.Add(clientMsg.ObjectGuid, new Dictionary <int, ExampleClass>());
                    }

                    if (ExampleDB[clientMsg.ObjectGuid].ContainsKey(newRec.Revision))
                    {
                        throw new Exception("Database already contains revision being entered.");
                    }

                    if (ExampleDBByRevision.ContainsKey(newRec.Revision))
                    {
                        throw new Exception("Database already contains revision being entered.");
                    }

                    ExampleDB[clientMsg.ObjectGuid].Add(newRec.Revision, newRec);
                    ExampleDBByRevision.Add(newRec.Revision, newRec);
                }
                var msg = syncer.MakeMessageCycle(clientMsg.Message);
                return(new Factory <ExampleClass> .MessagePacket(clientMsg.SessionGuid, clientMsg.ObjectGuid, msg));
            }
        }
    }