Ejemplo n.º 1
0
        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);
        }