Beispiel #1
0
    async Task MainLoopAsync(CancellationToken cancel)
    {
        while (cancel.IsCancellationRequested == false)
        {
            RefInt nextPollingInterval = Host.Settings.PollingIntervalsSec * 1000;

            try
            {
                SortedDictionary <string, string> ret = new SortedDictionary <string, string>(StrComparer.IgnoreCaseTrimComparer);

                await GetValueAsync(ret, nextPollingInterval, cancel);

                this.CurrentValues = ret;
            }
            catch (Exception ex)
            {
                this.CurrentValues = new SortedDictionary <string, string>();

                ex._Debug();
            }

            int interval = nextPollingInterval;
            if (interval <= 0)
            {
                interval = Host.Settings.PollingIntervalsSec * 1000;
            }

            await cancel._WaitUntilCanceledAsync(Util.GenRandInterval(interval));
        }
    }
Beispiel #2
0
        private static void UpdateExpectationMatrixPass2(object _args)
        {
            object[] args      = (object[])_args;
            int      start_idx = (int)args[0];
            int      end_idx   = (int)args[1];

            SparseMatrix <double> .ReadOnly   train_mtx_tr = (SparseMatrix <double> .ReadOnly)args[2];
            IdxDat <SparseVector <double> >[] rows         = (IdxDat <SparseVector <double> >[])args[3];
            double[][] mtx      = (double[][])args[4];
            double[]   z        = (double[])args[5];
            RefInt     progress = (RefInt)args[6];

            for (int i = start_idx; i <= end_idx; i++)
            {
                IdxDat <SparseVector <double> > row = rows[i];
                int item_idx = 0;
                foreach (IdxDat <double> item in row.Dat)
                {
                    SparseVector <double> .ReadOnly pom = train_mtx_tr[item.Idx];
                    foreach (IdxDat <double> pom_item in pom)
                    {
                        row.Dat.SetDirect(item_idx, row.Dat.GetDatDirect(item_idx) + mtx[row.Idx][pom_item.Idx] / z[pom_item.Idx] * pom_item.Dat);
                    }
                    item_idx++;
                }
                progress.Val++;
            }
        }
 public static string RegisterRefInt(RefInt r)
 {
     return(RegisterCallback(() =>
     {
         return (r.Value != 0);
     }));
 }
Beispiel #4
0
        private static void UpdateExpectationMatrixPass1(object _args)
        {
            object[] args      = (object[])_args;
            int      start_idx = (int)args[0];
            int      end_idx   = (int)args[1];

            SparseMatrix <double> .ReadOnly            train_mtx_tr = (SparseMatrix <double> .ReadOnly)args[2];
            IdxDat <SparseVector <double> .ReadOnly>[] rows         = (IdxDat <SparseVector <double> .ReadOnly>[])args[3];
            double[][] mtx      = (double[][])args[4];
            RefInt     progress = (RefInt)args[5];

            for (int i = start_idx; i <= end_idx; i++)
            {
                IdxDat <SparseVector <double> .ReadOnly> row = rows[i];
                foreach (IdxDat <double> item in row.Dat)
                {
                    if (train_mtx_tr.ContainsRowAt(item.Idx))
                    {
                        SparseVector <double> .ReadOnly train_mtx_row = train_mtx_tr[item.Idx];
                        foreach (IdxDat <double> train_mtx_item in train_mtx_row)
                        {
                            mtx[row.Idx][train_mtx_item.Idx] += train_mtx_item.Dat * item.Dat;
                        }
                    }
                }
                progress.Val++;
            }
        }
	public void Setup (VectorLine line) {
		if (line.lineColors == null) {
			Debug.LogError ("In order to use Brightness.Fog, the line \"" + line.vectorObject.name + "\" must contain segment colors");
			return;
		}
		objectNumber = new RefInt(0);
		VectorManager.use.CheckDistanceSetup (transform, line, line.lineColors[0], objectNumber);
		VectorManager.use.SetDistanceColor (objectNumber.i);
	}
 public void Setup(VectorLine line, bool m_useLine)
 {
     m_objectNumber = new RefInt(0);
     VectorManager.CheckDistanceSetup (transform, line, line.color, m_objectNumber);
     VectorManager.SetDistanceColor (m_objectNumber.i);
     if (m_useLine) {	// Only if there are no Visibility scripts being used
         this.m_useLine = true;
         m_vectorLine = line;
     }
 }
        private IEnumerable <string> GetStrings(string key, RefInt r)
        {
            const string newline = "\r\n";
            const string escaped = @"\r\n";

            while (r.i < LangItems.Count && LangItems[r.i].Key == key)
            {
                yield return(LangItems[r.i++].Translated.Replace(newline, escaped));
            }
        }
 public void Setup(VectorLine line, bool m_useLine)
 {
     m_objectNumber = new RefInt(0);
     VectorManager.CheckDistanceSetup(transform, line, line.color, m_objectNumber);
     VectorManager.SetDistanceColor(m_objectNumber.i);
     if (m_useLine)                  // Only if there are no Visibility scripts being used
     {
         this.m_useLine = true;
         m_vectorLine   = line;
     }
 }
Beispiel #9
0
 public void Setup(VectorLine line)
 {
     if (line.lineColors == null)
     {
         Debug.LogError("In order to use Brightness.Fog, the line \"" + line.vectorObject.name + "\" must contain segment colors");
         return;
     }
     objectNumber = new RefInt(0);
     VectorManager.use.CheckDistanceSetup(transform, line, line.lineColors[0], objectNumber);
     VectorManager.use.SetDistanceColor(objectNumber.i);
 }
Beispiel #10
0
 public static void VisibilityStaticSetup(VectorLine line, out RefInt objectNum)
 {
     if (vectorLines == null)
     {
         vectorLines   = new List <VectorLine>();
         objectNumbers = new List <RefInt>();
     }
     vectorLines.Add(line);
     objectNum = new RefInt(_arrayCount++);
     objectNumbers.Add(objectNum);
     VectorLine.LineManagerEnable();
 }
Beispiel #11
0
 public static void VisibilitySetup(Transform thisTransform, VectorLine line, out RefInt objectNum)
 {
     if (vectorLines2 == null)
     {
         vectorLines2   = new List <VectorLine>();
         objectNumbers2 = new List <RefInt>();
     }
     line.drawTransform = thisTransform;
     vectorLines2.Add(line);
     objectNum = new RefInt(_arrayCount2++);
     objectNumbers2.Add(objectNum);
     VectorLine.LineManagerEnable();
 }
Beispiel #12
0
	public void Setup (VectorLine line, bool useLine) {
		if (line.lineColors == null) {
			Debug.LogError ("In order to use Brightness.Fog, the line \"" + line.vectorObject.name + "\" must contain segment colors");
			return;
		}
		m_objectNumber = new RefInt(0);
		VectorManager.CheckDistanceSetup (transform, line, line.lineColors[0], m_objectNumber);
		VectorManager.SetDistanceColor (m_objectNumber.i);
		if (useLine) {	// Only if there are no Visibility scripts being used
			this.useLine = true;
			vectorLine = line;
		}
	}
Beispiel #13
0
 public void VisibilityStaticSetup(VectorLine line, out RefInt objectNum)
 {
     if (!visibilityRunning)
     {
         isVisible         = new List <bool>();
         vectorLines       = new List <VectorLine>();
         objectNumbers     = new List <RefInt>();
         visibilityRunning = true;
     }
     isVisible.Add(true);
     vectorLines.Add(line);
     objectNum = new RefInt(arrayCount++);
     objectNumbers.Add(objectNum);
 }
Beispiel #14
0
 public static void VisibilitySetup(Transform thisTransform, VectorLine line, out RefInt objectNum)
 {
     if (vectorLines2 == null)
     {
         vectorLines2   = new List <VectorLine>();
         objectNumbers2 = new List <RefInt>();
         transforms     = new List <Matrix4x4?>();
     }
     vectorLines2.Add(line);
     transforms.Add(thisTransform.localToWorldMatrix);
     objectNum = new RefInt(_arrayCount2++);
     objectNumbers2.Add(objectNum);
     VectorLine.LineManagerEnable();
 }
Beispiel #15
0
 public void VisibilitySetup(Transform thisTransform, VectorLine line, out RefInt objectNum)
 {
     if (!visibilityRunning2)
     {
         isVisible2         = new List <bool>();
         vectorLines2       = new List <VectorLine>();
         objectNumbers2     = new List <RefInt>();
         transforms         = new List <Transform>();
         visibilityRunning2 = true;
     }
     isVisible2.Add(true);
     vectorLines2.Add(line);
     transforms.Add(thisTransform);
     objectNum = new RefInt(arrayCount2++);
     objectNumbers2.Add(objectNum);
 }
Beispiel #16
0
 public void Setup(VectorLine line, bool useLine)
 {
     if (line.lineColors == null)
     {
         Debug.LogError("In order to use Brightness.Fog, the line \"" + line.vectorObject.name + "\" must contain segment colors");
         return;
     }
     m_objectNumber = new RefInt(0);
     VectorManager.CheckDistanceSetup(transform, line, line.lineColors[0], m_objectNumber);
     VectorManager.SetDistanceColor(m_objectNumber.i);
     if (useLine)            // Only if there are no Visibility scripts being used
     {
         this.useLine = true;
         vectorLine   = line;
     }
 }
Beispiel #17
0
 public static void CheckDistanceSetup(Transform thisTransform, VectorLine line, Color color, RefInt objectNum)
 {
     VectorLine.LineManagerEnable();
     if (vectorLines3 == null) {
         vectorLines3 = new List<VectorLine>();
         transforms3 = new List<Transform>();
         oldDistances = new List<int>();
         colors = new List<Color>();
         objectNumbers3 = new List<RefInt>();
         VectorLine.LineManagerCheckDistance();
     }
     transforms3.Add(thisTransform);
     vectorLines3.Add(line);
     oldDistances.Add(-1);
     colors.Add(color);
     objectNum.i = _arrayCount3++;
     objectNumbers3.Add(objectNum);
 }
Beispiel #18
0
 private static IEnumerable <T> BuildNestedStructure <T>(RefInt r, int max, Converter <UserApp, T> makeAppNode, Func <string, T[], T> makeFolderNode) where T : class
 {
     for (int j = 0; j < max && r.i < appList.Count; j++)
     {
         UserApp app = appList[r.i++];
         T       node;
         if (app.IsFolder)
         {
             var children = BuildNestedStructure(r, app.ChildrenCount, makeAppNode, makeFolderNode);
             node = makeFolderNode(app.Name, children.ToArray());
         }
         else
         {
             node = makeAppNode(app);
         }
         if (node != null)
         {
             yield return(node);
         }
     }
 }
        private void btnSave_Click(object sender, RoutedEventArgs e)
        {
            string path;

            using (SaveFileDialog sfd = new SaveFileDialog()) {
                sfd.Filter           = QTUtility.TextResourcesDic["FileFilters"][1] + "|*.xml";
                sfd.RestoreDirectory = true;
                sfd.FileName         = "Lng_QTTabBar_" + LangItems[1].Translated + ".xml";
                if (DialogResult.OK != sfd.ShowDialog())
                {
                    return;
                }
                path = sfd.FileName;
            }

            try {
                using (XmlTextWriter writer = new XmlTextWriter(path, Encoding.UTF8)) {
                    writer.WriteStartDocument();
                    writer.WriteWhitespace(Environment.NewLine);
                    writer.WriteStartElement("root");
                    writer.WriteWhitespace(Environment.NewLine);
                    for (int i = 0; i < 3; i++)
                    {
                        LangEntry entry = LangItems[i];
                        if (entry.Translated == "")
                        {
                            continue;
                        }
                        writer.WriteWhitespace(Environment.NewLine);
                        writer.WriteStartElement(entry.Key);
                        writer.WriteWhitespace(Environment.NewLine);
                        writer.WriteValue(entry.Translated);
                        writer.WriteWhitespace(Environment.NewLine);
                        writer.WriteEndElement();
                        writer.WriteWhitespace(Environment.NewLine);
                    }
                    writer.WriteWhitespace(Environment.NewLine);
                    writer.WriteStartElement("Version_QTTabBar");
                    writer.WriteWhitespace(Environment.NewLine);
                    writer.WriteValue(QTUtility2.MakeVersionString());
                    writer.WriteWhitespace(Environment.NewLine);
                    writer.WriteEndElement();
                    writer.WriteWhitespace(Environment.NewLine);
                    writer.WriteWhitespace(Environment.NewLine);
                    writer.WriteStartElement("DateModified");
                    writer.WriteWhitespace(Environment.NewLine);
                    writer.WriteValue(DateTime.Now.ToString("MM/dd/yyyy"));
                    writer.WriteWhitespace(Environment.NewLine);
                    writer.WriteEndElement();
                    writer.WriteWhitespace(Environment.NewLine);
                    writer.WriteWhitespace(Environment.NewLine);
                    writer.WriteComment(" data start ");
                    writer.WriteWhitespace(Environment.NewLine);
                    RefInt r = new RefInt {
                        i = 3
                    };
                    while (r.i < LangItems.Count)
                    {
                        string key  = LangItems[r.i].Key;
                        string line = GetStrings(key, r).StringJoin(Environment.NewLine);
                        writer.WriteWhitespace(Environment.NewLine);
                        writer.WriteStartElement(key);
                        writer.WriteWhitespace(Environment.NewLine);
                        writer.WriteValue(line);
                        writer.WriteWhitespace(Environment.NewLine);
                        writer.WriteEndElement();
                        writer.WriteWhitespace(Environment.NewLine);
                    }
                    writer.WriteWhitespace(Environment.NewLine);
                    writer.WriteComment(" data end ");
                    writer.WriteWhitespace(Environment.NewLine);
                    writer.WriteWhitespace(Environment.NewLine);
                    writer.WriteEndElement();
                    writer.WriteWhitespace(Environment.NewLine);
                }
            }
            catch (XmlException) {
                MessageBox.Show(QTUtility.TextResourcesDic["Options_Page13_Language"][10]);
            }
            catch (Exception exception2) {
                QTUtility2.MakeErrorLog(exception2);
            }
        }
    protected override async Task GetValueAsync(SortedDictionary <string, string> ret, RefInt nextPollingInterval, CancellationToken cancel = default)
    {
        if (isBirdcExists)
        {
            await RunAndParseBirdAsync(Consts.LinuxCommands.Birdc, ret, 4, cancel)._TryAwait();
        }

        if (isBirdc6Exists)
        {
            await RunAndParseBirdAsync(Consts.LinuxCommands.Birdc6, ret, 6, cancel)._TryAwait();
        }
    }
    protected override async Task GetValueAsync(SortedDictionary <string, string> ret, RefInt nextPollingInterval, CancellationToken cancel = default)
    {
        var result = await EasyExec.ExecAsync(Consts.LinuxCommands.Free, "-b -w");

        string[] lines = result.OutputStr._GetLines();

        List <string> headers = new List <string>();

        KeyValueList <string, string> dataList = new KeyValueList <string, string>();

        foreach (string line in lines)
        {
            string[] tokens = line._Split(StringSplitOptions.RemoveEmptyEntries, ' ', '\t');

            if (tokens.Length >= 2)
            {
                if (headers.Count == 0)
                {
                    if (tokens[0]._IsSamei("total"))
                    {
                        // ヘッダ行
                        foreach (string token in tokens)
                        {
                            headers.Add(token);
                        }
                    }
                }
                else
                {
                    // データ行
                    if (tokens[0]._IsSamei("Mem:"))
                    {
                        for (int i = 1; i < tokens.Length; i++)
                        {
                            if (headers.Count >= (i - 1))
                            {
                                dataList.Add(headers[i - 1], tokens[i]);
                            }
                        }
                    }
                }
            }
        }

        // total
        long total     = dataList._GetStrFirst("total", "-1")._ToLong();
        long available = dataList._GetStrFirst("available", "-1")._ToLong();

        if (total >= 0 && available >= 0)
        {
            available = Math.Min(available, total);
            ret.TryAdd($"available", NormalizeDoubleValue(((double)available * 100.0 / (double)total).ToString("F3")));
        }
    }
    protected override async Task GetValueAsync(SortedDictionary <string, string> ret, RefInt nextPollingInterval, CancellationToken cancel = default)
    {
        SnmpWorkSettings settings = Host.Settings;

        if (settings.PingTargets._IsSamei("none") || settings.PingTargets._IsSamei("null"))
        {
            return;
        }

        string[] pingTargets = settings.PingTargets._Split(StringSplitOptions.RemoveEmptyEntries, ",");

        KeyValueList <string, IPAddress> kvList = new KeyValueList <string, IPAddress>();

        // 名前解決
        foreach (string pingTarget in pingTargets)
        {
            cancel.ThrowIfCancellationRequested();

            try
            {
                ParseTargetString(pingTarget, out string hostname, out string alias);

                IPAddress ip = await LocalNet.GetIpAsync(hostname, cancel : cancel);

                kvList.Add(alias, ip);
            }
            catch (Exception ex)
            {
                ex._Debug();
            }
        }

        List <Task <double> > taskList = new List <Task <double> >();

        int interval = 0;
        int count    = 3;

        // SpeedTest が動作中の場合は SpeedTest が完了するまで待機する
        numPerform++;
        if (numPerform >= 2)
        {
            interval = settings.PktLossIntervalMsec;
            count    = settings.PktLossTryCount;

            await TaskUtil.AwaitWithPollAsync(Timeout.Infinite, 10, () => !SpeedTestClient.IsInProgress, cancel);
        }

        // 並列実行の開始
        foreach (var kv in kvList)
        {
            taskList.Add(PerformOneAsync(kv.Value, count, settings.PktLossTimeoutMsecs, interval, cancel));
        }

        // すべて終了するまで待機し、結果を整理
        for (int i = 0; i < kvList.Count; i++)
        {
            var kv   = kvList[i];
            var task = taskList[i];

            double lossRate = await task._TryAwait();

            double quality = 1.0 - lossRate;

            quality = Math.Max(quality, 0.0);
            quality = Math.Min(quality, 1.0);

            ret.TryAdd($"{kv.Key}", ((double)quality * 100.0).ToString("F3"));
        }
    }
Beispiel #23
0
 public static void VisibilitySetup(Transform thisTransform, VectorLine line, out RefInt objectNum)
 {
     if (vectorLines2 == null) {
         vectorLines2 = new List<VectorLine>();
         objectNumbers2 = new List<RefInt>();
         transforms = new List<Transform>();
     }
     vectorLines2.Add(line);
     transforms.Add(thisTransform);
     objectNum = new RefInt(_arrayCount2++);
     objectNumbers2.Add(objectNum);
     VectorLine.LineManagerEnable();
 }
Beispiel #24
0
 public void CheckDistanceSetup(Transform thisTransform, VectorLine line, Color color, RefInt objectNum)
 {
     if (!checkRunning)
     {
         isVisible3     = new List <bool>();
         transforms3    = new List <Transform>();
         vectorLines3   = new List <VectorLine>();
         oldDistances   = new List <int>();
         colors         = new List <Color>();
         objectNumbers3 = new List <RefInt>();
         InvokeRepeating("CheckDistance", .01f, distanceCheckFrequency);
         checkRunning = true;
     }
     isVisible3.Add(true);
     transforms3.Add(thisTransform);
     vectorLines3.Add(line);
     oldDistances.Add(-1);
     colors.Add(color);
     objectNum.i = arrayCount3++;
     objectNumbers3.Add(objectNum);
 }
 private IEnumerable<string> GetStrings(string key, RefInt r) {
     const string newline = "\r\n";
     const string escaped = @"\r\n";
     while(r.i < LangItems.Count && LangItems[r.i].Key == key) {
         yield return LangItems[r.i++].Translated.Replace(newline, escaped);
     }
 }
	public void CheckDistanceSetup (Transform thisTransform, VectorLine line, Color color, RefInt objectNum) {
		if (!checkRunning) {
			isVisible3 = new List<bool>();
			transforms3 = new List<Transform>();
			vectorLines3 = new List<VectorLine>();
			oldDistances = new List<int>();
			colors = new List<Color>();
			objectNumbers3 = new List<RefInt>();
			InvokeRepeating("CheckDistance", .01f, distanceCheckFrequency);
			checkRunning = true;
		}
		isVisible3.Add(true);
		transforms3.Add(thisTransform);
		vectorLines3.Add(line);
		oldDistances.Add(-1);
		colors.Add(color);
		objectNum.i = arrayCount3++;
		objectNumbers3.Add(objectNum);
	}
    protected override async Task GetValueAsync(SortedDictionary <string, string> ret, RefInt nextPollingInterval, CancellationToken cancel = default)
    {
        if (IsConnTrackOk)
        {
            try
            {
                // ConnTrack
                var result = await EasyExec.ExecAsync(Consts.LinuxCommands.ConnTrack, "-C");

                string valueStr = result.OutputStr._GetFirstFilledLineFromLines();

                ret.TryAdd($"ConnTrack Sessions", valueStr._ToInt().ToString());
            }
            catch (Exception ex)
            {
                ex._Debug();
            }
        }

        if (true)
        {
            try
            {
                // Threads
                var result = EasyExec.ExecBashAsync("ps -eo nlwp | tail -n +2 | awk '{ num_threads += $1 } END { print num_threads }'")._GetResult();

                string valueStr = result.OutputStr._GetFirstFilledLineFromLines();

                ret.TryAdd($"Threads", valueStr._ToInt().ToString());
            }
            catch (Exception ex)
            {
                ex._Debug();
            }
        }

        if (true)
        {
            try
            {
                // FDs
                string result = await Lfs.ReadStringFromFileAsync(Consts.LinuxPaths.FileNr, flags : FileFlags.NoCheckFileSize);

                string valueStr = result._GetFirstFilledLineFromLines();

                string[] tokens = valueStr._Split(StringSplitOptions.RemoveEmptyEntries, " ", "\t");

                int numFd = -1;

                if (tokens.Length >= 1)
                {
                    numFd = tokens[0]._ToInt();
                }

                ret.TryAdd($"FDs", numFd.ToString());
            }
            catch (Exception ex)
            {
                ex._Debug();
            }
        }

        if (true)
        {
            try
            {
                // Sockets
                string[] lines = (await Lfs.ReadStringFromFileAsync(Consts.LinuxPaths.SockStat, flags: FileFlags.NoCheckFileSize))._GetLines();

                int numSockets = -1;
                int numTcp     = -1;
                int numUdp     = -1;

                foreach (string line in lines)
                {
                    string[] tokens = line._Split(StringSplitOptions.RemoveEmptyEntries, " ");

                    if (tokens.Length >= 3)
                    {
                        if (tokens[0]._IsSamei("sockets:"))
                        {
                            numSockets = tokens[2]._ToInt();
                        }

                        if (tokens[0]._IsSamei("TCP:"))
                        {
                            numTcp = tokens[2]._ToInt();
                        }

                        if (tokens[0]._IsSamei("UDP:"))
                        {
                            numUdp = tokens[2]._ToInt();
                        }
                    }
                }

                if (numSockets >= 0 && numTcp >= 0 && numUdp >= 0)
                {
                    ret.TryAdd($"Sockets", numSockets.ToString());
                    ret.TryAdd($"TCP", numTcp.ToString());
                    ret.TryAdd($"UDP", numUdp.ToString());
                }
            }
            catch (Exception ex)
            {
                ex._Debug();
            }
        }
    }
 private void btnSave_Click(object sender, RoutedEventArgs e) {
     string path;
     using(SaveFileDialog sfd = new SaveFileDialog()) {
         sfd.Filter = QTUtility.TextResourcesDic["FileFilters"][1] + "|*.xml";
         sfd.RestoreDirectory = true;
         sfd.FileName = "Lng_QTTabBar_" + LangItems[1].Translated + ".xml";
         if(DialogResult.OK != sfd.ShowDialog()) return;
         path = sfd.FileName;
     }
     
     try {
         using(XmlTextWriter writer = new XmlTextWriter(path, Encoding.UTF8)) {
             writer.WriteStartDocument();
             writer.WriteWhitespace(Environment.NewLine);
             writer.WriteStartElement("root");
             writer.WriteWhitespace(Environment.NewLine);
             for(int i = 0; i < 3; i++) {
                 LangEntry entry = LangItems[i];
                 if(entry.Translated == "") continue;
                 writer.WriteWhitespace(Environment.NewLine);
                 writer.WriteStartElement(entry.Key);
                 writer.WriteWhitespace(Environment.NewLine);
                 writer.WriteValue(entry.Translated);
                 writer.WriteWhitespace(Environment.NewLine);
                 writer.WriteEndElement();
                 writer.WriteWhitespace(Environment.NewLine);
             }
             writer.WriteWhitespace(Environment.NewLine);
             writer.WriteStartElement("Version_QTTabBar");
             writer.WriteWhitespace(Environment.NewLine);
             writer.WriteValue(QTUtility2.MakeVersionString());
             writer.WriteWhitespace(Environment.NewLine);
             writer.WriteEndElement();
             writer.WriteWhitespace(Environment.NewLine);
             writer.WriteWhitespace(Environment.NewLine);
             writer.WriteStartElement("DateModified");
             writer.WriteWhitespace(Environment.NewLine);
             writer.WriteValue(DateTime.Now.ToString("MM/dd/yyyy"));
             writer.WriteWhitespace(Environment.NewLine);
             writer.WriteEndElement();
             writer.WriteWhitespace(Environment.NewLine);
             writer.WriteWhitespace(Environment.NewLine);
             writer.WriteComment(" data start ");
             writer.WriteWhitespace(Environment.NewLine);
             RefInt r = new RefInt { i = 3 };
             while(r.i < LangItems.Count) {
                 string key = LangItems[r.i].Key;
                 string line = GetStrings(key, r).StringJoin(Environment.NewLine);
                 writer.WriteWhitespace(Environment.NewLine);
                 writer.WriteStartElement(key);
                 writer.WriteWhitespace(Environment.NewLine);
                 writer.WriteValue(line);
                 writer.WriteWhitespace(Environment.NewLine);
                 writer.WriteEndElement();
                 writer.WriteWhitespace(Environment.NewLine);                        
             }
             writer.WriteWhitespace(Environment.NewLine);
             writer.WriteComment(" data end ");
             writer.WriteWhitespace(Environment.NewLine);
             writer.WriteWhitespace(Environment.NewLine);
             writer.WriteEndElement();
             writer.WriteWhitespace(Environment.NewLine);
         }
     }
     catch(XmlException) {
         MessageBox.Show(QTUtility.TextResourcesDic["Options_Page13_Language"][10]);
     }
     catch(Exception exception2) {
         QTUtility2.MakeErrorLog(exception2);
     }
 }
    // 1 つのディレクトリをバックアップする
    public async Task DoSingleDirBackupAsync(string srcDir, string destDir, CancellationToken cancel = default, string?ignoreDirNames = null)
    {
        DateTimeOffset now = DateTimeOffset.Now;

        FileSystemEntity[]? srcDirEnum = null;

        string[] ignoreDirNamesList = ignoreDirNames._NonNull()._Split(StringSplitOptions.RemoveEmptyEntries, ",", ";");

        FileMetadata?srcDirMetadata = null;

        bool noError = true;

        try
        {
            if (srcDir._IsSamei(destDir))
            {
                throw new CoresException($"srcDir == destDir. Directory path: '{srcDir}'");
            }

            srcDirMetadata = await Fs.GetDirectoryMetadataAsync(srcDir, cancel : cancel);

            srcDirEnum = (await Fs.EnumDirectoryAsync(srcDir, false, EnumDirectoryFlags.NoGetPhysicalSize, cancel)).OrderBy(x => x.Name, StrComparer.IgnoreCaseComparer).ToArray();

            FileSystemEntity[] destDirEnum = new FileSystemEntity[0];

            DirSuperBackupMetadata?destDirOldMetaData = null;

            DirSuperBackupMetadata destDirNewMetaData;

            // 宛先ディレクトリがすでに存在しているかどうか検査する
            if (await Fs.IsDirectoryExistsAsync(destDir, cancel))
            {
                destDirEnum = await Fs.EnumDirectoryAsync(destDir, false, EnumDirectoryFlags.NoGetPhysicalSize, cancel);

                // 宛先ディレクトリに存在するメタデータファイルのうち最新のファイルを取得する
                destDirOldMetaData = await GetLatestMetaDataFileNameAsync(destDir, destDirEnum, cancel);
            }
            else
            {
                // 宛先ディレクトリがまだ存在していない場合は作成する
                await Fs.CreateDirectoryAsync(destDir, FileFlags.BackupMode | FileFlags.AutoCreateDirectory, cancel);
            }

            // 宛先ディレクトリの日付情報のみ属性書き込みする
            try
            {
                await Fs.SetFileMetadataAsync(destDir, srcDirMetadata.Clone(FileMetadataCopyMode.TimeAll), cancel);
            }
            catch
            {
                // 属性書き込みは失敗してもよい
            }

            // 新しいメタデータを作成する
            destDirNewMetaData             = new DirSuperBackupMetadata();
            destDirNewMetaData.FileList    = new List <DirSuperBackupMetadataFile>();
            destDirNewMetaData.TimeStamp   = now;
            destDirNewMetaData.DirMetadata = srcDirMetadata;
            destDirNewMetaData.DirList     = new List <string>();

            // 元ディレクトリに存在するサブディレクトリ名一覧をメタデータに追記する
            foreach (var subDir in srcDirEnum.Where(x => x.IsDirectory && x.IsCurrentOrParentDirectory == false))
            {
                // シンボリックリンクは無視する
                if (subDir.IsSymbolicLink == false)
                {
                    // 無視リストのいずれにも合致しない場合のみ
                    if (ignoreDirNamesList.Where(x => x._IsSamei(subDir.Name)).Any() == false)
                    {
                        destDirNewMetaData.DirList.Add(subDir.Name);
                    }
                }
            }

            // 元ディレクトリに存在するファイルを 1 つずつバックアップする
            var fileEntries = srcDirEnum.Where(x => x.IsFile);

            RefInt concurrentNum = new RefInt();

            AsyncLock SafeLock = new AsyncLock();

            await TaskUtil.ForEachAsync(Options.NumThreads, fileEntries, async (srcFile, taskIndex, cancel) =>
            {
                long?encryptedPhysicalSize = null;

                await Task.Yield();

                string destFilePath = Fs.PathParser.Combine(destDir, srcFile.Name);

                if (Options.EncryptPassword._IsNullOrZeroLen() == false)
                {
                    destFilePath += Consts.Extensions.CompressedXtsAes256;
                }

                FileMetadata?srcFileMetadata = null;

                concurrentNum.Increment();

                try
                {
                    srcFileMetadata = await Fs.GetFileMetadataAsync(srcFile.FullPath, cancel: cancel);

                    // このファイルと同一のファイル名がすでに宛先ディレクトリに物理的に存在するかどうか確認する
                    bool exists = await Fs.IsFileExistsAsync(destFilePath, cancel);

                    bool fileChangedOrNew = false;

                    if (exists)
                    {
                        // すでに宛先ディレクトリに存在する物理的なファイルのメタデータを取得する
                        FileMetadata destExistsMetadata = await Fs.GetFileMetadataAsync(destFilePath, cancel: cancel);

                        if (Options.EncryptPassword._IsNullOrZeroLen())
                        {
                            // 暗号化なし
                            // ファイルサイズを比較する
                            if (destExistsMetadata.Size != srcFile.Size)
                            {
                                // ファイルサイズが異なる
                                fileChangedOrNew = true;
                            }
                        }
                        else
                        {
                            // 暗号化あり
                            // 宛先ディレクトリのメタデータにファイル情報が存在し、そのメタデータ情報におけるファイルサイズが元ファイルと同じであり、
                            // かつそのメタデータ情報に記載されている EncryptedPhysicalSize が宛先ディレクトリにある物理ファイルと全く同一である
                            // 場合は、宛先ファイルが正しく存在すると仮定する

                            string tmp1 = Fs.PathParser.GetFileName(destFilePath);
                            if ((destDirOldMetaData?.FileList.Where(x => x.EncrypedFileName._IsSamei(tmp1) && x.EncryptedPhysicalSize == destExistsMetadata.Size && x.MetaData.Size == srcFile.Size).Any() ?? false) == false)
                            {
                                // ファイルサイズが異なるとみなす
                                fileChangedOrNew = true;
                            }
                        }

                        // 日付を比較する。ただし宛先ディレクトリの物理的なファイルの日付は信用できないので、メタデータ上のファイルサイズと比較する
                        if (destDirOldMetaData != null)
                        {
                            DirSuperBackupMetadataFile?existsFileMetadataFromDirMetadata = destDirOldMetaData.FileList.Where(x => x.FileName._IsSamei(srcFile.Name)).SingleOrDefault();
                            if (existsFileMetadataFromDirMetadata == null)
                            {
                                // メタデータ上に存在しない
                                fileChangedOrNew = true;
                            }
                            else
                            {
                                if (existsFileMetadataFromDirMetadata.MetaData !.LastWriteTime !.Value.Ticks != srcFileMetadata.LastWriteTime !.Value.Ticks)
                                {
                                    // 最終更新日時が異なる
                                    fileChangedOrNew = true;
                                }
                            }
                        }
                        else
                        {
                            // 宛先ディレクトリ上にメタデータがない
                            fileChangedOrNew = true;
                        }
                    }
                    else
                    {
                        // 新しいファイルである
                        fileChangedOrNew = true;
                    }

                    string?oldFilePathToDelete = null;

                    if (fileChangedOrNew)
                    {
                        // ファイルが新しいか、または更新された場合は、そのファイルをバックアップする
                        // ただし、バックアップ先に同名のファイルがすでに存在する場合は、
                        // .old.xxxx.YYYYMMDD_HHMMSS.0123._backup_history のような形式でまだ存在しない連番に古いファイル名をリネームする

                        if (exists)
                        {
                            using (await SafeLock.LockWithAwait(cancel))
                            {
                                string yymmdd = Str.DateTimeToStrShort(DateTime.UtcNow);
                                string newOldFileName;

                                // 連番でかつ存在していないファイル名を決定する
                                for (int i = 0; ; i++)
                                {
                                    string newOldFileNameCandidate = $".old.{Fs.PathParser.GetFileName(destFilePath)}.{yymmdd}.{i:D4}{Consts.Extensions.DirSuperBackupHistory}";

                                    if (srcDirEnum.Where(x => x.Name._IsSamei(newOldFileNameCandidate)).Any() == false)
                                    {
                                        if (await Fs.IsFileExistsAsync(Fs.PathParser.Combine(destDir, newOldFileNameCandidate), cancel) == false)
                                        {
                                            newOldFileName = newOldFileNameCandidate;
                                            break;
                                        }
                                    }
                                }

                                // 変更されたファイル名を ._backup_history ファイルにリネーム実行する
                                string newOldFilePath = Fs.PathParser.Combine(destDir, newOldFileName);
                                await WriteLogAsync(DirSuperBackupLogType.Info, Str.CombineStringArrayForCsv("FileRename", destFilePath, newOldFilePath));
                                await Fs.MoveFileAsync(destFilePath, newOldFilePath, cancel);

                                oldFilePathToDelete = newOldFilePath;

                                // 隠しファイルにする
                                try
                                {
                                    var meta = await Fs.GetFileMetadataAsync(newOldFilePath, cancel: cancel);
                                    if (meta.Attributes != null && meta.Attributes.Bit(FileAttributes.Hidden) == false)
                                    {
                                        FileMetadata meta2 = new FileMetadata(attributes: meta.Attributes.BitAdd(FileAttributes.Hidden));

                                        await Fs.SetFileMetadataAsync(newOldFilePath, meta2, cancel);
                                    }
                                }
                                catch { }
                            }
                        }

                        // ファイルをコピーする
                        // 属性は、ファイルの日付情報のみコピーする
                        await WriteLogAsync(DirSuperBackupLogType.Info, Str.CombineStringArrayForCsv("FileCopy", srcFile.FullPath, destFilePath));

                        FileFlags flags = FileFlags.BackupMode | FileFlags.Async;

                        if (this.Options.Flags.Bit(DirSuperBackupFlags.BackupNoVerify) == false)
                        {
                            flags |= FileFlags.CopyFile_Verify;
                        }

                        await Fs.CopyFileAsync(srcFile.FullPath, destFilePath,
                                               new CopyFileParams(flags: flags, metadataCopier: new FileMetadataCopier(FileMetadataCopyMode.TimeAll),
                                                                  encryptOption: Options.EncryptPassword._IsNullOrZeroLen() ? EncryptOption.None : EncryptOption.Encrypt | EncryptOption.Compress,
                                                                  encryptPassword: Options.EncryptPassword, deleteFileIfVerifyFailed: true),
                                               cancel: cancel);

                        try
                        {
                            if (Options.EncryptPassword._IsNullOrZeroLen() == false)
                            {
                                var newFileMetadata = await Fs.GetFileMetadataAsync(destFilePath, FileMetadataGetFlags.NoPhysicalFileSize, cancel);

                                encryptedPhysicalSize = newFileMetadata.Size;
                            }
                        }
                        catch
                        {
                        }

                        if (Options.Flags.Bit(DirSuperBackupFlags.BackupMakeHistory) == false)
                        {
                            // History を残さない場合
                            // コピーに成功したので ._backup_history ファイルは削除する
                            if (oldFilePathToDelete._IsNotZeroLen())
                            {
                                try
                                {
                                    await Fs.DeleteFileAsync(oldFilePathToDelete, flags: FileFlags.BackupMode | FileFlags.ForceClearReadOnlyOrHiddenBitsOnNeed, cancel);
                                }
                                catch
                                {
                                }
                            }
                        }

                        Stat.Copy_NumFiles++;
                        Stat.Copy_TotalSize += srcFile.Size;
                    }
                    else
                    {
                        if (Options.EncryptPassword._IsNullOrZeroLen() == false)
                        {
                            string tmp1 = Fs.PathParser.GetFileName(destFilePath);

                            encryptedPhysicalSize = destDirOldMetaData?.FileList.Where(x => x.EncrypedFileName._IsSame(tmp1) && x.MetaData.Size == srcFile.Size).FirstOrDefault()?.EncryptedPhysicalSize;

                            if (encryptedPhysicalSize.HasValue == false)
                            {
                                encryptedPhysicalSize = destDirOldMetaData?.FileList.Where(x => x.EncrypedFileName._IsSamei(tmp1) && x.MetaData.Size == srcFile.Size).FirstOrDefault()?.EncryptedPhysicalSize;
                            }
                        }

                        Stat.Skip_NumFiles++;
                        Stat.Skip_TotalSize += srcFile.Size;

                        // ファイルの日付情報のみ更新する
                        try
                        {
                            await Fs.SetFileMetadataAsync(destFilePath, srcFileMetadata.Clone(FileMetadataCopyMode.TimeAll), cancel);
                        }
                        catch
                        {
                            // ファイルの日付情報の更新は失敗してもよい
                        }
                    }
                }
                catch (Exception ex)
                {
                    Stat.Error_NumFiles++;
                    Stat.Error_TotalSize += srcFile.Size;

                    // ファイル単位のエラー発生
                    await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("FileError", srcFile.FullPath, destFilePath, ex.Message));

                    noError = false;
                }
                finally
                {
                    concurrentNum.Decrement();
                }

                // このファイルに関するメタデータを追加する
                if (srcFileMetadata != null)
                {
                    lock (destDirNewMetaData.FileList)
                    {
                        destDirNewMetaData.FileList.Add(new DirSuperBackupMetadataFile()
                        {
                            FileName              = srcFile.Name,
                            EncrypedFileName      = Options.EncryptPassword._IsNullOrZeroLen() ? null : srcFile.Name + Consts.Extensions.CompressedXtsAes256,
                            MetaData              = srcFileMetadata,
                            EncryptedPhysicalSize = encryptedPhysicalSize,
                        });
                    }
                }
            }, cancel : cancel);

            // 新しいメタデータをファイル名でソートする
            destDirNewMetaData.FileList = destDirNewMetaData.FileList.OrderBy(x => x.FileName, StrComparer.IgnoreCaseComparer).ToList();
            destDirNewMetaData.DirList  = destDirNewMetaData.DirList.OrderBy(x => x, StrComparer.IgnoreCaseComparer).ToList();

            // 新しいメタデータを書き込む
            string newMetadataFilePath = Fs.PathParser.Combine(destDir, $"{PrefixMetadata}{Str.DateTimeToStrShortWithMilliSecs(now.UtcDateTime)}{SuffixMetadata}");

            await Fs.WriteJsonToFileAsync(newMetadataFilePath, destDirNewMetaData, FileFlags.BackupMode | FileFlags.OnCreateSetCompressionFlag, cancel : cancel);
        }
        catch (Exception ex)
        {
            Stat.Error_Dir++;

            noError = false;

            // ディレクトリ単位のエラー発生
            await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("DirError1", srcDir, destDir, ex.Message));
        }

        // 再度 宛先ディレクトリの日付情報のみ属性書き込みする (Linux の場合、中のファイルを更新するとディレクトリの日時が変ってしまうため)
        try
        {
            if (srcDirMetadata != null)
            {
                await Fs.SetFileMetadataAsync(destDir, srcDirMetadata.Clone(FileMetadataCopyMode.TimeAll), cancel);
            }
        }
        catch
        {
            // 属性書き込みは失敗してもよい
        }

        if (srcDirEnum != null)
        {
            bool ok = false;

            try
            {
                // ソースディレクトリの列挙に成功した場合は、サブディレクトリに対して再帰的に実行する
                foreach (var subDir in srcDirEnum.Where(x => x.IsDirectory && x.IsCurrentOrParentDirectory == false))
                {
                    // シンボリックリンクは無視する
                    if (subDir.IsSymbolicLink == false)
                    {
                        // 無視リストのいずれにも合致しない場合のみ
                        if (ignoreDirNamesList.Where(x => x._IsSamei(subDir.Name)).Any() == false)
                        {
                            await DoSingleDirBackupAsync(Fs.PathParser.Combine(srcDir, subDir.Name), Fs.PathParser.Combine(destDir, subDir.Name), cancel, ignoreDirNames);
                        }
                    }
                }

                ok = true;
            }
            catch (Exception ex)
            {
                // 何らかのディレクトリ単位のエラーで catch されていないものが発生
                Stat.Error_Dir++;

                // ディレクトリ単位のエラー発生
                await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("DirError2", srcDir, destDir, ex.Message));
            }

            if (ok)
            {
                if (noError)
                {
                    // ここまでの処理で何も問題がなければ (このディレクトリ内のすべてのファイルのコピーやメタデータの更新に成功しているなであれば)
                    // Sync オプションが付与されている場合、不要なサブディレクトリとファイルを削除する

                    if (this.Options.Flags.Bit(DirSuperBackupFlags.BackupSync))
                    {
                        try
                        {
                            // 両方のディレクトリを再列挙いたします
                            var srcDirEnum2  = (await Fs.EnumDirectoryAsync(srcDir, false, EnumDirectoryFlags.NoGetPhysicalSize, cancel)).OrderBy(x => x.Name, StrComparer.IgnoreCaseComparer).ToArray();
                            var destDirEnum2 = (await Fs.EnumDirectoryAsync(destDir, false, EnumDirectoryFlags.NoGetPhysicalSize, cancel)).OrderBy(x => x.Name, StrComparer.IgnoreCaseComparer).ToArray();

                            // 余分なファイルを削除いたします
                            var extraFiles = destDirEnum2.Where(x => x.IsFile && x.IsSymbolicLink == false)
                                             .Where(x => x.Name._StartWithi(DirSuperBackup.PrefixMetadata) == false && x.Name._EndsWithi(DirSuperBackup.SuffixMetadata) == false)
                                             .Where(x => srcDirEnum2.Where(y => y.IsFile && y.Name._IsSameiTrim(x.Name)).Any() == false)
                                             .Where(x => srcDirEnum2.Where(y => y.IsFile && (y.Name + Consts.Extensions.CompressedXtsAes256)._IsSameiTrim(x.Name)).Any() == false);

                            foreach (var extraFile in extraFiles)
                            {
                                string fullPath = Fs.PathParser.Combine(destDir, extraFile.Name);

                                await WriteLogAsync(DirSuperBackupLogType.Info, Str.CombineStringArrayForCsv("DirSyncDeleteFile", fullPath));

                                try
                                {
                                    await Fs.DeleteFileAsync(fullPath, FileFlags.BackupMode | FileFlags.ForceClearReadOnlyOrHiddenBitsOnNeed, cancel);

                                    Stat.SyncDelete_NumFiles++;
                                }
                                catch (Exception ex)
                                {
                                    Stat.Error_NumDeleteFiles++;
                                    await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("DirSyncDeleteFileError", fullPath, ex.Message));
                                }
                            }

                            // 余分なサブディレクトリを削除いたします
                            var extraSubDirs = destDirEnum2.Where(x => x.IsDirectory && x.IsCurrentOrParentDirectory == false && x.IsSymbolicLink == false)
                                               .Where(x => srcDirEnum2.Where(y => y.IsDirectory && y.IsCurrentOrParentDirectory == false && y.Name._IsSameiTrim(x.Name)).Any() == false);

                            foreach (var extraSubDir in extraSubDirs)
                            {
                                string fullPath = Fs.PathParser.Combine(destDir, extraSubDir.Name);

                                await WriteLogAsync(DirSuperBackupLogType.Info, Str.CombineStringArrayForCsv("DirSyncDeleteSubDir", fullPath));

                                try
                                {
                                    await Fs.DeleteDirectoryAsync(fullPath, true, cancel);

                                    Stat.SyncDelete_NumDirs++;
                                }
                                catch (Exception ex)
                                {
                                    Stat.Error_NumDeleteDirs++;
                                    await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("DirSyncDeleteSubDirError", fullPath, ex.Message));
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            // 何らかのディレクトリ単位のエラーで catch されていないものが発生
                            Stat.Error_Dir++;

                            // ディレクトリ単位のエラー発生
                            await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("DirSyncEnumError", srcDir, destDir, ex.Message));
                        }
                    }
                }
            }
        }


        // 再度 宛先ディレクトリの日付情報のみ属性書き込みする (Linux の場合、中のファイルを更新するとディレクトリの日時が変ってしまうため)
        try
        {
            if (srcDirMetadata != null)
            {
                await Fs.SetFileMetadataAsync(destDir, srcDirMetadata.Clone(FileMetadataCopyMode.TimeAll), cancel);
            }
        }
        catch
        {
            // 属性書き込みは失敗してもよい
        }
    }
    // 1 つのディレクトリを復元する
    public async Task DoSingleDirRestoreAsync(string srcDir, string destDir, CancellationToken cancel = default, string?ignoreDirNames = null)
    {
        DateTimeOffset now = DateTimeOffset.Now;

        FileSystemEntity[]? srcDirEnum = null;

        string[] ignoreDirNamesList = ignoreDirNames._NonNull()._Split(StringSplitOptions.RemoveEmptyEntries, ",", ";");

        try
        {
            if (srcDir._IsSamei(destDir))
            {
                throw new CoresException($"srcDir == destDir. Directory path: '{srcDir}'");
            }

            // 元ディレクトリが存在していることを確認する
            if (await Fs.IsDirectoryExistsAsync(srcDir, cancel) == false)
            {
                throw new CoresException($"The directory '{srcDir}' not found.");
            }

            // 元ディレクトリを列挙する
            srcDirEnum = (await Fs.EnumDirectoryAsync(srcDir, false, EnumDirectoryFlags.NoGetPhysicalSize, cancel)).OrderBy(x => x.Name, StrComparer.IgnoreCaseComparer).ToArray();

            // 元ディレクトリに存在するメタデータファイルのうち最新のファイルを取得する
            // なお、メタデータファイルのパースがエラーになったら、必ずエラーを発生し中断する
            DirSuperBackupMetadata?dirMetaData = await GetLatestMetaDataFileNameAsync(srcDir, srcDirEnum, cancel, throwJsonParseError : true) !;

            if (dirMetaData == null)
            {
                throw new CoresException($"Metadata not found on the directory '{srcDir}'.");
            }

            // 先ディレクトリがまだ存在していない場合は作成をする
            if (await Fs.IsDirectoryExistsAsync(destDir, cancel) == false)
            {
                FileFlags newDirFlags = FileFlags.None;

                // ディレクトリの圧縮フラグを適切に設定する
                if (dirMetaData.DirMetadata.SpecialOperationFlags.Bit(FileSpecialOperationFlags.SetCompressionFlag) || (dirMetaData.DirMetadata.Attributes?.Bit(FileAttributes.Compressed) ?? false))
                {
                    newDirFlags |= FileFlags.OnCreateSetCompressionFlag;
                }
                else
                {
                    newDirFlags |= FileFlags.OnCreateRemoveCompressionFlag;
                }

                try
                {
                    await Fs.CreateDirectoryAsync(destDir, newDirFlags, cancel);
                }
                catch
                {
                    // ヘンな圧縮フラグの設定に失敗した場合もう一度作成試行する
                    try
                    {
                        await Fs.CreateDirectoryAsync(destDir, FileFlags.None, cancel);
                    }
                    catch
                    {
                        // ディレクトリ作成コマンドでなぜかエラーになっても、結果としてディレクトリが作成されればそれでよい
                        if (await Fs.IsDirectoryExistsAsync(destDir, cancel) == false)
                        {
                            throw;
                        }

                        // やはりディレクトリの作成に失敗したらここでエラーを発生させる
                    }
                }
            }

            // ディレクトリの属性を設定する
            try
            {
                var newDirMetadata = dirMetaData.DirMetadata;

                if (Options.Flags.Bit(DirSuperBackupFlags.RestoreNoAcl))
                {
                    newDirMetadata.Security = null;
                }

                await Fs.SetDirectoryMetadataAsync(destDir, newDirMetadata, cancel);
            }
            catch (Exception ex)
            {
                // ディレクトリの属性の設定に失敗したが、軽微なエラーなのでエラーを出して続行する
                await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("DirAttributeSetError", srcDir, destDir, ex.Message));

                Stat.Error_Dir++;
            }

            // 元ディレクトリに存在するはずのファイル (メタデータに書いてある) を 1 つずつ復元する
            RefInt concurrentNum = new RefInt();

            AsyncLock SafeLock = new AsyncLock();

            await TaskUtil.ForEachAsync(Options.NumThreads, dirMetaData.FileList, async (srcFile, taskIndex, cancel) =>
            {
                await Task.Yield();

                string srcFilePath           = Fs.PathParser.Combine(srcDir, srcFile.FileName);
                string destFilePath          = Fs.PathParser.Combine(destDir, srcFile.FileName);
                FileMetadata?srcFileMetadata = null;

                concurrentNum.Increment();

                try
                {
                    bool isEncrypted       = false;
                    string encryptPassword = "";

                    if (srcFile.EncrypedFileName._IsNullOrZeroLen() == false)
                    {
                        srcFilePath = Fs.PathParser.Combine(srcDir, srcFile.EncrypedFileName);

                        // 暗号化ファイルである
                        if (Options.EncryptPassword._IsNullOrZeroLen())
                        {
                            // パスワードが指定されていない
                            throw new CoresException($"The file '{srcFilePath}' is encrypted, but no password is specified.");
                        }

                        isEncrypted     = true;
                        encryptPassword = this.Options.EncryptPassword;
                    }

                    srcFileMetadata = srcFile.MetaData;

                    // このファイルと同一の先ファイル名がすでに宛先ディレクトリに物理的に存在するかどうか確認する
                    bool exists = await Fs.IsFileExistsAsync(destFilePath, cancel);

                    bool restoreThisFile = false;

                    if (exists)
                    {
                        // すでに宛先ディレクトリに存在する物理的なファイルのメタデータを取得する
                        FileMetadata destExistsMetadata = await Fs.GetFileMetadataAsync(destFilePath, cancel: cancel);

                        if (Options.Flags.Bit(DirSuperBackupFlags.RestoreOnlyNewer) == false)
                        {
                            // 古いファイルも復元する
                            if (Options.Flags.Bit(DirSuperBackupFlags.RestoreDoNotSkipExactSame))
                            {
                                // 必ず上書きする
                                restoreThisFile = true;
                            }
                            else
                            {
                                // ファイルサイズを比較する
                                if (destExistsMetadata.Size != srcFileMetadata.Size)
                                {
                                    // ファイルサイズが異なる
                                    restoreThisFile = true;
                                }

                                // 日付を比較する
                                if (srcFileMetadata !.LastWriteTime !.Value.Ticks != destExistsMetadata.LastWriteTime !.Value.Ticks)
                                {
                                    // 最終更新日時が異なる
                                    restoreThisFile = true;
                                }

                                if (restoreThisFile == false)
                                {
                                    // 新旧両方のファイルが存在する場合で、ファイルサイズも日付も同じであれば、復元先ファイル内容がバックアップファイルと同一かチェックし、同一の場合はコピーをスキップする
                                    ResultOrError <int> sameRet;

                                    if (isEncrypted == false)
                                    {
                                        sameRet = await FileUtil.CompareFileHashAsync(new FilePath(srcFilePath, Fs, flags: FileFlags.BackupMode), new FilePath(destFilePath, Fs, flags: FileFlags.BackupMode), cancel: cancel);
                                    }
                                    else
                                    {
                                        sameRet = await FileUtil.CompareEncryptedFileHashAsync(encryptPassword, true, new FilePath(destFilePath, Fs, flags: FileFlags.BackupMode), new FilePath(srcFilePath, Fs, flags: FileFlags.BackupMode), cancel: cancel);
                                    }

                                    if (sameRet.IsOk == false || sameRet.Value != 0)
                                    {
                                        restoreThisFile = true;
                                    }
                                }
                            }
                        }
                        else
                        {
                            // バックアップのほうが新しい場合のみ復元するモード
                            // 日付を比較する
                            if (srcFileMetadata !.LastWriteTime !.Value.Ticks > destExistsMetadata.LastWriteTime !.Value.Ticks)
                            {
                                // 最終更新日時がバックアップのほうが新しい
                                restoreThisFile = true;
                            }
                        }
                    }
                    else
                    {
                        restoreThisFile = true;
                    }

                    if (restoreThisFile)
                    {
                        // すべての判断に合格したら、このファイルの復元を実施する
                        if (exists)
                        {
                            if (Options.Flags.Bit(DirSuperBackupFlags.RestoreMakeBackup))
                            {
                                // 復元先に同名のファイルがすでに存在する場合は、
                                // .original.xxxx.0123.original のような形式でまだ存在しない連番に古いファイル名をリネームする
                                using (await SafeLock.LockWithAwait(cancel))
                                {
                                    string newOldFileName;

                                    // 連番でかつ存在していないファイル名を決定する
                                    for (int i = 0; ; i++)
                                    {
                                        string newOldFileNameCandidate = $".original.{srcFile.FileName}.{i:D4}.original";

                                        if (await Fs.IsFileExistsAsync(Fs.PathParser.Combine(destDir, newOldFileNameCandidate), cancel) == false)
                                        {
                                            newOldFileName = newOldFileNameCandidate;
                                            break;
                                        }
                                    }

                                    // 変更されたファイル名を .old ファイルにリネーム実行する
                                    string newOldFilePath = Fs.PathParser.Combine(destDir, newOldFileName);
                                    await WriteLogAsync(DirSuperBackupLogType.Info, Str.CombineStringArrayForCsv("FileRename", destFilePath, newOldFilePath));
                                    await Fs.MoveFileAsync(destFilePath, newOldFilePath, cancel);

                                    // 隠しファイルにする
                                    try
                                    {
                                        var meta = await Fs.GetFileMetadataAsync(newOldFilePath, cancel: cancel);
                                        if (meta.Attributes != null)
                                        {
                                            FileMetadata meta2 = new FileMetadata(attributes: meta.Attributes?.BitAdd(FileAttributes.Hidden));

                                            await Fs.SetFileMetadataAsync(newOldFilePath, meta2, cancel);
                                        }
                                    }
                                    catch { }
                                }
                            }
                        }

                        // 復元メイン
                        await WriteLogAsync(DirSuperBackupLogType.Info, Str.CombineStringArrayForCsv("FileCopy", srcFilePath, destFilePath));

                        FileFlags flags = FileFlags.BackupMode | FileFlags.Async;

                        if (this.Options.Flags.Bit(DirSuperBackupFlags.RestoreNoVerify) == false)
                        {
                            flags |= FileFlags.CopyFile_Verify;
                        }

                        // ファイルをコピーする
                        await Fs.CopyFileAsync(srcFilePath, destFilePath,
                                               new CopyFileParams(flags: flags,
                                                                  metadataCopier: new FileMetadataCopier(FileMetadataCopyMode.TimeAll),
                                                                  encryptOption: isEncrypted ? EncryptOption.Decrypt | EncryptOption.Compress : EncryptOption.None,
                                                                  encryptPassword: encryptPassword),
                                               cancel: cancel,
                                               newFileMeatadata: Options.Flags.Bit(DirSuperBackupFlags.RestoreNoAcl) ? null : srcFileMetadata);

                        Stat.Copy_NumFiles++;
                        Stat.Copy_TotalSize += srcFile.MetaData.Size;

                        // メタデータを再度復元
                        try
                        {
                            var meta = Options.Flags.Bit(DirSuperBackupFlags.RestoreNoAcl) ? srcFileMetadata.Clone(FileMetadataCopyMode.TimeAll | FileMetadataCopyMode.Attributes | FileMetadataCopyMode.ReplicateArchiveBit | FileMetadataCopyMode.AlternateStream | FileMetadataCopyMode.Author) : srcFileMetadata;

                            await Fs.SetFileMetadataAsync(destFilePath, meta, cancel);
                        }
                        catch (Exception ex)
                        {
                            FileMetadata?existingFileMetadata = null;
                            try
                            {
                                existingFileMetadata = await Fs.GetFileMetadataAsync(destFilePath, cancel: cancel);
                            }
                            catch { }
                            if ((existingFileMetadata?.Attributes?.Bit(FileAttributes.ReadOnly) ?? true) == false)
                            {
                                // メタデータの属性の設定に失敗したが、軽微なエラーなのでエラーを出して続行する
                                // (宛先ファイルが ReadOnly の場合は、この操作はエラーとなる可能性が高い。このような場合は、予期されている動作なので、エラーは表示しない)
                                await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("FileAttributeSetError", srcFilePath, destFilePath, ex.Message));
                                Stat.Error_NumFiles++;
                            }
                        }
                    }
                    else
                    {
                        Stat.Skip_NumFiles++;
                        Stat.Skip_TotalSize += srcFile.MetaData.Size;
                    }
                }
                catch (Exception ex)
                {
                    Stat.Error_NumFiles++;
                    Stat.Error_TotalSize += srcFileMetadata?.Size ?? 0;

                    // ファイル単位のエラー発生
                    await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("FileError", srcFilePath, destFilePath, ex.Message));
                }
                finally
                {
                    concurrentNum.Decrement();
                }
            });

            // このディレクトリの全ファイルの復元が終わったら、ディレクトリのタイムスタンプ情報を再書き込みする
            // (中のファイルが新しくなったことが原因で、ディレクトリの更新日時が新しくなってしまう可能性があるためである)
            try
            {
                await Fs.SetFileMetadataAsync(destDir, dirMetaData.DirMetadata.Clone(FileMetadataCopyMode.TimeAll), cancel);
            }
            catch
            {
                // 属性書き込みは失敗してもよい
            }

            try
            {
                // ソースディレクトリの列挙に成功した場合は、サブディレクトリに対して再帰的に実行する
                foreach (var subDir in dirMetaData.DirList)
                {
                    // 無視リストのいずれにも合致しない場合のみ
                    if (ignoreDirNamesList.Where(x => x._IsSamei(subDir)).Any() == false)
                    {
                        await DoSingleDirRestoreAsync(Fs.PathParser.Combine(srcDir, subDir), Fs.PathParser.Combine(destDir, subDir), cancel, ignoreDirNames);
                    }
                }
            }
            catch (Exception ex)
            {
                // 何らかのディレクトリ単位のエラーで catch されていないものが発生
                Stat.Error_Dir++;

                // ディレクトリ単位のエラー発生
                await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("DirError1", srcDir, destDir, ex.Message));
            }

            // 再度 宛先ディレクトリの日付情報のみ属性書き込みする (Linux の場合、中のファイルを更新するとディレクトリの日時が変ってしまうため)
            try
            {
                if (dirMetaData != null)
                {
                    await Fs.SetFileMetadataAsync(destDir, dirMetaData.DirMetadata.Clone(FileMetadataCopyMode.TimeAll), cancel);
                }
            }
            catch
            {
                // 属性書き込みは失敗してもよい
            }
        }
        catch (Exception ex)
        {
            Stat.Error_Dir++;

            // ディレクトリ単位のエラー発生
            await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("DirError2", srcDir, destDir, ex.Message));
        }
    }
    protected override async Task GetValueAsync(SortedDictionary <string, string> ret, RefInt nextPollingInterval, CancellationToken cancel = default)
    {
        var result = await EasyExec.ExecAsync(Consts.LinuxCommands.Df, "-a -B1");

        string[] lines = result.OutputStr._GetLines();

        string[] ignores = "/dev /run /sys /snap /tmp /proc"._Split(StringSplitOptions.RemoveEmptyEntries, " ");

        foreach (string line in lines)
        {
            string[] tokens = line._Split(StringSplitOptions.RemoveEmptyEntries, ' ', '\t');

            if (tokens.Length >= 6)
            {
                string totalStr     = tokens[1];
                string availableStr = tokens[3];
                string path         = tokens[5];

                if (totalStr != "-" && availableStr != "-")
                {
                    if (path.StartsWith("/") && ignores.Where(x => path.StartsWith(x, StringComparison.OrdinalIgnoreCase)).Any() == false)
                    {
                        long total     = totalStr._ToLong();
                        long available = availableStr._ToLong();

                        if (total > 0 && available >= 0)
                        {
                            available = Math.Min(available, total);
                            ret.TryAdd($"available - {path}", NormalizeDoubleValue(((double)available * 100.0 / (double)total).ToString("F3")));
                        }
                    }
                }
            }
        }
    }
	public void VisibilityStaticSetup (VectorLine line, out RefInt objectNum) {
		if (!visibilityRunning) {
			isVisible = new List<bool>();
			vectorLines = new List<VectorLine>();
			objectNumbers = new List<RefInt>();
			visibilityRunning = true;
		}
		isVisible.Add(true);
		vectorLines.Add(line);
		objectNum = new RefInt(arrayCount++); 
		objectNumbers.Add(objectNum);
	}
    protected override async Task GetValueAsync(SortedDictionary <string, string> ret, RefInt nextPollingInterval, CancellationToken cancel = default)
    {
        SnmpWorkSettings settings = Host.Settings;

        if (settings.PingTargets._IsSamei("none") || settings.PingTargets._IsSamei("null"))
        {
            return;
        }

        string hopsStr = "Hops";

        if (settings.HopsToTTL)
        {
            hopsStr = "TTL";
        }

        string[] pingTargets = settings.PingTargets._Split(StringSplitOptions.RemoveEmptyEntries, ",");

        numPerform++;

        foreach (string pingTarget in pingTargets)
        {
            cancel.ThrowIfCancellationRequested();

            ParseTargetString(pingTarget, out string hostname, out string alias);

            bool ok = false;

            try
            {
                IPAddress ipAddress = await LocalNet.GetIpAsync(hostname, cancel : cancel);

                if (FirstPing.IsFirstCall())
                {
                    // JIT 対策
                    try
                    {
                        await LocalNet.SendPingAsync(ipAddress, pingCancel : cancel);
                    }
                    catch { }
                }

                int numTry = 3;

                if (numPerform >= 2)
                {
                    // SpeedTest が動作中の場合は SpeedTest が完了するまで待機する
                    await TaskUtil.AwaitWithPollAsync(Timeout.Infinite, 10, () => !SpeedTestClient.IsInProgress, cancel);

                    // 試行回数を指定する
                    numTry = Math.Min(Math.Max(settings.PingNumTry, 1), 100);
                }

                SendPingReply reply = await LocalNet.SendPingAndGetBestResultAsync(ipAddress, pingCancel : cancel, numTry : numTry);

                if (reply.Ok)
                {
                    double rtt = reply.RttDouble;

                    rtt = Math.Min(rtt, 2.0);

                    int ttl = reply.Ttl;

                    bool ttl_ok = false;

                    if (ttl == 0)
                    {
                        // Use ping command to get TTL
                        try
                        {
                            var result = await EasyExec.ExecAsync(ipAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6?Consts.LinuxCommands.Ping6 : Consts.LinuxCommands.Ping,
                                                                  $"-W 1 -c 1 {ipAddress.ToString()}",
                                                                  cancel : cancel,
                                                                  throwOnErrorExitCode : false);

                            string[] lines = result.OutputStr._GetLines(true);

                            foreach (string line in lines)
                            {
                                OneLineParams param  = new OneLineParams(line, ' ', false);
                                string        ttlStr = param._GetStrFirst("ttl");
                                if (ttlStr._IsFilled())
                                {
                                    ttl    = ttlStr._ToInt();
                                    ttl_ok = true;
                                    break;
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            ex._Debug();
                        }
                    }
                    else
                    {
                        ttl_ok = true;
                    }

                    ret.TryAdd($"Time - {alias}", (rtt * 1000.0).ToString("F3"));


                    if (ttl > 128)
                    {
                        ttl -= 128;
                    }
                    else if (ttl > 64)
                    {
                        ttl -= 64;
                    }

                    int hops = 64 - ttl;

                    if (ttl_ok == false)
                    {
                        hops = 0;
                    }

                    hops._SetMax(0);
                    hops._SetMin(64);

                    ret.TryAdd($"{hopsStr} - {alias}", hops.ToString());

                    ok = true;
                }
            }
            catch (Exception ex)
            {
                ex._Debug();
            }

            if (ok == false)
            {
                ret.TryAdd($"Time - {alias}", "");
                ret.TryAdd($"{hopsStr} - {alias}", "0");
            }
        }
    }
	public void VisibilitySetup (Transform thisTransform, VectorLine line, out RefInt objectNum) {
		if (!visibilityRunning2) {
			isVisible2 = new List<bool>();
			vectorLines2 = new List<VectorLine>();
			objectNumbers2 = new List<RefInt>();
			transforms = new List<Transform>();
			visibilityRunning2 = true;
		}
		isVisible2.Add(true);
		vectorLines2.Add(line);
		transforms.Add(thisTransform);
		objectNum = new RefInt(arrayCount2++); 
		objectNumbers2.Add(objectNum);
	}
    protected override async Task GetValueAsync(SortedDictionary <string, string> ret, RefInt nextPollingInterval, CancellationToken cancel = default)
    {
        SnmpWorkSettings settings = Host.Settings;

        if (settings.SpeedTargets._IsSamei("none") || settings.SpeedTargets._IsSamei("null"))
        {
            return;
        }

        string[] speedTargets = settings.SpeedTargets._Split(StringSplitOptions.RemoveEmptyEntries, ",");

        count++;


        foreach (string target in speedTargets)
        {
            ParseTargetString(target, out string hostnameAndPort, out string alias);

            cancel.ThrowIfCancellationRequested();

            string[] tokens = hostnameAndPort._Split(StringSplitOptions.RemoveEmptyEntries, '|');
            string   host;
            int      port = 9821;
            host = tokens[0];
            if (tokens.Length >= 2)
            {
                port = tokens[1]._ToInt();
            }

            //long downloadBps_1 = 0;
            //long uploadBps_1 = 0;
            long downloadBps_32 = 0;
            long uploadBps_32   = 0;

            int intervalBetween = settings.SpeedIntervalsSec * 1000;
            if (count <= 1)
            {
                intervalBetween = 0;
            }

            int numTry = settings.SpeedTryCount;
            if (count <= 1)
            {
                numTry = 1;
            }

            int span = settings.SpeedSpanSec * 1000;
            if (count <= 1)
            {
                span = 2000;
            }

            try
            {
                IPAddress ipAddress = await LocalNet.GetIpAsync(host, cancel : cancel);

                try
                {
                    var downloadResult_32 = await SpeedTestClient.RunSpeedTestWithMultiTryAsync(LocalNet, ipAddress, port, 32, span, SpeedTestModeFlag.Download, numTry, intervalBetween, cancel);

                    downloadBps_32 = downloadResult_32.Select(x => x.BpsDownload).OrderByDescending(x => x).FirstOrDefault();
                }
                catch (Exception ex)
                {
                    ex._Debug();
                }
                try
                {
                    var uploadResult_32 = await SpeedTestClient.RunSpeedTestWithMultiTryAsync(LocalNet, ipAddress, port, 32, span, SpeedTestModeFlag.Upload, numTry, intervalBetween, cancel);

                    uploadBps_32 = uploadResult_32.Select(x => x.BpsUpload).OrderByDescending(x => x).FirstOrDefault();
                }
                catch (Exception ex)
                {
                    ex._Debug();
                }


                //try
                //{
                //    var downloadResult_1 = await SpeedTestClient.RunSpeedTestWithMultiTryAsync(LocalNet, ipAddress, port, 1, span, SpeedTestModeFlag.Download, numTry, intervalBetween, cancel);

                //    downloadBps_1 = downloadResult_1.Select(x => x.BpsDownload).OrderByDescending(x => x).FirstOrDefault();
                //}
                //catch (Exception ex)
                //{
                //    ex._Debug();
                //}


                //try
                //{
                //    var uploadResult_1 = await SpeedTestClient.RunSpeedTestWithMultiTryAsync(LocalNet, ipAddress, port, 1, span, SpeedTestModeFlag.Upload, numTry, intervalBetween, cancel);

                //    uploadBps_1 = uploadResult_1.Select(x => x.BpsUpload).OrderByDescending(x => x).FirstOrDefault();
                //}
                //catch (Exception ex)
                //{
                //    ex._Debug();
                //}
            }
            catch (Exception ex)
            {
                ex._Debug();
            }

            ret.TryAdd($"{alias} - RX (Mbps)", ((double)downloadBps_32 / 1000.0 / 1000.0).ToString("F3"));
            ret.TryAdd($"{alias} - TX (Mbps)", ((double)uploadBps_32 / 1000.0 / 1000.0).ToString("F3"));

            //ret.TryAdd($"{alias} - 01_RX (Mbps)", ((double)downloadBps_1 / 1000.0 / 1000.0).ToString("F3"));
            //ret.TryAdd($"{alias} - 01_TX (Mbps)", ((double)uploadBps_1 / 1000.0 / 1000.0).ToString("F3"));
        }
    }
    protected override async Task GetValueAsync(SortedDictionary <string, string> ret, RefInt nextPollingInterval, CancellationToken cancel = default)
    {
        if (this.Web == null)
        {
            nextPollingInterval.Set(100);
            return;
        }

        var webret = await this.Web.SimpleQueryAsync(WebMethods.GET, this.Url, cancel);

        string body = webret.Data._GetString_UTF8();

        string[] lines = body._GetLines(true);

        foreach (string line in lines)
        {
            string line2 = line.Trim();
            if (line2.StartsWith("#") == false)
            {
                if (line2._GetKeyAndValue(out string key, out string value, ":"))
                {
                    key   = key.Trim();
                    value = value.Trim();

                    if (key._IsFilled() && value._IsFilled())
                    {
                        ret.TryAdd(key, value);
                    }
                }
            }
        }

        DoNothing();
    }
Beispiel #37
0
 public static void CheckDistanceSetup(Transform thisTransform, VectorLine line, Color color, RefInt objectNum)
 {
     VectorLine.LineManagerEnable();
     if (vectorLines3 == null)
     {
         vectorLines3   = new List <VectorLine>();
         transforms3    = new List <Transform>();
         oldDistances   = new List <int>();
         colors         = new List <Color>();
         objectNumbers3 = new List <RefInt>();
         VectorLine.LineManagerCheckDistance();
     }
     transforms3.Add(thisTransform);
     vectorLines3.Add(line);
     oldDistances.Add(-1);
     colors.Add(color);
     objectNum.i = _arrayCount3++;
     objectNumbers3.Add(objectNum);
 }
Beispiel #38
0
 public static void VisibilityStaticSetup(VectorLine line, out RefInt objectNum)
 {
     if (vectorLines == null) {
         vectorLines = new List<VectorLine>();
         objectNumbers = new List<RefInt>();
     }
     vectorLines.Add(line);
     objectNum = new RefInt(_arrayCount++);
     objectNumbers.Add(objectNum);
     VectorLine.LineManagerEnable();
 }
Beispiel #39
0
 protected abstract Task GetValueAsync(SortedDictionary <string, string> ret, RefInt nextPollingInterval, CancellationToken cancel = default);
    protected override async Task GetValueAsync(SortedDictionary <string, string> ret, RefInt nextPollingInterval, CancellationToken cancel = default)
    {
        // sys/class/thermal/ から温度取得
        foreach (var thermalFile in this.ThermalFiles)
        {
            string value = (await Lfs.ReadStringFromFileAsync(thermalFile.Value))._GetFirstFilledLineFromLines();

            double d = ((double)value._ToInt()) / 1000.0;

            ret.TryAdd($"{thermalFile.Key}", NormalizeDoubleValue(d.ToString("F3")));
        }

        if (IsSensorsCommandOk)
        {
            try
            {
                // Sensors コマンドで温度取得
                var result = await EasyExec.ExecAsync(Consts.LinuxCommands.Sensors, "-u", cancel : cancel);

                string[] lines = result.OutputStr._GetLines(true);

                string groupName = "";
                string fieldName = "";

                foreach (string line2 in lines)
                {
                    string line = line2.TrimEnd();

                    if (line.StartsWith(" ") == false && line._InStr(":") == false)
                    {
                        // グループ名
                        groupName = line.Trim();
                    }
                    else if (line.StartsWith(" ") == false && line.EndsWith(":"))
                    {
                        // 値名
                        fieldName = line.Substring(0, line.Length - 1);
                    }
                    else if (line.StartsWith(" ") && line._GetKeyAndValue(out string key, out string value, ":"))
                    {
                        // 値サブ名 : 値
                        key   = key.Trim();
                        value = value.Trim();

                        if (key.EndsWith("_input", StringComparison.OrdinalIgnoreCase))
                        {
                            ret.TryAdd($"{groupName}/{fieldName}", NormalizeDoubleValue(value));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                ex._Debug();
            }
        }
    }
    protected override async Task GetValueAsync(SortedDictionary <string, string> ret, RefInt nextPollingInterval, CancellationToken cancel = default)
    {
        await Task.Yield();

        var data = Sensor.CurrentData;

        foreach (var item in data.ValueList)
        {
            if (item.Value._IsFilled())
            {
                string key = "value";

                if (item.Key._IsFilled())
                {
                    key = item.Key.Trim();
                }

                ret.TryAdd(key, item.Value);
            }
        }
    }