|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- using Microsoft.Extensions.Logging;
- using MQTTnet.Server.Configuration;
- using Newtonsoft.Json;
-
- namespace MQTTnet.Server.Mqtt
- {
- public class MqttServerStorage : IMqttServerStorage
- {
- private readonly List<MqttApplicationMessage> _messages = new List<MqttApplicationMessage>();
-
- private readonly SettingsModel _settings;
- private readonly ILogger<MqttServerStorage> _logger;
-
- private string _filename;
- private bool _messagesHaveChanged;
-
- public MqttServerStorage(SettingsModel settings, ILogger<MqttServerStorage> logger)
- {
- _settings = settings ?? throw new ArgumentNullException(nameof(settings));
- _logger = logger ?? throw new ArgumentNullException(nameof(logger));
- }
-
- public void Configure()
- {
- if (_settings.RetainedApplicationMessages?.Persist != true)
- {
- _logger.LogInformation("Persisting of retained application messages is disabled.");
- return;
- }
-
- _filename = ExpandFilename();
-
- // The retained application messages are stored in a separate thread.
- // This is mandatory because writing them to a slow storage (like RaspberryPi SD card)
- // will slow down the whole message processing speed.
- Task.Run(SaveRetainedMessagesInternalAsync, CancellationToken.None);
- }
-
- public Task SaveRetainedMessagesAsync(IList<MqttApplicationMessage> messages)
- {
- lock (_messages)
- {
- _messages.Clear();
- _messages.AddRange(messages);
-
- _messagesHaveChanged = true;
- }
-
- return Task.CompletedTask;
- }
-
- private async Task SaveRetainedMessagesInternalAsync()
- {
- while (true)
- {
- try
- {
- await Task.Delay(TimeSpan.FromSeconds(_settings.RetainedApplicationMessages.WriteInterval)).ConfigureAwait(false);
-
- List<MqttApplicationMessage> messages;
- lock (_messages)
- {
- if (!_messagesHaveChanged)
- {
- continue;
- }
-
- messages = new List<MqttApplicationMessage>(_messages);
- _messagesHaveChanged = false;
- }
-
- var json = JsonConvert.SerializeObject(messages);
- await File.WriteAllTextAsync(_filename, json, Encoding.UTF8).ConfigureAwait(false);
-
- _logger.LogInformation($"{messages.Count} retained MQTT messages written.");
- }
- catch (Exception exception)
- {
- _logger.LogError(exception, "Error while writing retained MQTT messages.");
- }
- }
- }
-
- public async Task<IList<MqttApplicationMessage>> LoadRetainedMessagesAsync()
- {
- if (_settings.RetainedApplicationMessages?.Persist != true)
- {
- return null;
- }
-
- if (!File.Exists(_filename))
- {
- return null;
- }
-
- try
- {
- var json = await File.ReadAllTextAsync(_filename).ConfigureAwait(false);
- var applicationMessages = JsonConvert.DeserializeObject<List<MqttApplicationMessage>>(json);
-
- _logger.LogInformation($"{applicationMessages.Count} retained MQTT messages loaded.");
-
- return applicationMessages;
- }
- catch (Exception exception)
- {
- _logger.LogWarning(exception, "Error while loading persisted retained application messages.");
- return null;
- }
- }
-
- private string ExpandFilename()
- {
- var filename = _settings.RetainedApplicationMessages.Filename;
-
- var uri = new Uri(filename, UriKind.RelativeOrAbsolute);
- if (!uri.IsAbsoluteUri)
- {
- filename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, filename);
- }
-
- return filename;
- }
- }
- }
|