Skip to content

Commit c8a7d83

Browse files
author
Charles PIGNEROL
committed
Version 6.14.0. Process::finalize takes as an additional argument a delay granted to child processes to terminate without being killed. FileLock class allows locking a file against concurrent access. Partial rewrite of the ApplicationStats class + logUsage method logging version and OS.
1 parent 7d8c046 commit c8a7d83

File tree

3 files changed

+92
-197
lines changed

3 files changed

+92
-197
lines changed

src/TkUtil/ApplicationStats.cpp

Lines changed: 90 additions & 195 deletions
Original file line numberDiff line numberDiff line change
@@ -68,219 +68,114 @@ string ApplicationStats::getFileName (const string& appName, const string& logDi
6868

6969
void ApplicationStats::logUsage (const string& appName, const string& logDir)
7070
{
71-
// En vue de ne pas altérer le comportement de l'application tout est effectuée dans un processus fils => exit (0) en toutes circonstances.
72-
errno = 0;
73-
const pid_t pid = fork ( );
74-
if ((pid_t)-1 == pid)
75-
{
76-
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
77-
ConsoleOutput::cerr ( ) << "ApplicationStats::logUsage : échec de fork : " << strerror (errno) << co_endl;
78-
return;
79-
} // if ((pid_t)-1 == pid)
80-
if (0 != pid)
81-
{
82-
Process::killAtEnd (pid);
83-
return; // Parent
84-
}
85-
86-
// On détache complètement le fils du parent => peut importe qui fini en premier, l'autre ira jusqu'au bout :
87-
const pid_t sid = setsid ( );
88-
if ((pid_t)-1 == sid)
89-
{
90-
{
91-
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
92-
ConsoleOutput::cerr ( ) << "ApplicationStats::logUsage : échec de setsid : " << strerror (errno) << co_endl;
93-
}
94-
exit (0);
95-
} // if ((pid_t)-1 == sid)
96-
97-
if ((true == appName.empty ( )) || (true == logDir.empty ( )))
98-
{
99-
{
100-
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
101-
ConsoleOutput::cerr ( ) << "ApplicationStats::logUsage : nom d'application ou répertoire des logs non renseigné (" << appName << "/" << logDir << ")." << co_endl;
102-
}
103-
exit (0);
104-
} // if ((true == appName.empty ( )) || (true == logDir.empty ( )))
105-
106-
// Le nom du fichier :
107-
const Date date;
108-
const string user (UserData (true).getName ( ));
109-
UTF8String fileName (getFileName (appName, logDir, (unsigned long)date.getMonth ( ), date.getYear ( )), Charset::UTF_8);
71+
FILE* file = 0;
72+
string fileName;
11073

111-
// On ouvre le fichier en lecture/écriture :
112-
FILE* file = fopen (fileName.utf8 ( ).c_str ( ), "r+"); // Ne créé pas le fichier => on le créé ci-dessous si nécessaire :
113-
const bool created = NULL == file ? true : false;
114-
file = NULL == file ? fopen (fileName.utf8 ( ).c_str ( ), "a+") : file;
115-
if (NULL == file)
74+
try
11675
{
117-
try
118-
{ // On peut avoir des exceptions de levées : chemin non traversable, ...
119-
File dir (logDir);
120-
if ((false == dir.exists ( )) || (false == dir.isDirectory ( )) || (false == dir.isExecutable ( )) || (false == dir.isWritable ( )))
121-
{
122-
{
123-
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
124-
ConsoleOutput::cerr ( ) << "Erreur, " << logDir << " n'est pas un répertoire existant avec les droits en écriture pour vous." << co_endl;
125-
}
126-
exit (0);
127-
} // if ((false == dir.exists ( )) || (false == dir.isDirectory ( )) || ...
128-
File logFile (fileName.utf8 ( ));
129-
if (false == logFile.isWritable ( ))
130-
{
131-
{
132-
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
133-
ConsoleOutput::cerr ( ) << "Erreur lors de l'ouverture du fichier de logs " << fileName << " : absence de droits en écriture." << co_endl;
134-
}
135-
exit (0);
136-
} // if (false == logFile.isWritable ( ))
137-
}
138-
catch (const Exception& exc)
76+
if ((true == appName.empty ( )) || (true == logDir.empty ( )))
13977
{
14078
{
141-
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
142-
ConsoleOutput::cerr ( ) << "Erreur lors de l'ouverture du fichier de logs " << fileName << " : " << exc.getFullMessage ( ) << co_endl;
79+
80+
ConsoleOutput::cerr ( ) << "ApplicationStats::logUsage : nom d'application ou répertoire des logs non renseigné (" << appName << "/" << logDir << ")." << co_endl;
14381
}
144-
exit (0);
145-
}
146-
catch (...)
147-
{
148-
}
14982

150-
{
151-
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
152-
ConsoleOutput::cerr ( ) << "Erreur lors de l'ouverture du fichier de logs " << fileName << " : erreur non documentée." << co_endl;
153-
}
83+
return; // Tolérance aux erreurs
84+
} // if ((true == appName.empty ( )) || (true == logDir.empty ( )))
15485

155-
exit (0);
156-
} // if (NULL == file)
86+
// Le nom du fichier :
87+
const Date date;
88+
const string user (UserData (true).getName ( ));
89+
fileName = getFileName (appName, logDir, (unsigned long)date.getMonth ( ), date.getYear ( ));
15790

158-
// Obtenir le descripteur de fichier :
159-
int fd = fileno (file);
160-
if (-1 == fd)
161-
{
162-
{
163-
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
164-
ConsoleOutput::cerr ( ) << "Erreur lors de l'ouverture du fichier de logs " << fileName << co_endl;
165-
}
166-
exit (0);
167-
} // if (-1 == fd)
91+
file = initLogSession (fileName);
92+
if (0 == file)
93+
return; // Process père
16894

169-
// Appliquer un verrou exclusif sur le fichier de logs :
170-
errno = 0;
171-
if (0 != flock (fd, LOCK_EX))
172-
{
173-
{
174-
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
175-
ConsoleOutput::cerr ( ) << "Erreur lors du verrouillage du fichier de logs " << fileName << " : " << strerror (errno) << co_endl;
176-
}
177-
fclose (file);
178-
exit (0);
179-
} // if (0 != flock (fd, LOCK_EX))
95+
{ // FileLock scope
96+
FileLock logLock (fileName, file);
97+
98+
// Lecture et actualisation des logs existants :
99+
map<string, size_t> logs;
100+
char name [256];
101+
size_t count = 0, line = 1;
102+
bool found = false;
103+
int flag = 0;
104+
errno = 0;
105+
while (2 == (flag = fscanf (file, "%s\t%lu", name, &count)))
106+
{
107+
line++;
108+
if (name == user)
109+
{
110+
found = true;
111+
count++;
112+
} // if (name == user)
113+
logs.insert (pair<string, size_t> (name, count));
114+
count = 0;
115+
} // while (2 == fscanf (file, "%s\t%lu", name, &count))
116+
if (0 != errno)
117+
{
118+
UTF8String error (charset);
119+
error << "Erreur lors de la lecture du fichier de logs " << fileName << " en ligne " << (unsigned long)line << strerror (errno);
120+
errno = 0;
121+
throw Exception (error);
122+
} // if (0 != errno)
123+
else if ((flag < 2) && (EOF != flag))
124+
{
125+
UTF8String error (charset);
126+
error << "Erreur lors de la lecture du fichier de logs " << fileName << " en ligne " << (unsigned long)line << " : fichier probablement corrompu.";
127+
throw Exception (error);
128+
} // if (flag < 2)
129+
if (false == found)
130+
logs.insert (pair<string, size_t> (user, 1));
131+
132+
// Réécriture des logs actualisés :
133+
errno = 0;
134+
if (0 != fseek (file, 0, SEEK_SET))
135+
{
136+
UTF8String error (charset);
137+
error << "Erreur lors de la réécriture du fichier de logs " << fileName << " : " << strerror (errno);
138+
errno = 0;
139+
throw Exception (error);
140+
} // if (0 != fseek (file, 0, SEEK_SET))
180141

181-
// Conférer aufichier les droits en écriture pour tous le monde si il vient d'être créé :
182-
if (true == created)
183-
{
184-
if (0 != fchmod (fd, S_IRWXU | S_IRWXG | S_IRWXO))
185-
{
142+
for (map<string, size_t>::const_iterator itl = logs.begin ( ); logs.end ( ) != itl; itl++)
186143
{
187-
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
188-
ConsoleOutput::cerr ( ) << "Erreur lors du confèrement à autrui des droits en écriture sur le fichier de logs " << fileName << " : " << strerror (errno) << co_endl;
189-
}
190-
fclose (file);
191-
exit (0);
144+
if (fprintf (file, "%s\t%lu\n", (*itl).first.c_str ( ), (*itl).second) < 0)
145+
{
146+
UTF8String error (charset);
147+
error << "Erreur lors de la réécriture du fichier de logs " << fileName << ".";
148+
throw Exception (error);
149+
} // if (fprintf (file, "%s\t%lu\n", (*itl).first.c_str ( ), (*itl).second) < 0)
150+
} // for (map<string, size_t>::const_iterator itl = logs.begin ( ); logs.end ( ) != itl; itl++)
192151

193-
} // if (0 != fchmod (fd, S_IRWXU | S_IRWXG | S_IRWXO))
194-
} // if (true == created)
152+
errno = 0;
153+
if (0 != fflush (file))
154+
{
155+
UTF8String error (charset);
156+
error << "Erreur lors de la réécriture du fichier de logs " << fileName << " : " << strerror (errno);
157+
errno = 0;
158+
throw Exception (error);
159+
} // if (0 != fflush (file))
195160

196-
// Lecture et actualisation des logs existants :
197-
map<string, size_t> logs;
198-
char name [256];
199-
size_t count = 0, line = 1;
200-
bool found = false;
201-
int flag = 0;
202-
errno = 0;
203-
while (2 == (flag = fscanf (file, "%s\t%lu", name, &count)))
204-
{
205-
line++;
206-
if (name == user)
207-
{
208-
found = true;
209-
count++;
210-
} // if (name == user)
211-
logs.insert (pair<string, size_t> (name, count));
212-
count = 0;
213-
} // while (2 == fscanf (file, "%s\t%lu", name, &count))
214-
if (0 != errno)
215-
{
216-
{
217-
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
218-
ConsoleOutput::cerr ( ) << "Erreur lors de la lecture du fichier de logs " << fileName << " en ligne " << (unsigned long)line << " : " << strerror (errno) << co_endl;
219-
}
220-
fclose (file);
221-
exit (0);
222-
} // if (0 != errno)
223-
else if ((flag < 2) && (EOF != flag))
224-
{
225-
{
226-
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
227-
ConsoleOutput::cerr ( ) << "Erreur lors de la lecture du fichier de logs " << fileName << " en ligne " << (unsigned long)line << " : fichier probablement corrompu." << co_endl;
228-
}
229-
fclose (file);
230-
exit (0);
231-
} // if (flag < 2)
232-
if (false == found)
233-
logs.insert (pair<string, size_t> (user, 1));
234-
235-
// Ecriture des logs actualisés :
236-
errno = 0;
237-
if (0 != fseek (file, 0, SEEK_SET))
238-
{
239-
{
240-
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
241-
ConsoleOutput::cerr ( ) << "Erreur lors de la réécriture du fichier de logs " << fileName << " : " << strerror (errno) << co_endl;
242-
}
243-
fclose (file);
244-
exit (0);
245-
} // if (0 != fseek (file, 0, SEEK_SET))
246-
247-
for (map<string, size_t>::const_iterator itl = logs.begin ( ); logs.end ( ) != itl; itl++)
161+
} // FileLock scope
162+
}
163+
catch (const Exception& exc)
248164
{
249-
if (fprintf (file, "%s\t%lu\n", (*itl).first.c_str ( ), (*itl).second) < 0)
250-
{
251-
{
252-
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
253-
ConsoleOutput::cerr ( ) << "Erreur lors de la réécriture du fichier de logs " << fileName << "."<< co_endl;
254-
}
255-
fclose (file);
256-
exit (0);
257-
} // if (fprintf (file, "%s\t%lu\n", (*itl).first.c_str ( ), (*itl).second) < 0)
258-
} // for (map<string, size_t>::const_iterator itl = logs.begin ( ); logs.end ( ) != itl; itl++)
259-
errno = 0;
260-
if (0 != fflush (file))
165+
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
166+
ConsoleOutput::cerr ( ) << exc.getFullMessage ( ) << co_endl;
167+
}
168+
catch (...)
261169
{
262-
{
263-
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
264-
ConsoleOutput::cerr ( ) << "Erreur lors de la réécriture du fichier de logs " << fileName << " : " << strerror (errno) << co_endl;
265-
}
266-
fclose (file);
267-
exit (0);
268-
} // if (0 != fflush (file))
170+
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
171+
ConsoleOutput::cerr ( ) << "ApplicationStats::logUsage : erreur non renseignée lors de l'écriture d'informations dans le fichier \"" << fileName << "\"." << co_endl;
172+
}
269173

270-
// Libération du verrou :
271-
errno = 0;
272-
if (0 != flock (fd, LOCK_UN))
174+
if (0 != file)
273175
{
274-
{
275-
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
276-
ConsoleOutput::cerr ( ) << "Erreur lors du déverrouillage du fichier de logs " << fileName << " : " << strerror (errno) << co_endl;
277-
}
278176
fclose (file);
279-
} // if (0 != flock (fd, LOCK_UN))
280-
281-
fclose (file);
282-
file = NULL;
283-
fd = -1;
177+
file = 0;
178+
} // if (0 != file)
284179

285180
exit (0);
286181
} // ApplicationStats::logUsage

src/tests/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ set (ALL_EXECUTABLES
88
logs memory modify_script process remoteProcess removefile script_tags
99
scripting_logs thread_manager thread_pool timer tmpfile
1010
unicode urlfifo user_representation userinfos utf8 utf8chars
11-
app_usage
11+
# app_usage
1212
)
1313
set(CMAKE_CTEST_ARGUMENTS "--verbose")
1414
enable_testing()

versions.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Process::finalize prend en argument supplémentaire un délai accordé aux proce
55

66
Classe FileLock permettant de verrouiller un fichier contre des accès concurents.
77

8-
Réécriture partielle de la classe ApplicationStatis + méthode logUsage enregistrant version + OS.
8+
Réécriture partielle de la classe ApplicationStats + méthode logUsage enregistrant version + OS.
99

1010

1111
Version 6.13.1 : 20/06/25

0 commit comments

Comments
 (0)