Skip to content
Snippets Groups Projects
Commit 4db22bae authored by Jiří Kalvoda's avatar Jiří Kalvoda
Browse files

Module reform: Add ModuleSourceThreadAndParser abstraction

parent 54c5c4e3
No related branches found
No related tags found
No related merge requests found
......@@ -117,37 +117,28 @@ text = ERR
}
}
[ModuleName("pipe")]
class ModulePipe: Module
abstract class ModuleSourceThreadAndParser: Module
{
StatusBar bar;
string path;
string text;
InnerStatusBar ifNoData;
InnerStatusBar ifReadError;
protected StatusBar bar;
protected string data;
protected long dataTick;
Thread inputThread;
int msgSeparator;
int scheudleIn_ms;
bool pipeError = false;
Parser parser;
public void Init(StatusBar _bar, ConfigSection section)
protected InnerStatusBar ifNoData;
protected int scheudleIn_ms;
protected Parser parser;
int? maxOld_ms;
int? showOld_ms;
protected abstract void inputThreadFunc();
public virtual void Init(StatusBar _bar, ConfigSection section)
{
bar = _bar;
path = section.Mandatory("path").AsPath();
ifNoData = new InnerStatusBar(_bar, section.Optional("no_data")?.AsConfig() ??
ifNoData = new InnerStatusBar(_bar, section.Optional("no_data_handler")?.AsConfig() ??
new ConfigParser(
@"
"));
ifReadError = new InnerStatusBar(_bar, section.Optional("read_error")?.AsConfig() ??
new ConfigParser(
@"
[constant]
color = red
text = ERR
"));
msgSeparator = section.Optional("separator")?.AsInt() ?? 0;
scheudleIn_ms = section.Optional("delay")?.AsMs() ?? 10;
showOld_ms = section.Optional("show_old")?.AsMs();
maxOld_ms = section.Optional("max_old")?.AsMs();
parser = _bar.GetGlobal<ParserGetter>().ByNameFromConfig(section.Optional("parser"));
parser.Init(_bar, this, section);
......@@ -155,84 +146,155 @@ text = ERR
inputThread.IsBackground = true;
inputThread.Start();
}
void inputThreadFunc()
protected void setData(string _data, long t)
{
while(true)
lock(this)
{
int r = POSIX.mkfifo(path, (7<<6)+(7<<3)+7);
int err = POSIX.ERRNO;
Console.WriteLine($"{r} {err}");
if(r == 0) break;
if(r != 0 && err == POSIX.EEXIST)
data = _data;
dataTick = t;
}
bar.Schedule(scheudleIn_ms);
}
public abstract IEnumerable<Element> Get();
protected IEnumerable<Element> parse(string _text, long _dataTick)
{
File.Delete(path);
continue;
long t = Environment.TickCount64;
if(_text == null )
return ifNoData.Get();
if(maxOld_ms != null && _dataTick + maxOld_ms <= t)
return ifNoData.Get();
var v = parser.Parse(_text);
if(showOld_ms != null && _dataTick + showOld_ms <= t)
{
bool first = true;
v = v.Select(x => {
if(first) x = x with { text = $"[{TimeShow.Show((t-_dataTick)/1000)}] {x.text}" };
first = false;
return x;
}).ToArray();
}
pipeError = true;
throw new Exception($"POSIX.mkfifo fail with ERRNO {err}");
return v;
}
var sr = new StreamReader(path);
var sw = new StreamWriter(path);
// Only for keeping pipe alive
}
abstract class ModuleAbstractPipe: ModuleSourceThreadAndParser
{
int msgSeparator;
public override void Init(StatusBar _bar, ConfigSection section)
{
msgSeparator = section.Optional("separator")?.AsInt() ?? 0;
base.Init(_bar, section);
}
protected abstract StreamReader getPipe();
protected override void inputThreadFunc()
{
var sr = getPipe();
StringBuilder s = new();
while(true)
{
int c = sr.Read();
if(c == -1)
throw new IOException();
if(c == msgSeparator)
{
lock(this)
{
text = s.ToString();
setData(s.ToString(), Environment.TickCount64);
s = new StringBuilder();
}
bar.Schedule(scheudleIn_ms);
}
else
{
s.Append((char)c);
}
}
}
public IEnumerable<Element> Get()
override public IEnumerable<Element> Get()
{
string _text;
long _dataTick;
lock(this)
{
_text = text;
_text = data;
_dataTick = dataTick;
}
if(pipeError)
return ifReadError.Get();
if(_text == null)
return ifNoData.Get();
return parser.Parse(_text);
return parse(_text, _dataTick);
}
}
[ModuleName("pipe")]
class ModulePipe: ModuleAbstractPipe
{
string path;
public override void Init(StatusBar _bar, ConfigSection section)
{
path = section.Mandatory("path").AsPath();
base.Init(_bar, section);
}
StreamWriter sw;
// Only for keeping pipe alive
protected override StreamReader getPipe()
{
while(true)
{
int r = POSIX.mkfifo(path, (7<<6)+(7<<3)+7);
int err = POSIX.ERRNO;
if(r == 0) break;
if(r != 0 && err == POSIX.EEXIST)
{
File.Delete(path);
continue;
}
throw new Exception($"POSIX.mkfifo fail with ERRNO {err}");
}
var sr = new StreamReader(path);
sw = new StreamWriter(path);
// Only for keeping pipe alive
return sr;
}
}
[ModuleName("exec")]
class ModuleExec: ModuleAbstractPipe
{
string programName;
string arguments;
Process process;
string stdinString;
public override void Init(StatusBar _bar, ConfigSection section)
{
programName = section.Mandatory("program").AsPath();
stdinString = section.Optional("stdin")?.AsString() ?? "";
arguments = section.Optional("arguments")?.AsString() ?? "";
base.Init(_bar, section);
}
protected override StreamReader getPipe()
{
process = new();
process.StartInfo.FileName = programName;
process.StartInfo.Arguments = arguments;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
TextWriter stdin = process.StandardInput;
var stdout = process.StandardOutput;
stdin.Write(stdinString);
stdin.Close();
return stdout;
}
}
[ModuleName("http")]
class ModuleHttp: Module
class ModuleHttp: ModuleSourceThreadAndParser
{
StatusBar bar;
string url;
string text;
HttpRequestException error;
long dataTick;
InnerStatusBar ifNoData;
InnerStatusBar ifReadError;
Thread inputThread;
int period_ms;
Parser parser;
int maxOld_ms;
int showOld_ms;
int timeout_ms;
public void Init(StatusBar _bar, ConfigSection section)
public override void Init(StatusBar _bar, ConfigSection section)
{
bar = _bar;
url = section.Mandatory("url").AsString();
ifNoData = new InnerStatusBar(_bar, section.Optional("no_data_handler")?.AsConfig() ??
new ConfigParser(
@"
"));
ifReadError = new InnerStatusBar(_bar, section.Optional("error_handler")?.AsConfig() ??
new ConfigParser(
@"
......@@ -242,31 +304,32 @@ text = ERR
"));
period_ms = section.Optional("period")?.AsMs() ?? 10000;
timeout_ms = section.Optional("period")?.AsMs() ?? 10000;
showOld_ms = section.Optional("show_old")?.AsMs() ?? 30000;
maxOld_ms = section.Optional("max_old")?.AsMs() ?? 300000;
parser = _bar.GetGlobal<ParserGetter>().ByNameFromConfig(section.Optional("parser"));
parser.Init(_bar, this, section);
inputThread = new Thread(this.inputThreadFunc);
inputThread.IsBackground = true;
inputThread.Start();
base.Init(_bar, section);
}
async void inputThreadFunc()
async override protected void inputThreadFunc()
{
HttpClient client = null;
void reloadClient()
{
if(client != null)
client.Dispose();
client = new HttpClient();
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36");
client.Timeout = TimeSpan.FromMilliseconds(10000);
}
reloadClient();
while(true)
{
try
{
long t = Environment.TickCount64;
using var client = new HttpClient();
client.Timeout = TimeSpan.FromMilliseconds(10000);
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36");
string _text = await client.GetStringAsync(url);
string _data = await client.GetStringAsync(url);
lock(this)
{
dataTick = t;
text = _text;
data = _data;
error = null;
}
}
......@@ -284,36 +347,21 @@ text = ERR
Thread.Sleep(period_ms);
}
}
public IEnumerable<Element> Get()
public override IEnumerable<Element> Get()
{
string _text;
string _data;
long _dataTick;
HttpRequestException _error;
lock(this)
{
_text = text;
_data = data;
_dataTick = dataTick;
_error = error;
}
long t = Environment.TickCount64;
if(_error != null)
return ifReadError.Get();
if(_text == null )
return ifNoData.Get();
if(maxOld_ms != 0 && _dataTick + maxOld_ms <= t)
return ifNoData.Get();
var v = parser.Parse(_text);
if(_dataTick + showOld_ms <= t)
{
bool first = true;
v.Select(x => {
var v = x;
if(first) v = v with { text = $"[{TimeShow.Show((t-_dataTick)/1000)}] {v.text}" };
first = false;
return v;
}).ToArray();
}
return v;
return parse(_data, _dataTick);
}
}
......@@ -417,3 +465,34 @@ class ModuleI3Status: Module
}
public IEnumerable<Element> Get() => elements ?? new Element[]{};
}
[ModuleName("time")]
class ModuleTime: Module
{
StatusBar bar;
string format;
Color color;
bool refresh;
int round_ms;
public void Init(StatusBar _bar, ConfigSection section)
{
bar = _bar;
format = section.Optional("format")?.AsString() ?? "yyyy-MM-dd HH:mm:ss";
DateTime.Now.ToString(format);
color = section["color"]?.AsColor() ?? Color.White;
refresh = section.Optional("refresh")?.AsBool() ?? false;
round_ms = section.Optional("round")?.AsMs() ?? 1000;
}
public IEnumerable<Element> Get()
{
var t = DateTime.Now;
var t_ms = (long)t.TimeOfDay.TotalMilliseconds;
t = t.AddMilliseconds(-(t_ms % round_ms));
string s = t.ToString(format);
if(refresh)
bar.Schedule((int)(round_ms - t_ms % round_ms + 1));
return new Element[]{new Element(s, color: color)};
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment