Files
ChunilENG/Packages/com.tivadar.best.mqtt/Runtime/MQTT/Databases/UInt16Database.cs
정영민 2dd5d814a7 update
2025-02-20 09:59:37 +09:00

148 lines
4.3 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using Best.HTTP.Shared.PlatformSupport.Threading;
using Best.HTTP.Shared.Databases;
using Best.HTTP.Shared.Databases.Indexing;
using Best.HTTP.Shared.Databases.MetadataIndexFinders;
using Best.HTTP.Shared.Databases.Utils;
namespace Best.MQTT.Databases
{
internal class UInt16Metadata : Metadata
{
public UInt16 value;
public override void SaveTo(Stream stream)
{
base.SaveTo(stream);
stream.EncodeUnsignedVariableByteInteger(value);
}
public override void LoadFrom(Stream stream)
{
base.LoadFrom(stream);
this.value = (UInt16)stream.DecodeUnsignedVariableByteInteger();
}
public override string ToString()
{
return $"[Metadata Idx: {Index}, IsDeleted: {IsDeleted}, Value: {value}]";
}
}
internal class UInt16MetadataService : MetadataService<UInt16Metadata, UInt16>
{
public UInt16MetadataService(IndexingService<ushort, UInt16Metadata> indexingService)
: base(indexingService, new FindDeletedMetadataIndexFinder<UInt16Metadata>())
{
}
public UInt16Metadata Create(UInt16 value)
{
var result = base.CreateDefault(value, 0, 0, (content, metadata) => metadata.value = content);
return result;
}
}
internal class UInt16IndexingService : IndexingService<UInt16, UInt16Metadata>
{
internal AVLTree<UInt16, int> index = new AVLTree<ushort, int>(Comparer<UInt16>.Default);
public override void Index(UInt16Metadata metadata)
{
base.Index(metadata);
this.index.Add(metadata.value, metadata.Index, true);
}
public override void Remove(UInt16Metadata metadata)
{
base.Remove(metadata);
this.index.Remove(metadata.value);
}
public override void Clear()
{
base.Clear();
this.index.Clear();
}
public override IEnumerable<int> GetOptimizedIndexes() => this.index.WalkHorizontal();
}
internal class UInt16DiskContentParser : IDiskContentParser<UInt16>
{
public void Encode(Stream stream, ushort content) {}
public ushort Parse(Stream stream, int length) => 0;
}
internal class UInt16DatabaseOptions : DatabaseOptions
{
public UInt16DatabaseOptions(string dbName) : base(dbName)
{
base.UseHashFile = false;
}
}
internal class UInt16Database : Database<UInt16, UInt16Metadata, UInt16IndexingService, UInt16MetadataService>
{
public UInt16Database(string directory, string dbName, UInt16IndexingService indexingService)
: base(directory, new UInt16DatabaseOptions(dbName), indexingService, new UInt16DiskContentParser(), new UInt16MetadataService(indexingService))
{
}
public void Add(UInt16 value)
{
using (new WriteLock(this.rwlock))
{
base.MetadataService.Create(value);
base.FlagDirty(1);
}
}
public bool Contains(UInt16 key) => this.IndexingService.index.ContainsKey(key);
public void Remove(UInt16 value)
{
using (new WriteLock(this.rwlock))
{
var metadataIndexes = this.IndexingService.index.Find(value);
base.Delete(metadataIndexes);
}
}
public (bool found, UInt16 value) GetNext(UInt16 value)
{
using (new ReadLock(this.rwlock))
{
// find the smallest one that larger than value
UInt16 smallest = UInt16.MaxValue;
for (int i = 0; i < this.MetadataService.Metadatas.Count; ++i)
{
UInt16 currentValue = this.MetadataService.Metadatas[i].value;
if (currentValue < smallest && currentValue > value)
smallest = currentValue;
}
if (smallest == UInt16.MaxValue)
return (false, 0);
return (true, smallest);
}
}
internal ushort Count()
{
using (new ReadLock(this.rwlock))
return (ushort)this.IndexingService.index.ElemCount;
}
}
}