nfs-ganesha 1.4

nfs_stats_thread.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
00003  *
00004  * Copyright CEA/DAM/DIF  (2008)
00005  * contributeur : Philippe DENIEL   philippe.deniel@cea.fr
00006  *                Thomas LEIBOVICI  thomas.leibovici@cea.fr
00007  *
00008  * This program is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 3 of the License, or (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021  *
00022  * ---------------------------------------
00023  */
00024 
00036 #ifdef HAVE_CONFIG_H
00037 #include "config.h"
00038 #endif
00039 
00040 #ifdef _SOLARIS
00041 #include "solaris_port.h"
00042 #endif
00043 
00044 #include <stdio.h>
00045 #include <string.h>
00046 #include <pthread.h>
00047 #include <assert.h>
00048 #include <sys/stat.h>
00049 #include <time.h>
00050 #include "nfs_core.h"
00051 #include "nfs_stat.h"
00052 #include "nfs_exports.h"
00053 #include "log.h"
00054 
00055 extern hash_table_t *ht_ip_stats[NB_MAX_WORKER_THREAD];
00056 
00057 void set_min_latency(nfs_request_stat_item_t *cur_stat, unsigned int val)
00058 {
00059   if(val > 0)
00060     {
00061       if(val < cur_stat->min_latency)
00062         {
00063           cur_stat->min_latency = val;
00064         }
00065     }
00066 }
00067 
00068 void set_max_latency(nfs_request_stat_item_t *cur_stat, unsigned int val)
00069 {
00070   if(val > cur_stat->max_latency)
00071     {
00072       cur_stat->max_latency = val;
00073     }
00074 }
00075 
00076 /*
00077  * This function collects statistics from all Ganesha system modules so that they can then
00078  * be pushed into various users (e.g.: a statistics file, a network mgmt serviece, ...)
00079  * That is why collection of statistics is separated into its own function so that any user
00080  * can call for it.
00081  */
00082 void stats_collect (ganesha_stats_t                 *ganesha_stats)
00083 {
00084     hash_stat_t            *cache_inode_stat = &ganesha_stats->cache_inode_hstat;
00085     nfs_worker_stat_t      *global_worker_stat = &ganesha_stats->global_worker_stat;
00086     fsal_statistics_t      *global_fsal_stat = &ganesha_stats->global_fsal;
00087     unsigned int           i, j;
00088 
00089     /* This is done only on worker[0]: the hashtable is shared and worker 0 always exists */
00090     HashTable_GetStats(fh_to_cache_entry_ht, cache_inode_stat);
00091 
00092     /* Merging the NFS protocols stats together */
00093     global_worker_stat->nb_total_req = 0;
00094     global_worker_stat->nb_udp_req = 0;
00095     global_worker_stat->nb_tcp_req = 0;
00096     global_worker_stat->stat_req.nb_mnt1_req = 0;
00097     global_worker_stat->stat_req.nb_mnt3_req = 0;
00098     global_worker_stat->stat_req.nb_nfs2_req = 0;
00099     global_worker_stat->stat_req.nb_nfs3_req = 0;
00100     global_worker_stat->stat_req.nb_nfs4_req = 0;
00101     global_worker_stat->stat_req.nb_nlm4_req = 0;
00102     global_worker_stat->stat_req.nb_nfs40_op = 0;
00103     global_worker_stat->stat_req.nb_nfs41_op = 0;
00104     global_worker_stat->stat_req.nb_rquota1_req = 0;
00105     global_worker_stat->stat_req.nb_rquota2_req = 0;
00106 
00107     /* prepare for computing pending request stats */
00108     ganesha_stats->min_pending_request = 10000000;
00109     ganesha_stats->max_pending_request = 0;
00110     ganesha_stats->total_pending_request = 0;
00111     ganesha_stats->average_pending_request = 0;
00112     ganesha_stats->len_pending_request = 0;
00113 
00114     for (i = 0; i < nfs_param.core_param.nb_worker; i++) {
00115         global_worker_stat->nb_total_req += workers_data[i].stats.nb_total_req;
00116         global_worker_stat->nb_udp_req += workers_data[i].stats.nb_udp_req;
00117         global_worker_stat->nb_tcp_req += workers_data[i].stats.nb_tcp_req;
00118         global_worker_stat->stat_req.nb_mnt1_req +=
00119             workers_data[i].stats.stat_req.nb_mnt1_req;
00120         global_worker_stat->stat_req.nb_mnt3_req +=
00121             workers_data[i].stats.stat_req.nb_mnt3_req;
00122         global_worker_stat->stat_req.nb_nfs2_req +=
00123             workers_data[i].stats.stat_req.nb_nfs2_req;
00124         global_worker_stat->stat_req.nb_nfs3_req +=
00125             workers_data[i].stats.stat_req.nb_nfs3_req;
00126         global_worker_stat->stat_req.nb_nfs4_req +=
00127             workers_data[i].stats.stat_req.nb_nfs4_req;
00128         global_worker_stat->stat_req.nb_nfs40_op +=
00129             workers_data[i].stats.stat_req.nb_nfs40_op;
00130         global_worker_stat->stat_req.nb_nfs41_op +=
00131             workers_data[i].stats.stat_req.nb_nfs41_op;
00132 
00133         global_worker_stat->stat_req.nb_nlm4_req +=
00134             workers_data[i].stats.stat_req.nb_nlm4_req;
00135 
00136         global_worker_stat->stat_req.nb_rquota1_req +=
00137             workers_data[i].stats.stat_req.nb_nlm4_req;
00138 
00139         global_worker_stat->stat_req.nb_rquota2_req +=
00140             workers_data[i].stats.stat_req.nb_nlm4_req;
00141 
00142         for (j = 0; j < MNT_V1_NB_COMMAND; j++) {
00143             if (i == 0) {
00144                 global_worker_stat->stat_req.stat_req_mnt1[j].total =
00145                     workers_data[i].stats.stat_req.stat_req_mnt1[j].total;
00146                 global_worker_stat->stat_req.stat_req_mnt1[j].success =
00147                     workers_data[i].stats.stat_req.stat_req_mnt1[j].success;
00148                 global_worker_stat->stat_req.stat_req_mnt1[j].dropped =
00149                     workers_data[i].stats.stat_req.stat_req_mnt1[j].dropped;
00150             } else {
00151                 global_worker_stat->stat_req.stat_req_mnt1[j].total +=
00152                     workers_data[i].stats.stat_req.stat_req_mnt1[j].total;
00153                 global_worker_stat->stat_req.stat_req_mnt1[j].success +=
00154                     workers_data[i].stats.stat_req.stat_req_mnt1[j].success;
00155                 global_worker_stat->stat_req.stat_req_mnt1[j].dropped +=
00156                     workers_data[i].stats.stat_req.stat_req_mnt1[j].dropped;
00157             }
00158         }
00159 
00160         for (j = 0; j < MNT_V3_NB_COMMAND; j++) {
00161             if (i == 0) {
00162                 global_worker_stat->stat_req.stat_req_mnt3[j].total =
00163                     workers_data[i].stats.stat_req.stat_req_mnt3[j].total;
00164                 global_worker_stat->stat_req.stat_req_mnt3[j].success =
00165                     workers_data[i].stats.stat_req.stat_req_mnt3[j].success;
00166                 global_worker_stat->stat_req.stat_req_mnt3[j].dropped =
00167                     workers_data[i].stats.stat_req.stat_req_mnt3[j].dropped;
00168             } else {
00169                 global_worker_stat->stat_req.stat_req_mnt3[j].total +=
00170                     workers_data[i].stats.stat_req.stat_req_mnt3[j].total;
00171                 global_worker_stat->stat_req.stat_req_mnt3[j].success +=
00172                     workers_data[i].stats.stat_req.stat_req_mnt3[j].success;
00173                 global_worker_stat->stat_req.stat_req_mnt3[j].dropped +=
00174                     workers_data[i].stats.stat_req.stat_req_mnt3[j].dropped;
00175             }
00176         }
00177 
00178         for (j = 0; j < NFS_V2_NB_COMMAND; j++) {
00179             if (i == 0) {
00180                 global_worker_stat->stat_req.stat_req_nfs2[j].total =
00181                     workers_data[i].stats.stat_req.stat_req_nfs2[j].total;
00182                 global_worker_stat->stat_req.stat_req_nfs2[j].success =
00183                     workers_data[i].stats.stat_req.stat_req_nfs2[j].success;
00184                 global_worker_stat->stat_req.stat_req_nfs2[j].dropped =
00185                     workers_data[i].stats.stat_req.stat_req_nfs2[j].dropped;
00186             } else {
00187                 global_worker_stat->stat_req.stat_req_nfs2[j].total +=
00188                     workers_data[i].stats.stat_req.stat_req_nfs2[j].total;
00189                 global_worker_stat->stat_req.stat_req_nfs2[j].success +=
00190                     workers_data[i].stats.stat_req.stat_req_nfs2[j].success;
00191                 global_worker_stat->stat_req.stat_req_nfs2[j].dropped +=
00192                     workers_data[i].stats.stat_req.stat_req_nfs2[j].dropped;
00193             }
00194         }
00195 
00196         for (j = 0; j < NFS_V3_NB_COMMAND; j++) {
00197             if (i == 0) {
00198                 global_worker_stat->stat_req.stat_req_nfs3[j].total =
00199                     workers_data[i].stats.stat_req.stat_req_nfs3[j].total;
00200                 global_worker_stat->stat_req.stat_req_nfs3[j].success =
00201                     workers_data[i].stats.stat_req.stat_req_nfs3[j].success;
00202                 global_worker_stat->stat_req.stat_req_nfs3[j].dropped =
00203                     workers_data[i].stats.stat_req.stat_req_nfs3[j].dropped;
00204                 global_worker_stat->stat_req.stat_req_nfs3[j].tot_latency =
00205                     workers_data[i].stats.stat_req.stat_req_nfs3[j].tot_latency;
00206                 global_worker_stat->stat_req.stat_req_nfs3[j].min_latency =
00207                     workers_data[i].stats.stat_req.stat_req_nfs3[j].min_latency;
00208                 global_worker_stat->stat_req.stat_req_nfs3[j].max_latency =
00209                     workers_data[i].stats.stat_req.stat_req_nfs3[j].max_latency;
00210             } else {
00211                 global_worker_stat->stat_req.stat_req_nfs3[j].total +=
00212                     workers_data[i].stats.stat_req.stat_req_nfs3[j].total;
00213                 global_worker_stat->stat_req.stat_req_nfs3[j].success +=
00214                     workers_data[i].stats.stat_req.stat_req_nfs3[j].success;
00215                 global_worker_stat->stat_req.stat_req_nfs3[j].dropped +=
00216                     workers_data[i].stats.stat_req.stat_req_nfs3[j].dropped;
00217                 global_worker_stat->stat_req.stat_req_nfs3[j].tot_latency +=
00218                     workers_data[i].stats.stat_req.stat_req_nfs3[j].tot_latency;
00219                 set_min_latency(&(global_worker_stat->stat_req.stat_req_nfs3[j]),
00220                                 workers_data[i].stats.stat_req.stat_req_nfs3[j].min_latency);
00221                 set_max_latency(&(global_worker_stat->stat_req.stat_req_nfs3[j]),
00222                                 workers_data[i].stats.stat_req.stat_req_nfs3[j].max_latency);
00223             }
00224         }
00225 
00226         for (j = 0; j < NFS_V4_NB_COMMAND; j++) {
00227             if (i == 0) {
00228                 global_worker_stat->stat_req.stat_req_nfs4[j].total =
00229                     workers_data[i].stats.stat_req.stat_req_nfs4[j].total;
00230                 global_worker_stat->stat_req.stat_req_nfs4[j].success =
00231                     workers_data[i].stats.stat_req.stat_req_nfs4[j].success;
00232                 global_worker_stat->stat_req.stat_req_nfs4[j].dropped =
00233                     workers_data[i].stats.stat_req.stat_req_nfs4[j].dropped;
00234             } else {
00235                 global_worker_stat->stat_req.stat_req_nfs4[j].total +=
00236                     workers_data[i].stats.stat_req.stat_req_nfs4[j].total;
00237                 global_worker_stat->stat_req.stat_req_nfs4[j].success +=
00238                     workers_data[i].stats.stat_req.stat_req_nfs4[j].success;
00239                 global_worker_stat->stat_req.stat_req_nfs4[j].dropped +=
00240                     workers_data[i].stats.stat_req.stat_req_nfs4[j].dropped;
00241             }
00242         }
00243 
00244         for (j = 0; j < NFS_V40_NB_OPERATION; j++) {
00245             if (i == 0) {
00246                 global_worker_stat->stat_req.stat_op_nfs40[j].total =
00247                     workers_data[i].stats.stat_req.stat_op_nfs40[j].total;
00248                 global_worker_stat->stat_req.stat_op_nfs40[j].success =
00249                     workers_data[i].stats.stat_req.stat_op_nfs40[j].success;
00250                 global_worker_stat->stat_req.stat_op_nfs40[j].failed =
00251                     workers_data[i].stats.stat_req.stat_op_nfs40[j].failed;
00252             } else {
00253                 global_worker_stat->stat_req.stat_op_nfs40[j].total +=
00254                     workers_data[i].stats.stat_req.stat_op_nfs40[j].total;
00255                 global_worker_stat->stat_req.stat_op_nfs40[j].success +=
00256                     workers_data[i].stats.stat_req.stat_op_nfs40[j].success;
00257                 global_worker_stat->stat_req.stat_op_nfs40[j].failed +=
00258                     workers_data[i].stats.stat_req.stat_op_nfs40[j].failed;
00259             }
00260         }
00261 
00262         for (j = 0; j < NFS_V41_NB_OPERATION; j++) {
00263             if (i == 0) {
00264                 global_worker_stat->stat_req.stat_op_nfs41[j].total =
00265                     workers_data[i].stats.stat_req.stat_op_nfs41[j].total;
00266                 global_worker_stat->stat_req.stat_op_nfs41[j].success =
00267                     workers_data[i].stats.stat_req.stat_op_nfs41[j].success;
00268                 global_worker_stat->stat_req.stat_op_nfs41[j].failed =
00269                     workers_data[i].stats.stat_req.stat_op_nfs41[j].failed;
00270             } else {
00271                 global_worker_stat->stat_req.stat_op_nfs41[j].total +=
00272                     workers_data[i].stats.stat_req.stat_op_nfs41[j].total;
00273                 global_worker_stat->stat_req.stat_op_nfs41[j].success +=
00274                     workers_data[i].stats.stat_req.stat_op_nfs41[j].success;
00275                 global_worker_stat->stat_req.stat_op_nfs41[j].failed +=
00276                     workers_data[i].stats.stat_req.stat_op_nfs41[j].failed;
00277             }
00278         }
00279 
00280         for (j = 0; j < NLM_V4_NB_OPERATION; j++) {
00281             if (i == 0) {
00282                 global_worker_stat->stat_req.stat_req_nlm4[j].total =
00283                     workers_data[i].stats.stat_req.stat_req_nlm4[j].total;
00284                 global_worker_stat->stat_req.stat_req_nlm4[j].success =
00285                     workers_data[i].stats.stat_req.stat_req_nlm4[j].success;
00286                 global_worker_stat->stat_req.stat_req_nlm4[j].dropped =
00287                     workers_data[i].stats.stat_req.stat_req_nlm4[j].dropped;
00288             } else {
00289                 global_worker_stat->stat_req.stat_req_nlm4[j].total +=
00290                     workers_data[i].stats.stat_req.stat_req_nlm4[j].total;
00291                 global_worker_stat->stat_req.stat_req_nlm4[j].success +=
00292                     workers_data[i].stats.stat_req.stat_req_nlm4[j].success;
00293                 global_worker_stat->stat_req.stat_req_nlm4[j].dropped +=
00294                     workers_data[i].stats.stat_req.stat_req_nlm4[j].dropped;
00295             }
00296         }
00297 
00298         for (j = 0; j < RQUOTA_NB_COMMAND; j++) {
00299             if (i == 0) {
00300                 global_worker_stat->stat_req.stat_req_rquota1[j].total =
00301                     workers_data[i].stats.stat_req.stat_req_rquota1[j].total;
00302                 global_worker_stat->stat_req.stat_req_rquota1[j].success =
00303                     workers_data[i].stats.stat_req.stat_req_rquota1[j].success;
00304                 global_worker_stat->stat_req.stat_req_rquota1[j].dropped =
00305                     workers_data[i].stats.stat_req.stat_req_rquota1[j].dropped;
00306 
00307                 global_worker_stat->stat_req.stat_req_rquota2[j].total =
00308                     workers_data[i].stats.stat_req.stat_req_rquota2[j].total;
00309                 global_worker_stat->stat_req.stat_req_rquota2[j].success =
00310                     workers_data[i].stats.stat_req.stat_req_rquota2[j].success;
00311                 global_worker_stat->stat_req.stat_req_rquota2[j].dropped =
00312                     workers_data[i].stats.stat_req.stat_req_rquota2[j].dropped;
00313             } else {
00314                 global_worker_stat->stat_req.stat_req_rquota1[j].total +=
00315                     workers_data[i].stats.stat_req.stat_req_rquota1[j].total;
00316                 global_worker_stat->stat_req.stat_req_rquota1[j].success +=
00317                     workers_data[i].stats.stat_req.stat_req_rquota1[j].success;
00318                 global_worker_stat->stat_req.stat_req_rquota1[j].dropped +=
00319                     workers_data[i].stats.stat_req.stat_req_rquota1[j].dropped;
00320 
00321                 global_worker_stat->stat_req.stat_req_rquota2[j].total +=
00322                     workers_data[i].stats.stat_req.stat_req_rquota2[j].total;
00323                 global_worker_stat->stat_req.stat_req_rquota2[j].success +=
00324                     workers_data[i].stats.stat_req.stat_req_rquota2[j].success;
00325                 global_worker_stat->stat_req.stat_req_rquota2[j].dropped +=
00326                     workers_data[i].stats.stat_req.stat_req_rquota2[j].dropped;
00327             }
00328         }
00329 
00330         ganesha_stats->len_pending_request = workers_data[i].pending_request_len;
00331         if (ganesha_stats->len_pending_request < ganesha_stats->min_pending_request)
00332             ganesha_stats->min_pending_request = ganesha_stats->len_pending_request;
00333 
00334         if (ganesha_stats->len_pending_request > ganesha_stats->max_pending_request)
00335             ganesha_stats->max_pending_request = ganesha_stats->len_pending_request;
00336 
00337         ganesha_stats->total_pending_request += ganesha_stats->len_pending_request;
00338     }                       /* for( i = 0 ; i < nfs_param.core_param.nb_worker ; i++ ) */
00339 
00340     /* Compute average pending request */
00341     ganesha_stats->average_pending_request = ganesha_stats->total_pending_request / nfs_param.core_param.nb_worker;
00342 
00343     for (j = 0; j < NFS_V3_NB_COMMAND; j++) {
00344         if (global_worker_stat->stat_req.stat_req_nfs3[j].total > 0) {
00345             ganesha_stats->avg_latency = (global_worker_stat->stat_req.stat_req_nfs3[j].tot_latency /
00346                                          global_worker_stat->stat_req.stat_req_nfs3[j].total);
00347         } else {
00348             ganesha_stats->avg_latency = 0;
00349         }
00350     }
00351 
00352     /* Printing the cache inode hash stat */
00353     nfs_dupreq_get_stats(&ganesha_stats->drc_udp, &ganesha_stats->drc_tcp);
00354 
00355     /* Printing the UIDMAP_TYPE hash table stats */
00356     idmap_get_stats(UIDMAP_TYPE, &ganesha_stats->uid_map, &ganesha_stats->uid_reverse);
00357     /* Printing the GIDMAP_TYPE hash table stats */
00358     idmap_get_stats(GIDMAP_TYPE, &ganesha_stats->gid_map, &ganesha_stats->gid_reverse);
00359     /* Stats for the IP/Name hashtable */
00360     nfs_ip_name_get_stats(&ganesha_stats->ip_name_map);
00361 
00362     /* fsal statistics */
00363     memset(global_fsal_stat, 0, sizeof(fsal_statistics_t));
00364     ganesha_stats->total_fsal_calls = 0;
00365 
00366     for (i = 0; i < nfs_param.core_param.nb_worker; i++) {
00367         for (j = 0; j < FSAL_NB_FUNC; j++) {
00368             ganesha_stats->total_fsal_calls += workers_data[i].stats.fsal_stats.func_stats.nb_call[j];
00369 
00370             global_fsal_stat->func_stats.nb_call[j] +=
00371                 workers_data[i].stats.fsal_stats.func_stats.nb_call[j];
00372             global_fsal_stat->func_stats.nb_success[j] +=
00373                 workers_data[i].stats.fsal_stats.func_stats.nb_success[j];
00374             global_fsal_stat->func_stats.nb_err_retryable[j] +=
00375                 workers_data[i].stats.fsal_stats.func_stats.nb_err_retryable[j];
00376             global_fsal_stat->func_stats.nb_err_unrecover[j] +=
00377                 workers_data[i].stats.fsal_stats.func_stats.nb_err_unrecover[j];
00378         }
00379     }
00380 }
00381 
00382 void *stats_thread(void *UnusedArg)
00383 {
00384   FILE *stats_file = NULL;
00385   struct stat statref;
00386   struct stat stattest;
00387   time_t current_time;
00388   struct tm *current_time_struct;
00389   struct tm *boot_time_struct;
00390   char strdate[1024];
00391   char strbootdate[1024];
00392   unsigned int j = 0;
00393   int reopen_stats = FALSE;
00394 
00395   ganesha_stats_t        ganesha_stats;
00396   nfs_worker_stat_t      *global_worker_stat = &ganesha_stats.global_worker_stat;
00397   hash_stat_t            *cache_inode_stat = &ganesha_stats.cache_inode_hstat;
00398   hash_stat_t            *uid_map_hstat = &ganesha_stats.uid_map;
00399   hash_stat_t            *gid_map_hstat = &ganesha_stats.gid_map;
00400   hash_stat_t            *ip_name_hstat = &ganesha_stats.ip_name_map;
00401   hash_stat_t            *hstat_uid_reverse = &ganesha_stats.uid_reverse;
00402   hash_stat_t            *hstat_gid_reverse = &ganesha_stats.gid_reverse;
00403   hash_stat_t            *hstat_drc_udp = &ganesha_stats.drc_udp;
00404   hash_stat_t            *hstat_drc_tcp = &ganesha_stats.drc_tcp;
00405   fsal_statistics_t      *global_fsal_stat = &ganesha_stats.global_fsal;
00406 
00407 
00408   SetNameFunction("stat_thr");
00409 
00410   /* Open the stats file, in append mode */
00411   if((stats_file = fopen(nfs_param.core_param.stats_file_path, "a")) == NULL)
00412     {
00413       LogCrit(COMPONENT_MAIN,
00414               "NFS STATS : Could not open stats file %s, no stats will be made...",
00415               nfs_param.core_param.stats_file_path);
00416       return NULL;
00417     }
00418 
00419   if(stat(nfs_param.core_param.stats_file_path, &statref) != 0)
00420     {
00421       LogCrit(COMPONENT_MAIN,
00422               "NFS STATS : Could not get inode for %s, no stats will be made...",
00423               nfs_param.core_param.stats_file_path);
00424       fclose(stats_file);
00425       return NULL;
00426     }
00427 
00428 #ifdef _SNMP_ADM_ACTIVE
00429   /* start snmp library */
00430   if(stats_snmp() == 0)
00431     LogInfo(COMPONENT_MAIN,
00432             "NFS STATS: SNMP stats service was started successfully");
00433   else
00434     LogCrit(COMPONENT_MAIN,
00435             "NFS STATS: ERROR starting SNMP stats export thread");
00436 #endif /*_SNMP_ADM_ACTIVE*/
00437 
00438   while(1)
00439     {
00440       /* Initial wait */
00441       sleep(nfs_param.core_param.stats_update_delay);
00442 
00443       /* Debug trace */
00444       LogInfo(COMPONENT_MAIN, "NFS STATS : now dumping stats");
00445 
00446       /* Stats main loop */
00447       if(stat(nfs_param.core_param.stats_file_path, &stattest) == 0)
00448         {
00449           if(stattest.st_ino != statref.st_ino)
00450             reopen_stats = TRUE;
00451         }
00452       else
00453         {
00454           if(errno == ENOENT)
00455             reopen_stats = TRUE;
00456         }
00457 
00458       /* Check is file has changed (the inode number will be different) */
00459       if(reopen_stats == TRUE)
00460         {
00461           /* Stats file has changed */
00462           LogEvent(COMPONENT_MAIN,
00463                    "NFS STATS : stats file has changed or was removed, I close and reopen it");
00464           fflush(stats_file);
00465           fclose(stats_file);
00466           if((stats_file = fopen(nfs_param.core_param.stats_file_path, "a")) == NULL)
00467             {
00468               LogCrit(COMPONENT_MAIN,
00469                       "NFS STATS : Could not open stats file %s, no further stats will be made...",
00470                       nfs_param.core_param.stats_file_path);
00471               return NULL;
00472             }
00473           statref = stattest;
00474           reopen_stats = FALSE;
00475         }
00476 
00477       /* Get the current epoch time */
00478       current_time = time(NULL);
00479       current_time_struct = localtime(&current_time);
00480       snprintf(strdate, 1024, "%u, %.2d/%.2d/%.4d %.2d:%.2d:%.2d ",
00481                (unsigned int)current_time,
00482                current_time_struct->tm_mday,
00483                current_time_struct->tm_mon + 1,
00484                1900 + current_time_struct->tm_year,
00485                current_time_struct->tm_hour,
00486                current_time_struct->tm_min,
00487                current_time_struct->tm_sec);
00488 
00489       /* Printing the general Stats */
00490       boot_time_struct = localtime(&ServerBootTime);
00491       snprintf(strbootdate, 1024, "%u, %.2d/%.2d/%.4d %.2d:%.2d:%.2d ",
00492                (unsigned int)ServerBootTime,
00493                boot_time_struct->tm_mday,
00494                boot_time_struct->tm_mon + 1,
00495                1900 + boot_time_struct->tm_year,
00496                boot_time_struct->tm_hour,
00497                boot_time_struct->tm_min,
00498                boot_time_struct->tm_sec);
00499 
00500       fprintf(stats_file, "NFS_SERVER_GENERAL,%s;%s\n", strdate, strbootdate);
00501 
00502       /* collect statistics */
00503       stats_collect(&ganesha_stats);
00504 
00505       /* Pinting the cache inode hash stat */
00506       /* This is done only on worker[0]: the hashtable is shared and worker 0 always exists */
00507       HashTable_GetStats(fh_to_cache_entry_ht, cache_inode_stat);
00508 
00509       fprintf(stats_file,
00510               "CACHE_INODE_HASH,%s;%zu,%zu,%zu,%zu\n",
00511               strdate, cache_inode_stat->entries,
00512               cache_inode_stat->min_rbt_num_node,
00513               cache_inode_stat->max_rbt_num_node,
00514               cache_inode_stat->average_rbt_num_node);
00515 
00516       fprintf(stats_file, "NFS/MOUNT STATISTICS,%s;%u,%u,%u|%u,%u,%u,%u,%u|%u,%u,%u,%u\n",
00517               strdate,
00518               global_worker_stat->nb_total_req,
00519               global_worker_stat->nb_udp_req,
00520               global_worker_stat->nb_tcp_req,
00521               global_worker_stat->stat_req.nb_mnt1_req,
00522               global_worker_stat->stat_req.nb_mnt3_req,
00523               global_worker_stat->stat_req.nb_nfs2_req,
00524               global_worker_stat->stat_req.nb_nfs3_req,
00525               global_worker_stat->stat_req.nb_nfs4_req,
00526               ganesha_stats.total_pending_request,
00527               ganesha_stats.min_pending_request,
00528               ganesha_stats.max_pending_request,
00529               ganesha_stats.average_pending_request);
00530 
00531       fprintf(stats_file, "MNT V1 REQUEST,%s;%u", strdate,
00532               global_worker_stat->stat_req.nb_mnt1_req);
00533       for(j = 0; j < MNT_V1_NB_COMMAND; j++)
00534         fprintf(stats_file, "|%u,%u,%u",
00535                 global_worker_stat->stat_req.stat_req_mnt1[j].total,
00536                 global_worker_stat->stat_req.stat_req_mnt1[j].success,
00537                 global_worker_stat->stat_req.stat_req_mnt1[j].dropped);
00538       fprintf(stats_file, "\n");
00539 
00540       fprintf(stats_file, "MNT V3 REQUEST,%s;%u", strdate,
00541               global_worker_stat->stat_req.nb_mnt3_req);
00542       for(j = 0; j < MNT_V3_NB_COMMAND; j++)
00543         fprintf(stats_file, "|%u,%u,%u",
00544                 global_worker_stat->stat_req.stat_req_mnt3[j].total,
00545                 global_worker_stat->stat_req.stat_req_mnt3[j].success,
00546                 global_worker_stat->stat_req.stat_req_mnt3[j].dropped);
00547       fprintf(stats_file, "\n");
00548 
00549       fprintf(stats_file, "NFS V2 REQUEST,%s;%u", strdate,
00550               global_worker_stat->stat_req.nb_nfs2_req);
00551       for(j = 0; j < NFS_V2_NB_COMMAND; j++)
00552         fprintf(stats_file, "|%u,%u,%u",
00553                 global_worker_stat->stat_req.stat_req_nfs2[j].total,
00554                 global_worker_stat->stat_req.stat_req_nfs2[j].success,
00555                 global_worker_stat->stat_req.stat_req_nfs2[j].dropped);
00556       fprintf(stats_file, "\n");
00557 
00558       fprintf(stats_file, "NFS V3 REQUEST,%s;%u", strdate,
00559               global_worker_stat->stat_req.nb_nfs3_req);
00560       for (j = 0; j < NFS_V3_NB_COMMAND; j++)
00561         {
00562           fprintf(stats_file, "|%u,%u,%u,%u,%u,%u,%u",
00563                   global_worker_stat->stat_req.stat_req_nfs3[j].total,
00564                   global_worker_stat->stat_req.stat_req_nfs3[j].success,
00565                   global_worker_stat->stat_req.stat_req_nfs3[j].dropped,
00566                   global_worker_stat->stat_req.stat_req_nfs3[j].tot_latency,
00567                   ganesha_stats.avg_latency,
00568                   global_worker_stat->stat_req.stat_req_nfs3[j].min_latency,
00569                   global_worker_stat->stat_req.stat_req_nfs3[j].max_latency);
00570         }
00571       fprintf(stats_file, "\n");
00572 
00573       fprintf(stats_file, "NFS V4 REQUEST,%s;%u", strdate,
00574               global_worker_stat->stat_req.nb_nfs4_req);
00575       for(j = 0; j < NFS_V4_NB_COMMAND; j++)
00576         fprintf(stats_file, "|%u,%u,%u",
00577                 global_worker_stat->stat_req.stat_req_nfs4[j].total,
00578                 global_worker_stat->stat_req.stat_req_nfs4[j].success,
00579                 global_worker_stat->stat_req.stat_req_nfs4[j].dropped);
00580       fprintf(stats_file, "\n");
00581 
00582       fprintf(stats_file, "NFS V4.0 OPERATIONS,%s;%u", strdate,
00583               global_worker_stat->stat_req.nb_nfs40_op);
00584       for(j = 0; j < NFS_V40_NB_OPERATION; j++)
00585         fprintf(stats_file, "|%u,%u,%u",
00586                 global_worker_stat->stat_req.stat_op_nfs40[j].total,
00587                 global_worker_stat->stat_req.stat_op_nfs40[j].success,
00588                 global_worker_stat->stat_req.stat_op_nfs40[j].failed);
00589       fprintf(stats_file, "\n");
00590 
00591       fprintf(stats_file, "NFS V4.1 OPERATIONS,%s;%u", strdate,
00592               global_worker_stat->stat_req.nb_nfs41_op);
00593       for(j = 0; j < NFS_V41_NB_OPERATION; j++)
00594         fprintf(stats_file, "|%u,%u,%u",
00595                 global_worker_stat->stat_req.stat_op_nfs41[j].total,
00596                 global_worker_stat->stat_req.stat_op_nfs41[j].success,
00597                 global_worker_stat->stat_req.stat_op_nfs41[j].failed);
00598       fprintf(stats_file, "\n");
00599 
00600       fprintf(stats_file, "NLM V4 REQUEST,%s;%u", strdate,
00601               global_worker_stat->stat_req.nb_nlm4_req);
00602       for(j = 0; j < NLM_V4_NB_OPERATION; j++)
00603         fprintf(stats_file, "|%u,%u,%u",
00604                 global_worker_stat->stat_req.stat_req_nlm4[j].total,
00605                 global_worker_stat->stat_req.stat_req_nlm4[j].success,
00606                 global_worker_stat->stat_req.stat_req_nlm4[j].dropped);
00607       fprintf(stats_file, "\n");
00608 
00609       fprintf(stats_file, "RQUOTA V1 REQUEST,%s;%u", strdate,
00610               global_worker_stat->stat_req.nb_rquota1_req);
00611       for(j = 0; j < RQUOTA_NB_COMMAND; j++)
00612         fprintf(stats_file, "|%u,%u,%u",
00613                 global_worker_stat->stat_req.stat_req_rquota1[j].total,
00614                 global_worker_stat->stat_req.stat_req_rquota1[j].success,
00615                 global_worker_stat->stat_req.stat_req_rquota1[j].dropped);
00616       fprintf(stats_file, "\n");
00617 
00618       fprintf(stats_file, "RQUOTA V2 REQUEST,%s;%u", strdate,
00619               global_worker_stat->stat_req.nb_rquota2_req);
00620       for(j = 0; j < RQUOTA_NB_COMMAND; j++)
00621         fprintf(stats_file, "|%u,%u,%u",
00622                 global_worker_stat->stat_req.stat_req_rquota2[j].total,
00623                 global_worker_stat->stat_req.stat_req_rquota2[j].success,
00624                 global_worker_stat->stat_req.stat_req_rquota2[j].dropped);
00625       fprintf(stats_file, "\n");
00626 
00627       fprintf(stats_file,
00628               "DUP_REQ_HASH,%s;%zu,%zu,%zu,%zu\n",
00629               strdate,
00630               hstat_drc_udp->entries + hstat_drc_tcp->entries,
00631               hstat_drc_udp->min_rbt_num_node +
00632               hstat_drc_tcp->min_rbt_num_node,
00633               hstat_drc_udp->max_rbt_num_node +
00634               hstat_drc_tcp->max_rbt_num_node,
00635               hstat_drc_udp->average_rbt_num_node +
00636               hstat_drc_tcp->average_rbt_num_node);
00637 
00638       fprintf(stats_file,
00639               "UIDMAP_HASH,%s;%zu,%zu,%zu,%zu\n", strdate,
00640               uid_map_hstat->entries, uid_map_hstat->min_rbt_num_node,
00641               uid_map_hstat->max_rbt_num_node,
00642               uid_map_hstat->average_rbt_num_node);
00643       fprintf(stats_file,
00644               "UNAMEMAP_HASH,%s;%zu,%zu,%zu,%zu",
00645               strdate, hstat_uid_reverse->entries,
00646               hstat_uid_reverse->min_rbt_num_node,
00647               hstat_uid_reverse->max_rbt_num_node,
00648               hstat_uid_reverse->average_rbt_num_node);
00649 
00650       fprintf(stats_file,
00651               "GIDMAP_HASH,%s;%zu,%zu,%zu,%zu\n", strdate,
00652               gid_map_hstat->entries,
00653               gid_map_hstat->min_rbt_num_node,
00654               gid_map_hstat->max_rbt_num_node,
00655               gid_map_hstat->average_rbt_num_node);
00656       fprintf(stats_file,
00657               "GNAMEMAP_HASH,%s;%zu,%zu,%zu,%zu\n",
00658               strdate, hstat_gid_reverse->entries,
00659               hstat_gid_reverse->min_rbt_num_node,
00660               hstat_gid_reverse->max_rbt_num_node,
00661               hstat_gid_reverse->average_rbt_num_node);
00662 
00663       fprintf(stats_file,
00664               "IP_NAME_HASH,%s;%zu,%zu,%zu,%zu\n",
00665               strdate, ip_name_hstat->entries,
00666               ip_name_hstat->min_rbt_num_node,
00667               ip_name_hstat->max_rbt_num_node,
00668               ip_name_hstat->average_rbt_num_node);
00669 
00670       fprintf(stats_file, "FSAL_CALLS,%s;%llu", strdate,
00671               ganesha_stats.total_fsal_calls);
00672       for(j = 0; j < FSAL_NB_FUNC; j++)
00673         fprintf(stats_file, "|%u,%u,%u,%u",
00674                 global_fsal_stat->func_stats.nb_call[j],
00675                 global_fsal_stat->func_stats.nb_success[j],
00676                 global_fsal_stat->func_stats.nb_err_retryable[j],
00677                 global_fsal_stat->func_stats.nb_err_unrecover[j]);
00678       fprintf(stats_file, "\n");
00679 
00680       /* Flush the data written */
00681       fprintf(stats_file, "END, ----- NO MORE STATS FOR THIS PASS ----\n");
00682       fflush(stats_file);
00683 
00684       /* Now managed IP stats dump */
00685       nfs_ip_stats_dump(ht_ip_stats,
00686                         nfs_param.core_param.nb_worker,
00687                         nfs_param.core_param.stats_per_client_directory);
00688 
00689     }                           /* while ( 1 ) */
00690 
00691   return NULL;
00692 }                               /* stats_thread */