Projekt

Obecné

Profil

« Předchozí | Další » 

Revize 68087f99

Přidáno uživatelem Pultak před více než 2 roky(ů)

re #9712 restructuring of info fetcher

Zobrazit rozdíly:

ld_client/LDClient/detection/AInfoFetcher.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Threading.Tasks;
6
using LDClient.utils;
7

  
8
namespace LDClient.detection; 
9

  
10
/// <summary>
11
/// This abstract class implements the common functions of the IInfoFetcher interface
12
/// which defines the functionality of an info fetcher.
13
/// </summary>
14
public abstract class AInfoFetcher : IInfoFetcher {
15

  
16
    /// <summary>
17
    /// Default value of a serial number (undefined).
18
    /// </summary>
19
    private const string UndefinedSerialNumber = "number";
20

  
21
    /// <summary>
22
    /// Returns the head serial number of the debugger.
23
    /// </summary>
24
    public string HeadSerialNumber { get; set; } = UndefinedSerialNumber;
25

  
26
    /// <summary>
27
    /// Returns the body serial number of the debugger.
28
    /// </summary>
29
    public string BodySerialNumber { get; set; } = UndefinedSerialNumber;
30

  
31
    /// <summary>
32
    /// Instance of FileUtils which encapsulates common functionality
33
    /// when it comes to dealing with files (limited by the needs of this application).
34
    /// </summary>
35
    public IFileUtils FileUtils;
36

  
37
    /// <summary>
38
    /// Maximum number of attempts to locate and parse the .txt file.
39
    /// </summary>
40
    protected readonly uint _maxAttempts;
41

  
42
    /// <summary>
43
    /// Period (how often) the application tries to locate and parse the .txt file.
44
    /// </summary>
45
    protected readonly uint _waitPeriodMs;
46

  
47
    /// <summary>
48
    /// Path to the .txt file which is generated from the debugger.
49
    /// </summary>
50
    protected readonly string _infoFilePath;
51

  
52
    /// <summary>
53
    /// Abstract constructor of this class 
54
    /// </summary>
55
    /// <param name="maxAttempts">Maximum number of attempts to locate and parse the .txt file</param>
56
    /// <param name="waitPeriodMs">Period (how often) the application tries to locate and parse the .txt file</param>
57
    /// <param name="infoFilePath">Path to the .txt file which is generated from the debugger</param>
58

  
59
    protected AInfoFetcher(uint maxAttempts, uint waitPeriodMs, string infoFilePath) {
60
        this.FileUtils = new FileUtils();
61
        this._maxAttempts = maxAttempts;
62
        this._waitPeriodMs = waitPeriodMs;
63
        this._infoFilePath = infoFilePath;
64
    }
65

  
66
    /// <summary>
67
    /// Abstract definition of the data fetching function
68
    /// Function should send the commands to the debugger.
69
    /// </summary>
70
    /// <returns>true on success</returns>
71
    protected abstract bool FetchData();
72

  
73
    /// <summary>
74
    /// Fetches data from the debugger. It sends the commands defined
75
    /// in the appsettings.json file to the debugger and tries to
76
    /// parse the .txt (contains the serial numbers).
77
    /// </summary>
78
    /// <returns>True, if data was fetched successfully. False otherwise.</returns>
79
    public async Task<bool> FetchDataAsync() {
80
        Program.DefaultLogger.Info("Fetching data from the debugger.");
81
        // Send the commands to the debugger.
82
        var success = FetchData();
83

  
84
        // Make sure that all commands were sent and executed successfully.
85
        if (!success) {
86
            Program.DefaultLogger.Error("Failed to fetch data from the debugger.");
87
            return false;
88
        }
89
        // Periodically try to parse the .txt file. 
90
        for (var i = 0; i < _maxAttempts; i++) {
91
            Program.DefaultLogger.Info($"{i}. attempt to parse the info file.");
92
            // Try to parse .txt file.
93
            if (RetrieveDebuggerInfo(_infoFilePath)) {
94
                Program.DefaultLogger.Info($"Info file has been parsed successfully.");
95
                return true;
96
            }
97
            // Wait for a specified number of milliseconds.
98
            await Task.Delay((int)_waitPeriodMs);
99
        }
100
        Program.DefaultLogger.Error("Failed to parse the into file. It may have not been created.");
101
        return false;
102
    }
103

  
104
    /// <summary>
105
    /// Tries to retrieve information from the debugger.
106
    /// </summary>
107
    /// <param name="filePath">path to the .txt file that contains all information</param>
108
    /// <returns>True if the information was retrieved successfully. False, otherwise.</returns>
109

  
110
    protected bool RetrieveDebuggerInfo(string filePath) {
111
        try {
112
            // Read the content of the .txt file.
113
            var fileContent = FileUtils.ReadFileAllLines(filePath).Aggregate("", (current, line) => $"{current}{line}\n");
114

  
115
            // Parse it (try to find the serial numbers)
116
            var (headSerialNumber, bodySerialNumber) = DebuggerInfoParser.Parse(fileContent);
117

  
118
            // Store the serial numbers into class variables (properties)
119
            HeadSerialNumber = headSerialNumber;
120
            BodySerialNumber = bodySerialNumber;
121

  
122
            // Finally, delete the file.
123
            //File.Delete(filePath);
124
        } catch (Exception exception) {
125
            Program.DefaultLogger.Error($"Failed to retrieve debugger info. File {filePath} may not exist or it does not have the right format. {exception.Message}");
126
            return false;
127
        }
128
        return true;
129
    }
130
}
ld_client/LDClient/detection/IT32Utils.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Threading.Tasks;
6

  
7
namespace LDClient.detection {
8
    public interface IT32Utils {
9

  
10
        public bool InitConnection();
11
        public bool ExecuteCommands();
12
        public bool CloseConnection();
13

  
14
    }
15
}
ld_client/LDClient/detection/InfoFetcher.cs
1
using System.Diagnostics;
2
using LDClient.utils;
3
using LDClient.utils.loggers;
4

  
5
namespace LDClient.detection {
6

  
7
    /// <summary>
8
    /// This class implements the IInfoFetcher interface
9
    /// which defines the functionality of an info fetcher.
10
    /// </summary>
11
    public class InfoFetcher : IInfoFetcher {
12
        
13
        /// <summary>
14
        /// Default value of a serial number (undefined).
15
        /// </summary>
16
        private const string UndefinedSerialNumber = "number";
17

  
18
        /// <summary>
19
        /// Path to the t32rem.exe file which is used to send commands to the debugger.
20
        /// </summary>
21
        private readonly string _f32RemExecutable;
22
        
23
        /// <summary>
24
        /// Arguments (commands) sent to the debugger in order to generate a .txt file
25
        /// containing all the desired information.
26
        /// </summary>
27
        private readonly string[] _f32RemArguments;
28
        
29
        /// <summary>
30
        /// Status code indicating a successful termination of t32rem.exe
31
        /// </summary>
32
        private readonly int _f32SuccessExitCode;
33
        
34
        /// <summary>
35
        /// Timeout used when waiting for the t32rem.exe to finish.
36
        /// </summary>
37
        private readonly int _f32WaitTimeoutMs;
38
        
39
        /// <summary>
40
        /// Maximum number of attempts to locate and parse the .txt file.
41
        /// </summary>
42
        private readonly uint _maxAttempts;
43
        
44
        /// <summary>
45
        /// Period (how often) the application tries to locate and parse the .txt file.
46
        /// </summary>
47
        private readonly uint _waitPeriodMs;
48
        
49
        /// <summary>
50
        /// Path to the .txt file which is generated from the debugger.
51
        /// </summary>
52
        private readonly string _infoFilePath;
53

  
54
        /// <summary>
55
        /// Instance of ProcessUtils which encapsulates common functionality
56
        /// when it comes to dealing with processes (limited by the needs of this application).
57
        /// </summary>
58
        public IProcessUtils ProcessUtils;
59
        
60
        /// <summary>
61
        /// Instance of FileUtils which encapsulates common functionality
62
        /// when it comes to dealing with files (limited by the needs of this application).
63
        /// </summary>
64
        public IFileUtils FileUtils;
65

  
66
        /// <summary>
67
        /// Returns the head serial number of the debugger.
68
        /// </summary>
69
        public string HeadSerialNumber { get; set; } = UndefinedSerialNumber;
70
        
71
        /// <summary>
72
        /// Returns the body serial number of the debugger.
73
        /// </summary>
74
        public string BodySerialNumber { get; set; } = UndefinedSerialNumber;
75
        
76
        /// <summary>
77
        /// Creates an instance of this class.
78
        /// </summary>
79
        /// <param name="maxAttempts">Maximum number of attempts to locate and parse the .txt file</param>
80
        /// <param name="waitPeriodMs">Period (how often) the application tries to locate and parse the .txt file</param>
81
        /// <param name="infoFilePath">Path to the .txt file which is generated from the debugger</param>
82
        /// <param name="f32RemExecutable">Path to the t32rem.exe file which is used to send commands to the debugger</param>
83
        /// <param name="f32RemArguments">Arguments (commands) sent to the debugger in order to generate a .txt file containing all the desired information.</param>
84
        /// <param name="f32SuccessExitCode">Status code indicating a successful termination of t32rem.exe</param>
85
        /// <param name="f32WaitTimeoutMs">Timeout used when waiting for the t32rem.exe to finish</param>
86
        public InfoFetcher(uint maxAttempts, uint waitPeriodMs, string infoFilePath, string f32RemExecutable,
87
            string[] f32RemArguments, int f32SuccessExitCode, int f32WaitTimeoutMs) {
88
            // Store the parameters into the class variables.
89
            _maxAttempts = maxAttempts;
90
            _waitPeriodMs = waitPeriodMs;
91
            _infoFilePath = infoFilePath;
92
            _f32RemExecutable = f32RemExecutable;
93
            _f32RemArguments = f32RemArguments;
94
            _f32SuccessExitCode = f32SuccessExitCode;
95
            _f32WaitTimeoutMs = f32WaitTimeoutMs;
96
            
97
            // Create an instance of ProcessUtils.
98
            ProcessUtils = new ProcessUtils();
99
            
100
            // Create an instance of FileUtils.
101
            FileUtils = new FileUtils();
102
        }
103

  
104
        /// <summary>
105
        /// Fetches data from the debugger. It sends the commands defined
106
        /// in the appsettings.json file to the debugger and tries to
107
        /// parse the .txt (contains the serial numbers).
108
        /// </summary>
109
        /// <returns>True, if data was fetched successfully. False otherwise.</returns>
110
        public async Task<bool> FetchDataAsync() {
111
            Program.DefaultLogger.Info("Fetching data from the debugger.");
112
            
113
            // Send the commands to the debugger.
114
            var success = SendRetrieveInfoCommands(_f32RemExecutable, _f32RemArguments, _f32SuccessExitCode, _f32WaitTimeoutMs);
115
            
116
            // Make sure that all commands were sent and executed successfully.
117
            if (!success) {
118
                Program.DefaultLogger.Error("Failed to fetch data from the debugger.");
119
                return false;
120
            }
121
            
122
            // Periodically try to parse the .txt file. 
123
            for (var i = 0; i < _maxAttempts; i++) {
124
                Program.DefaultLogger.Info($"{i}. attempt to parse the info file.");
125
                
126
                // Try to parse .txt file.
127
                if (RetrieveDebuggerInfo(_infoFilePath)) {
128
                    Program.DefaultLogger.Info($"Info file has been parsed successfully.");
129
                    return true;
130
                }
131
                // Wait for a specified number of milliseconds.
132
                await Task.Delay((int)_waitPeriodMs);
133
            }
134
            Program.DefaultLogger.Error("Failed to parse the into file. It may have not been created.");
135
            return false;
136
        }
137

  
138
        /// <summary>
139
        /// Tries to retrieve information from the debugger.
140
        /// </summary>
141
        /// <param name="filePath">path to the .txt file that contains all information</param>
142
        /// <returns>True if the information was retrieved successfully. False, otherwise.</returns>
143
        private bool RetrieveDebuggerInfo(string filePath) {
144
            try {
145
                // Read the content of the .txt file.
146
                var fileContent = FileUtils.ReadFileAllLines(filePath).Aggregate("", (current, line) => $"{current}{line}\n");
147
                
148
                // Parse it (try to find the serial numbers)
149
                var (headSerialNumber, bodySerialNumber) = DebuggerInfoParser.Parse(fileContent);
150
                
151
                // Store the serial numbers into class variables (properties)
152
                HeadSerialNumber = headSerialNumber;
153
                BodySerialNumber = bodySerialNumber;
154
                
155
                // Finally, delete the file.
156
                File.Delete(filePath);
157
            } catch (Exception exception) {
158
                Program.DefaultLogger.Error($"Failed to retrieve debugger info. File {filePath} may not exist or it does not have the right format. {exception.Message}");
159
                return false;
160
            }
161
            return true;
162
        }
163

  
164
        /// <summary>
165
        /// Sends commands to the debugger.
166
        /// </summary>
167
        /// <param name="executableFile">Path to the t32rem.exe file</param>
168
        /// <param name="arguments">Arguments sent to the debugger through t32rem.exe (one argument is one command)</param>
169
        /// <param name="desiredExitCode">Status code indicating successful termination of t32rem.exe</param>
170
        /// <param name="waitTimeoutMs">Timeout used when waiting for t32rem.exe to finish</param>
171
        /// <returns>True if all the commands were executed successfully. False, otherwise.</returns>
172
        private bool SendRetrieveInfoCommands(string executableFile, IReadOnlyList<string>? arguments, int desiredExitCode, int waitTimeoutMs) {
173
            if (arguments == null) {
174
                Program.DefaultLogger.Error($"Failed to run {executableFile} - no parameters were given");
175
                return false;
176
            }
177
            // Execute one all arguments (commands) one by one.
178
            foreach (var argument in arguments) {
179
                if (!ProcessUtils.ExecuteNewProcess(executableFile, argument, waitTimeoutMs, desiredExitCode)) {
180
                    return false;
181
                }
182
            }
183
            return true;
184
        }
185
    }
186
}

Také k dispozici: Unified diff