]> git.sur5r.net Git - openldap/blob - servers/slurpd/st.c
032705f86583a715ce2e5072dcbbb2813f365a64
[openldap] / servers / slurpd / st.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2000 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     memset( st->st_data[ ind ]->last, '\0', sizeof( st->st_data[ ind ]->last )); 
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                 Debug( LDAP_DEBUG_ANY,
101                         "Error: cannot open status file \"%s\": %s\n",
102                         sglob->slurpd_status_file, sys_errlist[ errno ], 0 );
103                 st->st_err_logged = 1;
104                 ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
105                 return -1;
106             }
107         } else {
108             st->st_err_logged = 0;
109         }
110     }
111
112     /* Write data to the file */
113     truncate( sglob->slurpd_status_file, 0L );
114     fseek( st->st_fp, 0L, 0 );
115     for ( i = 0; i < st->st_nreplicas; i++ ) {
116         stel = st->st_data[ i ];
117         fprintf( st->st_fp, "%s:%d:%s:%d\n", stel->hostname, stel->port,
118                 stel->last, stel->seq );
119     }
120     fflush( st->st_fp );
121
122     ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
123
124     return 0;
125 }
126     
127
128
129
130 /*
131  * Update the entry for a given host.
132  */
133 static int
134 St_update(
135     St          *st,
136     Stel        *stel,
137     Re          *re
138 )
139 {
140     if ( stel == NULL || re == NULL ) {
141         return -1;
142     }
143
144     ldap_pvt_thread_mutex_lock( &(st->st_mutex ));
145     strcpy( stel->last, re->re_timestamp );
146     stel->seq = re->re_seq;
147     ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
148     return 0;
149 }
150
151
152
153
154 /*
155  * Read status information from disk file.
156  */
157 static int
158 St_read(
159     St  *st
160 )
161 {
162     FILE        *fp;
163     FILE        *lfp;
164     char        buf[ 255 ];
165     int         i;
166     int         rc;
167     char        *hostname, *port, *timestamp, *seq, *p, *t;
168     int         found;
169
170     if ( st == NULL ) {
171         return -1;
172     }
173     ldap_pvt_thread_mutex_lock( &(st->st_mutex ));
174     if ( access( sglob->slurpd_status_file, F_OK ) < 0 ) {
175         /*
176          * File doesn't exist, so create it and return.
177          */
178         if (( fp = fopen( sglob->slurpd_status_file, "w" )) == NULL ) {
179             Debug( LDAP_DEBUG_ANY, "Error: cannot create status file \"%s\"\n",
180                     sglob->slurpd_status_file, 0, 0 );
181             ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
182             return -1;
183         }
184         (void) fclose( fp );
185         ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
186         Debug( LDAP_DEBUG_ARGS, "No status file found, defaulting values\n",
187                 0, 0, 0 );
188         return 0;
189     }
190     if (( rc = acquire_lock( sglob->slurpd_status_file, &fp, &lfp)) < 0 ) {
191         ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
192         return 0;
193     }
194     while ( fgets( buf, sizeof( buf ), fp ) != NULL ) {
195         p = buf;
196         hostname = p;
197         if (( t = strchr( p, ':' )) == NULL ) {
198             goto bad;
199         }
200         *t++ = '\0';
201         p = t;
202         port = p;
203         if (( t = strchr( p, ':' )) == NULL ) {
204             goto bad;
205         }
206         *t++ = '\0';
207         p = t;
208         timestamp = p;
209         if (( t = strchr( p, ':' )) == NULL ) {
210             goto bad;
211         }
212         *t++ = '\0';
213         seq = t;
214         if (( t = strchr( seq, '\n' )) != NULL ) {
215             *t = '\0';
216         }
217
218         found = 0;
219         for ( i = 0; i < sglob->st->st_nreplicas; i++ ) {
220             if ( !strcmp( hostname, sglob->st->st_data[ i ]->hostname ) &&
221                     atoi( port ) == sglob->st->st_data[ i ]->port ) {
222                 found = 1;
223                 strcpy( sglob->st->st_data[ i ]->last, timestamp );
224                 sglob->st->st_data[ i ]->seq = atoi( seq );
225                 break;
226             }
227         }
228         if ( found ) {
229             char tbuf[ 255 ];
230             sprintf( tbuf, "%s:%s (timestamp %s.%s)", hostname, port,
231                     timestamp, seq );
232             Debug( LDAP_DEBUG_ARGS,
233                     "Retrieved state information for %s\n", tbuf, 0, 0 );
234         } else {
235             Debug(  LDAP_DEBUG_ANY,
236                     "Warning: saved state for %s:%s, not a known replica\n",
237                     hostname, port, 0 );
238         }
239     }
240     (void) relinquish_lock( sglob->slurpd_status_file, fp, lfp);
241     ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
242     return 0;
243
244 bad:
245     (void) relinquish_lock( sglob->slurpd_status_file, fp, lfp);
246     ldap_pvt_thread_mutex_unlock( &(st->st_mutex ));
247     return -1;
248 }
249     
250
251
252
253 /*
254  * Lock an St struct.
255  */
256 static int
257 St_lock(
258     St *st
259 )
260 {
261     return( ldap_pvt_thread_mutex_lock( &st->st_mutex ));
262 }
263
264
265
266
267 /*
268  * Lock an St struct.
269  */
270 static int
271 St_unlock(
272     St *st
273 )
274 {
275     return( ldap_pvt_thread_mutex_unlock( &st->st_mutex ));
276 }
277
278
279
280
281 /*
282  * Allocate and initialize an St struct.
283  */
284 int
285 St_init(
286     St **st
287 )
288 {
289     if ( st == NULL ) {
290         return -1;
291     }
292
293     (*st) = (St *) malloc( sizeof( St ));
294     if ( *st == NULL ) {
295         return -1;
296     }
297
298     ldap_pvt_thread_mutex_init( &((*st)->st_mutex) );
299     (*st)->st_data = NULL;
300     (*st)->st_fp = NULL;
301     (*st)->st_lfp = NULL;
302     (*st)->st_nreplicas = 0;
303     (*st)->st_err_logged = 0;
304     (*st)->st_update = St_update;
305     (*st)->st_add = St_add;
306     (*st)->st_write = St_write;
307     (*st)->st_read = St_read;
308     (*st)->st_lock = St_lock;
309     (*st)->st_unlock = St_unlock;
310     return 0;
311 }
312