protected ShardedSessionFactoryImpl(
            ShardedSessionFactoryImpl parent,
            IEnumerable <ShardId> shardIds,
            IShardStrategyFactory shardStrategyFactory)
        {
            this.shardIdsBySessionFactory                    = new Dictionary <ISessionFactoryImplementor, ICollection <ShardId> >();
            this.classesWithoutTopLevelSaveSupport           = parent.classesWithoutTopLevelSaveSupport;
            this.checkAllAssociatedObjectsForDifferentShards = parent.checkAllAssociatedObjectsForDifferentShards;
            this.controlSessionFactory = parent.controlSessionFactory;

            var uniqueShardIds = new HashSet <ShardId>(shardIds);

            foreach (var pair in parent.shardIdsBySessionFactory)
            {
                var shardIdsSubset = new HashSet <ShardId>(pair.Value);
                shardIdsSubset.IntersectWith(uniqueShardIds);
                if (shardIdsSubset.Count > 0)
                {
                    this.shardIdsBySessionFactory.Add(pair.Key, shardIdsSubset);
                }
            }

            shardStrategy = shardStrategyFactory.NewShardStrategy(
                shardIdsBySessionFactory.SelectMany(c => c.Value));
        }
        public When_Using_Sharded_Servers()
        {
            server = "localhost";

            port1 = 8080;
            port2 = 8081;

            path1 = GetPath("TestShardedDb1");
            path2 = GetPath("TestShardedDb2");

            RavenDbServer.EnsureCanListenToWhenInNonAdminContext(port1);
            RavenDbServer.EnsureCanListenToWhenInNonAdminContext(port2);

            company1 = new Company { Name = "Company1" };
            company2 = new Company { Name = "Company2" };

            server1 = GetNewServer(port1, path1);
            server2 = GetNewServer(port2, path2);

            shards = new Shards {
                new DocumentStore(server, port1) { Identifier="Shard1" },
                new DocumentStore(server, port2) { Identifier="Shard2" }
            };

            shardSelection = MockRepository.GenerateStub<IShardSelectionStrategy>();
            shardSelection.Stub(x => x.SelectShardIdForNewObject(company1)).Return("Shard1");
            shardSelection.Stub(x => x.SelectShardIdForNewObject(company2)).Return("Shard2");

            shardResolution = MockRepository.GenerateStub<IShardResolutionStrategy>();

            shardStrategy = MockRepository.GenerateStub<IShardStrategy>();
            shardStrategy.Stub(x => x.ShardSelectionStrategy).Return(shardSelection);
            shardStrategy.Stub(x => x.ShardResolutionStrategy).Return(shardResolution);
        }
Exemple #3
0
        /// <summary>
        /// 注册类型的分区策略
        /// </summary>
        /// <param name="entityType"></param>
        /// <param name="shardStragegyType"></param>
        /// <param name="attributes"></param>
        public IShardStrategy RegisterShardStragety(Type entityType, Type shardStragegyType, IDictionary <string, string> attributes = null)
        {
            if (entityType == null)
            {
                throw new ArgumentNullException("entityType");
            }
            if (shardStragegyType == null)
            {
                throw new ArgumentNullException("shardStragegyType");
            }

            IShardStrategy strategy = (IShardStrategy)FastActivator.Create(shardStragegyType);

            if (strategy == null)
            {
                throw new ArgumentNullException("strategy");
            }

            if (strategy is AbstractShardStrategy && attributes != null)
            {
                ((AbstractShardStrategy)strategy).Init(attributes);
            }

            if (stategies.ContainsKey(entityType))
            {
                stategies[entityType] = strategy;
            }
            else
            {
                stategies.Add(entityType, strategy);
            }
            return(strategy);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="BlobStorageTelemetryWriterConfiguration"/> class.
        /// </summary>
        /// <param name="containerShardStrategy">The container shard strategy.</param>
        /// <param name="blobShardStrategy">The BLOB shard strategy.</param>
        public BlobStorageTelemetryWriterConfiguration(IShardStrategy containerShardStrategy = null, IShardStrategy blobShardStrategy = null)
        {
            if (null == containerShardStrategy)
            {
                containerShardStrategy = new DefaultContainerShardStrategy();
            }

            if (null == blobShardStrategy)
            {
                blobShardStrategy = new ShardPerDayStrategy();
            }

            SetField.NotNull(out _containerShardStrategy, nameof(containerShardStrategy), containerShardStrategy);
            SetField.NotNull(out _blobShardStrategy, nameof(blobShardStrategy), blobShardStrategy);

            try
            {
                StorageConnectionString = CloudConfigurationManager.GetSetting("StorageConnectionString");
            }
            catch (Exception)
            {
                //because this is an attempt to read from a well-known location it may fail
                // so swallow all errors vs. throwing from the ctor
            }
        }
Exemple #5
0
        public AbstractDatabase(IConnectionManager connectionManager, IShardStrategy shardStrategy, ISchemaManager schemaManager)
        {
            AssertUtil.ArgumentNotNull(connectionManager, nameof(connectionManager));

            this.ConnectionManager = connectionManager;
            this.ShardStrategy     = shardStrategy;
            this.SchemaManager     = schemaManager;
        }
Exemple #6
0
        protected DbTable(DbSession session, ISchemaManager schemaManager,
                          object shardObject, object partitionObject, IShardStrategy shardStrategy)
            : base(session)
        {
            this.SchemaManager = schemaManager;

            this.ShardObject     = shardObject;
            this.PartitionObject = partitionObject;
            this.ShardStrategy   = shardStrategy;

            string tableName = this.EntityType.Name;

            if (this.SchemaManager != null)
            {
                this.Schema = this.SchemaManager.GetSchema <TEntity>();
                if (this.Schema != null)
                {
                    tableName = this.Schema.TableName;
                }
            }

            if (this.Schema == null)
            {
                this.Schema = SchemaParser.GetSchema <TEntity>();
                if (this.Schema != null)
                {
                    tableName = this.Schema.TableName;
                }
            }

            if (this.Schema == null)
            {
                throw new InvalidOperationException($"Cannot parse entity '{this.EntityType}'s schema.");
            }


            this.TableName = tableName;
            if (this.ShardStrategy != null)
            {
                string tableShardNo = this.ShardStrategy.GetTableShardNo(tableName, this.ShardObject);
                if (!string.IsNullOrWhiteSpace(tableShardNo))
                {
                    this.TableName += ("_" + tableShardNo.Trim());
                }

                string tablePartitionNo = this.ShardStrategy.GetTablePartitionNo(tableName, this.ShardObject, this.PartitionObject);
                if (!string.IsNullOrWhiteSpace(tablePartitionNo))
                {
                    this.TableName += ("_" + tablePartitionNo.Trim());
                }
            }


            this.QueryContext = new DbQueryContext(session);
            this.QueryContext.SetFrom <TEntity>(this);
        }
		/// <summary>
		/// Initializes a new instance of the <see cref="ShardedDocumentStore"/> class.
		/// </summary>
		/// <param name="shardStrategy">The shard strategy.</param>
		/// <param name="shards">The shards.</param>
		public ShardedDocumentStore(IShardStrategy shardStrategy, Shards shards)
		{
			if (shards == null || shards.Count == 0) 
				throw new ArgumentException("Must have one or more shards", "shards");
			if (shardStrategy == null)
				throw new ArgumentException("Must have shard strategy", "shardStrategy");

			this.shardStrategy = shardStrategy;
			this.shards = shards;
		}
        /// <summary>
        /// Initializes a new instance of the <see cref="TextFileTelemetryWriterConfiguration"/> class.
        /// </summary>
        /// <param name="fileShardStrategy">The file shard strategy.</param>
        public TextFileTelemetryWriterConfiguration(IShardStrategy fileShardStrategy = null)
        {
            if (null == fileShardStrategy)
            {
                fileShardStrategy = new ShardPerDayStrategy();
            }

            SetField.NotNull(out _fileShardStrategy, nameof(fileShardStrategy), fileShardStrategy);
            Filename = BuildDefaultFilename();
        }
Exemple #9
0
        public ShardedDocumentSession(IShardStrategy shardStrategy, params IDocumentSession[] shardSessions)
        {
            this.shardStrategy = shardStrategy;
            this.shardSessions = shardSessions;

            foreach (var shardSession in shardSessions)
            {
                shardSession.Stored            += Stored;
                shardSession.OnEntityConverted += OnEntityConverted;
            }
        }
Exemple #10
0
        internal void Initialize(bool master, ISchemaManager schemaManager,
                                 object shardObject, IShardStrategy shardStrategy, IConnectionManager connectionManager)
        {
            this.UsingMaster = master;

            this.SchemaManager = schemaManager;

            this.ShardObject       = shardObject;
            this.ShardStrategy     = shardStrategy;
            this.ConnectionManager = connectionManager;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ShardedDocumentStore"/> class.
        /// </summary>
        /// <param name="shardStrategy">The shard strategy.</param>
        /// <param name="shards">The shards.</param>
        public ShardedDocumentStore(IShardStrategy shardStrategy, Shards shards)
        {
            if (shards == null || shards.Count == 0)
            {
                throw new ArgumentException("Must have one or more shards", "shards");
            }
            if (shardStrategy == null)
            {
                throw new ArgumentException("Must have shard strategy", "shardStrategy");
            }

            this.shardStrategy = shardStrategy;
            this.shards        = shards;
        }
Exemple #12
0
        IShardStrategy CreateShardStrategy(SettingNode node, string path)
        {
            var type = node.TryGetValue(path);

            if (String.IsNullOrEmpty(type))
            {
                return(null);
            }

            IShardStrategy strategy = (IShardStrategy)FastActivator.Create(type);

            if (strategy != null && strategy is AbstractShardStrategy)
            {
                ((AbstractShardStrategy)strategy).Init(node.Attributes);
            }

            return(strategy);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="QueueStorageTelemetryWriterConfiguration"/> class.
        /// </summary>
        /// <param name="queueShardStrategy">The queue shard strategy.</param>
        public QueueStorageTelemetryWriterConfiguration(IShardStrategy queueShardStrategy = null)
        {
            if (null == queueShardStrategy)
            {
                queueShardStrategy = new DefaultQueueShardStrategy();
            }

            SetField.NotNull(out _queueShardStrategy, nameof(queueShardStrategy), queueShardStrategy);

            try
            {
                StorageConnectionString = CloudConfigurationManager.GetSetting("StorageConnectionString");
            }
            catch (Exception)
            {
                //because this is an attempt to read from a well-known location it may fail
                // so swallow all errors vs. throwing from the ctor
            }
        }
Exemple #14
0
        public MemcachedClientManager(string configKey, IShardStrategy shardStrategy)
        {
            AssertUtil.ArgumentNotEmpty(configKey, nameof(configKey));
            AssertUtil.ArgumentNotNull(shardStrategy, nameof(shardStrategy));

            m_ConfigKey      = configKey.Trim();
            m_pShardStrategy = shardStrategy;

            ConfigurationManager.Changed += (e) =>
            {
                if (string.Compare(m_ConfigKey, e.Key, true) == 0)
                {
                    InitializeConnectionPools();
                }
            };


            InitializeConnectionPools();
        }
Exemple #15
0
 public AbstractDatabase(IConnectionManager connectionManager, IShardStrategy shardStrategy)
     : this(connectionManager, shardStrategy, null)
 {
 }
        protected ShardedSessionFactoryImpl(
            ShardedSessionFactoryImpl parent,
            IEnumerable<ShardId> shardIds,
            IShardStrategyFactory shardStrategyFactory)
        {
            this.shardIdsBySessionFactory = new Dictionary<ISessionFactoryImplementor, ICollection<ShardId>>();
            this.classesWithoutTopLevelSaveSupport = parent.classesWithoutTopLevelSaveSupport;
            this.checkAllAssociatedObjectsForDifferentShards = parent.checkAllAssociatedObjectsForDifferentShards;
            this.controlSessionFactory = parent.controlSessionFactory;

            var uniqueShardIds = new HashSet<ShardId>(shardIds);
            foreach (var pair in parent.shardIdsBySessionFactory)
            {
                var shardIdsSubset = new HashSet<ShardId>(pair.Value);
                shardIdsSubset.IntersectWith(uniqueShardIds);
                if (shardIdsSubset.Count > 0)
                {
                    this.shardIdsBySessionFactory.Add(pair.Key, shardIdsSubset);
                }
            }

            shardStrategy = shardStrategyFactory.NewShardStrategy(
                shardIdsBySessionFactory.SelectMany(c => c.Value));
        }
Exemple #17
0
 public ShardingSession(IDictionary <string, ISession> sessions, IShardStrategy shardStrategy, IStore store)
 {
     _sessions      = sessions;
     _shardStrategy = shardStrategy;
     _store         = store;
 }
        /// <summary>
        /// Constructs a ShardedSessionFactoryImpl
        /// </summary>
        /// <param name="shardIds"> The ids of the shards with which this SessionFactory should be associated.</param>
        /// <param name="sessionFactoryShardIdMap">Mapping of SessionFactories to shard ids. 
        ///  When using virtual shards, this map associates SessionFactories (physical
        ///  shards) with virtual shards (shard ids).  Map cannot be empty.
        ///  Map keys cannot be null.  Map values cannot be null or empty.</param>
        /// <param name="shardStrategyFactory">factory that knows how to create the <see cref="IShardStrategy"/> 
        ///  that will be used for all shard-related operations</param>
        /// <param name="classesWithoutTopLevelSaveSupport"> All classes that cannot be saved
        ///  as top-level objects</param>
        /// <param name="checkAllAssociatedObjectsForDifferentShards">Flag that controls
        ///  whether or not we do full cross-shard relationshp checking (very slow)</param>
        public ShardedSessionFactoryImpl(
			ICollection<ShardId> shardIds,
			IDictionary<ISessionFactoryImplementor, Set<ShardId>> sessionFactoryShardIdMap,
			IShardStrategyFactory shardStrategyFactory,
			ISet<System.Type> classesWithoutTopLevelSaveSupport,
			bool checkAllAssociatedObjectsForDifferentShards)
        {
            Preconditions.CheckNotNull(sessionFactoryShardIdMap);
            Preconditions.CheckArgument(!(sessionFactoryShardIdMap.Count == 0));
            Preconditions.CheckNotNull(shardStrategyFactory);
            Preconditions.CheckNotNull(classesWithoutTopLevelSaveSupport);

            sessionFactories = new List<ISessionFactoryImplementor>(sessionFactoryShardIdMap.Keys);
            this.sessionFactoryShardIdMap = new Dictionary<ISessionFactoryImplementor, Set<ShardId>>();
            fullSessionFactoryShardIdMap = sessionFactoryShardIdMap;
            this.classesWithoutTopLevelSaveSupport = new HashedSet<System.Type>(classesWithoutTopLevelSaveSupport);
            this.checkAllAssociatedObjectsForDifferentShards = checkAllAssociatedObjectsForDifferentShards;
            Set<ShardId> uniqueShardIds = new HashedSet<ShardId>();
            ISessionFactoryImplementor controlSessionFactoryToSet = null;

            foreach (var entry in sessionFactoryShardIdMap)
            {
                ISessionFactoryImplementor implementor = entry.Key;
                Preconditions.CheckNotNull(implementor);
                Set<ShardId> shardIdSet = entry.Value;
                Preconditions.CheckNotNull(shardIdSet);
                Preconditions.CheckState(!(shardIdSet.Count == 0));

                foreach (ShardId shardId in shardIdSet)
                {
                    //TODO: we should change it so we specify control shard in configuration
                    if (shardId.Id == CONTROL_SHARD_ID)
                    {
                        controlSessionFactoryToSet = implementor;
                    }
                    if (!uniqueShardIds.Add(shardId))
                    {
                        string msg = string.Format("Cannot have more than one shard with shard id {0}.", shardId.Id);
                        log.Error(msg);
                        throw new HibernateException(msg);
                    }
                    if (shardIds.Contains(shardId))
                    {
                        if (!this.sessionFactoryShardIdMap.ContainsKey(implementor))
                            this.sessionFactoryShardIdMap.Add(implementor, new HashedSet<ShardId>());

                        this.sessionFactoryShardIdMap[implementor].Add(shardId);
                    }
                }
            }
            // make sure someone didn't associate a session factory with a shard id
            // that isn't in the full list of shards
            foreach (ShardId shardId in shardIds)
            {
                Preconditions.CheckState(uniqueShardIds.Contains(shardId));
            }
            controlSessionFactory = controlSessionFactoryToSet;
            // now that we have all our shard ids, construct our shard strategy
            shardStrategy = shardStrategyFactory.NewShardStrategy(shardIds);
            SetupIdGenerators();
        }
Exemple #19
0
 internal SQLiteTable(SQLiteSession session, ISchemaManager schemaManager,
                      object shardObject, object partitionObject, IShardStrategy shardStrategy)
     : base(session, schemaManager, shardObject, partitionObject, shardStrategy)
 {
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="ShardedDocumentSession"/> class.
 /// </summary>
 /// <param name="shardStrategy">The shard strategy.</param>
 /// <param name="shardSessions">The shard sessions.</param>
 /// <param name="documentStore"></param>
 public ShardedDocumentSession(IShardStrategy shardStrategy, IDocumentSession[] shardSessions, ShardedDocumentStore documentStore)
 {
     this.shardStrategy = shardStrategy;
     this.shardSessions = shardSessions;
     this.documentStore = documentStore;
 }
Exemple #21
0
 public SQLServerDatabase(IConnectionManager connectionManager, IShardStrategy shardStrategy)
     : base(connectionManager, shardStrategy, null)
 {
 }
Exemple #22
0
 public SQLServerDatabase(IConnectionManager connectionManager, IShardStrategy shardStrategy, ISchemaManager schemaManager)
     : base(connectionManager, shardStrategy, schemaManager)
 {
 }
        /// <summary>
        /// Constructs a ShardedSessionFactoryImpl
        /// </summary>
        /// <param name="shardIds"> The ids of the shards with which this SessionFactory should be associated.</param>
        /// <param name="sessionFactoryShardIdMap">Mapping of SessionFactories to shard ids.
        ///  When using virtual shards, this map associates SessionFactories (physical
        ///  shards) with virtual shards (shard ids).  Map cannot be empty.
        ///  Map keys cannot be null.  Map values cannot be null or empty.</param>
        /// <param name="shardStrategyFactory">factory that knows how to create the <see cref="IShardStrategy"/>
        ///  that will be used for all shard-related operations</param>
        /// <param name="classesWithoutTopLevelSaveSupport"> All classes that cannot be saved
        ///  as top-level objects</param>
        /// <param name="checkAllAssociatedObjectsForDifferentShards">Flag that controls
        ///  whether or not we do full cross-shard relationshp checking (very slow)</param>
        public ShardedSessionFactoryImpl(
            ICollection <ShardId> shardIds,
            IDictionary <ISessionFactoryImplementor, Set <ShardId> > sessionFactoryShardIdMap,
            IShardStrategyFactory shardStrategyFactory,
            ISet <System.Type> classesWithoutTopLevelSaveSupport,
            bool checkAllAssociatedObjectsForDifferentShards)
        {
            Preconditions.CheckNotNull(sessionFactoryShardIdMap);
            Preconditions.CheckArgument(!(sessionFactoryShardIdMap.Count == 0));
            Preconditions.CheckNotNull(shardStrategyFactory);
            Preconditions.CheckNotNull(classesWithoutTopLevelSaveSupport);

            sessionFactories = new List <ISessionFactoryImplementor>(sessionFactoryShardIdMap.Keys);
            this.sessionFactoryShardIdMap                    = new Dictionary <ISessionFactoryImplementor, Set <ShardId> >();
            fullSessionFactoryShardIdMap                     = sessionFactoryShardIdMap;
            this.classesWithoutTopLevelSaveSupport           = new HashedSet <System.Type>(classesWithoutTopLevelSaveSupport);
            this.checkAllAssociatedObjectsForDifferentShards = checkAllAssociatedObjectsForDifferentShards;
            Set <ShardId> uniqueShardIds = new HashedSet <ShardId>();
            ISessionFactoryImplementor controlSessionFactoryToSet = null;

            foreach (var entry in sessionFactoryShardIdMap)
            {
                ISessionFactoryImplementor implementor = entry.Key;
                Preconditions.CheckNotNull(implementor);
                Set <ShardId> shardIdSet = entry.Value;
                Preconditions.CheckNotNull(shardIdSet);
                Preconditions.CheckState(!(shardIdSet.Count == 0));

                foreach (ShardId shardId in shardIdSet)
                {
                    //TODO: we should change it so we specify control shard in configuration
                    if (shardId.Id == CONTROL_SHARD_ID)
                    {
                        controlSessionFactoryToSet = implementor;
                    }
                    if (!uniqueShardIds.Add(shardId))
                    {
                        string msg = string.Format("Cannot have more than one shard with shard id {0}.", shardId.Id);
                        log.Error(msg);
                        throw new HibernateException(msg);
                    }
                    if (shardIds.Contains(shardId))
                    {
                        if (!this.sessionFactoryShardIdMap.ContainsKey(implementor))
                        {
                            this.sessionFactoryShardIdMap.Add(implementor, new HashedSet <ShardId>());
                        }

                        this.sessionFactoryShardIdMap[implementor].Add(shardId);
                    }
                }
            }
            // make sure someone didn't associate a session factory with a shard id
            // that isn't in the full list of shards
            foreach (ShardId shardId in shardIds)
            {
                Preconditions.CheckState(uniqueShardIds.Contains(shardId));
            }
            controlSessionFactory = controlSessionFactoryToSet;
            // now that we have all our shard ids, construct our shard strategy
            shardStrategy = shardStrategyFactory.NewShardStrategy(shardIds);
            SetupIdGenerators();
        }
        /// <summary>
        /// Constructs a ShardedSessionFactoryImpl
        /// </summary>
        /// <param name="shardIdsBySessionFactory">Mapping of SessionFactories to shard ids.
        ///  When using virtual shards, this map associates SessionFactories (physical
        ///  shards) with virtual shards (shard ids).  Map cannot be empty.
        ///  Map keys cannot be null.  Map values cannot be null or empty.</param>
        /// <param name="shardStrategyFactory">factory that knows how to create the <see cref="IShardStrategy"/>
        ///  that will be used for all shard-related operations</param>
        /// <param name="classesWithoutTopLevelSaveSupport"> All classes that cannot be saved
        ///  as top-level objects</param>
        /// <param name="checkAllAssociatedObjectsForDifferentShards">Flag that controls
        ///  whether or not we do full cross-shard relationshp checking (very slow)</param>
        public ShardedSessionFactoryImpl(
            IDictionary <ISessionFactoryImplementor, ICollection <ShardId> > shardIdsBySessionFactory,
            IShardStrategyFactory shardStrategyFactory,
            IEnumerable <System.Type> classesWithoutTopLevelSaveSupport,
            bool checkAllAssociatedObjectsForDifferentShards)
        {
            Preconditions.CheckNotNull(shardIdsBySessionFactory);
            Preconditions.CheckNotNull(shardStrategyFactory);
            Preconditions.CheckNotNull(classesWithoutTopLevelSaveSupport);

            this.shardIdsBySessionFactory                    = new Dictionary <ISessionFactoryImplementor, ICollection <ShardId> >(shardIdsBySessionFactory);
            this.classesWithoutTopLevelSaveSupport           = new HashSet <System.Type>(classesWithoutTopLevelSaveSupport);
            this.checkAllAssociatedObjectsForDifferentShards = checkAllAssociatedObjectsForDifferentShards;

            var uniqueShardIds = new HashSet <ShardId>();

            foreach (var entry in shardIdsBySessionFactory)
            {
                ISessionFactoryImplementor implementor = entry.Key;
                Preconditions.CheckNotNull(implementor);

                var shardIdSet = entry.Value;
                Preconditions.CheckNotNull(shardIdSet);
                Preconditions.CheckState(!(shardIdSet.Count == 0));

                foreach (ShardId shardId in shardIdSet)
                {
                    //TODO: we should change it so we specify control shard in configuration
                    if (shardId.Id == CONTROL_SHARD_ID)
                    {
                        this.controlSessionFactory = implementor;
                    }
                    if (!uniqueShardIds.Add(shardId))
                    {
                        string msg = string.Format("Cannot have more than one shard with shard id {0}.", shardId.Id);
                        Log.Error(msg);
                        throw new HibernateException(msg);
                    }

                    if (!this.shardIdsBySessionFactory.ContainsKey(implementor))
                    {
                        this.shardIdsBySessionFactory.Add(implementor, new HashSet <ShardId>());
                    }
                    this.shardIdsBySessionFactory[implementor].Add(shardId);
                }
            }

            if (this.controlSessionFactory == null)
            {
                string message = string.Format(
                    CultureInfo.InvariantCulture,
                    "Cannot find control shard. Please ensure that one control shard exists with shard id '{0}'. " +
                    "A control shard is required for operations that cannot be distributed across shards, such as the " +
                    "generation of unique sequence numbers within the shard.",
                    CONTROL_SHARD_ID);
                Log.Error(message);
                throw new ArgumentException(message, "shardIdsBySessionFactory");
            }

            // now that we have all our shard ids, construct our shard strategy
            shardStrategy = shardStrategyFactory.NewShardStrategy(
                shardIdsBySessionFactory.SelectMany(c => c.Value));
            SetupIdGenerators();
        }
        /// <summary>
        /// Constructs a ShardedSessionFactoryImpl
        /// </summary>
        /// <param name="shardIdsBySessionFactory">Mapping of SessionFactories to shard ids. 
        ///  When using virtual shards, this map associates SessionFactories (physical
        ///  shards) with virtual shards (shard ids).  Map cannot be empty.
        ///  Map keys cannot be null.  Map values cannot be null or empty.</param>
        /// <param name="shardStrategyFactory">factory that knows how to create the <see cref="IShardStrategy"/> 
        ///  that will be used for all shard-related operations</param>
        /// <param name="classesWithoutTopLevelSaveSupport"> All classes that cannot be saved
        ///  as top-level objects</param>
        /// <param name="checkAllAssociatedObjectsForDifferentShards">Flag that controls
        ///  whether or not we do full cross-shard relationshp checking (very slow)</param>
        public ShardedSessionFactoryImpl(
            IDictionary<ISessionFactoryImplementor, ICollection<ShardId>> shardIdsBySessionFactory,
            IShardStrategyFactory shardStrategyFactory,
            IEnumerable<System.Type> classesWithoutTopLevelSaveSupport,
            bool checkAllAssociatedObjectsForDifferentShards)
        {
            Preconditions.CheckNotNull(shardIdsBySessionFactory);
            Preconditions.CheckNotNull(shardStrategyFactory);
            Preconditions.CheckNotNull(classesWithoutTopLevelSaveSupport);

            this.shardIdsBySessionFactory = new Dictionary<ISessionFactoryImplementor, ICollection<ShardId>>(shardIdsBySessionFactory);
            this.classesWithoutTopLevelSaveSupport = new HashSet<System.Type>(classesWithoutTopLevelSaveSupport);
            this.checkAllAssociatedObjectsForDifferentShards = checkAllAssociatedObjectsForDifferentShards;

            var uniqueShardIds = new HashSet<ShardId>();
            foreach (var entry in shardIdsBySessionFactory)
            {
                ISessionFactoryImplementor implementor = entry.Key;
                Preconditions.CheckNotNull(implementor);

                var shardIdSet = entry.Value;
                Preconditions.CheckNotNull(shardIdSet);
                Preconditions.CheckState(!(shardIdSet.Count == 0));

                foreach (ShardId shardId in shardIdSet)
                {
                    //TODO: we should change it so we specify control shard in configuration
                    if (shardId.Id == CONTROL_SHARD_ID)
                    {
                        this.controlSessionFactory = implementor;
                    }
                    if (!uniqueShardIds.Add(shardId))
                    {
                        string msg = string.Format("Cannot have more than one shard with shard id {0}.", shardId.Id);
                        Log.Error(msg);
                        throw new HibernateException(msg);
                    }

                    if (!this.shardIdsBySessionFactory.ContainsKey(implementor))
                    {
                        this.shardIdsBySessionFactory.Add(implementor, new HashSet<ShardId>());
                    }
                    this.shardIdsBySessionFactory[implementor].Add(shardId);
                }
            }

            if (this.controlSessionFactory == null)
            {
                string message = string.Format(
                    CultureInfo.InvariantCulture,
                    "Cannot find control shard. Please ensure that one control shard exists with shard id '{0}'. " +
                    "A control shard is required for operations that cannot be distributed across shards, such as the " +
                    "generation of unique sequence numbers within the shard.",
                    CONTROL_SHARD_ID);
                Log.Error(message);
                throw new ArgumentException(message, "shardIdsBySessionFactory");
            }

            // now that we have all our shard ids, construct our shard strategy
            shardStrategy = shardStrategyFactory.NewShardStrategy(
                shardIdsBySessionFactory.SelectMany(c => c.Value));
            SetupIdGenerators();
        }