]> git.sur5r.net Git - openldap/blob - servers/slurpd/st.c
fix controls propagation (ITS#3813)
[openldap] / servers / slurpd / st.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2005 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15 /* Portions Copyright (c) 1996 Regents of the University of Michigan.
16  * All rights reserved.
17  *
18  * Redistribution and use in source and binary forms are permitted
19  * provided that this notice is preserved and that due credit is given
20  * to the University of Michigan at Ann Arbor. The name of the University
21  * may not be used to endorse or promote products derived from this
22  * software without specific prior written permission. This software
23  * is provided ``as is'' without express or implied warranty.
24  */
25 /* ACKNOWLEDGEMENTS:
26  * This work was originally developed by the University of Michigan
27  * (as part of U-MICH LDAP).
28  */
29
30
31 /*
32  * st.c - routines for managing the status structure, and for reading and
33  * writing status information to disk.
34  */
35
36 #include "portable.h"
37
38 #include <stdio.h>
39
40 #include <ac/stdlib.h>
41 #include <ac/string.h>
42 #include <ac/unistd.h>
43
44 #include "slurp.h"
45 #include "globals.h"
46
47 /*
48  * Add information about replica host specified by Ri to list
49  * of hosts.
50  */
51 static Stel *
52 St_add(
53     St  *st,
54     Ri  *ri
55 )
56 {
57     int ind;
58
59     if ( st == NULL || ri == NULL ) {
60         return NULL;
61     }
62
63     /* Serialize access to the St struct */
64     ldap_pvt_thread_mutex_lock( &(st->st_mutex ));
65
66     st->st_nreplicas++;
67     ind = st->st_nreplicas - 1;
68     st->st_data = ( Stel ** ) ch_realloc( st->st_data, 
69             ( st->st_nreplicas * sizeof( Stel * )));
70     if ( st->st_data == NULL ) {
71         ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
72         return NULL;
73     }
74     st->st_data[ ind ]  = ( Stel * ) ch_malloc( sizeof( Stel ) );
75     if ( st->st_data[ ind ] == NULL ) {
76         ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
77         return NULL;
78     }
79
80     st->st_data[ ind ]->hostname = strdup( ri->ri_hostname );
81     st->st_data[ ind ]->port = ri->ri_port;
82     st->st_data[ ind ]->last = 0; 
83     st->st_data[ ind ]->seq = 0;
84
85     ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
86     return st->st_data[ ind ];
87 }
88
89
90
91 /*
92  * Write the contents of an St to disk.
93  */
94 static int
95 St_write (
96     St  *st
97 )
98 {
99     int         rc;
100     Stel        *stel;
101     int         i;
102
103     if ( st == NULL ) {
104         return -1;
105     }
106     ldap_pvt_thread_mutex_lock( &(st->st_mutex ));
107     if ( st->st_fp == NULL ) {
108         /* Open file */
109         if (( rc = acquire_lock( sglob->slurpd_status_file, &(st->st_fp),
110                 &(st->st_lfp))) < 0 ) {
111             if ( !st->st_err_logged ) {
112 #ifdef NEW_LOGGING
113                 LDAP_LOG ( SLURPD, ERR, "St_write: "
114                         "Error: cannot open status file \"%s\":%s\n",
115                         sglob->slurpd_status_file, sys_errlist[ errno ], 0 );
116 #else
117                 Debug( LDAP_DEBUG_ANY,
118                         "Error: cannot open status file \"%s\": %s\n",
119                         sglob->slurpd_status_file, sys_errlist[ errno ], 0 );
120 #endif
121                 st->st_err_logged = 1;
122                 ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
123                 return -1;
124             }
125         } else {
126             st->st_err_logged = 0;
127         }
128     }
129
130     /* Write data to the file */
131     truncate( sglob->slurpd_status_file, 0L );
132     fseek( st->st_fp, 0L, 0 );
133     for ( i = 0; i < st->st_nreplicas; i++ ) {
134         stel = st->st_data[ i ];
135         fprintf( st->st_fp, "%s:%d:%ld:%d\n",
136                 stel->hostname, stel->port,
137                 (long) stel->last, stel->seq );
138     }
139     fflush( st->st_fp );
140
141     ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
142
143     return 0;
144 }
145     
146
147
148
149 /*
150  * Update the entry for a given host.
151  */
152 static int
153 St_update(
154     St          *st,
155     Stel        *stel,
156     Re          *re
157 )
158 {
159     if ( stel == NULL || re == NULL ) {
160         return -1;
161     }
162
163     ldap_pvt_thread_mutex_lock( &(st->st_mutex ));
164     stel->last = re->re_timestamp;
165     stel->seq = re->re_seq;
166     ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
167     return 0;
168 }
169
170
171
172
173 /*
174  * Read status information from disk file.
175  */
176 static int
177 St_read(
178     St  *st
179 )
180 {
181     FILE        *fp;
182     FILE        *lfp;
183     char        buf[ 255 ];
184     int         i;
185     int         rc;
186     char        *hostname, *port, *timestamp, *seq, *p, *t;
187     int         found;
188
189     if ( st == NULL ) {
190         return -1;
191     }
192     ldap_pvt_thread_mutex_lock( &(st->st_mutex ));
193     if ( access( sglob->slurpd_status_file, F_OK ) < 0 ) {
194         /*
195          * File doesn't exist, so create it and return.
196          */
197         if (( fp = fopen( sglob->slurpd_status_file, "w" )) == NULL ) {
198 #ifdef NEW_LOGGING
199                 LDAP_LOG ( SLURPD, ERR, "St_write: "
200                         "Error: cannot create status file \"%s\"\n",
201                     sglob->slurpd_status_file, 0, 0 );
202 #else
203             Debug( LDAP_DEBUG_ANY, "Error: cannot create status file \"%s\"\n",
204                     sglob->slurpd_status_file, 0, 0 );
205 #endif
206             ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
207             return -1;
208         }
209         (void) fclose( fp );
210         ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
211 #ifdef NEW_LOGGING
212         LDAP_LOG ( SLURPD, DETAIL1, "St_write: "
213                 "No status file found, defaulting values\n", 0, 0, 0 );
214 #else
215         Debug( LDAP_DEBUG_ARGS, "No status file found, defaulting values\n",
216                 0, 0, 0 );
217 #endif
218         return 0;
219     }
220     if (( rc = acquire_lock( sglob->slurpd_status_file, &fp, &lfp)) < 0 ) {
221         ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
222         return 0;
223     }
224     while ( fgets( buf, sizeof( buf ), fp ) != NULL ) {
225         p = buf;
226         hostname = p;
227         if (( t = strchr( p, ':' )) == NULL ) {
228             goto bad;
229         }
230         *t++ = '\0';
231         p = t;
232         port = p;
233         if (( t = strchr( p, ':' )) == NULL ) {
234             goto bad;
235         }
236         *t++ = '\0';
237         p = t;
238         timestamp = p;
239         if (( t = strchr( p, ':' )) == NULL ) {
240             goto bad;
241         }
242         *t++ = '\0';
243         seq = t;
244         if (( t = strchr( seq, '\n' )) != NULL ) {
245             *t = '\0';
246         }
247
248         found = 0;
249         for ( i = 0; i < sglob->st->st_nreplicas; i++ ) {
250             if ( !strcmp( hostname, sglob->st->st_data[ i ]->hostname ) &&
251                     atoi( port ) == sglob->st->st_data[ i ]->port ) {
252                 found = 1;
253                 sglob->st->st_data[ i ]->last = atol( timestamp );
254                 sglob->st->st_data[ i ]->seq = atoi( seq );
255                 break;
256             }
257         }
258         if ( found ) {
259             char tbuf[ 255 ];
260             sprintf( tbuf, "%s:%s (timestamp %s.%s)", hostname, port,
261                     timestamp, seq );
262 #ifdef NEW_LOGGING
263                 LDAP_LOG ( SLURPD, DETAIL1, "St_write: "
264                         "Retrieved state information for %s\n", tbuf, 0, 0 );
265 #else
266             Debug( LDAP_DEBUG_ARGS,
267                     "Retrieved state information for %s\n", tbuf, 0, 0 );
268 #endif
269         } else {
270 #ifdef NEW_LOGGING
271                 LDAP_LOG ( SLURPD, WARNING, "St_write: "
272                         "Warning: saved state for %s:%s, not a known replica\n", 
273                         hostname, port, 0 );
274 #else
275             Debug(  LDAP_DEBUG_ANY,
276                     "Warning: saved state for %s:%s, not a known replica\n",
277                     hostname, port, 0 );
278 #endif
279         }
280     }
281     (void) relinquish_lock( sglob->slurpd_status_file, fp, lfp);
282     ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
283     return 0;
284
285 bad:
286     (void) relinquish_lock( sglob->slurpd_status_file, fp, lfp);
287     ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
288     return -1;
289 }
290     
291
292
293
294 /*
295  * Lock an St struct.
296  */
297 static int
298 St_lock(
299     St *st
300 )
301 {
302     return( ldap_pvt_thread_mutex_lock( &st->st_mutex ));
303 }
304
305
306
307
308 /*
309  * Lock an St struct.
310  */
311 static int
312 St_unlock(
313     St *st
314 )
315 {
316     return( ldap_pvt_thread_mutex_unlock( &st->st_mutex ));
317 }
318
319
320
321
322 /*
323  * Allocate and initialize an St struct.
324  */
325 int
326 St_init(
327     St **st
328 )
329 {
330     if ( st == NULL ) {
331         return -1;
332     }
333
334     (*st) = (St *) malloc( sizeof( St ));
335     if ( *st == NULL ) {
336         return -1;
337     }
338
339     ldap_pvt_thread_mutex_init( &((*st)->st_mutex) );
340     (*st)->st_data = NULL;
341     (*st)->st_fp = NULL;
342     (*st)->st_lfp = NULL;
343     (*st)->st_nreplicas = 0;
344     (*st)->st_err_logged = 0;
345     (*st)->st_update = St_update;
346     (*st)->st_add = St_add;
347     (*st)->st_write = St_write;
348     (*st)->st_read = St_read;
349     (*st)->st_lock = St_lock;
350     (*st)->st_unlock = St_unlock;
351     return 0;
352 }
353