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