Skip to content

Commit d55ebc5

Browse files
Merge pull request #15 from LIHPC-Computational-Geometry/appstats-dev
Version 6.12.0. Version 6.12.0. ApplicationStats::logUsage fix: the f…
2 parents 012097c + 2b251fd commit d55ebc5

File tree

9 files changed

+320
-9
lines changed

9 files changed

+320
-9
lines changed

cmake/version.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#
44

55
set (TK_UTIL_MAJOR_VERSION "6")
6-
set (TK_UTIL_MINOR_VERSION "11")
6+
set (TK_UTIL_MINOR_VERSION "12")
77
set (TK_UTIL_RELEASE_VERSION "0")
88
set (TK_UTIL_VERSION ${TK_UTIL_MAJOR_VERSION}.${TK_UTIL_MINOR_VERSION}.${TK_UTIL_RELEASE_VERSION})
99

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ enable_testing ( )
33
add_subdirectory (TkUtil)
44
add_subdirectory (TkUtilScripting)
55
add_subdirectory (TkutilLauncher)
6+
add_subdirectory (appstats)
67
add_subdirectory (tests)
78
add_subdirectory (encoding)
89
add_subdirectory (socket_proxy)

src/TkUtil/ApplicationStats.cpp

Lines changed: 130 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "TkUtil/ApplicationStats.h"
33
#include "TkUtil/Exception.h"
44
#include "TkUtil/File.h"
5+
#include "TkUtil/NumericConversions.h"
56
#include "TkUtil/UTF8String.h"
67

78
#include <TkUtil/Date.h>
@@ -16,6 +17,7 @@
1617
#include <sys/file.h> // flock
1718
#include <stdio.h> // fopen, fseek, fscanf, fprintf
1819
#include <string.h> // strerror
20+
#include <sys/stat.h> // fchmod
1921
#include <sys/types.h>
2022
#include <unistd.h> // fork, setsid
2123

@@ -49,6 +51,15 @@ ApplicationStats::~ApplicationStats ( )
4951
} // ApplicationStats::~ApplicationStats
5052

5153

54+
string ApplicationStats::getFileName (const string& appName, const string& logDir, size_t month, size_t year)
55+
{
56+
UTF8String fileName (Charset::UTF_8);
57+
fileName << logDir << "/" << appName << "_" << NumericConversions::toStr (year, 4) << NumericConversions::toStr (month, 2) << ".logs";
58+
59+
return fileName.utf8 ( );
60+
} // ApplicationStats::getFileName
61+
62+
5263
void ApplicationStats::logUsage (const string& appName, const string& logDir)
5364
{
5465
// En vue de ne pas altérer le comportement de l'application tout est effectuée dans un processus fils.
@@ -81,11 +92,11 @@ void ApplicationStats::logUsage (const string& appName, const string& logDir)
8192
// Le nom du fichier :
8293
const Date date;
8394
const string user (UserData (true).getName ( ));
84-
UTF8String fileName;
85-
fileName << logDir << "/" << appName << "_" << IN_UTIL setw (4) << date.getYear ( ) << setw (2) << (unsigned long)date.getMonth ( ) << ".logs";
95+
UTF8String fileName (getFileName (appName, logDir, (unsigned long)date.getMonth ( ), date.getYear ( )), Charset::UTF_8);
8696

8797
// On ouvre le fichier en lecture/écriture :
88-
FILE* file = fopen (fileName.utf8 ( ).c_str ( ), "r+"); // Ne créé pas le fichier => on le créé ci-dessous si nécessaire :
98+
FILE* file = fopen (fileName.utf8 ( ).c_str ( ), "r+"); // Ne créé pas le fichier => on le créé ci-dessous si nécessaire :
99+
const bool created = NULL == file ? true : false;
89100
file = NULL == file ? fopen (fileName.utf8 ( ).c_str ( ), "a+") : file;
90101
if (NULL == file)
91102
{
@@ -134,6 +145,18 @@ void ApplicationStats::logUsage (const string& appName, const string& logDir)
134145
fclose (file);
135146
return;
136147
} // if (0 != flock (fd, LOCK_EX))
148+
149+
// Conférer aufichier les droits en écriture pour tous le monde si il vient d'être créé :
150+
if (true == created)
151+
{
152+
if (0 != fchmod (fd, S_IRWXU | S_IRWXG | S_IRWXO))
153+
{
154+
ConsoleOutput::cerr ( ) << "Erreur lors du confèrement à autrui des droits en écriture sur le fichier de logs " << fileName << " : " << strerror (errno) << co_endl;
155+
fclose (file);
156+
return;
157+
158+
} // if (0 != fchmod (fd, S_IRWXU | S_IRWXG | S_IRWXO))
159+
} // if (true == created)
137160

138161
// Lecture et actualisation des logs existants :
139162
map<string, size_t> logs;
@@ -200,8 +223,111 @@ void ApplicationStats::logUsage (const string& appName, const string& logDir)
200223
{
201224
ConsoleOutput::cerr ( ) << "Erreur lors du déverrouillage du fichier de logs " << fileName << " : " << strerror (errno) << co_endl;
202225
fclose (file);
203-
} // if (0 != flock (fd, LOCK_UN))
226+
} // if (0 != flock (fd, LOCK_UN))
227+
228+
fclose (file);
229+
file = NULL;
230+
fd = -1;
204231
} // ApplicationStats::logUsage
205232

206233

234+
void ApplicationStats::logStats (std::ostream& output, const std::string& appName, const string& from, const string& to, const std::string& logDir)
235+
{
236+
map<string, size_t> logs;
237+
const size_t fromMonth = NumericConversions::strToULong (UTF8String (from).substring (0, 1));
238+
const size_t fromYear = NumericConversions::strToULong (UTF8String (from).substring (2));
239+
const size_t toMonth = NumericConversions::strToULong (UTF8String (to).substring (0, 1));
240+
const size_t toYear = NumericConversions::strToULong (UTF8String (to).substring (2));
241+
242+
if (fromYear == toYear)
243+
{
244+
for (size_t m = fromMonth; m <= toMonth; m++)
245+
{
246+
cout << "Performing " << m << "/" << fromYear << endl;
247+
UTF8String fileName (getFileName (appName, logDir, m, fromYear), Charset::UTF_8);
248+
249+
if (0 != readLogs (fileName, logs))
250+
ConsoleOutput::cerr ( ) << "Erreur lors de la lecture du fichier de logs " << fileName << " : " << strerror (errno) << co_endl;
251+
} // for (size_t m = fromMonth; m <= toMonth; m++)
252+
} // if (fromYear == toYear)
253+
else
254+
{
255+
for (size_t m = fromMonth; m <= 12; m++)
256+
{
257+
cout << "Performing " << m << "/" << fromYear << endl;
258+
UTF8String fileName (getFileName (appName, logDir, m, fromYear), Charset::UTF_8);
259+
260+
if (0 != readLogs (fileName, logs))
261+
ConsoleOutput::cerr ( ) << "Erreur lors de la lecture du fichier de logs " << fileName << " : " << strerror (errno) << co_endl;
262+
}
263+
for (size_t y = fromYear + 1; y < toYear; y++)
264+
for (size_t m = 1; m <= 12; m++)
265+
{
266+
cout << "Performing " << m << "/" << y << endl;
267+
UTF8String fileName (getFileName (appName, logDir, m, y), Charset::UTF_8);
268+
269+
if (0 != readLogs (fileName, logs))
270+
ConsoleOutput::cerr ( ) << "Erreur lors de la lecture du fichier de logs " << fileName << " : " << strerror (errno) << co_endl;
271+
}
272+
for (size_t m = 1; m <= toMonth; m++)
273+
{
274+
cout << "Performing " << m << "/" << toYear << endl;
275+
UTF8String fileName (getFileName (appName, logDir, m, toYear), Charset::UTF_8);
276+
277+
if (0 != readLogs (fileName, logs))
278+
ConsoleOutput::cerr ( ) << "Erreur lors de la lecture du fichier de logs " << fileName << " : " << strerror (errno) << co_endl;
279+
}
280+
} // else if (fromYear == toYear)
281+
282+
// On imprime les résultats dans le flux :
283+
for (map<string, size_t>::const_iterator itl = logs.begin ( ); logs.end ( ) != itl; itl++)
284+
output << (*itl).first << "\t\t" << (*itl).second << endl;
285+
} // ApplicationStats::logStats
286+
287+
288+
int ApplicationStats::readLogs (const string& fileName, map<string, size_t>& logs)
289+
{
290+
File logFile (fileName);
291+
if (false == logFile.isReadable ( ))
292+
return 0;
293+
294+
int retval = 0;
295+
errno = 0;
296+
FILE* file = fopen (fileName.c_str ( ), "r");
297+
if (NULL != file)
298+
{
299+
retval = readLogs (*file, fileName, logs);
300+
fclose (file);
301+
} // if (NULL != file)
302+
303+
return retval;
304+
} // ApplicationStats::readLogs
305+
306+
307+
int ApplicationStats::readLogs (FILE& file, const string& fileName, map<string, size_t>& logs)
308+
{
309+
errno = 0;
310+
size_t line = 1, count = 0;
311+
int flag = 0;
312+
char name [256];
313+
while (2 == (flag = fscanf (&file, "%s\t%u", name, &count)))
314+
{
315+
line++;
316+
map<string, size_t>::iterator itl = logs.find (name);
317+
if (logs.end ( ) == itl)
318+
logs.insert (pair<string, size_t> (name, count));
319+
else
320+
(*itl).second += count;
321+
count = 0;
322+
} // while (2 == fscanf (file, "%s\t%u", name, &count))
323+
if ((flag < 2) && (EOF != flag))
324+
{
325+
ConsoleOutput::cerr ( ) << "Erreur lors de la lecture du fichier de logs " << fileName << " en ligne " << (unsigned long)line << " : fichier probablement corrompu." << co_endl;
326+
return -1;
327+
} // if (flag < 2)
328+
329+
return errno;
330+
} // ApplicationStats::readLogs
331+
332+
207333
END_NAMESPACE_UTIL

src/TkUtil/public/TkUtil/ApplicationStats.h

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33

44
#include <TkUtil/util_config.h>
55

6+
#include <map>
67
#include <string>
78

9+
#include <stdio.h>
10+
811

912
BEGIN_NAMESPACE_UTIL
1013

@@ -27,20 +30,45 @@ class ApplicationStats
2730
* utilisateur nbutilisations
2831
*/
2932
//@{ Fichier simplifié d'utilisation d'applications
30-
33+
34+
/**
35+
* @param appName est le nom de l'application
36+
* @param logDir est le répertoire où sont stockés les fichiers de logs
37+
* @param Mois et année concernés
38+
* @return Un nom de fichier simplifié de logs.
39+
*/
40+
static std::string getFileName (const std::string& appName, const std::string& logDir, size_t month, size_t year);
41+
3142
/**
3243
* Ajoute une utilisation de cette application à l'utilisateur courrant. L'opération se fait dans un processus détaché.
3344
* Toute erreur rencontrée est affichée dans la console de lancement de l'application.
3445
* @param appName est le nom de l'application
3546
* @param logDir est le répertoire où sont stockés les fichiers de logs
3647
*/
3748
static void logUsage (const std::string& appName, const std::string& logDir);
38-
49+
50+
/**
51+
* Rassemble les utilisations d'une application sur la période demandée et en affiche la synthèse dans le flux transmis en argument.
52+
* Toute erreur rencontrée est affichée dans la console de lancement de l'application.
53+
* @param flux où est écrit la synthèse
54+
* @param appName est le nom de l'application
55+
* @param est la date de début au format MMYYYY
56+
* @param est la date de fin au format MMYYYY
57+
* @param logDir est le répertoire où sont stockés les fichiers de logs
58+
*/
59+
static void logStats (std::ostream& output, const std::string& appName, const std::string& logDir, const std::string& from, const std::string& to);
3960
//@} Fichier simplifié d'utilisation d'applications
4061

4162

4263
private :
43-
64+
65+
/**
66+
* Charge les logs du fichiers ouvert transmis en argument dans la map transmise en second argument.
67+
* @return 0 en cas de succès. En cas d'erreur errno est positionné.
68+
*/
69+
static int readLogs (const std::string& fileName, std::map<std::string, size_t>& logs);
70+
static int readLogs (FILE& file, const std::string& fileName, std::map<std::string, size_t>& logs);
71+
4472
/**
4573
* Constructeurs/Destructeur : interdits.
4674
*/

src/appstats/CMakeLists.txt

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
set (CURRENT_PACKAGE_NAME "Appstats")
2+
3+
include (${CMAKE_SOURCE_DIR}/cmake/version.cmake)
4+
include (${GUIToolkitsVariables_CMAKE_DIR}/common.cmake)
5+
include (${GUIToolkitsVariables_CMAKE_DIR}/workarounds.cmake)
6+
7+
add_executable (appstats appstats.cpp)
8+
9+
target_link_libraries (appstats PUBLIC TkUtil)
10+
# INSTALL_RPATH modifie le rpath pour les libs internes au projet :
11+
set_target_properties (appstats PROPERTIES INSTALL_RPATH_USE_LINK_PATH 1 INSTALL_RPATH ${CMAKE_PACKAGE_RPATH_DIR})
12+
13+
# INSTALLATION :
14+
include(CMakePackageConfigHelpers)
15+
# ConfigPackageLocation : c'est plus ou moins standardisé, le défaut étant lib/cmake.
16+
# On nos recommande très vivement d'utiliser ce répertoire afin de limiter les soucis par la suite,
17+
# notamment au niveau des vues.
18+
set (ConfigPackageLocation ${CMAKE_CMAKE_DIR})
19+
20+
install(TARGETS appstats EXPORT Appstats DESTINATION ${CMAKE_INSTALL_BINDIR} PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
21+
22+
# Utilisation par d'autres modules de appstats :
23+
set (RUNTIME_INSTALL_DIR bin/) # appstats_RUNTIME_DIR avec AppstatsConfig.cmake.in
24+
configure_package_config_file(cmake/${CURRENT_PACKAGE_NAME}Config.cmake.in
25+
${CMAKE_CURRENT_BINARY_DIR}/${CURRENT_PACKAGE_NAME}/${CURRENT_PACKAGE_NAME}Config.cmake
26+
INSTALL_DESTINATION ${CMAKE_CMAKE_DIR}
27+
PATH_VARS RUNTIME_INSTALL_DIR
28+
)
29+
write_basic_package_version_file(
30+
${CMAKE_CURRENT_BINARY_DIR}/${CURRENT_PACKAGE_NAME}/${CURRENT_PACKAGE_NAME}ConfigVersion.cmake
31+
VERSION ${TK_UTIL_VERSION}
32+
COMPATIBILITY SameMinorVersion
33+
)
34+
install (
35+
FILES
36+
${CMAKE_CURRENT_BINARY_DIR}/${CURRENT_PACKAGE_NAME}/${CURRENT_PACKAGE_NAME}Config.cmake
37+
${CMAKE_CURRENT_BINARY_DIR}/${CURRENT_PACKAGE_NAME}/${CURRENT_PACKAGE_NAME}ConfigVersion.cmake
38+
DESTINATION ${ConfigPackageLocation} PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ GROUP_WRITE WORLD_READ
39+
)
40+
41+

0 commit comments

Comments
 (0)