private dynamic ReadCircleArchive(int sn, DateTime currentDate, List <dynamic> ranges, ArchiveInfo info) { setArchiveDepth(info.archiveType, info.archiveCapacity); dynamic ret = new ExpandoObject(); ret.success = false; ret.error = ""; ret.isCancel = false; List <dynamic> archiveRecords = new List <dynamic>(); //Получение записи #0 - точка отсчета DateTime date0; { if (cancel()) { ret.isCancel = true; ret.error = "задача отменена"; return(ret); } dynamic arecord = info.TryGetArchiveRecord(sn, 0); if (!arecord.success) { ret.error = $"ошибка при получении записи #0: {arecord.error}"; return(ret); } log($"индекс записи #0 дата {arecord.date:dd.MM.yyyy HH:mm}", level: 3); date0 = arecord.date; } if (date0 == RECORDDT_EMPTY_MIN) { ret.error = "архив пуст"; return(ret); } //Предполагаемая дата последней записи DateTime currentRecordDate = info.RoundDateTime(currentDate).Add(-info.recordPeriod); //info.GetCurrentRecordDateFromCurrentDt(currentDate);//.Date.AddDays(-1); //Поиск границ архива - начало и конец DateTime firstRecordDate = RECORDDT_ERROR_MAX; int firstInx = -1; DateTime lastRecordDate = RECORDDT_ERROR_MAX; int lastInx = -1; int lastRecordOffset = info.GetRecordDateOffset(currentRecordDate, date0) + 1; if (lastRecordOffset >= info.archiveCapacity) { lastRecordOffset = info.archiveCapacity - 1; } for (int i = 0; i < info.archiveCapacity; i++) // поиск по всему архиву "вниз" до получения начального и конечного дней { if (cancel()) { ret.isCancel = true; ret.error = "задача отменена"; return(ret); } int circleInx = lastRecordOffset >= i ? lastRecordOffset - i : info.archiveCapacity - (i - lastRecordOffset); dynamic arecord = info.TryGetArchiveRecord(sn, circleInx); if (!arecord.success) { ret.error = $"не удалось получить архивную запись: {arecord.error}"; return(ret); } DateTime recDt = (DateTime)arecord.date; log($"индекс записи #{circleInx} дата {recDt:dd.MM.yyyy HH:mm}", level: 3); if (firstRecordDate == RECORDDT_ERROR_MAX) { firstRecordDate = (recDt == RECORDDT_EMPTY_MIN) ? RECORDDT_EMPTY_MIN : info.RoundDateTime(recDt); // если запись пуста, то все равно записываем firstInx = circleInx; } else if (recDt <= firstRecordDate) { firstRecordDate = info.RoundDateTime(recDt); firstInx = circleInx; } else { lastRecordDate = info.RoundDateTime(recDt); lastInx = circleInx; break; } } log($"начало буфера #{firstInx} {firstRecordDate:dd.MM.yyyy} конец #{lastInx} {lastRecordDate:dd.MM.yyyy}", level: 3); if ((firstInx == -1) || (lastInx == -1)) { ret.error = "ошибка при определении границ архива"; return(ret); } foreach (var range in ranges) { DateTime start = range.start; DateTime end = range.end; for (DateTime date = start; date <= end; date = date.Add(info.recordPeriod)) { if (cancel()) { ret.isCancel = true; ret.error = "задача отменена"; return(ret); } //log($"дата {date:dd.MM.yy HH} проверка на пределы архива {firstDay:dd.MM.yy HH}-{lastDay:dd.MM.yy HH} "); if (date < firstRecordDate) { log(string.Format($"{info.recordFormatDt} за пределами архива", date), level: 2); continue; } if (date > lastRecordDate) { log(string.Format($"{info.recordFormatDt} ещё не сформирована, остановка опроса", date), level: 2); break; } //поиск в архиве от смещения (lastDay - date) "вверх" до lastDay for (int i = info.GetRecordDateOffset(lastRecordDate, date); i >= 0; i--) { if (cancel()) { ret.isCancel = true; ret.error = "задача отменена"; return(ret); } int circleInx = lastInx >= i ? lastInx - i : info.archiveCapacity - (i - lastInx); dynamic arecord = info.TryGetArchiveRecord(sn, circleInx); if (!arecord.success) { ret.error = $"не удалось получить архивную запись: {arecord.error}"; return(ret); } DateTime recordDate = info.RoundDateTime(arecord.date); log($"индекс записи #{circleInx} дата {recordDate:dd.MM.yyyy HH:mm}", level: 3); //log($"дата {date:dd.MM.yy HH} прочитана #{circleInx} {day.date:dd.MM.yy HH} (сут.{dayDate:dd.MM.yy HH}) "); if (recordDate == date) { log(string.Format($"{info.recordFormatDt} #{circleInx} получена", date)); records(arecord.records); archiveRecords.AddRange(arecord.records); break; } else if (recordDate > date) { log(string.Format($"{info.recordFormatDt} НЕ получена (дыра в архиве?)", date)); break; } else { //log($"запрошен {date} получен {dayDate}, пропуск"); } } } } ret.records = archiveRecords; ret.success = true; return(ret); }