]> git.sur5r.net Git - openldap/blob - servers/slurpd/st.c
Happy new year!
[openldap] / servers / slurpd / st.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2006 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 #include "lutil.h"
47
48 /*
49  * Add information about replica host specified by Ri to list
50  * of hosts.
51  */
52 static Stel *
53 St_add(
54     St  *st,
55     Ri  *ri
56 )
57 {
58     int ind;
59
60     if ( st == NULL || ri == NULL ) {
61         return NULL;
62     }
63
64     /* Serialize access to the St struct */
65     ldap_pvt_thread_mutex_lock( &(st->st_mutex ));
66
67     st->st_nreplicas++;
68     ind = st->st_nreplicas - 1;
69     st->st_data = ( Stel ** ) ch_realloc( st->st_data, 
70             ( st->st_nreplicas * sizeof( Stel * )));
71     if ( st->st_data == NULL ) {
72         ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
73         return NULL;
74     }
75     st->st_data[ ind ]  = ( Stel * ) ch_malloc( sizeof( Stel ) );
76     if ( st->st_data[ ind ] == NULL ) {
77         ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
78         return NULL;
79     }
80
81     st->st_data[ ind ]->hostname = strdup( ri->ri_hostname );
82     st->st_data[ ind ]->port = ri->ri_port;
83     st->st_data[ ind ]->last = 0; 
84     st->st_data[ ind ]->seq = 0;
85
86     ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
87     return st->st_data[ ind ];
88 }
89
90
91
92 /*
93  * Write the contents of an St to disk.
94  */
95 static int
96 St_write (
97     St  *st
98 )
99 {
100     int         rc;
101     Stel        *stel;
102     int         i;
103
104     if ( st == NULL ) {
105         return -1;
106     }
107     ldap_pvt_thread_mutex_lock( &(st->st_mutex ));
108     if ( st->st_fp == NULL ) {
109         /* Open file */
110         if (( rc = acquire_lock( sglob->slurpd_status_file, &(st->st_fp),
111                 &(st->st_lfp))) < 0 ) {
112             if ( !st->st_err_logged ) {
113                 Debug( LDAP_DEBUG_ANY,
114                         "Error: cannot open status file \"%s\": %s\n",
115                         sglob->slurpd_status_file, sys_errlist[ errno ], 0 );
116                 st->st_err_logged = 1;
117                 ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
118                 return -1;
119             }
120         } else {
121             st->st_err_logged = 0;
122         }
123     }
124
125     /* Write data to the file */
126     truncate( sglob->slurpd_status_file, 0L );
127     fseek( st->st_fp, 0L, 0 );
128     for ( i = 0; i < st->st_nreplicas; i++ ) {
129         stel = st->st_data[ i ];
130         fprintf( st->st_fp, "%s:%d:%ld:%d\n",
131                 stel->hostname, stel->port,
132                 (long) stel->last, stel->seq );
133     }
134     fflush( st->st_fp );
135
136     ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
137
138     return 0;
139 }
140     
141
142
143
144 /*
145  * Update the entry for a given host.
146  */
147 static int
148 St_update(
149     St          *st,
150     Stel        *stel,
151     Re          *re
152 )
153 {
154     if ( stel == NULL || re == NULL ) {
155         return -1;
156     }
157
158     ldap_pvt_thread_mutex_lock( &(st->st_mutex ));
159     stel->last = re->re_timestamp;
160     stel->seq = re->re_seq;
161     ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
162     return 0;
163 }
164
165
166
167
168 /*
169  * Read status information from disk file.
170  */
171 static int
172 St_read(
173     St  *st
174 )
175 {
176     FILE        *fp;
177     FILE        *lfp;
178     char        buf[ 255 ];
179     int         i;
180     int         rc;
181     char        *hostname, *port, *timestamp, *seq, *p, *t;
182     int         found;
183
184     if ( st == NULL ) {
185         return -1;
186     }
187     ldap_pvt_thread_mutex_lock( &(st->st_mutex ));
188     if ( access( sglob->slurpd_status_file, F_OK ) < 0 ) {
189         /*
190          * File doesn't exist, so create it and return.
191          */
192         if (( fp = fopen( sglob->slurpd_status_file, "w" )) == NULL ) {
193             Debug( LDAP_DEBUG_ANY, "Error: cannot create status file \"%s\"\n",
194                     sglob->slurpd_status_file, 0, 0 );
195             ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
196             return -1;
197         }
198         (void) fclose( fp );
199         ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
200         Debug( LDAP_DEBUG_ARGS, "No status file found, defaulting values\n",
201                 0, 0, 0 );
202         return 0;
203     }
204     if (( rc = acquire_lock( sglob->slurpd_status_file, &fp, &lfp)) < 0 ) {
205         ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
206         return 0;
207     }
208     while ( fgets( buf, sizeof( buf ), fp ) != NULL ) {
209         p = buf;
210         hostname = p;
211         if (( t = strchr( p, ':' )) == NULL ) {
212             goto bad;
213         }
214         *t++ = '\0';
215         p = t;
216         port = p;
217         if (( t = strchr( p, ':' )) == NULL ) {
218             goto bad;
219         }
220         *t++ = '\0';
221         p = t;
222         timestamp = p;
223         if (( t = strchr( p, ':' )) == NULL ) {
224             goto bad;
225         }
226         *t++ = '\0';
227         seq = t;
228         if (( t = strchr( seq, '\n' )) != NULL ) {
229             *t = '\0';
230         }
231
232         found = 0;
233         for ( i = 0; i < sglob->st->st_nreplicas; i++ ) {
234             int p;
235             if ( !strcmp( hostname, sglob->st->st_data[ i ]->hostname ) &&
236                     lutil_atoi( &p, port ) == 0 && p == sglob->st->st_data[ i ]->port )
237             {
238                 found = 1;
239                 if ( lutil_atol( &sglob->st->st_data[ i ]->last, timestamp ) != 0
240                         || lutil_atoi( &sglob->st->st_data[ i ]->seq, seq ) != 0 )
241                 {
242                     found = 0;
243                 }
244                 break;
245             }
246         }
247         if ( found ) {
248             char tbuf[ 255 ];
249             sprintf( tbuf, "%s:%s (timestamp %s.%s)", hostname, port,
250                     timestamp, seq );
251             Debug( LDAP_DEBUG_ARGS,
252                     "Retrieved state information for %s\n", tbuf, 0, 0 );
253         } else {
254             Debug(  LDAP_DEBUG_ANY,
255                     "Warning: saved state for %s:%s, not a known replica\n",
256                     hostname, port, 0 );
257         }
258     }
259     (void) relinquish_lock( sglob->slurpd_status_file, fp, lfp);
260     ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
261     return 0;
262
263 bad:
264     (void) relinquish_lock( sglob->slurpd_status_file, fp, lfp);
265     ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
266     return -1;
267 }
268     
269
270
271
272 /*
273  * Lock an St struct.
274  */
275 static int
276 St_lock(
277     St *st
278 )
279 {
280     return( ldap_pvt_thread_mutex_lock( &st->st_mutex ));
281 }
282
283
284
285
286 /*
287  * Lock an St struct.
288  */
289 static int
290 St_unlock(
291     St *st
292 )
293 {
294     return( ldap_pvt_thread_mutex_unlock( &st->st_mutex ));
295 }
296
297
298
299
300 /*
301  * Allocate and initialize an St struct.
302  */
303 int
304 St_init(
305     St **st
306 )
307 {
308     if ( st == NULL ) {
309         return -1;
310     }
311
312     (*st) = (St *) malloc( sizeof( St ));
313     if ( *st == NULL ) {
314         return -1;
315     }
316
317     ldap_pvt_thread_mutex_init( &((*st)->st_mutex) );
318     (*st)->st_data = NULL;
319     (*st)->st_fp = NULL;
320     (*st)->st_lfp = NULL;
321     (*st)->st_nreplicas = 0;
322     (*st)->st_err_logged = 0;
323     (*st)->st_update = St_update;
324     (*st)->st_add = St_add;
325     (*st)->st_write = St_write;
326     (*st)->st_read = St_read;
327     (*st)->st_lock = St_lock;
328     (*st)->st_unlock = St_unlock;
329     return 0;
330 }
331