Beispiel #1
0
        /// <summary>
        /// This is an extension of an in-memory provider sample that is used to illustrate the responsibilites of a provider working on behalf 
        /// of a store. For instance, what do do with an item create/update/delete, how to get changes, how to apply changes, how to detect conflicts, 
        /// and how to resolve them using a custom action such as merge...
        /// 
        /// Please note that this sample is most useful with breakpoints in MyTestProgram.cs to find out HOW synchronization using the 
        /// Microsoft Sync Framework works. This sample is not designed to be a boot-strapper like the NTFS providers for native and managed...
        /// </summary>
        /// <param name="args"></param>
        public static void Main(string[] args)
        {
            const string DATA = "data";
            string providerA = "A";
            string providerB = "B";
            string providerC = "C";
            List<string> arguments = new List<string>(args);

            //start clean
            CleanUpProvider(providerA);
            CleanUpProvider(providerB);
            CleanUpProvider(providerC);

            //Initialize the stores
            storeA = new MySimpleDataStore();
            storeB = new MySimpleDataStore();
            storeC = new MySimpleDataStore();

            //Create items on each store using a global ID and the data of the item (Note, in order to verify results against
            //a baseline we are using hardcoded global ids for the items. In a real application CreateItem should be called without
            //the Guid parameter, which would generate a new Guid id and return it.
            Guid[] itemIds = new Guid[9];
            itemIds[1] = new Guid("11111111-1111-1111-1111-111111111111");
            itemIds[2] = new Guid("22222222-2222-2222-2222-222222222222");
            itemIds[3] = new Guid("33333333-3333-3333-3333-333333333333");
            itemIds[4] = new Guid("44444444-4444-4444-4444-444444444444");
            itemIds[5] = new Guid("55555555-5555-5555-5555-555555555555");
            itemIds[6] = new Guid("66666666-6666-6666-6666-666666666666");
            itemIds[7] = new Guid("77777777-7777-7777-7777-777777777777");
            itemIds[8] = new Guid("88888888-8888-8888-8888-888888888888");

            storeA.CreateItem(new ItemData(DATA, "1"), itemIds[1]);
            storeA.CreateItem(new ItemData(DATA, "2"), itemIds[2]);
            storeA.CreateItem(new ItemData(DATA, "7"), itemIds[7]);
            storeA.CreateItem(new ItemData(DATA, "8"), itemIds[8]);
            storeB.CreateItem(new ItemData(DATA, "3"), itemIds[3]);
            storeB.CreateItem(new ItemData(DATA, "4"), itemIds[4]);
            storeC.CreateItem(new ItemData(DATA, "5"), itemIds[5]);
            storeC.CreateItem(new ItemData(DATA, "6"), itemIds[6]);

            //Show the contents of the stores, prior to ANY any synchronization...
            Console.WriteLine("Show the contents of the stores, prior to any synchronization...");
            Console.WriteLine(new MySyncProvider(providerA, storeA).ToString());
            Console.WriteLine(storeA.ToString());
            Console.WriteLine(new MySyncProvider(providerB, storeB).ToString());
            Console.WriteLine(storeB.ToString());
            Console.WriteLine(new MySyncProvider(providerC, storeC).ToString());
            Console.WriteLine(storeC.ToString());

            //Sync providers A and provider B
            DoBidirectionalSync(providerA, storeA, providerB, storeB);

            if (arguments.Contains("-q") != true)
            {
                Console.WriteLine("Sync has finished...");
                Console.ReadLine();
            }
            //Create an update-update conflict on item 1 and show merge... (Note - this sample handles update-update conflicts and simply merges the data)
            Console.WriteLine("A and B are going to create a conflict on item 1. A writes 'Did Merging' and B writes 'Work?'");

            //Create an update-update conflict to merge...
            storeA.UpdateItem(itemIds[1], new ItemData(DATA, "Did Merging"));
            storeB.UpdateItem(itemIds[1], new ItemData(DATA, " Work?"));

            //Sync providers A and provider B
            DoBidirectionalSync(providerA, storeA, providerB, storeB);

            //Delete an item on B and show that the delete propagates
            Console.WriteLine("Deleting item '4' on B");
            storeB.DeleteItem(itemIds[4]);

            //Sync B and C
            DoBidirectionalSync(providerB, storeB, providerC, storeC);

            //Close the sync loop by syncing A and C
            Console.WriteLine("Closing the \"sync loop\" by syncing A and C...");
            DoBidirectionalSync(providerA, storeA, providerC, storeC);

            //Delete item 2 on B
            Console.WriteLine("{0}Deleting item '2' on B.", Environment.NewLine);
            storeB.DeleteItem(itemIds[2]);

            // Sync B and C
            DoBidirectionalSync(providerB, storeB, providerC, storeC);

            //Cleanup Tombstones on B
            Console.WriteLine("{0}Clean up Tombstones on B.", Environment.NewLine);
            new MySyncProvider(providerB, storeB).CleanupTombstones(TimeSpan.Zero);

            // Sync B and C
            DoBidirectionalSync(providerB, storeB, providerC, storeC);

            //Close the sync loop by syncing A and C
            DoBidirectionalSync(providerA, storeA, providerC, storeC);

            if (arguments.Contains("-q") != true)
            {
                Console.WriteLine("Sync has finished...");
                Console.ReadLine();
            }
        }
Beispiel #2
0
        //Save the item, taking the appropriate action for the 'change' and the data from the item (in 'context')
        public void SaveItemChange(SaveChangeAction saveChangeAction, ItemChange change, SaveChangeContext context)
        {
            Thread.Sleep(1000);

            ulong        timeStamp = 0;
            ItemMetadata item      = null;
            ItemData     data      = null;

            change.WorkEstimate = 1;
            switch (saveChangeAction)
            {
            case SaveChangeAction.Create:
                //Do duplicate detection here
                item = _metadata.FindItemMetadataById(change.ItemId);
                if (null != item)
                {
                    throw new Exception("SaveItemChange must not have Create action for existing items.");
                }
                item = _metadata.CreateItemMetadata(change.ItemId, change.CreationVersion);
                item.ChangeVersion = change.ChangeVersion;
                data = new ItemData((ItemData)context.ChangeData);
                //We are using the same id for both the local and global item id.
                _store.CreateItem(data, change.ItemId.GetGuidId());
                SaveItemMetadata(item, _store.Get(change.ItemId.GetGuidId()).TimeStamp);
                break;

            case SaveChangeAction.UpdateVersionAndData:
            case SaveChangeAction.UpdateVersionOnly:
                item = _metadata.FindItemMetadataById(change.ItemId);
                if (null == item)
                {
                    throw new Exception("Item Not Found in Store!?");
                }

                item.ChangeVersion = change.ChangeVersion;
                if (saveChangeAction == SaveChangeAction.UpdateVersionOnly)
                {
                    SaveItemMetadata(item);
                }
                else      //Also update the data and the timestamp.
                {
                    data      = new ItemData((ItemData)context.ChangeData);
                    timeStamp = _store.UpdateItem(item.GlobalId.GetGuidId(), data);
                    SaveItemMetadata(item, timeStamp);
                }
                break;

            case SaveChangeAction.DeleteAndStoreTombstone:
                item = _metadata.FindItemMetadataById(change.ItemId);
                if (null == item)
                {
                    item = _metadata.CreateItemMetadata(change.ItemId, change.CreationVersion);
                }

                if (change.ChangeKind == ChangeKind.Deleted)
                {
                    item.MarkAsDeleted(change.ChangeVersion);
                }
                else
                {
                    // This should never happen in Sync Framework V1.0
                    throw new Exception("Invalid ChangeType");
                }

                item.ChangeVersion = change.ChangeVersion;
                SaveItemMetadata(item, 0);      // set timestamp to 0 for tombstones
                _store.DeleteItem(item.GlobalId.GetGuidId());
                break;

            //Merge the changes! (Take the data from the local item + the remote item),noting to update the tick count to propagate the resolution!
            case SaveChangeAction.UpdateVersionAndMergeData:
                item = _metadata.FindItemMetadataById(change.ItemId);

                if (null == item)
                {
                    throw new Exception("Item Not Found in Store!?");
                }
                if (item.IsDeleted != true)
                {
                    //Note - you must update the change version to propagate the resolution!
                    item.ChangeVersion = new SyncVersion(0, _metadata.GetNextTickCount());

                    //Combine the conflicting data...
                    ItemData mergedData = (_store.Get(item.GlobalId.GetGuidId())).Merge((ItemData)context.ChangeData);
                    timeStamp = _store.UpdateItem(item.GlobalId.GetGuidId(), mergedData);
                    SaveItemMetadata(item, timeStamp);
                }
                break;

            case SaveChangeAction.DeleteAndRemoveTombstone:
                item = _metadata.FindItemMetadataById(change.ItemId);
                if (item != null)
                {
                    List <SyncId> ids = new List <SyncId>();
                    ids.Add(item.GlobalId);
                    _metadata.RemoveItemMetadata(ids);
                }
                _store.DeleteItem(change.ItemId.GetGuidId());
                break;
            }
        }
Beispiel #3
0
        /// <summary>
        /// This is an extension of an in-memory provider sample that is used to illustrate the responsibilites of a provider working on behalf
        /// of a store. For instance, what do do with an item create/update/delete, how to get changes, how to apply changes, how to detect conflicts,
        /// and how to resolve them using a custom action such as merge...
        ///
        /// Please note that this sample is most useful with breakpoints in MyTestProgram.cs to find out HOW synchronization using the
        /// Microsoft Sync Framework works. This sample is not designed to be a boot-strapper like the NTFS providers for native and managed...
        /// </summary>
        /// <param name="args"></param>
        public static void Main(string[] args)
        {
            const string  DATA      = "data";
            string        providerA = "A";
            string        providerB = "B";
            string        providerC = "C";
            List <string> arguments = new List <string>(args);

            //start clean
            CleanUpProvider(providerA);
            CleanUpProvider(providerB);
            CleanUpProvider(providerC);

            //Initialize the stores
            storeA = new MySimpleDataStore();
            storeB = new MySimpleDataStore();
            storeC = new MySimpleDataStore();

            //Create items on each store using a global ID and the data of the item (Note, in order to verify results against
            //a baseline we are using hardcoded global ids for the items. In a real application CreateItem should be called without
            //the Guid parameter, which would generate a new Guid id and return it.
            Guid[] itemIds = new Guid[9];
            itemIds[1] = new Guid("11111111-1111-1111-1111-111111111111");
            itemIds[2] = new Guid("22222222-2222-2222-2222-222222222222");
            itemIds[3] = new Guid("33333333-3333-3333-3333-333333333333");
            itemIds[4] = new Guid("44444444-4444-4444-4444-444444444444");
            itemIds[5] = new Guid("55555555-5555-5555-5555-555555555555");
            itemIds[6] = new Guid("66666666-6666-6666-6666-666666666666");
            itemIds[7] = new Guid("77777777-7777-7777-7777-777777777777");
            itemIds[8] = new Guid("88888888-8888-8888-8888-888888888888");



            storeA.CreateItem(new ItemData(DATA, "1"), itemIds[1]);
            storeA.CreateItem(new ItemData(DATA, "2"), itemIds[2]);
            storeA.CreateItem(new ItemData(DATA, "7"), itemIds[7]);
            storeA.CreateItem(new ItemData(DATA, "8"), itemIds[8]);
            storeB.CreateItem(new ItemData(DATA, "3"), itemIds[3]);
            storeB.CreateItem(new ItemData(DATA, "4"), itemIds[4]);
            storeC.CreateItem(new ItemData(DATA, "5"), itemIds[5]);
            storeC.CreateItem(new ItemData(DATA, "6"), itemIds[6]);

            //Show the contents of the stores, prior to ANY any synchronization...
            Console.WriteLine("Show the contents of the stores, prior to any synchronization...");
            Console.WriteLine(new MySyncProvider(providerA, storeA).ToString());
            Console.WriteLine(storeA.ToString());
            Console.WriteLine(new MySyncProvider(providerB, storeB).ToString());
            Console.WriteLine(storeB.ToString());
            Console.WriteLine(new MySyncProvider(providerC, storeC).ToString());
            Console.WriteLine(storeC.ToString());

            //Sync providers A and provider B
            DoBidirectionalSync(providerA, storeA, providerB, storeB);

            if (arguments.Contains("-q") != true)
            {
                Console.WriteLine("Sync has finished...");
                Console.ReadLine();
            }
            //Create an update-update conflict on item 1 and show merge... (Note - this sample handles update-update conflicts and simply merges the data)
            Console.WriteLine("A and B are going to create a conflict on item 1. A writes 'Did Merging' and B writes 'Work?'");

            //Create an update-update conflict to merge...
            storeA.UpdateItem(itemIds[1], new ItemData(DATA, "Did Merging"));
            storeB.UpdateItem(itemIds[1], new ItemData(DATA, " Work?"));

            //Sync providers A and provider B
            DoBidirectionalSync(providerA, storeA, providerB, storeB);

            //Delete an item on B and show that the delete propagates
            Console.WriteLine("Deleting item '4' on B");
            storeB.DeleteItem(itemIds[4]);

            //Sync B and C
            DoBidirectionalSync(providerB, storeB, providerC, storeC);

            //Close the sync loop by syncing A and C
            Console.WriteLine("Closing the \"sync loop\" by syncing A and C...");
            DoBidirectionalSync(providerA, storeA, providerC, storeC);

            //Delete item 2 on B
            Console.WriteLine("{0}Deleting item '2' on B.", Environment.NewLine);
            storeB.DeleteItem(itemIds[2]);

            // Sync B and C
            DoBidirectionalSync(providerB, storeB, providerC, storeC);

            //Cleanup Tombstones on B
            Console.WriteLine("{0}Clean up Tombstones on B.", Environment.NewLine);
            new MySyncProvider(providerB, storeB).CleanupTombstones(TimeSpan.Zero);

            // Sync B and C
            DoBidirectionalSync(providerB, storeB, providerC, storeC);

            //Close the sync loop by syncing A and C
            DoBidirectionalSync(providerA, storeA, providerC, storeC);

            if (arguments.Contains("-q") != true)
            {
                Console.WriteLine("Sync has finished...");
                Console.ReadLine();
            }
        }