sensors protected by pthread mutex instead of g_mutex
[psensor.git] / src / lib / slog.c
1 /*
2  * Copyright (C) 2010-2012 jeanfi@gmail.com
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301 USA
18  */
19 #include <locale.h>
20 #include <libintl.h>
21 #define _(str) gettext(str)
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/stat.h>
27 #include <sys/time.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30
31 #include "bool.h"
32 #include "config.h"
33 #include "log.h"
34 #include "slog.h"
35
36 static FILE *file;
37 static struct timeval stv;
38 static double *last_values;
39 static int period;
40 static struct psensor **sensors;
41 static pthread_mutex_t *sensors_mutex;
42 static pthread_t thread;
43
44 static const char *DEFAULT_FILENAME = "sensors.log";
45
46 static char *get_default_path()
47 {
48         char *home, *path, *dir;
49
50         home = getenv("HOME");
51
52         if (home) {
53                 dir = malloc(strlen(home)+1+strlen(".psensor")+1);
54                 sprintf(dir, "%s/%s", home, ".psensor");
55                 mkdir(dir, 0777);
56
57                 path = malloc(strlen(dir)+1+strlen(DEFAULT_FILENAME)+1);
58                 sprintf(path, "%s/%s", dir, DEFAULT_FILENAME);
59
60                 free(dir);
61
62                 return path;
63         } else {
64                 log_warn(_("HOME variable not set."));
65                 return strdup(DEFAULT_FILENAME);
66         }
67 }
68
69 static bool slog_open(const char *path, struct psensor **sensors)
70 {
71         char *lpath;
72
73         if (file) {
74                 log_err(_("Sensor log file already open."));
75                 return 0;
76         }
77
78         lpath = path ? (char *)path : get_default_path();
79
80         file = fopen(lpath, "a");
81
82         if (!file)
83                 log_err(_("Cannot open sensor log file: %s."), lpath);
84
85         if (!path)
86                 free((char *)lpath);
87
88         if (!file)
89                 return 0;
90
91         if (gettimeofday(&stv, NULL)) {
92                 log_err(_("gettimeofday failed."));
93                 return 0;
94         }
95
96         fprintf(file, "I,%ld,%s\n", stv.tv_sec, VERSION);
97
98         while (*sensors) {
99                 fprintf(file, "S,%s,%x\n", (*sensors)->id,  (*sensors)->type);
100                 sensors++;
101         }
102
103         fflush(file);
104
105         return 1;
106 }
107
108 static void slog_write_sensors(struct psensor **sensors)
109 {
110         int count, i;
111         double v;
112         struct timeval tv;
113         bool first_call;
114
115         if (!file) {
116                 log_err(_("Sensor log file not open."));
117                 return ;
118         }
119
120         gettimeofday(&tv, NULL);
121
122         count = psensor_list_size(sensors);
123
124         if (last_values) {
125                 first_call = 0;
126         } else {
127                 first_call = 1;
128                 last_values = malloc(count * sizeof(double));
129         }
130
131         fprintf(file, "%ld", tv.tv_sec - stv.tv_sec);
132         for (i = 0; i < count; i++) {
133                 v = psensor_get_current_value(sensors[i]);
134
135                 if (!first_call && last_values[i] == v)
136                         fputc(',', file);
137                 else
138                         fprintf(file, ",%.1f", v);
139
140                 last_values[i] = v;
141         }
142
143         fputc('\n', file);
144
145         fflush(file);
146 }
147
148 static void *slog_routine(void *data)
149 {
150         while (1) {
151                 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
152                 pthread_mutex_lock(sensors_mutex);
153                 slog_write_sensors(sensors);
154                 pthread_mutex_unlock(sensors_mutex);
155                 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
156                 sleep(period);
157         }
158
159         pthread_exit(0);
160 }
161
162 void slog_close()
163 {
164         if (file) {
165                 pthread_cancel(thread);
166
167                 fclose(file);
168                 file = NULL;
169                 free(last_values);
170                 last_values = NULL;
171         } else {
172                 log_err(_("Sensor log not open, cannot close."));
173         }
174 }
175
176 bool slog_activate(const char *path,
177                    struct psensor **ss,
178                    pthread_mutex_t *mutex,
179                    int p)
180 {
181         bool ret;
182
183         sensors = ss;
184         sensors_mutex = mutex;
185         period = p;
186
187         pthread_mutex_lock(mutex);
188         ret = slog_open(path, sensors);
189         pthread_mutex_unlock(mutex);
190
191         if (ret)
192                 pthread_create(&thread, NULL, slog_routine, NULL);
193
194         return ret;
195 }