/// <summary> /// This function copies the schemas and geography data off an existing Swarmops installation. Runs in its own thread. /// </summary> public static void InitDatabaseThread() { // Ignore the session object, that method of sharing data didn't work, but a static variable did. _initProgress = 1; _initMessage = "Loading schema from Swarmops servers; creating tables and procs..."; Thread.Sleep(100); try { // Get the schema and initialize the database structures. Requires ADMIN access to database. Swarmops.Logic.Support.DatabaseMaintenance.FirstInitialization(); _initProgress = 6; _initMessage = "Applying all post-baseline database schema upgrades..."; Swarmops.Logic.Support.DatabaseMaintenance.UpgradeSchemata(); Thread.Sleep(100); _initProgress = 5; _initMessage = "Getting list of countries from Swarmops servers..."; Thread.Sleep(100); // Create translation lists Dictionary <int, int> geographyIdTranslation = new Dictionary <int, int>(); Dictionary <int, int> cityIdTranslation = new Dictionary <int, int>(); Dictionary <string, int> countryIdTranslation = new Dictionary <string, int>(); Dictionary <int, bool> cityIdsUsedLookup = new Dictionary <int, bool>(); // Initialize the root geography (which becomes #1 if everything works) int rootGeographyId = SwarmDb.GetDatabaseForWriting().CreateGeography("World", 0); // Get the list of countries Swarmops.Site.Automation.GetGeographyData geoDataFetcher = new GetGeographyData(); Swarmops.Site.Automation.Country[] countries = geoDataFetcher.GetCountries(); _initProgress = 7; _initMessage = "Creating all countries on local server..."; Thread.Sleep(100); int count = 0; int total = countries.Length; // Create all countries in our own database foreach (Swarmops.Site.Automation.Country country in countries) { countryIdTranslation[country.Code] = SwarmDb.GetDatabaseForWriting().CreateCountry(country.Name, country.Code, country.Culture, rootGeographyId, 5, string.Empty); count++; _initMessage = String.Format("Creating all countries on local server... ({0}%)", count * 100 / total); } _initProgress = 10; // Construct list of countries that have geographic data List <string> initializableCountries = new List <string>(); foreach (Swarmops.Site.Automation.Country country in countries) { if (country.GeographyId != 1) { initializableCountries.Add(country.Code); } } float initStepPerCountry = 90f / initializableCountries.Count; int countryCount = 0; // For each country... foreach (string countryCode in initializableCountries) { // Get the geography layout _initMessage = "Retrieving geography for " + countryCode + "..."; Thread.Sleep(100); Swarmops.Site.Automation.Geography geography = geoDataFetcher.GetGeographyForCountry(countryCode); _initProgress = 10 + (int)(countryCount * initStepPerCountry + initStepPerCountry / 6); _initMessage = "Setting up geography for " + countryCode + "..."; Thread.Sleep(100); // Create the country's root geography int countryRootGeographyId = SwarmDb.GetDatabaseForWriting().CreateGeography(geography.Name, rootGeographyId); geographyIdTranslation[geography.GeographyId] = countryRootGeographyId; SwarmDb.GetDatabaseForWriting().SetCountryGeographyId(countryIdTranslation[countryCode], countryRootGeographyId); count = 0; total = InitDatabaseThreadCountGeographyChildren(geography.Children); InitDatabaseThreadCreateGeographyChildren(geography.Children, countryRootGeographyId, ref geographyIdTranslation, countryCode, ref count, total); _initProgress = 10 + (int)(countryCount * initStepPerCountry + initStepPerCountry / 3); _initMessage = "Retrieving cities for " + countryCode + "..."; Thread.Sleep(100); // Get the postal codes and cities Swarmops.Site.Automation.City[] cities = null; try { cities = geoDataFetcher.GetCitiesForCountry(countryCode); } catch (Exception) // This is a SoapHeaderException in VS debugging, but SOMETHING ELSE! in Mono runtime, so make it generic { // This is typically a country that isn't populated with cities yet. Ignore. countryCount++; continue; } _initProgress = 10 + (int)(countryCount * initStepPerCountry + initStepPerCountry / 2); _initMessage = "Retrieving postal codes for " + countryCode + "..."; Thread.Sleep(100); Swarmops.Site.Automation.PostalCode[] postalCodes = geoDataFetcher.GetPostalCodesForCountry(countryCode); // Find which cities are actually used foreach (Swarmops.Site.Automation.PostalCode postalCode in postalCodes) { cityIdsUsedLookup[postalCode.CityId] = true; } _initProgress = 10 + (int)(countryCount * initStepPerCountry + initStepPerCountry * 2 / 3); // Insert cities int newCountryId = countryIdTranslation[countryCode]; int cityIdHighwater = SwarmDb.GetDatabaseForAdmin().ExecuteAdminCommandScalar("SELECT Max(CityId) FROM Cities;"); _initMessage = string.Format("Setting up {0:N0} cities for {1}...", cities.Length, countryCode); StringBuilder sqlCityBuild = new StringBuilder("INSERT INTO Cities (CityName, GeographyId, CountryId, Comment) VALUES ", 65536); bool insertComma = false; foreach (Swarmops.Site.Automation.City city in cities) { if (!geographyIdTranslation.ContainsKey(city.GeographyId)) { cityIdsUsedLookup[city.CityId] = false; // force non-use of invalid city } if (cityIdsUsedLookup[city.CityId]) { int newGeographyId = geographyIdTranslation[city.GeographyId]; if (insertComma) { sqlCityBuild.Append(","); } sqlCityBuild.Append("('" + city.Name.Replace("'", "\'") + "'," + newGeographyId.ToString() + "," + newCountryId.ToString() + ",'')"); insertComma = true; cityIdTranslation[city.CityId] = ++cityIdHighwater; // Note that we assume the assigned ID here. } } sqlCityBuild.Append(";"); SwarmDb.GetDatabaseForAdmin().ExecuteAdminCommand(sqlCityBuild.ToString()); // Inserts all cities in one bulk op, to save roundtrips // Insert postal codes _initProgress = 10 + (int)(countryCount * initStepPerCountry + initStepPerCountry * 5 / 6); _initMessage = string.Format("Setting up {0:N0} postal codes for {1}...", postalCodes.Length, countryCode); StringBuilder sqlBuild = new StringBuilder("INSERT INTO PostalCodes (PostalCode, CityId, CountryId) VALUES ", 65536); insertComma = false; foreach (Swarmops.Site.Automation.PostalCode postalCode in postalCodes) { if (cityIdsUsedLookup[postalCode.CityId] == false) { // Remnants of invalid pointers continue; } int newCityId = cityIdTranslation[postalCode.CityId]; if (insertComma) { sqlBuild.Append(","); } sqlBuild.Append("('" + postalCode.PostalCode.Replace("'", "\'") + "'," + newCityId.ToString() + "," + newCountryId.ToString() + ")"); insertComma = true; } sqlBuild.Append(";"); SwarmDb.GetDatabaseForAdmin().ExecuteAdminCommand(sqlBuild.ToString()); // Inserts all postal codes in one bulk op, to save roundtrips countryCount++; _initProgress = 10 + (int)(countryCount * initStepPerCountry); } // Set Geography at baseline (TODO: Ask for what baseline we got) Persistence.Key["LastGeographyUpdateId"] = "0"; // Set an installation ID Persistence.Key["SwarmopsInstallationId"] = Guid.NewGuid().ToString(); // Create initial currencies (European) Currency.Create("EUR", "Euros", "€"); Currency.Create("USD", "US Dollars", "$"); Currency.Create("CAD", "Canadian Dollars", "CA$"); Currency.Create("SEK", "Swedish Krona", string.Empty); Currency.Create("NOK", "Norwegian Krona", string.Empty); Currency.Create("DKK", "Danish Krona", string.Empty); Currency.Create("ISK", "Icelandic Krona", string.Empty); Currency.Create("CHF", "Swiss Franc", string.Empty); Currency.Create("GBP", "Pounds Sterling", "£"); Currency.Create("BTC", "Bitcoin", "฿"); // Create the sandbox Swarmops.Logic.Structure.Organization.Create(0, "Sandbox", "Sandbox", "Sandbox", "swarmops.com", "Ops", rootGeographyId, true, true, 0).EnableEconomy(Swarmops.Logic.Financial.Currency.FromCode("EUR")); _initProgress = 100; _initMessage = "Complete."; } catch (Exception failedException) { // Use initMessage to push info about what went wrong to the user _initMessage = failedException.ToString(); } Thread.Sleep(1000); // give some time for static var to stick and web interface to react before killing thread }
/// <summary> /// This function copies the schemas and geography data off an existing Swarmops installation. Runs in its own thread. /// </summary> public static void InitDatabaseThread() { // Ignore the session object, that method of sharing data didn't work, but a static variable did. _initProgress = 1; _initMessage = "Loading schema from Swarmops servers; creating tables and procs..."; Thread.Sleep(100); try { // Get the schema and initialize the database structures. Requires ADMIN access to database. DatabaseMaintenance.FirstInitialization(); _initProgress = 3; _initMessage = "Applying all post-baseline database schema upgrades..."; DatabaseMaintenance.UpgradeSchemata(); Thread.Sleep(100); _initProgress = 5; _initMessage = "Getting list of countries from Swarmops servers..."; Thread.Sleep(100); // Create translation lists Dictionary <string, int> countryIdTranslation = new Dictionary <string, int>(); // Initialize the root geography (which becomes #1 if everything works) int rootGeographyId = SwarmDb.GetDatabaseForWriting().CreateGeography("[LOC]World", 0); // Get the list of countries GetGeographyData geoDataFetcher = new GetGeographyData(); Country[] countries = geoDataFetcher.GetCountries(); _initProgress = 7; _initMessage = "Creating all countries on local server..."; Thread.Sleep(100); int count = 0; int total = countries.Length; // Create all countries in our own database foreach (Country country in countries) { countryIdTranslation[country.Code] = SwarmDb.GetDatabaseForWriting().CreateCountry(country.Name, country.Code, country.Culture, rootGeographyId, country.PostalCodeLength, string.Empty); count++; _initMessage = String.Format("Creating all countries on local server... ({0}%)", count * 100 / total); } _initProgress = 10; // Construct list of countries that have geographic data List <string> initializableCountries = new List <string>(); foreach (Country country in countries) { if (country.GeographyId != 1) { initializableCountries.Add(country.Code); } } float initStepPerCountry = 90f / initializableCountries.Count; int countryCount = 0; // For each country... foreach (string countryCode in initializableCountries) { // Get the geography layout _initMessage = "Initializing geography for country " + countryCode + "... "; Thread.Sleep(100); GeographyUpdate.PrimeCountry(countryCode); GuidCache.Set("DbInitProgress", string.Empty); countryCount++; _initProgress = 10 + (int)(countryCount * initStepPerCountry); } // Set Geography at baseline (TODO: Ask for what baseline we got) Persistence.Key["LastGeographyUpdateId"] = "0"; Persistence.Key["LastGeographyUpdate"] = "1900-01-01"; // Set an installation ID Persistence.Key["SwarmopsInstallationId"] = Guid.NewGuid().ToString(); _initMessage = "Initializing currencies..."; // Create initial currencies (European et al) Currency.Create("EUR", "Euros", "€"); Currency.Create("USD", "US Dollars", "$"); Currency.Create("CAD", "Canadian Dollars", "CA$"); Currency.Create("SEK", "Swedish Krona", string.Empty); Currency.Create("NOK", "Norwegian Krona", string.Empty); Currency.Create("DKK", "Danish Krona", string.Empty); Currency.Create("ISK", "Icelandic Krona", string.Empty); Currency.Create("CHF", "Swiss Franc", string.Empty); Currency.Create("GBP", "Pounds Sterling", "£"); Currency.Create("BTC", "Bitcoin", "฿"); // Fetch the first set of exchange rates, completing the currency collection ExchangeRateSnapshot.Create(); // Create the sandbox Organization.Create(0, "Sandbox", "Sandbox", "Sandbox", "swarmops.com", "Ops", rootGeographyId, true, true, 0).EnableEconomy(Currency.FromCode("EUR")); _initProgress = 100; _initMessage = "Complete."; } catch (Exception failedException) { // Use initMessage to push info about what went wrong to the user _initMessage = failedException.ToString(); } Thread.Sleep(1000); // give some time for static var to stick and web interface to react before killing thread }
/// <summary> /// This function copies the schemas and geography data off an existing Swarmops installation. Runs in its own thread. /// </summary> public static void InitDatabaseThread() { // Ignore the session object, that method of sharing data didn't work, but a static variable did. _initProgress = 1; _initMessage = "Loading schema from Swarmops servers; creating tables and procs..."; Thread.Sleep(100); try { // Get the schema and initialize the database structures. Requires ADMIN access to database. DatabaseMaintenance.FirstInitialization(); _initProgress = 3; _initMessage = "Applying all post-baseline database schema upgrades..."; DatabaseMaintenance.UpgradeSchemata(); Thread.Sleep(100); // SECURITY: With schemata to hold them in place, initialize the encryption keys Authentication.InitializeSymmetricDatabaseKey(); Authentication.InitializeSymmetricFileSystemKey(); // Set Geography at baseline (TODO: Ask for what baseline we got) Persistence.Key["LastGeographyUpdateId"] = "0"; Persistence.Key["LastGeographyUpdate"] = Constants.DateTimeLow.ToString("yyyy-MM-dd"); // Set an installation ID // Doubles as start signal to daemons (if installation ID exists, db is ready for processing) Persistence.Key["SwarmopsInstallationId"] = Guid.NewGuid().ToString(); _initProgress = 4; _initMessage = "Initializing currencies..."; // Create initial currencies (European et al) Currency.CreateFiat("EUR", "Euros", "€"); Currency.CreateFiat("USD", "US Dollars", "$"); Currency.CreateFiat("CAD", "Canadian Dollars", "CA$"); Currency.CreateFiat("SEK", "Swedish Krona", string.Empty); Currency.CreateFiat("NOK", "Norwegian Krona", string.Empty); Currency.CreateFiat("DKK", "Danish Krona", string.Empty); Currency.CreateFiat("ISK", "Icelandic Krona", string.Empty); Currency.CreateFiat("CHF", "Swiss Franc", string.Empty); Currency.CreateFiat("GBP", "Pounds Sterling", "£"); Currency.CreateCrypto("BTC", "Bitcoin Core", "฿"); Currency.CreateCrypto("BCH", "Bitcoin Cash", "฿"); // Fetch the first set of exchange rates, completing the currency collection ExchangeRateSnapshot.Create(); // Disable SSL required - the user must turn this on manually SystemSettings.RequireSsl = false; _initProgress = 5; _initMessage = "Getting list of countries from Swarmops servers..."; Thread.Sleep(100); // Create translation lists Dictionary <string, int> countryIdTranslation = new Dictionary <string, int>(); // Initialize the root geography (which becomes #1 if everything works) int rootGeographyId = SwarmDb.GetDatabaseForWriting().CreateGeography("[LOC]World", 0); // Create the sandbox Organization sandbox = Organization.Create(0, "Sandbox", "Sandbox", "Sandbox", "swarmops.com", "Ops", rootGeographyId, true, true, 0); sandbox.EnableEconomy(Currency.FromCode("EUR")); Positions.CreateOrganizationDefaultPositions(sandbox); // Get the list of countries GetGeographyData geoDataFetcher = new GetGeographyData(); Country[] countries = null; _initProgress = 7; _initMessage = "Creating all countries on local server..."; Thread.Sleep(100); int count = 0; int countryRetries = 0; try { countries = geoDataFetcher.GetCountries(); } catch (Exception) { // ignore for now, retrying below } while (++countryRetries < 10 && (countries == null || countries.Length < 20)) { _initMessage = "Network problem, retrying... "; if (countryRetries > 1) { _initMessage += String.Format("({0})", countryRetries); } Thread.Sleep(500); try { countries = geoDataFetcher.GetCountries(); } catch (Exception) { if (countryRetries > 8) { throw; } // otherwise ignore for now } } int total = countries.Length; // Create all countries in our own database foreach (Country country in countries) { countryIdTranslation[country.Code] = SwarmDb.GetDatabaseForWriting().CreateCountry(country.Name, country.Code, country.Culture, rootGeographyId, country.PostalCodeLength, string.Empty); count++; _initMessage = String.Format("Creating all countries on local server... ({0}%)", count * 100 / total); } _initProgress = 10; // Construct list of countries that have geographic data List <string> initializableCountries = new List <string>(); foreach (Country country in countries) { if (country.GeographyId != 1) { initializableCountries.Add(country.Code); } } float initStepPerCountry = 90f / initializableCountries.Count; int countryCount = 0; // For each country... foreach (string countryCode in initializableCountries) { // Get the geography layout _initMessage = "Initializing geography for country " + countryCode + "... "; Thread.Sleep(100); GeographyUpdate.PrimeCountry(countryCode); GuidCache.Set("DbInitProgress", string.Empty); countryCount++; _initProgress = 10 + (int)(countryCount * initStepPerCountry); } _initProgress = 100; _initMessage = "Complete."; } catch (Exception failedException) { // Use initMessage to push info about what went wrong to the user _initMessage = failedException.ToString(); } Thread.Sleep(1000); // give some time for static var to stick and web interface to react before killing thread }