Example #1
0
        /// <summary>
        /// The main entry point for the tool.
        /// </summary>
        static public void Run(string[] args)
        {
            string failedNodes = string.Empty;

            NCache.Port = NCache.UseTcp ? CacheConfigManager.NCacheTcpPort : CacheConfigManager.HttpPort;
            Alachisoft.NCache.Config.NewDom.CacheServerConfig[] caches = null;
            ICacheServer cacheServer = null;

            Alachisoft.NCache.Config.NewDom.CacheServerConfig _cacheConfig = null;

            try
            {
                object param = new ConfigureCacheParam();
                CommandLineArgumentParser.CommandLineParser(ref param, args);
                ccParam = (ConfigureCacheParam)param;

                if (ccParam.IsUsage)
                {
                    AssemblyUsage.PrintLogo(ccParam.IsLogo);
                    AssemblyUsage.PrintUsage();
                    return;
                }

                if (!ValidateParameters())
                {
                    return;
                }

                if (ccParam.Port != -1)
                {
                    NCache.Port = ccParam.Port;
                }

                if (ccParam.Port == -1)
                {
                    NCache.Port = NCache.UseTcp ? CacheConfigManager.NCacheTcpPort : CacheConfigManager.HttpPort;
                }

                if (ccParam.Path != null && ccParam.Path != string.Empty)
                {
                    if (Path.HasExtension(ccParam.Path))
                    {
                        string extension = Path.GetExtension(ccParam.Path);

                        if (!extension.Equals(".ncconf") && !extension.Equals(".xml"))
                        {
                            throw new Exception("Incorrect file format. Only .ncconf and .xml are supported.");
                        }
                    }
                    else
                    {
                        throw new Exception("Incorrect configuration file path specified.");
                    }

                    ConfigurationBuilder builder = new ConfigurationBuilder(ccParam.Path);
                    builder.RegisterRootConfigurationObject(typeof(Alachisoft.NCache.Config.NewDom.CacheServerConfig));
                    builder.ReadConfiguration();

                    if (builder.Configuration != null)
                    {
                        caches = new Alachisoft.NCache.Config.NewDom.CacheServerConfig[builder.Configuration.Length];
                        builder.Configuration.CopyTo(caches, 0);
                    }
                    else
                    {
                        throw new Exception("Configuration cannot be loaded.");
                    }
                    ConfigurationValidator validator = new ConfigurationValidator();
                    bool _isConfigValidated          = validator.ValidateConfiguration(caches);

                    _cacheConfig = caches[0];

                    if (_cacheConfig.CacheSettings.Name == null)
                    {
                        _cacheConfig.CacheSettings.Name = ccParam.CacheId;
                    }

                    if (_cacheConfig.CacheSettings.Storage == null || _cacheConfig.CacheSettings.Storage.Size == -1)
                    {
                        throw new Exception("Cache size is not specified.");
                    }

                    if (_cacheConfig.CacheSettings.EvictionPolicy == null)
                    {
                        _cacheConfig.CacheSettings.EvictionPolicy                 = new EvictionPolicy();
                        _cacheConfig.CacheSettings.EvictionPolicy.Policy          = "priority";
                        _cacheConfig.CacheSettings.EvictionPolicy.DefaultPriority = "normal";
                        _cacheConfig.CacheSettings.EvictionPolicy.EvictionRatio   = 5;
                        _cacheConfig.CacheSettings.EvictionPolicy.Enabled         = true;
                    }

                    if (_cacheConfig.CacheSettings.Cleanup == null)
                    {
                        _cacheConfig.CacheSettings.Cleanup          = new Cleanup();
                        _cacheConfig.CacheSettings.Cleanup.Interval = 15;
                    }

                    if (_cacheConfig.CacheSettings.Log == null)
                    {
                        _cacheConfig.CacheSettings.Log = new Log();
                    }

                    if (_cacheConfig.CacheSettings.PerfCounters == null)
                    {
                        _cacheConfig.CacheSettings.PerfCounters         = new PerfCounters();
                        _cacheConfig.CacheSettings.PerfCounters.Enabled = true;
                    }

                    if (_cacheConfig.CacheSettings.CacheType == "clustered-cache")
                    {
                        if (_cacheConfig.CacheSettings.CacheTopology.ClusterSettings == null)
                        {
                            throw new Exception("Cluster settings not specified for the cluster cache.");
                        }

                        if (_cacheConfig.CacheSettings.CacheTopology.ClusterSettings.Channel == null)
                        {
                            throw new Exception("Cluster channel related settings not specified for cluster cache.");
                        }

                        if (_cacheConfig.CacheSettings.CacheTopology.ClusterSettings.Channel.TcpPort == -1)
                        {
                            throw new Exception("Cluster port not specified for cluster cache.");
                        }
                    }
                }
                else
                {
                    _SimpleCacheConfig.CacheSettings                                = new Alachisoft.NCache.Config.NewDom.CacheServerConfigSetting();
                    _SimpleCacheConfig.CacheSettings.Name                           = ccParam.CacheId;
                    _SimpleCacheConfig.CacheSettings.Storage                        = new Alachisoft.NCache.Config.Dom.Storage();
                    _SimpleCacheConfig.CacheSettings.EvictionPolicy                 = new EvictionPolicy();
                    _SimpleCacheConfig.CacheSettings.Cleanup                        = new Cleanup();
                    _SimpleCacheConfig.CacheSettings.Log                            = new Log();
                    _SimpleCacheConfig.CacheSettings.PerfCounters                   = new PerfCounters();
                    _SimpleCacheConfig.CacheSettings.PerfCounters.Enabled           = true;
                    _SimpleCacheConfig.CacheSettings.Storage.Type                   = "heap";
                    _SimpleCacheConfig.CacheSettings.Storage.Size                   = ccParam.CacheSize;
                    _SimpleCacheConfig.CacheSettings.EvictionPolicy.Policy          = "priority";
                    _SimpleCacheConfig.CacheSettings.EvictionPolicy.DefaultPriority = "normal";
                    _SimpleCacheConfig.CacheSettings.EvictionPolicy.EvictionRatio   = 5;
                    _SimpleCacheConfig.CacheSettings.EvictionPolicy.Enabled         = false;
                    _SimpleCacheConfig.CacheSettings.Cleanup.Interval               = 15;
                    _SimpleCacheConfig.CacheSettings.CacheTopology                  = new Alachisoft.NCache.Config.NewDom.CacheTopology();

                    if (string.IsNullOrEmpty(ccParam.Topology))
                    {
                        _SimpleCacheConfig.CacheSettings.CacheTopology.Topology = "Local";
                    }
                    else
                    {
                        _SimpleCacheConfig.CacheSettings.CacheTopology.Topology = ccParam.Topology;
                    }

                    if (ccParam.IsInProc && _SimpleCacheConfig.CacheSettings.CacheTopology.Topology.Equals("local-cache"))
                    {
                        _SimpleCacheConfig.CacheSettings.InProc = true;
                    }


                    if (_SimpleCacheConfig.CacheSettings.CacheType == "clustered-cache")
                    {
                        _SimpleCacheConfig.CacheSettings.CacheTopology.ClusterSettings         = new Alachisoft.NCache.Config.NewDom.Cluster();
                        _SimpleCacheConfig.CacheSettings.CacheTopology.ClusterSettings.Channel = new Alachisoft.NCache.Config.NewDom.Channel();

                        _SimpleCacheConfig.CacheSettings.CacheTopology.ClusterSettings.Channel.TcpPort  = ccParam.ClusterPort;
                        _SimpleCacheConfig.CacheSettings.CacheTopology.ClusterSettings.StatsRepInterval = 600;
                        if (_SimpleCacheConfig.CacheSettings.CacheTopology.Topology == "partitioned-replica")
                        {
                            _SimpleCacheConfig.CacheSettings.CacheTopology.ClusterSettings.Channel.PortRange = 2;
                        }
                    }

                    if (ccParam.EvictionPolicy != null && ccParam.EvictionPolicy != string.Empty)
                    {
                        _SimpleCacheConfig.CacheSettings.EvictionPolicy.Policy  = ccParam.EvictionPolicy;
                        _SimpleCacheConfig.CacheSettings.EvictionPolicy.Enabled = true;
                    }

                    if (ccParam.Ratio != -1)
                    {
                        _SimpleCacheConfig.CacheSettings.EvictionPolicy.EvictionRatio = ccParam.Ratio;
                    }

                    if (ccParam.CleanupInterval != -1)
                    {
                        _SimpleCacheConfig.CacheSettings.Cleanup.Interval = ccParam.CleanupInterval;
                    }

                    if (ccParam.DefaultPriority != null && ccParam.DefaultPriority != string.Empty)
                    {
                        _SimpleCacheConfig.CacheSettings.EvictionPolicy.DefaultPriority = ccParam.DefaultPriority;
                        _SimpleCacheConfig.CacheSettings.EvictionPolicy.Enabled         = true;
                    }
                    _cacheConfig = _SimpleCacheConfig;
                }
                try
                {
                    _cacheConfig.CacheSettings.Name = ccParam.CacheId;

                    if (_cacheConfig.CacheSettings.CacheType == "clustered-cache")
                    {
                        if (_cacheConfig.CacheDeployment == null)
                        {
                            _cacheConfig.CacheDeployment         = new Alachisoft.NCache.Config.NewDom.CacheDeployment();
                            _cacheConfig.CacheDeployment.Servers = new Alachisoft.NCache.Config.NewDom.ServersNodes();
                        }
                        _cacheConfig.CacheDeployment.Servers.NodesList = GetServers(ccParam.Server);
                    }

                    Dictionary <int, Management.ClientConfiguration.Dom.CacheServer> serverList = new Dictionary <int, Management.ClientConfiguration.Dom.CacheServer>();
                    int serverCount = 0;
                    foreach (Alachisoft.NCache.Config.NewDom.ServerNode node in GetServers(ccParam.Server))
                    {
                        Management.ClientConfiguration.Dom.CacheServer tempServer = new Management.ClientConfiguration.Dom.CacheServer();
                        tempServer.ServerName = node.IP;
                        serverList.Add(serverCount, tempServer);
                        serverCount++;
                    }
                    Management.ClientConfiguration.CacheServerList servers = new Management.ClientConfiguration.CacheServerList(serverList);
                    List <string> serversToUpdate = new List <string>();
                    foreach (Alachisoft.NCache.Config.NewDom.ServerNode node in GetServers(ccParam.Server))
                    {
                        NCache.ServerName = node.IP;

                        Console.WriteLine(AppendBlankLine("\nCreating cache") + " '{0}' on server '{1}' ", _cacheConfig.CacheSettings.Name, NCache.ServerName);
                        try
                        {
                            cacheServer = NCache.GetCacheServer(new TimeSpan(0, 0, 0, 30));
                            if (cacheServer != null)
                            {
                                Alachisoft.NCache.Config.NewDom.CacheServerConfig serverConfig = cacheServer.GetNewConfiguration(_cacheConfig.CacheSettings.Name);

                                if (serverConfig != null)
                                {
                                    throw new Exception("Specified cache already exists.");
                                }

                                else if (serverConfig != null && ccParam.IsOverWrite)
                                {
                                    NCache.ServerName = node.IP;

                                    if (serverConfig.CacheDeployment != null)
                                    {
                                        if (serverConfig.CacheDeployment.ClientNodes != null)
                                        {
                                            _cacheConfig.CacheDeployment.ClientNodes = serverConfig.CacheDeployment.ClientNodes;
                                        }
                                    }
                                }

                                cacheServer.RegisterCache(_cacheConfig.CacheSettings.Name, _cacheConfig, "", ccParam.IsOverWrite, ccParam.IsHotApply);
                                cacheServer.UpdateClientServersList(_cacheConfig.CacheSettings.Name, servers, "NCACHE");
                                serversToUpdate.Add(node.IP);

                                Console.WriteLine("Cache '{0}' successfully created on server {1}:{2} .", _cacheConfig.CacheSettings.Name, NCache.ServerName, NCache.Port);
                            }
                        }
                        catch (Exception ex)
                        {
                            throw ex;
                        }
                    }
                    Management.Management.Util.ManagementWorkFlow.UpdateServerMappingConfig(serversToUpdate.ToArray());
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    if (cacheServer != null)
                    {
                        cacheServer.Dispose();
                    }
                }
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(AppendBlankLine("Failed") + " to create cache on server '{0}'. ", ccParam.Server);
                Console.Error.WriteLine("Error Detail: '{0}'. ", ex.Message);
                LogEvent(ex.Message);
            }
            finally
            {
                NCache.Dispose();
            }
        }
Example #2
0
        /// <summary>
        /// The main entry point for the tool.
        /// </summary>
        public static void Run(string[] args)
        {
            string failedNodes = string.Empty;
            NCache.Port = NCache.UseTcp ? CacheConfigManager.NCacheTcpPort : CacheConfigManager.HttpPort;
            Alachisoft.NCache.Config.NewDom.CacheServerConfig[] caches = null;
            ICacheServer cacheServer = null;
            Alachisoft.NCache.Config.NewDom.CacheServerConfig _cacheConfig = null;

            try
            {
                object param = new ConfigureCacheParam();
                CommandLineArgumentParser.CommandLineParser(ref param, args);
                ccParam = (ConfigureCacheParam)param;

                if (ccParam.IsUsage)
                {
                    AssemblyUsage.PrintLogo(ccParam.IsLogo);
                    AssemblyUsage.PrintUsage();
                    return;
                }

                if (!ValidateParameters()) return;

                if (ccParam.Port != -1)
                {
                    NCache.Port = ccParam.Port;
                }

                if (ccParam.Port == -1) NCache.Port = NCache.UseTcp ? CacheConfigManager.NCacheTcpPort : CacheConfigManager.HttpPort;

                if (ccParam.Path != null && ccParam.Path != string.Empty)
                {
                    if (Path.HasExtension(ccParam.Path))
                    {
                        string extension = Path.GetExtension(ccParam.Path);

                        if (!extension.Equals(".ncconf") && !extension.Equals(".xml"))
                        {
                            throw new Exception("Incorrect file format. Only .ncconf and .xml are supported.");
                        }
                    }
                    else
                        throw new Exception("Incorrect configuration file path specified.");

                    ConfigurationBuilder builder = new ConfigurationBuilder(ccParam.Path);
                    builder.RegisterRootConfigurationObject(typeof(Alachisoft.NCache.Config.NewDom.CacheServerConfig));
                    builder.ReadConfiguration();

                    if (builder.Configuration != null)
                    {
                        caches = new Alachisoft.NCache.Config.NewDom.CacheServerConfig[builder.Configuration.Length];
                        builder.Configuration.CopyTo(caches, 0);
                    }
                    else
                        throw new Exception("Configuration cannot be loaded.");
                    ConfigurationValidator validator = new ConfigurationValidator();
                    bool _isConfigValidated = validator.ValidateConfiguration(caches);

                    _cacheConfig = caches[0];

                    if (_cacheConfig.CacheSettings.Name == null)
                        _cacheConfig.CacheSettings.Name = ccParam.CacheId;

                    if (_cacheConfig.CacheSettings.Storage == null || _cacheConfig.CacheSettings.Storage.Size == -1)
                    {
                        throw new Exception("Cache size is not specified.");
                    }

                    if (_cacheConfig.CacheSettings.EvictionPolicy == null)
                    {
                        _cacheConfig.CacheSettings.EvictionPolicy = new EvictionPolicy();
                        _cacheConfig.CacheSettings.EvictionPolicy.Policy = "priority";
                        _cacheConfig.CacheSettings.EvictionPolicy.DefaultPriority = "normal";
                        _cacheConfig.CacheSettings.EvictionPolicy.EvictionRatio = 5;
                        _cacheConfig.CacheSettings.EvictionPolicy.Enabled = true;
                    }

                    if (_cacheConfig.CacheSettings.Cleanup == null)
                    {
                        _cacheConfig.CacheSettings.Cleanup = new Cleanup();
                        _cacheConfig.CacheSettings.Cleanup.Interval = 15;
                    }

                    if (_cacheConfig.CacheSettings.Log == null)
                    {
                        _cacheConfig.CacheSettings.Log = new Log();
                    }

                    if (_cacheConfig.CacheSettings.PerfCounters == null)
                    {
                        _cacheConfig.CacheSettings.PerfCounters = new PerfCounters();
                        _cacheConfig.CacheSettings.PerfCounters.Enabled = true;
                    }

                    if (_cacheConfig.CacheSettings.CacheType == "clustered-cache")
                    {
                        if (_cacheConfig.CacheSettings.CacheTopology.ClusterSettings == null)
                        {
                            throw new Exception("Cluster settings not specified for the cluster cache.");
                        }

                        if (_cacheConfig.CacheSettings.CacheTopology.ClusterSettings.Channel == null)
                        {
                            throw new Exception("Cluster channel related settings not specified for cluster cache.");
                        }

                        if (_cacheConfig.CacheSettings.CacheTopology.ClusterSettings.Channel.TcpPort == -1)
                        {
                            throw new Exception("Cluster port not specified for cluster cache.");
                        }
                    }
                }
                else
                {
                    _SimpleCacheConfig.CacheSettings = new Alachisoft.NCache.Config.NewDom.CacheServerConfigSetting();
                    _SimpleCacheConfig.CacheSettings.Name = ccParam.CacheId;
                    _SimpleCacheConfig.CacheSettings.Storage = new Alachisoft.NCache.Config.Dom.Storage();
                    _SimpleCacheConfig.CacheSettings.EvictionPolicy = new EvictionPolicy();
                    _SimpleCacheConfig.CacheSettings.Cleanup = new Cleanup();
                    _SimpleCacheConfig.CacheSettings.Log = new Log();
                    _SimpleCacheConfig.CacheSettings.PerfCounters = new PerfCounters();
                    _SimpleCacheConfig.CacheSettings.PerfCounters.Enabled = true;
                    _SimpleCacheConfig.CacheSettings.Storage.Type = "heap";
                    _SimpleCacheConfig.CacheSettings.Storage.Size = ccParam.CacheSize;
                    _SimpleCacheConfig.CacheSettings.EvictionPolicy.Policy = "priority";
                    _SimpleCacheConfig.CacheSettings.EvictionPolicy.DefaultPriority = "normal";
                    _SimpleCacheConfig.CacheSettings.EvictionPolicy.EvictionRatio = 5;
                    _SimpleCacheConfig.CacheSettings.EvictionPolicy.Enabled = false;
                    _SimpleCacheConfig.CacheSettings.Cleanup.Interval = 15;
                    _SimpleCacheConfig.CacheSettings.CacheTopology = new Alachisoft.NCache.Config.NewDom.CacheTopology();

                    if (string.IsNullOrEmpty(ccParam.Topology))
                    {
                        _SimpleCacheConfig.CacheSettings.CacheTopology.Topology = "Local";
                    }
                    else
                    {
                        _SimpleCacheConfig.CacheSettings.CacheTopology.Topology = ccParam.Topology;
                    }

                    if (ccParam.IsInProc && _SimpleCacheConfig.CacheSettings.CacheTopology.Topology.Equals("local-cache"))
                        _SimpleCacheConfig.CacheSettings.InProc = true;

                    if (_SimpleCacheConfig.CacheSettings.CacheType == "clustered-cache")
                    {
                        _SimpleCacheConfig.CacheSettings.CacheTopology.ClusterSettings = new Alachisoft.NCache.Config.NewDom.Cluster();
                        _SimpleCacheConfig.CacheSettings.CacheTopology.ClusterSettings.Channel = new Alachisoft.NCache.Config.NewDom.Channel();

                        _SimpleCacheConfig.CacheSettings.CacheTopology.ClusterSettings.Channel.TcpPort = ccParam.ClusterPort;
                        _SimpleCacheConfig.CacheSettings.CacheTopology.ClusterSettings.StatsRepInterval = 600;
                        if (_SimpleCacheConfig.CacheSettings.CacheTopology.Topology == "partitioned-replica")
                            _SimpleCacheConfig.CacheSettings.CacheTopology.ClusterSettings.Channel.PortRange = 2;

                    }

                    if (ccParam.EvictionPolicy != null && ccParam.EvictionPolicy != string.Empty)
                    {
                        _SimpleCacheConfig.CacheSettings.EvictionPolicy.Policy = ccParam.EvictionPolicy;
                        _SimpleCacheConfig.CacheSettings.EvictionPolicy.Enabled = true;
                    }

                    if (ccParam.Ratio != -1)
                    {
                        _SimpleCacheConfig.CacheSettings.EvictionPolicy.EvictionRatio = ccParam.Ratio;
                    }

                    if (ccParam.CleanupInterval != -1)
                    {
                        _SimpleCacheConfig.CacheSettings.Cleanup.Interval = ccParam.CleanupInterval;
                    }

                    if (ccParam.DefaultPriority != null && ccParam.DefaultPriority != string.Empty)
                    {
                        _SimpleCacheConfig.CacheSettings.EvictionPolicy.DefaultPriority = ccParam.DefaultPriority;
                        _SimpleCacheConfig.CacheSettings.EvictionPolicy.Enabled = true;
                    }
                    _cacheConfig = _SimpleCacheConfig;
                }
                try
                {
                    _cacheConfig.CacheSettings.Name = ccParam.CacheId;

                    if (_cacheConfig.CacheSettings.CacheType == "clustered-cache")
                    {
                        if (_cacheConfig.CacheDeployment == null)
                        {
                            _cacheConfig.CacheDeployment = new Alachisoft.NCache.Config.NewDom.CacheDeployment();
                            _cacheConfig.CacheDeployment.Servers = new Alachisoft.NCache.Config.NewDom.ServersNodes();

                        }
                        _cacheConfig.CacheDeployment.Servers.NodesList = GetServers(ccParam.Server);
                    }

                    Dictionary<int, Management.ClientConfiguration.Dom.CacheServer> serverList = new Dictionary<int, Management.ClientConfiguration.Dom.CacheServer>();
                    int serverCount = 0;
                    foreach (Alachisoft.NCache.Config.NewDom.ServerNode node in GetServers(ccParam.Server))
                    {
                        Management.ClientConfiguration.Dom.CacheServer tempServer = new Management.ClientConfiguration.Dom.CacheServer();
                        tempServer.ServerName = node.IP;
                        serverList.Add(serverCount, tempServer);
                        serverCount++;
                    }
                    Management.ClientConfiguration.CacheServerList servers = new Management.ClientConfiguration.CacheServerList(serverList);
                    List<string> serversToUpdate = new List<string>();
                    foreach (Alachisoft.NCache.Config.NewDom.ServerNode node in GetServers(ccParam.Server))
                    {
                        NCache.ServerName = node.IP;

                        Console.WriteLine(AppendBlankLine("\nCreating cache") + " '{0}' on server '{1}' ", _cacheConfig.CacheSettings.Name, NCache.ServerName);
                        try
                        {
                            cacheServer = NCache.GetCacheServer(new TimeSpan(0, 0, 0, 30));
                            if (cacheServer != null)
                            {
                                Alachisoft.NCache.Config.NewDom.CacheServerConfig serverConfig = cacheServer.GetNewConfiguration(_cacheConfig.CacheSettings.Name);

                                if (serverConfig != null)
                                {
                                    throw new Exception("Specified cache already exists.");

                                }

                                else if (serverConfig != null && ccParam.IsOverWrite)
                                {
                                    NCache.ServerName = node.IP;

                                    if (serverConfig.CacheDeployment != null)
                                    {
                                        if (serverConfig.CacheDeployment.ClientNodes != null)
                                            _cacheConfig.CacheDeployment.ClientNodes = serverConfig.CacheDeployment.ClientNodes;
                                    }

                                }

                                cacheServer.RegisterCache(_cacheConfig.CacheSettings.Name, _cacheConfig, "", ccParam.IsOverWrite, ccParam.IsHotApply);
                                cacheServer.UpdateClientServersList(_cacheConfig.CacheSettings.Name, servers, "NCACHE");
                                serversToUpdate.Add(node.IP);

                                Console.WriteLine("Cache '{0}' successfully created on server {1}:{2} .", _cacheConfig.CacheSettings.Name, NCache.ServerName, NCache.Port);
                            }

                        }
                        catch (Exception ex)
                        {
                            throw ex;
                        }
                    }
                    Management.Management.Util.ManagementWorkFlow.UpdateServerMappingConfig(serversToUpdate.ToArray());

                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    if (cacheServer != null)
                        cacheServer.Dispose();
                }

            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(AppendBlankLine("Failed") + " to create cache on server '{0}'. ", ccParam.Server);
                Console.Error.WriteLine("Error Detail: '{0}'. ", ex.Message);
                LogEvent(ex.Message);
            }
            finally
            {
                NCache.Dispose();
            }
        }