Initial Commit
commit
415e3e24c6
|
@ -0,0 +1,41 @@
|
|||
# Autosave files
|
||||
*~
|
||||
|
||||
# build
|
||||
[Oo]bj/
|
||||
[Bb]in/
|
||||
packages/
|
||||
TestResults/
|
||||
|
||||
# globs
|
||||
Makefile.in
|
||||
*.DS_Store
|
||||
*.sln.cache
|
||||
*.suo
|
||||
*.cache
|
||||
*.pidb
|
||||
*.userprefs
|
||||
*.usertasks
|
||||
config.log
|
||||
config.make
|
||||
config.status
|
||||
aclocal.m4
|
||||
install-sh
|
||||
autom4te.cache/
|
||||
*.user
|
||||
*.tar.gz
|
||||
tarballs/
|
||||
test-results/
|
||||
Thumbs.db
|
||||
.vs/
|
||||
|
||||
# Mac bundle stuff
|
||||
*.dmg
|
||||
*.app
|
||||
|
||||
# resharper
|
||||
*_Resharper.*
|
||||
*.Resharper
|
||||
|
||||
# dotCover
|
||||
*.dotCover
|
|
@ -0,0 +1,35 @@
|
|||
// /**
|
||||
// * File: AssemblyInfo.cs
|
||||
// * Author: haraldwolff
|
||||
// *
|
||||
// * This file and it's content is copyrighted by the Author and / or copyright holder.
|
||||
// * Any use wihtout proper permission is illegal and may lead to legal actions.
|
||||
// *
|
||||
// *
|
||||
// **/
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// Information about this assembly is defined by the following attributes.
|
||||
// Change them to the values specific to your project.
|
||||
|
||||
[assembly: AssemblyTitle("ln.perfdb")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("${AuthorCopyright}")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
// The following attributes are used to specify the signing key for the assembly,
|
||||
// if desired. See the Mono documentation for more information about signing.
|
||||
|
||||
//[assembly: AssemblyDelaySign(false)]
|
||||
//[assembly: AssemblyKeyFile("")]
|
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{D934C1E8-9215-4D8D-83B3-A296E4912792}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>ln.perfdb</RootNamespace>
|
||||
<AssemblyName>ln.perfdb</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<ConsolePause>false</ConsolePause>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<ConsolePause>false</ConsolePause>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="storage\PerfTable.cs" />
|
||||
<Compile Include="storage\PerfFile.cs" />
|
||||
<Compile Include="storage\SectionSpecification.cs" />
|
||||
<Compile Include="storage\ShortRead.cs" />
|
||||
<Compile Include="storage\PerfValue.cs" />
|
||||
<Compile Include="storage\Aggregates.cs" />
|
||||
<Compile Include="storage\PerfFile.PerfFileSection.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="storage\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ln.logging\ln.logging.csproj">
|
||||
<Project>{D471A566-9FB6-41B2-A777-3C32874ECD0E}</Project>
|
||||
<Name>ln.logging</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
|
@ -0,0 +1,56 @@
|
|||
// /**
|
||||
// * File: Aggregates.cs
|
||||
// * Author: haraldwolff
|
||||
// *
|
||||
// * This file and it's content is copyrighted by the Author and / or copyright holder.
|
||||
// * Any use wihtout proper permission is illegal and may lead to legal actions.
|
||||
// *
|
||||
// *
|
||||
// **/
|
||||
using System;
|
||||
namespace ln.perfdb.storage
|
||||
{
|
||||
public static class Aggregates
|
||||
{
|
||||
|
||||
public static PerfValue Aggregate(PerfValue[] perfValues,AggregationMethod method)
|
||||
{
|
||||
switch (method)
|
||||
{
|
||||
case AggregationMethod.AVERAGE:
|
||||
return Average(perfValues);
|
||||
default:
|
||||
return Average(perfValues);
|
||||
}
|
||||
}
|
||||
|
||||
public static PerfValue Average(PerfValue[] perfValues)
|
||||
{
|
||||
PerfValue result = new PerfValue();
|
||||
int numValues = 0;
|
||||
|
||||
foreach (PerfValue perfValue in perfValues)
|
||||
{
|
||||
if (perfValue.TimeStamp != 0)
|
||||
{
|
||||
result.Value += perfValue.Value;
|
||||
result.TimeStamp += perfValue.TimeStamp;
|
||||
numValues++;
|
||||
}
|
||||
}
|
||||
|
||||
if (numValues > 0)
|
||||
{
|
||||
result.Value /= numValues;
|
||||
result.TimeStamp /= numValues;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.TimeStamp = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,307 @@
|
|||
// /**
|
||||
// * File: PerfFile.cs
|
||||
// * Author: haraldwolff
|
||||
// *
|
||||
// * This file and it's content is copyrighted by the Author and / or copyright holder.
|
||||
// * Any use wihtout proper permission is illegal and may lead to legal actions.
|
||||
// *
|
||||
// *
|
||||
// **/
|
||||
using System;
|
||||
using System.IO;
|
||||
using ln.logging;
|
||||
namespace ln.perfdb.storage
|
||||
{
|
||||
|
||||
|
||||
|
||||
public partial class PerfFile
|
||||
{
|
||||
public class PerfFileSection
|
||||
{
|
||||
/**
|
||||
* Binary Section Header Format
|
||||
*
|
||||
* Offset Field
|
||||
* ---------------------------------
|
||||
* 0x00 Flags (not in use)
|
||||
* 0x04 nRecords
|
||||
* 0x08 tWindow
|
||||
* 0x0C AggregationMethod
|
||||
* 0x10 LastTimeStamp (64bit)
|
||||
*
|
||||
* 0x18 not in use
|
||||
* 0x1C not in use
|
||||
*
|
||||
**/
|
||||
|
||||
|
||||
public PerfFile PerfFile { get; private set; }
|
||||
public PerfFileSection ParentSection { get; private set; }
|
||||
|
||||
public int Offset { get; set; }
|
||||
public int DataOffset => Offset + 32;
|
||||
|
||||
public int NextOffset => DataOffset + (nRecords * 16);
|
||||
public PerfFileSection NextSection { get; private set; }
|
||||
public PerfFileSection LastSection => NextSection != null ? NextSection : this;
|
||||
|
||||
public int nRecords { get; private set; }
|
||||
public int tWindow { get; private set; }
|
||||
|
||||
public int TimeSpan => nRecords * tWindow;
|
||||
public long LastRecord { get; set; }
|
||||
|
||||
public AggregationMethod AggregationMethod { get; private set; }
|
||||
public FileStream FileStream => PerfFile.FileStream;
|
||||
|
||||
public int AggregateSize => NextSection == null ? 0 : (NextSection.tWindow / tWindow);
|
||||
public int AggregateGroups => AggregateSize > 0 ? nRecords / AggregateSize : 0;
|
||||
|
||||
internal PerfFileSection(PerfFile perfFile, PerfFileSection parent)
|
||||
{
|
||||
PerfFile = perfFile;
|
||||
ParentSection = parent;
|
||||
Offset = ParentSection != null ? ParentSection.NextOffset : 0x10;
|
||||
|
||||
Logging.Log(LogLevel.DEBUGDETAIL, "PerfFileSection: loading at offset 0x{0:x8}", Offset);
|
||||
|
||||
byte[] header = new byte[32];
|
||||
|
||||
FileStream.Position = Offset;
|
||||
int nread = perfFile.FileStream.Read(header, 0, 32);
|
||||
if (nread != 32)
|
||||
throw new ShortRead();
|
||||
|
||||
nRecords = BitConverter.ToInt32(header, 0x04);
|
||||
tWindow = BitConverter.ToInt32(header, 0x08);
|
||||
AggregationMethod = (AggregationMethod)BitConverter.ToInt32(header, 0x0C);
|
||||
|
||||
LastRecord = BitConverter.ToInt32(header, 0x10);
|
||||
|
||||
Logging.Log(LogLevel.DEBUGDETAIL, "PerfFileSection: Loaded: {0}", this);
|
||||
|
||||
if (FileStream.Length > NextOffset)
|
||||
{
|
||||
NextSection = new PerfFileSection(PerfFile, this);
|
||||
}
|
||||
}
|
||||
|
||||
public PerfFileSection(PerfFile perfFile, PerfFileSection parent, int nRecords, int tWindow, AggregationMethod aggregationMethod)
|
||||
{
|
||||
PerfFile = perfFile;
|
||||
ParentSection = parent;
|
||||
|
||||
if (parent != null)
|
||||
{
|
||||
if (parent.NextSection != null)
|
||||
{
|
||||
throw new ArgumentException("Parent already has NextSection", nameof(parent));
|
||||
}
|
||||
|
||||
ParentSection.NextSection = this;
|
||||
Offset = ParentSection.NextOffset;
|
||||
|
||||
if (((tWindow / parent.tWindow) * parent.tWindow) != tWindow)
|
||||
throw new ArgumentException("tWindow needs to be integer divideable with tWindow of parent", nameof(tWindow));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (perfFile.FirstSection != null)
|
||||
throw new ArgumentException("PerfFile already has a Section", nameof(perfFile));
|
||||
|
||||
perfFile.FirstSection = this;
|
||||
Offset = 0x10;
|
||||
}
|
||||
|
||||
this.tWindow = tWindow;
|
||||
this.nRecords = nRecords;
|
||||
this.AggregationMethod = aggregationMethod;
|
||||
|
||||
LastRecord = -1;
|
||||
|
||||
if (FileStream.Length < NextOffset)
|
||||
FileStream.SetLength(NextOffset);
|
||||
|
||||
byte[] sectionHeader = new byte[0x20];
|
||||
|
||||
Array.Copy(BitConverter.GetBytes((int)0), 0, sectionHeader, 0x00, 4);
|
||||
Array.Copy(BitConverter.GetBytes(nRecords), 0, sectionHeader, 0x04, 4);
|
||||
Array.Copy(BitConverter.GetBytes(tWindow), 0, sectionHeader, 0x08, 4);
|
||||
Array.Copy(BitConverter.GetBytes((int)AggregationMethod), 0, sectionHeader, 0x0C, 4);
|
||||
Array.Copy(BitConverter.GetBytes(LastRecord), 0, sectionHeader, 0x10, 8);
|
||||
|
||||
FileStream.Position = Offset;
|
||||
FileStream.Write(sectionHeader, 0, 0x20);
|
||||
FileStream.Flush();
|
||||
|
||||
Logging.Log(LogLevel.DEBUGDETAIL, "PerfFileSection: Created: {0}", this);
|
||||
}
|
||||
|
||||
public void Sync()
|
||||
{
|
||||
FileStream.Position = Offset + 0x10;
|
||||
FileStream.Write(BitConverter.GetBytes(LastRecord), 0, 8);
|
||||
|
||||
if (NextSection != null)
|
||||
NextSection.Sync();
|
||||
}
|
||||
|
||||
private long GetRecord(long timeStamp)
|
||||
{
|
||||
return timeStamp / tWindow;
|
||||
}
|
||||
|
||||
private int GetSlot(long rawRecord)
|
||||
{
|
||||
return (int)(rawRecord % nRecords);
|
||||
}
|
||||
|
||||
private int GetAggregateGroup(int slot)
|
||||
{
|
||||
return slot / AggregateSize;
|
||||
}
|
||||
|
||||
private void Aggregate(int group)
|
||||
{
|
||||
if (NextSection != null)
|
||||
{
|
||||
PerfValue[] perfValues = new PerfValue[AggregateSize];
|
||||
ReadRecords(perfValues, 0, group * AggregateSize, AggregateSize);
|
||||
NextSection.WriteRecord(Aggregates.Aggregate(perfValues, NextSection.AggregationMethod));
|
||||
|
||||
for (int n = 0; n < AggregateSize; n++)
|
||||
{
|
||||
ClearRecord((group * AggregateSize) + n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearRecord(int nRecord)
|
||||
{
|
||||
byte[] binaryRecord = new byte[16];
|
||||
int thisSlot = GetSlot(nRecord);
|
||||
FileStream.Position = DataOffset + (thisSlot * 16);
|
||||
FileStream.Write(binaryRecord, 0, 16);
|
||||
}
|
||||
|
||||
public void WriteRecord(PerfValue perfValue)
|
||||
{
|
||||
if (perfValue.TimeStamp >= LastRecord)
|
||||
{
|
||||
long thisRecord = GetRecord(perfValue.TimeStamp);
|
||||
int thisSlot = GetSlot(thisRecord);
|
||||
|
||||
if ((NextSection != null) && (LastRecord > 0))
|
||||
{
|
||||
int lastAGroup = GetAggregateGroup(GetSlot(LastRecord));
|
||||
int thisAGroup = GetAggregateGroup(thisSlot);
|
||||
|
||||
if ((lastAGroup != thisAGroup) || ((thisRecord - LastRecord) > nRecords))
|
||||
{
|
||||
int ag = (thisRecord - LastRecord) > nRecords ? thisAGroup : lastAGroup;
|
||||
|
||||
do
|
||||
{
|
||||
ag++;
|
||||
ag %= AggregateGroups;
|
||||
Aggregate(ag);
|
||||
} while (ag != thisAGroup);
|
||||
}
|
||||
}
|
||||
|
||||
FileStream.Position = DataOffset + (thisSlot * 16);
|
||||
FileStream.Write(BitConverter.GetBytes(perfValue.TimeStamp), 0, 8);
|
||||
FileStream.Write(BitConverter.GetBytes(perfValue.Value), 0, 8);
|
||||
|
||||
LastRecord = thisRecord;
|
||||
}
|
||||
}
|
||||
|
||||
public void ReadRecords(PerfValue[] target, int offset, int firstRecord, int numRecords)
|
||||
{
|
||||
//Logging.Log(LogLevel.DEBUG, "PerfFileSection: Read(<resultbuffer>,{0},{1},{2})",offset,firstRecord,numRecords);
|
||||
|
||||
byte[] binaryRow = new byte[16];
|
||||
|
||||
for (int n = 0; n < numRecords; n++)
|
||||
{
|
||||
int nRow = (firstRecord + n) % nRecords;
|
||||
FileStream.Position = DataOffset + (nRow * 16);
|
||||
int nread = FileStream.Read(binaryRow, 0, 16);
|
||||
|
||||
if (nread != 16)
|
||||
throw new ShortRead();
|
||||
|
||||
long rTimeStamp = BitConverter.ToInt64(binaryRow, 0);
|
||||
double rValue = BitConverter.ToDouble(binaryRow, 8);
|
||||
|
||||
if (rTimeStamp == 0)
|
||||
{
|
||||
target[offset + n] = new PerfValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
target[offset + n] = new PerfValue(rTimeStamp, rValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PerfValue[] Query(int queryRecords, int skipRecords, int nTrail)
|
||||
{
|
||||
Logging.Log(LogLevel.DEBUG, "PerfFileSection.Query({0},{1},{2})", queryRecords, skipRecords, nTrail);
|
||||
PerfValue[] result;
|
||||
|
||||
int maxQueryRecords = (skipRecords > nRecords) ? 0 : nRecords - skipRecords;
|
||||
|
||||
int mySkipRecords = (skipRecords > nRecords) ? nRecords : skipRecords;
|
||||
int nextSkipRecords = (skipRecords > nRecords) ? skipRecords - nRecords : 0;
|
||||
|
||||
int myQueryRecords = (maxQueryRecords > queryRecords) ? queryRecords : maxQueryRecords;
|
||||
int nextQueryRecords = queryRecords - myQueryRecords;
|
||||
|
||||
int myFirstRecord = (int)(LastRecord - mySkipRecords - myQueryRecords) + 1;
|
||||
|
||||
int myFirstSlot = GetSlot(myFirstRecord);
|
||||
int myFirstAG = GetAggregateGroup(myFirstSlot);
|
||||
int myLastAG = GetAggregateGroup(GetSlot(LastRecord));
|
||||
|
||||
if (myLastAG == myFirstAG)
|
||||
{
|
||||
int myPreSkip = AggregateSize - (myFirstRecord % AggregateSize);
|
||||
|
||||
myQueryRecords -= myPreSkip;
|
||||
myFirstRecord += myPreSkip;
|
||||
}
|
||||
|
||||
if ((nextQueryRecords == 0) || (NextSection == null))
|
||||
{
|
||||
result = new PerfValue[nTrail + myQueryRecords];
|
||||
}
|
||||
else
|
||||
{
|
||||
nextQueryRecords /= AggregateSize;
|
||||
nextSkipRecords /= AggregateSize;
|
||||
|
||||
result = NextSection.Query(nextQueryRecords,nextSkipRecords,nTrail + myQueryRecords);
|
||||
}
|
||||
|
||||
int myResultOffset = (result.Length - nTrail - myQueryRecords);
|
||||
|
||||
Logging.Log(LogLevel.DEBUG, "PerfFileSection.Query(): {0}", this);
|
||||
Logging.Log(LogLevel.DEBUG, "PerfFileSection.Query(): Loading {0} records starting at {1}", myQueryRecords, myFirstRecord);
|
||||
ReadRecords(result, myResultOffset, myFirstRecord, myQueryRecords);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("[PerfFileSection Offset=0x{0:x8} NextOffset={1:x8} nRecords={2} tWindow={3} TimeSpan={4} LastRecord={5}({6})]", Offset, NextOffset, nRecords, tWindow, new TimeSpan(0, 0, TimeSpan), LastRecord, GetSlot(LastRecord));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
// /**
|
||||
// * File: PerfFile.cs
|
||||
// * Author: haraldwolff
|
||||
// *
|
||||
// * This file and it's content is copyrighted by the Author and / or copyright holder.
|
||||
// * Any use wihtout proper permission is illegal and may lead to legal actions.
|
||||
// *
|
||||
// *
|
||||
// **/
|
||||
using System;
|
||||
using System.IO;
|
||||
using ln.logging;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Text;
|
||||
namespace ln.perfdb.storage
|
||||
{
|
||||
/**
|
||||
* PerfFile Format Specification
|
||||
*
|
||||
* File Header:
|
||||
*
|
||||
* 0x0000 4 MAGIC
|
||||
* 0x0004 4 Version
|
||||
* 0x0008 4 nSections
|
||||
* 0x000C 4 RESERVE
|
||||
* 0x0010 16 Section specification #0
|
||||
*[0x0020 16 Section specification #1]
|
||||
*[...]
|
||||
* Section Data #0
|
||||
*[Section Data #1]
|
||||
*
|
||||
* Section specification format:
|
||||
* 0x0000 4 Flags
|
||||
* 0x0004 4 nRecords
|
||||
* 0x0008 4 tWindow
|
||||
* 0x000C 4 Aggregation Method
|
||||
*
|
||||
**/
|
||||
|
||||
|
||||
public partial class PerfFile
|
||||
{
|
||||
public readonly ulong Magic1 = 0xBEAF8888BEAF8888L;
|
||||
public readonly ulong Magic2 = 0xBAD80000BAD80000L;
|
||||
|
||||
public readonly int SecondsPerHour = 3600;
|
||||
public readonly int SecondsPerDay = 3600 * 24;
|
||||
public readonly int SecondsPerWeek = 3600 * 24 * 7;
|
||||
|
||||
public String FileName { get; }
|
||||
public FileStream FileStream { get; private set; }
|
||||
|
||||
public PerfFileSection FirstSection { get; private set; }
|
||||
|
||||
public PerfFile(String filename)
|
||||
{
|
||||
FileName = filename;
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
if (FileStream.Length == 0)
|
||||
{
|
||||
FileStream.Write(BitConverter.GetBytes(Magic1), 0, 8);
|
||||
FileStream.Write(BitConverter.GetBytes(Magic2), 0, 8);
|
||||
FileStream.Flush();
|
||||
FirstSection = null;
|
||||
|
||||
Logging.Log(LogLevel.DEBUG, "PerfTable: created {0}", FileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] magics = new byte[16];
|
||||
FileStream.Position = 0;
|
||||
int nread = FileStream.Read(magics, 0, 16);
|
||||
if (nread != 16)
|
||||
throw new ShortRead();
|
||||
|
||||
ulong m1, m2;
|
||||
|
||||
m1 = BitConverter.ToUInt64(magics, 0);
|
||||
m2 = BitConverter.ToUInt64(magics, 8);
|
||||
|
||||
if ((m1 != Magic1) || (m2 != Magic2))
|
||||
throw new FormatException("Magic numbers do not match");
|
||||
|
||||
FirstSection = new PerfFileSection(this, null);
|
||||
}
|
||||
|
||||
Logging.Log(LogLevel.DEBUG, "PerfFile: Initialized for filename {0}", FileName);
|
||||
|
||||
long timespan = 0;
|
||||
|
||||
for (PerfFileSection section = FirstSection; section != null; section = section.NextSection)
|
||||
{
|
||||
Logging.Log(LogLevel.DEBUGDETAIL, " Section: nRecords={0,6} tWindow={1} TimeSpan={2} TimeInPast={3}", section.nRecords,new TimeSpan(0,0,section.tWindow),new TimeSpan(0,0,section.TimeSpan),new TimeSpan(0,0,(int)timespan));
|
||||
timespan += section.TimeSpan;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsOpen => (FileStream != null);
|
||||
public void Open()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (IsOpen)
|
||||
throw new IOException("Already opened");
|
||||
|
||||
FileStream = new FileStream(this.FileName, FileMode.OpenOrCreate);
|
||||
Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (!IsOpen)
|
||||
throw new IOException("not opened");
|
||||
|
||||
if (FirstSection != null)
|
||||
FirstSection.Sync();
|
||||
|
||||
FirstSection = null;
|
||||
|
||||
FileStream.Close();
|
||||
FileStream = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(long timestamp,double value)
|
||||
{
|
||||
Write(new PerfValue(timestamp, value));
|
||||
}
|
||||
public void Write(PerfValue perfValue)
|
||||
{
|
||||
FirstSection.WriteRecord(perfValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* QueryTime(): Query Results for timeWindow [s] before skipTime [s]
|
||||
**/
|
||||
public PerfValue[] QueryTime(int timeWindow, int skipTime)
|
||||
{
|
||||
int queryRecords = timeWindow / FirstSection.tWindow;
|
||||
int skipRecords = skipTime / FirstSection.tWindow;
|
||||
|
||||
return Query(queryRecords, skipRecords);
|
||||
}
|
||||
|
||||
public PerfValue[] Query(int queryRecords,int skipRecords)
|
||||
{
|
||||
return FirstSection.Query(queryRecords, skipRecords, 0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
// /**
|
||||
// * File: PerfTable.cs
|
||||
// * Author: haraldwolff
|
||||
// *
|
||||
// * This file and it's content is copyrighted by the Author and / or copyright holder.
|
||||
// * Any use wihtout proper permission is illegal and may lead to legal actions.
|
||||
// *
|
||||
// *
|
||||
// **/
|
||||
using System;
|
||||
namespace ln.perfdb.storage
|
||||
{
|
||||
public struct RetentionInterval
|
||||
{
|
||||
public int CheckInterval;
|
||||
public int RetentionAge;
|
||||
}
|
||||
|
||||
public class PerfTable
|
||||
{
|
||||
public PerfTable()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// /**
|
||||
// * File: PerfValue.cs
|
||||
// * Author: haraldwolff
|
||||
// *
|
||||
// * This file and it's content is copyrighted by the Author and / or copyright holder.
|
||||
// * Any use wihtout proper permission is illegal and may lead to legal actions.
|
||||
// *
|
||||
// *
|
||||
// **/
|
||||
using System;
|
||||
namespace ln.perfdb.storage
|
||||
{
|
||||
public struct PerfValue
|
||||
{
|
||||
public long TimeStamp;
|
||||
public double Value;
|
||||
|
||||
public PerfValue(long timeStamp, double value)
|
||||
{
|
||||
TimeStamp = timeStamp;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("Timestamp: {0,12} {1}",TimeStamp,Value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
using System;
|
||||
namespace ln.perfdb.storage
|
||||
{
|
||||
public enum AggregationMethod : int {
|
||||
AVERAGE = 0x00,
|
||||
MIN = 0x01,
|
||||
MAX = 0x02,
|
||||
STEP = 0x04
|
||||
}
|
||||
|
||||
public struct SectionSpecification
|
||||
{
|
||||
public int Flags;
|
||||
public int nRecords;
|
||||
public int tWindow;
|
||||
public AggregationMethod AggregationMethod;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
// /**
|
||||
// * File: ShortRead.cs
|
||||
// * Author: haraldwolff
|
||||
// *
|
||||
// * This file and it's content is copyrighted by the Author and / or copyright holder.
|
||||
// * Any use wihtout proper permission is illegal and may lead to legal actions.
|
||||
// *
|
||||
// *
|
||||
// **/
|
||||
using System;
|
||||
using System.IO;
|
||||
namespace ln.perfdb.storage
|
||||
{
|
||||
public class ShortRead : IOException
|
||||
{
|
||||
public ShortRead()
|
||||
{
|
||||
}
|
||||
public ShortRead(String message)
|
||||
:base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue