예제 #1
0
        /// <summary>
        /// Only build the database schema.
        /// </summary>
        /// <param name="dispatcher"></param>
        /// <param name="containerFileName"></param>
        /// <param name="connections"></param>
        /// <param name="configHash"></param>
        /// <returns></returns>
        private static MetadataContainer BuildMetadata(IQueryDispatcher dispatcher, string containerFileName,
                                                       List <Connection> connections, string configHash)
        {
            var container = new MetadataContainer {
                ConfigFileHash = configHash
            };

            //Copy connection strings
            foreach (var cs in connections)
            {
                container.ConnectionStrings.Add(
                    new SqlConnection(cs.Id)
                {
                    ProviderName     = cs.ProviderName,
                    ConnectionString = cs.ConnectionString
                });
            }

            FetchMetadata(dispatcher, ref container);
            container.Metadatas.FinalizeSchema();

            //Save container
            container.Save(containerFileName);
            return(container);
        }
예제 #2
0
        public static MetadataContainer Deserialize(BinaryReader input, FastAccessList <object> referenceTracking = null)
        {
            var config = new MetadataContainer {
                ConfigFileHash = input.ReadString()
            };

            DeserializeBody(input, config, referenceTracking);

            return(config);
        }
예제 #3
0
        private static void FetchMetadata(IQueryDispatcher dispatcher, ref MetadataContainer container)
        {
            dispatcher.InitProviders(container.Metadatas, container.ConnectionStrings);

            foreach (var cs in container.ConnectionStrings)
            {
                var provider = dispatcher.GetQueryHelper(cs.Id);

                foreach (var database in provider.GetDatabasesName())
                {
                    provider.GetColumns(container.Metadatas.LoadColumns, cs.Id, database);
                    provider.GetForeignKeys(container.Metadatas.LoadForeignKeys, cs.Id, database);
                    provider.GetUniqueKeys(container.Metadatas.LoadUniqueKeys, cs.Id, database);
                }
            }
        }
예제 #4
0
        private static MetadataContainer DeserializeBody(BinaryReader input, MetadataContainer config,
                                                         FastAccessList <object> referenceTracking = null)
        {
            var nbServerMap = input.ReadInt32();

            for (var i = 0; i < nbServerMap; i++)
            {
                var src = ServerIdentifier.Deserialize(input);
                var dst = ServerIdentifier.Deserialize(input);
                config.ServerMap.Add(src, dst);
            }
            var nbConnection = input.ReadInt32();

            for (var i = 0; i < nbConnection; i++)
            {
                config.ConnectionStrings.Add(SqlConnection.Deserialize(input));
            }

            config.Metadatas = AppMetadata.Deserialize(input, referenceTracking);

            return(config);
        }
예제 #5
0
        private static MetadataContainer TryLoadContainer(string containerFile, string configHash)
        {
            MetadataContainer container = null;

            if (File.Exists(containerFile))
            {
                using (var fs = new FileStream(containerFile, FileMode.Open))
                    using (var br = new BinaryReader(fs, Encoding.UTF8, true))
                    {
                        var fileHash = br.ReadString();

                        //Check if container file match with config file version
                        if (fileHash == configHash)
                        {
                            container = new MetadataContainer {
                                ConfigFileHash = fileHash
                            };
                            DeserializeBody(br, container);
                        }
                    }
            }
            return(container);
        }
예제 #6
0
        /// <summary>
        /// Verify if the last build of the container's metadata still match with the current cloning settings.
        /// </summary>
        /// <param name="dispatcher">Query dispatcher</param>
        /// <param name="app">Application user config</param>
        /// <param name="mapId">MapId</param>
        /// <param name="behaviourId">BehaviourId</param>
        /// <param name="container">Container</param>
        public static void VerifyIntegrityWithSettings(IQueryDispatcher dispatcher, Settings settings, ref MetadataContainer container)
        {
            if (dispatcher == null)
            {
                throw new ArgumentNullException(nameof(dispatcher));
            }
            if (settings == null)
            {
                throw new ArgumentNullException(nameof(settings));
            }
            if (settings.Project == null)
            {
                throw new ArgumentNullException(nameof(settings.Project));
            }
            if (String.IsNullOrWhiteSpace(settings.Project.Name))
            {
                throw new ArgumentException(nameof(settings.Project.Name));
            }
            if (settings.Project.ConnectionStrings != null &&
                !settings.Project.ConnectionStrings.Any())
            {
                throw new NullReferenceException("settings.Project.ConnectionStrings");
            }

            var       project           = settings.Project;
            var       containerFileName = project.Name + "_";
            Map       map             = null;
            Behaviour clonerBehaviour = null;

            //Hash the selected map, connnectionStrings and the cloner
            //configuration to see if it match the lasted builded container
            var configData = new MemoryStream();

            SerializationHelper.Serialize(configData, project.ConnectionStrings);

            if (settings.MapId.HasValue)
            {
                map = settings.Project.Maps.FirstOrDefault(m => m.Id == settings.MapId);
                if (map == null)
                {
                    throw new Exception($"Map id '{settings.MapId}' not found in configuration file for application '{project.Name}'!");
                }
                containerFileName += map.From + "-" + map.To;
                SerializationHelper.Serialize(configData, map);

                if (map.UsableBehaviours != null && map.UsableBehaviours.Split(',').ToList().Contains(settings.BehaviourId.ToString()))
                {
                    clonerBehaviour = project.Behaviours.FirstOrDefault(c => c.Id == settings.BehaviourId);
                    if (clonerBehaviour == null)
                    {
                        throw new KeyNotFoundException(
                                  $"There is no behaviour '{settings.BehaviourId}' in the configuration for the appName name '{project.Name}'.");
                    }

                    SerializationHelper.Serialize(configData, clonerBehaviour);
                    SerializationHelper.Serialize(configData, project.Templates);
                }
            }
            else
            {
                containerFileName += "defaultMap";
            }

            if (settings.BehaviourId != null)
            {
                containerFileName += "_" + settings.BehaviourId;
            }
            containerFileName += ".cache";

            //Hash user config
            configData.Position = 0;
            //var murmur = MurmurHash.Create32(managed: false);
            //var configHash = Encoding.UTF8.GetString(murmur.ComputeHash(configData));
            var configHash = container.ConfigFileHash + "random";

            //If in-memory container is good, we use it
            if (container != null && container.ConfigFileHash == configHash)
            {
                return;
            }

            if (!settings.UseInMemoryCacheOnly)
            {
                //If container on disk is good, we use it
                container = TryLoadContainer(containerFileName, configHash);
                if (container != null)
                {
                    dispatcher.InitProviders(container.Metadatas, container.ConnectionStrings);
                    return;
                }
            }

            //We rebuild the container
            container = BuildMetadataWithSettings(dispatcher, containerFileName, project, clonerBehaviour, map, configHash);

            //Persist container
            if (!settings.UseInMemoryCacheOnly)
            {
                container.Save(containerFileName);
            }
        }
예제 #7
0
        /// <summary>
        /// Also merge user configs
        /// </summary>
        /// <param name="dispatcher"></param>
        /// <param name="containerFileName"></param>
        /// <param name="proj"></param>
        /// <param name="clonerBehaviour"></param>
        /// <param name="map"></param>
        /// <param name="configHash"></param>
        /// <returns></returns>
        private static MetadataContainer BuildMetadataWithSettings(IQueryDispatcher dispatcher, string containerFileName,
                                                                   ProjectContainer proj, Behaviour clonerBehaviour,
                                                                   Map map, string configHash)
        {
            var container = new MetadataContainer {
                ConfigFileHash = configHash, ServerMap = map.ConvertToDictionnary()
            };

            ////Get servers source
            //var serversSource = map.Roads.Select(r => r.ServerSrc).Distinct().ToList();

            ////Replace variables
            //for (int i = 0; i < serversSource.Count(); i++)
            //{
            //    if (serversSource[i].IsVariable())
            //    {
            //        var configVar = map.Variables.FirstOrDefault(v => v.Name == serversSource[i]);
            //        if (configVar == null)
            //            throw new Exception($"The variable '{0}' is not found in the map with id='{1}'.", serversSource[i], map.Id));
            //        serversSource[i] = configVar.Value.ToString();
            //    }
            //}

            ////Copy connection strings
            //foreach (var cs in app.ConnectionStrings.Where(c => serversSource.Contains(c.Id.ToString())))
            //    container.ConnectionStrings.Add(new SqlConnection(cs.Id, cs.ProviderName, cs.ConnectionString));

            //Copy connection strings
            foreach (var cs in proj.ConnectionStrings)
            {
                container.ConnectionStrings.Add(
                    new SqlConnection(cs.Id)
                {
                    ProviderName     = cs.ProviderName,
                    ConnectionString = cs.ConnectionString
                });
            }

            if (container.ConnectionStrings.Count() == 0)
            {
                throw new Exception("No connectionStrings!");
            }

            FetchMetadata(dispatcher, ref container);

            Behaviour behaviour = null;

            if (clonerBehaviour != null)
            {
                List <Variable> vars = null;
                if (map != null)
                {
                    vars = map.Variables;
                }

                behaviour = clonerBehaviour.Build(proj.Templates, vars);
            }
            container.Metadatas.FinalizeMetadata(behaviour);

            return(container);
        }
예제 #8
0
        /// <summary>
        /// Verify if the last build of the container's metadata still match with the sql servers (application's connectionStrings).
        /// </summary>
        /// <param name="dispatcher">Query dispatcher</param>
        /// <param name="proj">Project config</param>
        /// <param name="container">Metadata container</param>
        public static void VerifyIntegrityOfSqlMetadata(IQueryDispatcher dispatcher, ProjectContainer proj, ref MetadataContainer container)
        {
            if (dispatcher == null)
            {
                throw new ArgumentNullException(nameof(dispatcher));
            }
            if (proj == null)
            {
                throw new ArgumentNullException(nameof(proj));
            }
            if (proj.ConnectionStrings != null && !proj.ConnectionStrings.Any())
            {
                throw new NullReferenceException("ConnectionStrings");
            }

            var containerFileName = proj.Name + ".schema";

            //Hash the connnectionStrings to see if it match the last build
            var configData = new MemoryStream();

            SerializationHelper.Serialize(configData, proj.ConnectionStrings);
            configData.Position = 0;

            //HashAlgorithm murmur = MurmurHash.Create32(managed: false);
            //var configHash = Encoding.UTF8.GetString(murmur.ComputeHash(configData));
            var configHash = container.ConfigFileHash + "random";

            //If in-memory container is good, we use it
            if (container != null && container.ConfigFileHash == configHash)
            {
                return;
            }
            //If container on disk is good, we use it
            container = TryLoadContainer(containerFileName, configHash);
            if (container != null)
            {
                dispatcher.InitProviders(container.Metadatas, container.ConnectionStrings);
            }
            //We rebuild the container
            else
            {
                container = BuildMetadata(dispatcher, containerFileName, proj.ConnectionStrings, configHash);
            }
        }