]> git.sur5r.net Git - openldap/blob - servers/slurpd/st.c
Update BDB requirements
[openldap] / servers / slurpd / st.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2007 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     long        last;
184
185     if ( st == NULL ) {
186         return -1;
187     }
188     ldap_pvt_thread_mutex_lock( &(st->st_mutex ));
189     if ( access( sglob->slurpd_status_file, F_OK ) < 0 ) {
190         /*
191          * File doesn't exist, so create it and return.
192          */
193         if (( fp = fopen( sglob->slurpd_status_file, "w" )) == NULL ) {
194             Debug( LDAP_DEBUG_ANY, "Error: cannot create status file \"%s\"\n",
195                     sglob->slurpd_status_file, 0, 0 );
196             ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
197             return -1;
198         }
199         (void) fclose( fp );
200         ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
201         Debug( LDAP_DEBUG_ARGS, "No status file found, defaulting values\n",
202                 0, 0, 0 );
203         return 0;
204     }
205     if (( rc = acquire_lock( sglob->slurpd_status_file, &fp, &lfp)) < 0 ) {
206         ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
207         return 0;
208     }
209     while ( fgets( buf, sizeof( buf ), fp ) != NULL ) {
210         p = buf;
211         hostname = p;
212         if (( t = strchr( p, ':' )) == NULL ) {
213             goto bad;
214         }
215         *t++ = '\0';
216         p = t;
217         port = p;
218         if (( t = strchr( p, ':' )) == NULL ) {
219             goto bad;
220         }
221         *t++ = '\0';
222         p = t;
223         timestamp = p;
224         if (( t = strchr( p, ':' )) == NULL ) {
225             goto bad;
226         }
227         *t++ = '\0';
228         seq = t;
229         if (( t = strchr( seq, '\n' )) != NULL ) {
230             *t = '\0';
231         }
232
233         found = 0;
234         for ( i = 0; i < sglob->st->st_nreplicas; i++ ) {
235             int p;
236             if ( !strcmp( hostname, sglob->st->st_data[ i ]->hostname ) &&
237                     lutil_atoi( &p, port ) == 0 && p == sglob->st->st_data[ i ]->port )
238             {
239                 found = (lutil_atol( &last, timestamp ) == 0);
240                 if ( found ) {
241                     sglob->st->st_data[i]->last = last;
242                     if ( lutil_atoi( &sglob->st->st_data[i]->seq, seq ) != 0 )
243                         found = 0;
244                 }
245                 break;
246             }
247         }
248         if ( found ) {
249             char tbuf[ 255 ];
250             sprintf( tbuf, "%s.%s", timestamp, seq );
251             Debug( LDAP_DEBUG_ARGS,
252                     "Retrieved state information for %s:%s (timestamp %s)\n", hostname, port, tbuf );
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