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