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