/// <summary> /// Load all data in once for one customer ... /// </summary> /// <param name="database"></param> /// <param name="customerId"></param> /// <param name="getDatabase"></param> public void Initialize(DatabaseContext database, int customerId, FunctionGetDatabase getDatabase) { if (!_enable) { Info($"[{customerId}] No cache enabled ..."); return; } _mutex.Wait(); // lock critical section if (_tick.ContainsKey(customerId)) { _mutex.Release(); // unlock critical section Warn($"[{customerId}] Data are still loaded!"); return; } if (_tables.Count == 0) { Debug("Initializing tables into the cache ..."); foreach (KeyValuePair <string, DSDatabase> schema in ConfigurationManager.Schemas) { foreach (KeyValuePair <string, DSTable> table in schema.Value.Tables) { if (_tables.ContainsKey(table.Key)) { continue; } Verbose($"Initializing the table '{table.Key}' ({table.Value.Area}) ..."); _tables[table.Key] = table.Value; } } Info($"{_tables.Count} tables initialized"); } Info($"[{customerId}] Loading data ..."); // Build the cache for the customer Dictionary <string, Dictionary <int, Tuple <DSRecord, InformationRecord> > > currentCache = null; if (!_records.ContainsKey(customerId)) { Debug($"[{customerId}] Initializing tables ..."); currentCache = new Dictionary <string, Dictionary <int, Tuple <DSRecord, InformationRecord> > >(_tables.Count); _records[customerId] = currentCache; foreach (KeyValuePair <string, DSTable> table in _tables) { currentCache[table.Key] = new Dictionary <int, Tuple <DSRecord, InformationRecord> >(table.Value.Capacity); } } else { currentCache = _records[customerId]; } Lock(customerId, false); _mutex.Release(); // unlock critical section // sort all tables by area ... foreach (string area in _tables.Select(t => t.Value.Area).Distinct()) { if (area == null) { continue; } Debug($"Loading tables from the area '{area}' ..."); try { using (DatabaseContext currentContext = getDatabase(area)) { // Load data into the current cache foreach (KeyValuePair <string, DSTable> table in _tables.Where(t => t.Value.Area.Equals(area))) { try { Debug($"[{customerId}] Loading table '{table.Key}' ..."); // Load all records between the last tick and the new one (only for request successfully executed) Dictionary <int, Tuple <DSRecord, InformationRecord> > currentTable = currentCache[table.Key]; foreach (Tuple <DSRecord, InformationRecord> record in table.Value.ReadRecords(currentContext, customerId)) { currentTable[record.Item1.Id] = record; } Info($"[{customerId}] {currentTable.Count} records read into the table '{table.Key}'"); GC.Collect(); } catch (System.Exception ex) { Exception($"[{customerId}] Unable to initialize the cache", ex); } } } } catch (System.Exception ex) { Exception($"[{customerId}] Unable to load the area {area}", ex); } } // Finalize the initialization of the cache for this customer _tick[customerId] = GetTick(database, customerId); Info($"[{customerId}] Cache initialized in tick {_tick[customerId]}"); Unlock(customerId); }
/// <summary> /// Check if the last tick loaded is different, and only load differences ... /// </summary> /// <param name="database"></param> /// <param name="customerId"></param> /// <param name="getDatabase"></param> public void UpdateCache(DatabaseContext database, int customerId, FunctionGetDatabase getDatabase) { if (!_enable) { return; } // Check if the customer is currently loaded if (!_tick.ContainsKey(customerId)) { Initialize(database, customerId, getDatabase); } // the current customer is available Lock(customerId); // lock critical section // If the tick into the cache is not the same as the current one ... update the cache manager int currentTick = GetTick(database, customerId); int previousTick = _tick[customerId]; if (currentTick <= previousTick) { Unlock(customerId); // unlock critical section return; } Debug($"[{customerId}] Updating cache between {previousTick} and {currentTick} ..."); int nbUpdates = 0; try { // Load all records between the last tick and the new one (only for request successfully executed) DSTable currentTable = null; Dictionary <int, Tuple <DSRecord, InformationRecord> > currentContent = null; foreach (RequestTableRecord request in database._RequestTable.Where(r => r.CustomerId == customerId && r.Id != null && previousTick < r.Tick && r.Tick <= currentTick).ToList().OrderBy(r => r.Table).ThenBy(r => r.Id)) { // new table ? if (currentTable == null || !currentTable.Name.Equals(request.Table)) { currentTable = null; currentContent = null; if (!_tables.ContainsKey(request.Table)) { if (IsVerbose()) { Verbose($"[{customerId}] The table '{request.Table}' doesn't exist into the cache. May be, the table doesn't exist into the schemas"); } continue; } currentTable = _tables[request.Table]; currentContent = _records[customerId][request.Table]; } // read the current record Tuple <DSRecord, InformationRecord> currentRecord = currentTable.GetRecord(database, request.Id.Value, customerId); if (currentRecord == null) { continue; } // Update the cache currentContent[request.Id.Value] = currentRecord; nbUpdates++; } _tick[customerId] = currentTick; } catch (System.Exception ex) { Exception($"[{customerId}] Unable to update the cache", ex); } Info($"[{customerId}] {nbUpdates} records loaded between {previousTick} and {currentTick}"); Unlock(customerId); // Unlock the critical section }
/// <summary> /// Load all data in once ... /// </summary> /// <param name="database"></param> /// <param name="customerIds">All customers Id to load</param> /// <param name="getDatabase"></param> public void Initialize(DatabaseContext database, List <int> customerIds, FunctionGetDatabase getDatabase) { if (!_enable) { Info($"No cache enabled ..."); return; } if (_tables.Count == 0) { Debug("Initializing tables into the cache ..."); foreach (KeyValuePair <string, DSDatabase> schema in ConfigurationManager.Schemas) { foreach (KeyValuePair <string, DSTable> table in schema.Value.Tables) { if (_tables.ContainsKey(table.Key)) { continue; } Verbose($"Initializing the table '{table.Key}' ({table.Value.Area}) ..."); _tables[table.Key] = table.Value; } } Info($"{_tables.Count} tables initialized"); } // Building the cache for all customers _mutex.Wait(); // lock critical section foreach (int customerId in customerIds) { Lock(customerId, false); // Build and clean the cache for the customers and lock all customers ... Debug($"Initializing tables for the customer '{customerId}' ..."); Dictionary <string, Dictionary <int, Tuple <DSRecord, InformationRecord> > > currentCache = new Dictionary <string, Dictionary <int, Tuple <DSRecord, InformationRecord> > >(_tables.Count); _records[customerId] = currentCache; // replace the cache already existing foreach (KeyValuePair <string, DSTable> table in _tables) { currentCache[table.Key] = new Dictionary <int, Tuple <DSRecord, InformationRecord> >(); } } _mutex.Release(); // unlock critical section // Loading all data foreach (string area in _tables.Select(t => t.Value.Area).Distinct()) { if (area == null) { continue; } Debug($"Loading tables from the area '{area}' ..."); try { using (DatabaseContext currentContext = getDatabase(area)) { // Load data into the current cache foreach (KeyValuePair <string, DSTable> table in _tables.Where(t => t.Value.Area.Equals(area))) { Debug($"Loading table '{table.Key}' ..."); try { int nbRecords = 0; // Load all records between the last tick and the new one (only for request successfully executed) foreach (Tuple <DSRecord, InformationRecord> record in table.Value.ReadRecords(currentContext)) { if (record.Item2.CustomerId < 0) { foreach (int customerId in customerIds) { _records[customerId][table.Key][record.Item1.Id] = record; } nbRecords++; } else if (customerIds.IndexOf(record.Item2.CustomerId) >= 0) { _records[record.Item2.CustomerId][table.Key][record.Item1.Id] = record; nbRecords++; } } Info($"{nbRecords} records read into the table '{table.Key}' ..."); GC.Collect(); } catch (System.Exception ex) { Exception($"Unable to initialize the cache for the table '{table.Key}'", ex); } } } } catch (System.Exception ex) { Exception($"Unable to load the area {area}", ex); } } // Finalize the initialization of the cache for this customer foreach (int customerId in customerIds) { _tick[customerId] = GetTick(database, customerId); Info($"[{customerId}] Cache initialized in tick {_tick[customerId]}"); Unlock(customerId); } }