This patch introduces a feature whereby rrdcached will disallow updates
[rrdtool.git] / src / rrd_thread_safe_nt.c
1 /*****************************************************************************
2  * RRDtool 1.3.2  Copyright by Tobi Oetiker, 1997-2008
3  * This file:     Copyright 2003 Peter Stamfest <peter@stamfest.at> 
4  *                             & Tobias Oetiker
5  * Distributed under the GPL
6  *****************************************************************************
7  * rrd_thread_safe.c   Contains routines used when thread safety is required
8  *                     for win32
9  *****************************************************************************
10  * $Id$
11  *************************************************************************** */
12
13 #include <windows.h>
14 #include <string.h>
15 /* #include <error.h> */
16 #include "rrd.h"
17 #include "rrd_tool.h"
18
19 /* Key for the thread-specific rrd_context */
20 static DWORD context_key;
21 static CRITICAL_SECTION CriticalSection;
22
23
24 /* Once-only initialisation of the key */
25 static DWORD context_key_once = 0;
26
27
28 /* Free the thread-specific rrd_context - we might actually use
29    rrd_free_context instead...
30  */
31 static void context_destroy_context(
32     void)
33 {
34     DeleteCriticalSection(&CriticalSection);
35     TlsFree(context_key);
36     context_key_once = 0;
37 }
38 static void context_init_context(
39     void)
40 {
41     if (!InterlockedExchange(&context_key_once, 1)) {
42         context_key = TlsAlloc();
43         InitializeCriticalSection(&CriticalSection);
44         atexit(context_destroy_context);
45     }
46 }
47 rrd_context_t *rrd_get_context(
48     void)
49 {
50     rrd_context_t *ctx;
51
52     context_init_context();
53
54     ctx = TlsGetValue(context_key);
55     if (!ctx) {
56         ctx = rrd_new_context();
57         TlsSetValue(context_key, ctx);
58     }
59     return ctx;
60 }
61
62 #undef strerror
63 const char *rrd_strerror(
64     int err)
65 {
66     rrd_context_t *ctx;
67
68     context_init_context();
69
70     ctx = rrd_get_context();
71
72     EnterCriticalSection(&CriticalSection);
73     strncpy(ctx->lib_errstr, strerror(err), sizeof(ctx->lib_errstr));
74     ctx->lib_errstr[sizeof(ctx->lib_errstr) - 1] = '\0';
75     LeaveCriticalSection(&CriticalSection);
76
77     return ctx->lib_errstr;
78 }
79
80 /*
81  * there much be a re-entrant version of these somewhere in win32 land
82  */
83 struct tm *localtime_r(
84     const time_t *timep,
85     struct tm *result)
86 {
87     struct tm *local;
88
89     context_init_context();
90
91     EnterCriticalSection(&CriticalSection);
92     local = localtime(timep);
93     memcpy(result, local, sizeof(struct tm));
94     LeaveCriticalSection(&CriticalSection);
95     return result;
96 }
97
98 char     *ctime_r(
99     const time_t *timep,
100     char *result)
101 {
102     char     *local;
103
104     context_init_context();
105
106     EnterCriticalSection(&CriticalSection);
107     local = ctime(timep);
108     strcpy(result, local);
109     LeaveCriticalSection(&CriticalSection);
110     return result;
111 }
112
113 struct tm *gmtime_r(
114     const time_t *timep,
115     struct tm *result)
116 {
117     struct tm *local;
118
119     context_init_context();
120
121     EnterCriticalSection(&CriticalSection);
122     local = gmtime(timep);
123     memcpy(result, local, sizeof(struct tm));
124     LeaveCriticalSection(&CriticalSection);
125     return result;
126 }
127
128 /* implementation from Apache's APR library */
129 char     *strtok_r(
130     char *str,
131     const char *sep,
132     char **last)
133 {
134     char     *token;
135
136     context_init_context();
137
138
139     if (!str)           /* subsequent call */
140         str = *last;    /* start where we left off */
141
142     /* skip characters in sep (will terminate at '\0') */
143     while (*str && strchr(sep, *str))
144         ++str;
145
146     if (!*str)          /* no more tokens */
147         return NULL;
148
149     token = str;
150
151     /* skip valid token characters to terminate token and
152      * prepare for the next call (will terminate at '\0) 
153      */
154     *last = token + 1;
155     while (**last && !strchr(sep, **last))
156         ++ * last;
157
158     if (**last) {
159         **last = '\0';
160         ++*last;
161     }
162
163     return token;
164 }