dev_timestamp
Harald Wolff 2019-08-26 13:11:56 +02:00
parent f80a158dcb
commit 5dcb7f60ec
16 changed files with 584 additions and 61 deletions

View File

@ -1,6 +1,9 @@
using System;
using System.Collections.Generic;
using System.Collections;
using System.Reflection;
using ln.logging;
using System.ComponentModel;
namespace ln.types
{
@ -43,11 +46,26 @@ namespace ln.types
}
/// <summary>
/// Argument container.
/// </summary>
/// <remarks>
/// This class parses command line arguments to a list of predefined well known arguments.
/// Remaining arguments will be found in <c>AdditionalArguments</c>.
///
/// <c>ArgumentContainer</c> also provides a global command line option:
/// --change-static <para>typename</para> <para>fieldname</para> <para>value</para>
/// It may be used multiple times on the command line.
/// It will load the type referenced by the qualified name <para>typename</para> and try to set the static field <para>fieldname</para> to <para>value</para>.
/// <para>value</para> will be casted to field type via Convert.ChangeType(...)
/// </remarks>
public class ArgumentContainer
{
List<Argument> arguments;
List<String> additionalArguments;
public string[] AdditionalArguments => additionalArguments.ToArray();
public ArgumentContainer()
{
arguments = new List<Argument>();
@ -138,10 +156,21 @@ namespace ln.types
if (currentOption[1].Equals('-'))
{
String aname = currentOption.Substring(2);
Argument argument = this[aname];
argument.IsSet = true;
if (argument.NeedsValue)
argument.Value = q.Dequeue();
if (aname.Equals("change-static"))
{
string typeName = q.Dequeue();
string fieldName = q.Dequeue();
string value = q.Dequeue();
ChangeStatic(typeName, fieldName, value);
}
else
{
Argument argument = this[aname];
argument.IsSet = true;
if (argument.NeedsValue)
argument.Value = q.Dequeue();
}
}
else
{
@ -161,5 +190,17 @@ namespace ln.types
}
}
}
public void ChangeStatic(string typeName,string fieldname,string value)
{
Type type = Type.GetType(typeName);
Logging.Log(LogLevel.INFO, "ArgumentContainer: ChangeStatic: Type: {0}",type);
FieldInfo fieldInfo = type.GetField(fieldname, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
Logging.Log(LogLevel.INFO, "ArgumentContainer: ChangeStatic: Field: {0} {1}", fieldname, fieldInfo);
object castValue = Convert.ChangeType(value, fieldInfo.FieldType);
fieldInfo.SetValue(null,castValue);
}
}
}

View File

@ -24,7 +24,7 @@ namespace ln.types
elements.Add(e);
return elements.ToArray();
}
public static T[] Remove<T>(this T[] me,IEnumerable<T> remove)
public static T[] Remove<T>(this T[] me, IEnumerable<T> remove)
{
HashSet<T> elements = new HashSet<T>(me);
foreach (T e in remove)
@ -33,7 +33,7 @@ namespace ln.types
}
public static bool AreEqual<T>(this T[] me,T[] you)
public static bool AreEqual<T>(this T[] me, T[] you)
{
if (me.Length != you.Length)
return false;
@ -73,34 +73,34 @@ namespace ln.types
stream.Write(BitConverter.GetBytes(i).BigEndian(), 0, 4);
}
public static long ReadLong(this Stream stream)
{
byte[] b = new byte[8];
stream.Read(b, 0, 8);
return BitConverter.ToInt64(b, 0);
}
public static void WriteLong(this Stream stream, long i)
{
stream.Write(BitConverter.GetBytes(i), 0, 8);
}
public static ulong ReadULong(this Stream stream)
{
byte[] b = new byte[8];
stream.Read(b, 0, 8);
return BitConverter.ToUInt64(b.BigEndian(), 0);
}
public static void WriteULong(this Stream stream, ulong i)
{
stream.Write(BitConverter.GetBytes(i).BigEndian(), 0, 8);
}
public static long ReadLong(this Stream stream)
{
byte[] b = new byte[8];
stream.Read(b, 0, 8);
return BitConverter.ToInt64(b, 0);
}
public static void WriteLong(this Stream stream, long i)
{
stream.Write(BitConverter.GetBytes(i), 0, 8);
}
public static ulong ReadULong(this Stream stream)
{
byte[] b = new byte[8];
stream.Read(b, 0, 8);
return BitConverter.ToUInt64(b.BigEndian(), 0);
}
public static void WriteULong(this Stream stream, ulong i)
{
stream.Write(BitConverter.GetBytes(i).BigEndian(), 0, 8);
}
public static void WriteBytes(this Stream stream,byte[] bytes)
public static void WriteBytes(this Stream stream, byte[] bytes)
{
stream.Write(bytes, 0, bytes.Length);
}
public static byte[] ReadBytes(this Stream stream,int length)
public static byte[] ReadBytes(this Stream stream, int length)
{
byte[] bytes = new byte[length];
stream.Read(bytes, 0, length);
@ -181,7 +181,7 @@ namespace ln.types
if (BitConverter.IsLittleEndian == bigEndian)
Array.Reverse(bytes);
return bytes;
}
public static int GetInt(this byte[] bytes, bool bigEndian = false) => GetInt(bytes, 0, bigEndian);
public static int GetInt(this byte[] bytes, int offset, bool bigEndian = false)
@ -240,9 +240,8 @@ namespace ln.types
}
public static T[] Slice<T>(this T[] me, int offset) => Slice(me, offset, me.Length - offset);
public static T[] Slice<T>(this T[] me,int offset,int length)
public static T[] Slice<T>(this T[] me, int offset, int length)
{
T[] slice = new T[length];
Array.Copy(me, offset, slice, 0, length);
@ -261,7 +260,7 @@ namespace ln.types
byte[] section = bytes.Slice(n, len);
for (int i=0;i<16;i++)
for (int i = 0; i < 16; i++)
{
if (i < section.Length)
stringBuilder.AppendFormat("{0:X2} ", section[i]);
@ -284,6 +283,36 @@ namespace ln.types
return stringBuilder.ToString();
}
public static Decimal ToDecimal(this double v)
{
if (v <= (double)Decimal.MinValue)
return decimal.MinValue;
if (v >= (double)Decimal.MaxValue)
return decimal.MaxValue;
return new Decimal(v);
}
}
public static class DateTimeExtensions
{
public static DateTime EPOCH = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
public static DateTime FromUnixTimeSeconds(double seconds)
{
return EPOCH.AddSeconds(seconds);
}
public static DateTime FromUnixTimeMilliseconds(double milliseconds)
{
return EPOCH.AddMilliseconds(milliseconds);
}
public static double ToUnixTimeSeconds(this DateTime dateTime)
{
return (dateTime - EPOCH).TotalSeconds;
}
public static double ToUnixTimeMilliseconds(this DateTime dateTime)
{
return (dateTime - EPOCH).TotalMilliseconds;
}
}
}

View File

@ -118,6 +118,9 @@
<Compile Include="odb\ng\mappings\ListMapping.cs" />
<Compile Include="odb\ng\Reference.cs" />
<Compile Include="stream\CharStream.cs" />
<Compile Include="odb\ng\Query.cs" />
<Compile Include="odb\ng\IStorage.cs" />
<Compile Include="odb\ng\Document.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="sync\" />

View File

@ -79,7 +79,7 @@ namespace ln.types.odb
{
Type ceType = byReferenceAttribute.ElementType ?? fieldInfo.FieldType;
String cAlias = byReferenceAttribute.Alias ?? ceType.FullName;
MappedCollection mappedCollection = document.Collection.ODB.GetCollection(ceType,cAlias);
MappedCollection mappedCollection = ODBCollection.CurrentODB.Value.GetCollection(ceType,cAlias);
ODBValue refID = document[fieldInfo.Name];
fieldInfo.SetValue(o, mappedCollection.SelectByID(refID));

View File

@ -201,6 +201,7 @@ namespace ln.types.odb
return null;
ODBDocument document = new ODBDocument(storageBytes, 0, storageBytes.Length);
document.Collection = this.Collection;
return document;
}
@ -322,7 +323,12 @@ namespace ln.types.odb
public IEnumerator<ODBValue> GetEnumerator()
{
return idLookup.Keys.GetEnumerator();
ODBValue[] docIDs;
lock (this)
{
docIDs = idLookup.Keys.ToArray();
}
return ((IEnumerable<ODBValue>)docIDs).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

View File

@ -10,10 +10,13 @@ using System.ComponentModel.Design.Serialization;
using System.ComponentModel;
using ln.logging;
using ln.types.btree;
using System.Threading;
namespace ln.types.odb
{
public partial class ODBCollection : IEnumerable<ODBDocument>, IDisposable
{
public static ThreadLocal<ODB> CurrentODB { get; } = new ThreadLocal<ODB>();
public ODB ODB { get; }
public String CollectionName { get; }
@ -127,14 +130,16 @@ namespace ln.types.odb
{
lock (this)
{
CurrentODB.Value = this.ODB;
if (documentCache.ContainsKey(documentID))
return documentCache[documentID];
ODBDocument doc = Index.LoadDocument(documentID);
if (!object.ReferenceEquals(doc,null))
if (!object.ReferenceEquals(doc, null))
documentCache.Add(doc);
if (!object.ReferenceEquals(null,doc))
if (!object.ReferenceEquals(null, doc))
doc.Collection = this;
return doc;
@ -204,7 +209,12 @@ namespace ln.types.odb
public IEnumerator<ODBDocument> GetEnumerator()
{
foreach (ODBValue id in documentIndex.ToArray())
ODBValue[] docIDs = null;
lock (this)
{
docIDs = documentIndex.ToArray();
}
foreach (ODBValue id in docIDs)
{
yield return GetDocumentByID(id);
}

164
odb/ng/Document.cs 100644
View File

@ -0,0 +1,164 @@
using System;
using System.Collections.Generic;
using System.IO;
using ln.types.odb.values;
using System.Linq;
namespace ln.types.odb.ng
{
public class Document : ODBValue
{
private Dictionary<ODBValue, ODBValue> properties = new Dictionary<ODBValue, ODBValue>();
public Document()
:base(0x1000)
{
ID = Guid.NewGuid();
}
public Guid ID { get; }
public DateTime StorageTimeStamp { get; private set; }
public ODBCollection Collection { get; internal set; }
public Document(Guid documentID,byte[] bytes)
: this(documentID, bytes, 0, bytes.Length)
{ }
public Document(Guid documentID,byte[] bytes,int offset,int length)
:this()
{
ID = documentID;
int endOffset = offset + length;
int nProps = BitConverter.ToInt32(bytes, offset);
offset += 4;
for (int n=0;n<nProps;n++)
{
ODBValue propName = ODBValue.Deserialize(bytes,ref offset);
ODBValue propValue = ODBValue.Deserialize(bytes, ref offset);
properties.Add(propName, propValue);
}
if (offset > endOffset)
throw new FormatException("Document deserialization read behind end of buffer");
}
public ODBValue this[ODBValue propName]
{
get
{
if (properties.ContainsKey(propName))
return properties[propName];
return ODBNull.Instance;
}
set
{
if (ODBNull.Instance.Equals(value) && properties.ContainsKey(propName))
{
properties.Remove(propName);
}
else
{
properties[propName] = value;
}
}
}
public IEnumerable<ODBValue> Keys => properties.Keys;
public override int CompareLevel => 128;
public bool Contains(ODBValue propName)
{
return !ODBNull.Instance.Equals(this[propName]);
}
public override byte[] ToStorage()
{
MemoryStream stream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(properties.Count);
foreach (ODBValue propName in properties.Keys)
{
ODBValue propValue = properties[propName];
propName.Store(writer);
propValue.Store(writer);
}
return stream.ToArray();
}
public override string ToString()
{
return String.Format("[Document ID={0} {1}]", ID.ToString(),String.Join(" ",properties.Select(kv=> String.Format("{0}={1}",kv.Key,kv.Value))));
}
public override int GetHashCode()
{
return ID.GetHashCode();
}
public override bool Equals(object obj)
{
if (obj is ODBDocument)
{
ODBDocument you = obj as ODBDocument;
return ID.Equals(you.ID);
}
return false;
}
public bool ContentEquals(ODBDocument other)
{
if (object.ReferenceEquals(null, other))
return false;
ODBValue[] keys = Keys.Union(other.Keys).ToArray();
foreach (ODBValue key in keys)
{
ODBValue value = this[key];
if (!value.ValueEquals(other[key]))
return false;
}
return true;
}
public override bool ValueEquals(ODBValue other)
{
return ContentEquals(other as ODBDocument);
}
public int CompareContent(ODBDocument other)
{
ODBValue[] keys = Keys.Union(other.Keys).ToArray();
foreach (ODBValue key in keys)
{
ODBValue mine = this[key];
ODBValue yours = other[key];
int c = ODBValue.Compare(mine, yours);
if (c != 0)
return c;
}
return 0;
}
public override int CompareInType(ODBValue other)
{
return CompareContent(other as ODBDocument);
}
public override int CompareValueInType(ODBValue other)
{
return CompareContent(other as ODBDocument);
}
static Document()
{
RegisterDeserializer(0x1001, (b,o,l) => new Document(Guid.Empty,b,o,l));
}
}
}

16
odb/ng/IStorage.cs 100644
View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
namespace ln.types.odb.ng
{
public interface IStorage
{
bool Open();
void Close();
bool IsOpen { get; }
ODBDocument Load(Guid documentID);
ODBDocument Save(ODBDocument document);
IEnumerable<Guid> GetDocumentIDs();
}
}

View File

@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Reflection;
using System.Linq;
using System.Collections;
using ln.types.net;
namespace ln.types.odb.ng
{
@ -98,6 +99,11 @@ namespace ln.types.odb.ng
(mapper, oval) => oval.AsBool
);
RegisterMapping<IPv4>(
(mapper, value) => new ODBUInteger(value.AsUInt),
(mapper, oval) => new IPv4(oval.AsUInt)
);
RegisterMapping(typeof(object),new mappings.ObjectMapping());
}

View File

@ -50,13 +50,13 @@ namespace ln.types.odb.ng
}
}
//public IEnumerable Select(Query query)
//{
// lock (this)
// {
// return new MappedEnumeration(this, query.Execute(DocumentCollection).ToArray());
// }
//}
public IEnumerable Select(Query query)
{
lock (this)
{
return new ObjectEnumeration(this, query.Execute(DocumentCollection).ToArray());
}
}
public bool Ensure(object o)
@ -247,24 +247,45 @@ namespace ln.types.odb.ng
return DocumentCollection.Index.Select((arg) => ODBMapper.UnmapValue(IDType, arg)).ToArray();
}
//public MappedEnumeration GetEnumeration()
//{
// lock (this)
// {
// return new MappedEnumeration(this, DocumentCollection.Index.ToArray());
// }
//}
public IEnumerable GetEnumeration()
{
lock (this)
{
return new ObjectEnumeration(this, DocumentCollection.Index.ToArray());
}
}
public IEnumerator GetEnumerator()
{
throw new NotImplementedException();
//return GetEnumeration().GetEnumerator();
return GetEnumeration().GetEnumerator();
}
public void Close()
{
DocumentCollection = null;
}
class ObjectEnumeration : IEnumerable
{
ObjectCollection collection;
IEnumerable<ODBValue> documentIDs;
public ObjectEnumeration(ObjectCollection collection,IEnumerable<ODBValue> documentIDs)
{
this.collection = collection;
this.documentIDs = documentIDs;
}
public IEnumerator GetEnumerator()
{
foreach (ODBValue documentID in this.documentIDs)
{
yield return this.collection.SelectByID(documentID);
}
}
}
}
@ -275,6 +296,7 @@ namespace ln.types.odb.ng
:base(odbmapper,typeof(T))
{}
public IEnumerable<T> SelectQuery(Query query) => base.Select(query).Cast<T>();
public T Select(object id) => (T)base.SelectByID(id);
public bool Ensure(T o) => base.Ensure(o);

190
odb/ng/Query.cs 100644
View File

@ -0,0 +1,190 @@
// /**
// * File: Query.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.Collections.Generic;
using ln.types.odb.values;
using ln.types.btree;
using System.Linq;
using ln.types.odb.index;
namespace ln.types.odb.ng
{
public abstract class Query
{
private Query()
{
}
public static Query AND(Query query,params Query[] queries)
{
return new IMPL.AND(query, queries);
}
public static Query OR(Query query, params Query[] queries)
{
return new IMPL.OR(query, queries);
}
public static Query NOT(Query query)
{
return new IMPL.NOT(query);
}
public static Query Equals<T>(string propertyName, object value) => Equals(IndexPath.TranslatePropertyPath(typeof(T), propertyName), ODBMapper.Default.MapValue(value));
public static Query Equals(String propertyName, ODBValue value)
{
if (object.ReferenceEquals(value,null))
value = ODBNull.Instance;
return IF(propertyName, (v) => value.ValueEquals(v));
}
public static Query EqualsNot<T>(string propertyName, ODBValue value) => EqualsNot(IndexPath.TranslatePropertyPath(typeof(T), propertyName), value);
public static Query EqualsNot(String propertyName, ODBValue value)
{
if (object.ReferenceEquals(value, null))
value = ODBNull.Instance;
return IF(propertyName, (v) => !value.ValueEquals(v));
}
public static Query Equals<T>(string propertyName, ODBValue[] values) => Equals(IndexPath.TranslatePropertyPath(typeof(T), propertyName), values);
public static Query Equals(String propertyName, ODBValue[] values)
{
return IF(propertyName, (v) => values.Contains(v));
}
public static Query Contains<T, A>(string propertyName, IEnumerable<A> values)
{
ODBValue[] oValues = values.Select(v => ODBMapper.Default.MapValue(v)).ToArray();
return IF(IndexPath.TranslatePropertyPath(typeof(T), propertyName), v => oValues.Contains(v));
}
public static Query IF<T>(string propertyName, Predicate<ODBValue> predicate) => IF(IndexPath.TranslatePropertyPath(typeof(T),propertyName), predicate);
public static Query IF(string propertyName,Predicate<ODBValue> predicate)
{
return new IMPL.IF(propertyName, predicate);
}
public abstract IEnumerable<ODBValue> Execute(ODBCollection collection);
class IMPL
{
public class IF : Query
{
public string PropertyName { get; }
public Predicate<ODBValue> Predicate { get; }
public IF(string propertyName,Predicate<ODBValue> predicate)
{
PropertyName = propertyName;
Predicate = predicate;
}
public override IEnumerable<ODBValue> Execute(ODBCollection collection)
{
return collection.QueryIDs(PropertyName,Predicate);
}
}
public class AND : Query
{
public Query Query { get; }
public Query[] Queries { get; }
public AND(Query query, params Query[] queries)
{
Query = query;
Queries = queries;
}
public override IEnumerable<ODBValue> Execute(ODBCollection collection)
{
BTree<ODBValue> firstSet = new BTree<ODBValue>(ODBValue.Compare);
firstSet.AddRange(
Query.Execute(collection)
);
foreach (Query aQuery in Queries)
{
if (firstSet.Count == 0)
return new ODBValue[0];
BTree<ODBValue> nextSet = new BTree<ODBValue>(ODBValue.Compare);
foreach (ODBValue documentID in aQuery.Execute(collection))
{
if (firstSet.ContainsKey(documentID))
nextSet.Add(documentID);
}
firstSet = nextSet;
}
return firstSet.Keys;
}
}
public class OR : Query
{
public Query Query { get; }
public Query[] Queries { get; }
public OR(Query query, params Query[] queries)
{
Query = query;
Queries = queries;
}
public override IEnumerable<ODBValue> Execute(ODBCollection collection)
{
BTree<ODBValue> result = new BTree<ODBValue>(ODBValue.Compare);
result.TryAddRange(
Query.Execute(collection)
);
foreach (Query aQuery in Queries)
{
foreach (ODBValue documentID in aQuery.Execute(collection))
result.TryAdd(documentID);
}
return result.Keys;
}
}
public class NOT : Query
{
public Query Query { get; }
public NOT(Query query)
{
Query = query;
}
public override IEnumerable<ODBValue> Execute(ODBCollection collection)
{
BTree<ODBValue> notSet = new BTree<ODBValue>();
BTree<ODBValue> result = new BTree<ODBValue>();
notSet.AddRange(Query.Execute(collection));
foreach (ODBValue documentID in collection.Index)
{
if (!notSet.ContainsKey(documentID))
result.Add(documentID);
}
return result.Keys;
}
}
}
}
}

View File

@ -15,6 +15,8 @@ namespace ln.types.odb.values
{
public ODBValue ODBValue { get; private set; }
public Type TargetType { get; private set; }
public override uint AsUInt => ODBValue.AsUInt;
internal ODBTypedValue()
: base(0x0020)

View File

@ -21,6 +21,7 @@ using System.IO;
* 0x0020 ODBTypedMapping
*
* 0x1000 ODBDocument
* 0x1001 Document (ln.types.odb.ng)
*
*
*

View File

@ -27,6 +27,22 @@ namespace ln.types.rpc
modules.Add(moduleName, rpcModule);
}
public void Remove(string moduleName)
{
modules.Remove(moduleName);
}
public void Remove(object moduleInstance)
{
foreach (RPCModule module in modules.Values)
{
if (module.ModuleInstance == moduleInstance)
{
modules.Remove(module.Name);
return;
}
}
}
public RPCResult Invoke(RPCCall call)
{
if ((call.ModuleName != null) && !modules.ContainsKey(call.ModuleName))
@ -86,9 +102,29 @@ namespace ln.types.rpc
ParameterInfo[] paramterInfos = methodInfo.GetParameters();
object[] parameters = new object[paramterInfos.Length];
for (int n=0;n<parameters.Length;n++)
for (int n = 0; n < parameters.Length; n++)
{
parameters[n] = Convert.ChangeType(call.Parameters[n], paramterInfos[n].ParameterType);
Type pType = paramterInfos[n].ParameterType;
if (pType.Equals(typeof(Guid)))
{
parameters[n] = Guid.Parse(call.Parameters[n].ToString());
} else if (pType.IsArray)
{
Type eType = pType.GetElementType();
object[] src = (object[])call.Parameters[n];
Array a = Array.CreateInstance(eType, src.Length);
for (int m=0;m<src.Length;m++)
{
a.SetValue(Convert.ChangeType(src[m], eType), m);
}
parameters[n] = a;
}
else
{
parameters[n] = Convert.ChangeType(call.Parameters[n], paramterInfos[n].ParameterType);
}
}
object result = methodInfo.Invoke(ModuleInstance, parameters);

View File

@ -10,6 +10,8 @@ namespace ln.types.threads
public class Pool : IDisposable
{
public static bool DEBUG = false;
public PoolThread[] PoolThreads
{
get
@ -330,11 +332,6 @@ namespace ln.types.threads
break;
}
if (Pool.poolThreads.Count > 4)
{
Logging.Log(LogLevel.DEBUGDETAIL, "--");
}
if (poolJob != null)
{
State = PoolThreadState.WORKING;

View File

@ -93,7 +93,7 @@ namespace ln.types.threads
JobState = PoolJobState.DONE;
if ((State != null) && !String.Empty.Equals(State))
if (Pool.DEBUG && (State != null) && !String.Empty.Equals(State))
Logging.Log(LogLevel.DEBUG, "PoolJob exited normally with State={0}", State);
}
catch (Exception e)