/// <summary> /// Asynchronously adds a log to storage /// </summary> /// <param name="channelName">The name of the channel associated with the log</param> /// <param name="log">The log to add</param> /// <exception cref="StorageException"/> public Task PutLog(string channelName, Log log) { return(AddTaskToQueue(() => { var logJsonString = LogSerializer.Serialize(log); var maxSize = _storageAdapter.GetMaxStorageSize(); var logSize = Encoding.UTF8.GetBytes(logJsonString).Length; if (maxSize < 0) { throw new StorageException("Failed to store a log to the database."); } if (maxSize <= logSize) { throw new StorageException($"Log is too large ({logSize} bytes) to store in database. " + $"Current maximum database size is {maxSize} bytes."); } while (true) { try { _storageAdapter.Insert(TableName, new[] { ColumnChannelName, ColumnLogName }, new List <object[]> { new object[] { channelName, logJsonString } }); return; } catch (StorageFullException) { var oldestLog = _storageAdapter.Select(TableName, ColumnChannelName, channelName, string.Empty, null, 1, new string[] { ColumnIdName }); if (oldestLog != null && oldestLog.Count > 0 && oldestLog[0].Length > 0) { _storageAdapter.Delete(TableName, ColumnIdName, oldestLog[0][0]); } else { throw new StorageException("Failed to add a new log. Storage is full and old logs cannot be purged."); } } } })); }