示例#1
0
        private int OffsetRecords(int sensorId, PosixTimeRange range, int offset)
        {
            int c = 0;

            if (0 == offset)
            {
                return(0);
            }

            if (!ForceConnectionOpen())
            {
                throw new Exception("Could not open database.");
            }

            const string delLowCommandText  = "DELETE FROM Record WHERE stamp >= @minDelRangeInclusive AND stamp < @maxDelRangeExclusive";
            const string delHighCommandText = "DELETE FROM Record WHERE stamp > @minDelRangeExclusive AND stamp <= @maxDelRangeInclusive";
            const string shiftCommandText   = "UPDATE Record SET stamp = stamp + @offset WHERE sensorId = @sensorId AND stamp = @stamp";

            using (var command = _connection.CreateTextCommand(String.Empty)) {
                command.Transaction = _connection.BeginTransaction();
                if (offset < 0)
                {
                    command.CommandText = delLowCommandText;
                    var minDelRangeInclusive = command.AddParameter("minDelRangeInclusive", DbType.Int32, range.Low.Value + offset);
                    var maxDelRangeExclusive = command.AddParameter("maxDelRangeExclusive", DbType.Int32, range.Low);
                    var deletedCount         = command.ExecuteNonQuery();

                    command.CommandText = shiftCommandText;
                    var sensorIdParam = command.AddParameter("sensorId", DbType.Int32, sensorId);
                    var stampParam    = command.AddParameter("stamp", DbType.Int32, 0);
                    var offsetParam   = command.AddParameter("offset", DbType.Int32, offset);
                    for (int i = range.Low; i <= range.High; i++)
                    {
                        stampParam.Value = i;
                        c += command.ExecuteNonQuery();
                    }
                }
                else
                {
                    command.CommandText = delHighCommandText;
                    var minDelRangeExclusive = command.AddParameter("minDelRangeExclusive", DbType.Int32, range.High);
                    var maxDelRangeInclusive = command.AddParameter("maxDelRangeInclusive", DbType.Int32, range.High.Value + offset);
                    var deletedCount         = command.ExecuteNonQuery();

                    command.CommandText = shiftCommandText;
                    var sensorIdParam = command.AddParameter("sensorId", DbType.Int32, sensorId);
                    var stampParam    = command.AddParameter("stamp", DbType.Int32, 0);
                    var offsetParam   = command.AddParameter("offset", DbType.Int32, offset);
                    for (int i = range.High; i >= range.Low; i--)
                    {
                        stampParam.Value = i;
                        c += command.ExecuteNonQuery();
                    }
                }
                command.Transaction.Commit();
            }
            return(c);
        }
示例#2
0
        private bool ShrinkRecords(int sensorId, PosixTimeRange range, int delta)
        {
            if (delta > 0)
            {
                return(false);
            }
            if (0 == delta)
            {
                return(true);
            }

            int totalDeletions = -delta;
            int rangeSpan      = range.Span;

            if (rangeSpan < totalDeletions)
            {
                return(false);
            }

            using (var command = _connection.CreateTextCommand(
                       "UPDATE OR REPLACE Record SET stamp = stamp - @offset WHERE sensorId = @sensorId AND stamp = @stamp")) {
                command.Transaction = _connection.BeginTransaction();

                var sensorIdParam = command.AddParameter("sensorId", DbType.Int32, sensorId);
                var stampParam    = command.AddParameter("stamp", DbType.Int32, 0);
                var offsetParam   = command.AddParameter("offset", DbType.Int32, 0);

                for (int delNumber = 0; delNumber < totalDeletions; delNumber++)
                {
                    // scoot it down
                    int delIndex  = (rangeSpan * (delNumber + 1)) / ((rangeSpan - totalDeletions) + 1);
                    int nextIndex = (rangeSpan * (delNumber + 2)) / ((rangeSpan - totalDeletions) + 1);
                    nextIndex         = Math.Min(nextIndex, range.High);
                    offsetParam.Value = delNumber + 1;
                    for (int i = delIndex; i < nextIndex; i++)
                    {
                        stampParam.Value = i;
                        command.ExecuteNonQuery();
                    }
                }

                command.CommandText = "DELETE FROM Record WHERE sensorId = @sensorId AND stamp > @minStamp AND stamp <= @maxStamp";
                command.Parameters.Clear();
                command.Parameters.Add(sensorIdParam);
                var minStampParam = command.AddParameter("minStamp", DbType.Int32, range.High - totalDeletions);
                var maxStampParam = command.AddParameter("maxStamp", DbType.Int32, range.High);

                command.ExecuteNonQuery();
                command.Transaction.Commit();
            }

            return(true);
        }
示例#3
0
 private bool UpdateSummaryRecords(PosixTimeRange rangeCovered, string sensorName, int sensorId)
 {
     return(UpdateSummaryRecords(
                new TimeRange(rangeCovered.Low.AsDateTime, rangeCovered.High.AsDateTime),
                sensorName, sensorId));
 }
示例#4
0
        private bool PushSummaries(int sensorId, string tableName, IEnumerable <ReadingsSummary> summaries, PosixTimeRange totalRange)
        {
            string insertCommandText = String.Format(
                "INSERT INTO {0} (sensorId,stamp,minValues,maxValues,meanValues,stddevValues,recordCount,tempCount,pressCount,humCount,speedCount,dirCount)"
                + " VALUES (@sensorId,@stamp,@minValues,@maxValues,@meanValues,@stddevValues,@recordCount,@tempCount,@pressCount,@humCount,@speedCount,@dirCount)",
                tableName
                );

            string deleteCommandText = String.Format(
                "DELETE FROM {0} WHERE stamp >= @minStamp AND stamp <= @maxStamp AND sensorId = @sensorId",
                tableName
                );

            using (var command = _connection.CreateTextCommand(deleteCommandText)) {
                command.Transaction = _connection.BeginTransaction();

                var sensorIdParam = command.AddParameter("sensorId", DbType.Int32, sensorId);

                if (totalRange.Span != 0)
                {
                    command.AddParameter("minStamp", DbType.Int32, totalRange.Low);
                    command.AddParameter("maxStamp", DbType.Int32, totalRange.High);
                    command.ExecuteNonQuery();
                }

                command.CommandText = insertCommandText;

                var stampParam     = command.AddParameter("stamp", DbType.Int32, null);
                var minValuesParam = command.AddParameter("minValues", DbType.Binary, null);
                minValuesParam.Size = 8;
                var maxValuesParam = command.AddParameter("maxValues", DbType.Binary, null);
                maxValuesParam.Size = 8;
                var meanValuesParam = command.AddParameter("meanValues", DbType.Binary, null);
                meanValuesParam.Size = 8;
                var stddevValuesParam = command.AddParameter("stddevValues", DbType.Binary, null);
                stddevValuesParam.Size = 8;
                var recordCountParam = command.AddParameter("recordCount", DbType.Int32, null);
                recordCountParam.ParameterName = "recordCount";
                var tempCountParam = command.AddParameter("tempCount", DbType.Binary, null);
                tempCountParam.Size = 0;
                var pressCountParam = command.AddParameter("pressCount", DbType.Binary, null);
                pressCountParam.Size = 0;
                var humCountParam = command.AddParameter("humCount", DbType.Binary, null);
                humCountParam.Size = 0;
                var speedCountParam = command.AddParameter("speedCount", DbType.Binary, null);
                speedCountParam.Size = 0;
                var dirCountParam = command.AddParameter("dirCount", DbType.Binary, null);
                dirCountParam.Size = 0;

                int counter = 0;
                foreach (var summary in summaries)
                {
                    stampParam.Value        = UnitUtility.ConvertToPosixTime(summary.BeginStamp);
                    minValuesParam.Value    = PackedReadingValues.ConvertToPackedBytes(summary.Min);
                    maxValuesParam.Value    = PackedReadingValues.ConvertToPackedBytes(summary.Max);
                    meanValuesParam.Value   = PackedReadingValues.ConvertToPackedBytes(summary.Mean);
                    stddevValuesParam.Value = PackedReadingValues.ConvertToPackedBytes(summary.SampleStandardDeviation);
                    recordCountParam.Value  = summary.Count;

                    byte[] data;
                    tempCountParam.Value  =
                        data              = PackedReadingValues.ConvertTemperatureCountsToPackedBytes(summary.TemperatureCounts);
                    tempCountParam.Size   = data.Length;
                    pressCountParam.Value = data = PackedReadingValues.ConvertPressureCountsToPackedBytes(summary.PressureCounts);
                    pressCountParam.Size  = data.Length;
                    humCountParam.Value   = data = PackedReadingValues.ConvertHumidityCountsToPackedBytes(summary.HumidityCounts);
                    humCountParam.Size    = data.Length;
                    speedCountParam.Value = data = PackedReadingValues.ConvertWindSpeedCountsToPackedBytes(summary.WindSpeedCounts);
                    speedCountParam.Size  = data.Length;
                    dirCountParam.Value   =
                        data              = PackedReadingValues.ConvertWindDirectionCountsToPackedBytes(summary.WindDirectionCounts);
                    dirCountParam.Size    = data.Length;

                    command.ExecuteNonQuery();
                    counter++;
                    if (counter >= RecordBatchQuantity)
                    {
                        counter = 0;
                        command.Transaction.Commit();
                        command.Transaction = _connection.BeginTransaction();
                    }
                }
                command.Transaction.Commit();
            }
            return(true);
        }
示例#5
0
        private bool ExpandRecords(int sensorId, PosixTimeRange range, int delta)
        {
            if (delta < 0)
            {
                return(false);
            }
            if (delta == 0)
            {
                return(true);
            }

            int totalInserts  = delta;
            int rangeSpan     = range.Span;
            int resultingSpan = rangeSpan + delta;

            if (totalInserts >= resultingSpan)
            {
                return(false);
            }

            int splitParts = Math.Min(rangeSpan, delta + 1);


            const string moveCommandText =
                "UPDATE OR REPLACE Record SET stamp = (stamp + @offset) WHERE sensorId = @sensorId AND stamp = @stamp";
            const string delOverflowCommand =
                "DELETE FROM Record WHERE stamp > @minRange AND stamp < @maxRange";

            using (var command = _connection.CreateTextCommand(String.Empty)) {
                command.Transaction = _connection.BeginTransaction();

                command.CommandText = delOverflowCommand;
                command.AddParameter("minRange", DbType.Int32, range.High);
                command.AddParameter("maxRange", DbType.Int32, range.High.Value + delta);
                command.ExecuteNonQuery();

                var sensorIdParam = command.AddParameter("sensorId", DbType.Int32, sensorId);
                var offsetParam   = command.AddParameter("offset", DbType.Int32, 0);
                var stampParam    = command.AddParameter("stamp", DbType.Int32, 0);

                command.CommandText = moveCommandText;
                for (int partIndex = splitParts - 1; partIndex >= 0; partIndex--)
                {
                    int curPartIndex  = ((partIndex * rangeSpan) / splitParts);
                    int nextPartIndex = Math.Min(((partIndex + 1) * rangeSpan) / splitParts, rangeSpan);
                    int destIndex     = (curPartIndex * (resultingSpan - 1)) / (rangeSpan - 1);
                    int shift         = (destIndex + range.Low) - (curPartIndex + range.Low);

                    // move all between ["curPartIndex","nextPartIndex") up by "shift"
                    //minStampParam.Value = curPartIndex;
                    //maxStampParam.Value = nextPartIndex;
                    offsetParam.Value = shift;
                    for (int i = nextPartIndex + range.Low - 1; i >= curPartIndex + range.Low; i--)
                    {
                        stampParam.Value = i;
                        command.ExecuteNonQuery();
                    }
                }
                command.Transaction.Commit();
            }
            return(true);
        }
示例#6
0
        public bool AdjustTimeStamps(
            string sensorName,
            PosixTimeRange currentRange,
            PosixTimeRange correctedRange,
            bool canOverwrite
            )
        {
            int delta  = correctedRange.Span - currentRange.Span;
            int offset = correctedRange.Low - currentRange.Low;

            if (delta == 0 && offset == 0)
            {
                return(false);
            }

            if (!ForceConnectionOpen())
            {
                throw new Exception("Could not open database.");
            }

            int sensorId = -1;

            using (var command = _connection.CreateTextCommand(
                       "SELECT sensorID FROM Sensor WHERE nameKey = @nameKey")) {
                command.AddParameter("nameKey", DbType.String, sensorName);
                using (var reader = command.ExecuteReader()) {
                    if (reader.Read())
                    {
                        sensorId = reader.GetInt32(0);
                    }
                }
            }

            if (sensorId < 0)
            {
                throw new KeyNotFoundException("Sensor not found in datastore.");
            }

            if (
                !canOverwrite &&
                (correctedRange.Low < currentRange.Low || correctedRange.High > currentRange.High)
                )
            {
                using (var command = _connection.CreateTextCommand("SELECT COUNT(*) FROM Record WHERE sensorId = @sensorId")) {
                    //var nameIdParam = command.AddParameter("sensorId", DbType.Int32, sensorId);

                    var orJoin = new List <string>();
                    if (correctedRange.Low < currentRange.Low)
                    {
                        orJoin.Add("(stamp >= @corLow AND stamp < @curLow)");
                    }

                    //var corLowParam = command.AddParameter("corLow", DbType.Int32, correctedRange.Low);
                    //var curLowParam = command.AddParameter("curLow", DbType.Int32, currentRange.Low);

                    if (correctedRange.High > currentRange.High)
                    {
                        orJoin.Add("(stamp <= @corHigh AND stamp > @curHigh)");
                    }
                    //var corHighParam = command.AddParameter("corHigh", DbType.Int32, correctedRange.High);
                    //var curHighParam = command.AddParameter("curHigh", DbType.Int32, currentRange.High);

                    command.CommandText += " AND (" +
                                           String.Join(" OR ", orJoin.ToArray()) +
                                           ") AND NOT (stamp >= @curLow AND stamp <= @curHigh)";

                    int count = 0;
                    using (var reader = command.ExecuteReader()) {
                        if (reader.Read())
                        {
                            count = reader.GetInt32(0);
                        }
                    }
                    if (count > 0)
                    {
                        throw new InvalidOperationException("Cannot overwrite existing datastore entries.");
                    }
                }
            }

            // at this point there is space to shift or grow into
            bool ok = false;

            if (delta < 0)
            {
                // shrinking
                ok = ShrinkRecords(sensorId, currentRange, delta);

                // then shift all if needed
                if (offset != 0)
                {
                    ok = (0 != OffsetRecords(sensorId, new PosixTimeRange(currentRange.Low, currentRange.Low + correctedRange.Span), offset))
                         | ok;
                }
            }
            else
            {
                // need to shift the start into place
                if (offset != 0)
                {
                    ok = 0 != OffsetRecords(sensorId, currentRange, offset);
                }
                // now we need to stretch the records
                if (delta > 0)
                {
                    //ok |= InterpolateInsertRecords(sensorId, new PosixTimeRange(currentRange.High - offset + 1, correctedRange.High), correctedRange);
                    ok |= ExpandRecords(sensorId, new PosixTimeRange(currentRange.Low + offset, currentRange.High + offset), delta);
                }
            }



            bool okUpdateCurrent, okUpdateCorrected;

            if (currentRange.Intersects(correctedRange))
            {
                var completeRange = new PosixTimeRange(
                    new PosixTime(Math.Min(currentRange.Low, correctedRange.Low)),
                    new PosixTime(Math.Max(currentRange.High, correctedRange.High))
                    );
                okUpdateCurrent = okUpdateCorrected =
                    UpdateSummaryRecords(completeRange, sensorName, sensorId);
            }
            else
            {
                okUpdateCurrent   = UpdateSummaryRecords(currentRange, sensorName, sensorId);
                okUpdateCorrected = UpdateSummaryRecords(correctedRange, sensorName, sensorId);
            }

            return(ok && okUpdateCurrent && okUpdateCorrected);
        }