wmclockmon: update change-log
[dockapps.git] / ascd / libworkman / index.c
blob668e011644243e88edbafc1a6f02e3d8b59c0835
1 /*
2 * $Id: index.c,v 1.2 1999/02/14 09:50:42 dirk Exp $
4 * This file is part of WorkMan, the civilized CD player library
5 * (c) 1991-1997 by Steven Grimm (original author)
6 * (c) by Dirk Försterling (current 'author' = maintainer)
7 * The maintainer can be contacted by his e-mail address:
8 * milliByte@DeathsDoor.com
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the Free
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 * Maintain an external index file for a WorkMan CD database.
26 * Uses the Berkeley libdb library, available from ftp.cs.berkeley.edu.
29 static char index_id[] = "$Id: index.c,v 1.2 1999/02/14 09:50:42 dirk Exp $";
31 #ifdef LIBDB
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <db.h>
36 #include <fcntl.h>
37 #include <string.h>
38 #include <netinet/in.h> /* for htonl() */
39 #include "include/wm_config.h"
40 #include "include/wm_index.h"
42 extern int suppress_locking;
45 * idx_find_entry()
47 * Find an entry in the index file.
49 * Input:
50 * file Name of database file (text version).
51 * ntracks Number of tracks on the CD we're looking for.
52 * tracks Array of track start times.
53 * len CD length in frames.
54 * fuzz Fuzz factor (tolerance value).
55 * pos Pointer to return value.
57 * Output:
58 * 1 No matching record found.
59 * 0 Record found; *pos contains offset into text file.
60 * -1 Index file out of date or inaccessible, or another error.
62 int
63 idx_find_entry( char *file, int ntracks, int *tracks,
64 int len, int fuzz, unsigned long *pos )
66 unsigned long dbpos;
67 char *indexname = NULL, keyval[8];
68 int c;
69 FILE *text;
70 DB *index;
71 DBT key, data;
72 BTREEINFO bti;
75 * First, see if the text file is accessible. Lock it if so.
77 text = fopen(file, "r");
78 if (text == NULL)
79 return (-1);
80 if ((c = getc(text)) == EOF)
82 fclose(text);
83 return (-1);
85 if (! suppress_locking)
86 if (lockit(fileno(text), F_RDLCK))
88 fclose(text);
89 return (-1);
93 * Open the index file.
95 indexname = malloc(strlen(file) + sizeof(".ind"));
96 if (indexname == NULL)
98 fclose(text);
99 return (-1);
101 strcpy(indexname, file);
102 strcat(indexname, ".ind");
103 bti.flags = 0;
104 bti.cachesize = 0;
105 bti.minkeypage = bti.maxkeypage = 0;
106 bti.psize = bti.lorder = 0;
107 bti.compare = NULL;
108 bti.prefix = NULL;
109 index = dbopen(indexname, O_RDONLY, 0666, DB_BTREE, &bti);
110 free(indexname);
111 if (index == NULL)
113 fclose(text);
114 return (-1);
118 * Search for the first matching entry.
120 sprintf(keyval, "%07d", tracks[ntracks - 1] - fuzz);
121 key.data = keyval;
122 key.size = 7;
123 if (c = (index->seq)(index, &key, &data, R_CURSOR))
125 (index->close)(index);
126 fclose(text);
127 return (c);
131 * Now loop through all the possible matches, collecting them into
132 * memory.
134 do {
135 char tracksline[750], *s;
136 int i, val;
138 /* Hit the end of the valid entries? */
139 sscanf(key.data, "%d", &val);
140 if (val > tracks[ntracks - 1] + fuzz)
141 break;
143 dbpos = ntohl(*((unsigned long *) data.data));
144 if (fseek(text, dbpos, 0))
145 break;
147 fgets(tracksline, sizeof(tracksline), text);
148 if (strncmp(tracksline, "tracks ", 7))
149 break;
150 (void) strtok(tracksline, " \t");
152 /* Got a valid tracks line. See if it matches the CD. */
153 s = strtok(NULL, " \t");
154 if (s == NULL)
155 break;
156 if (atoi(s) != ntracks)
157 continue;
159 for (i = 0; i < ntracks; i++)
161 s = strtok(NULL, " \t");
162 if (s == NULL)
163 break;
164 val = atoi(s);
165 if (val + fuzz < tracks[i] || val - fuzz > tracks[i])
166 break;
168 if (i != ntracks)
169 continue;
171 s = strtok(NULL, " \t");
172 if (s == NULL)
173 continue;
174 val = atoi(s);
175 if (val + fuzz / 75 < len / 75 || val + fuzz / 75 > len / 75)
176 continue;
178 /* XXX - add to sorted list! */
179 *pos = dbpos;
180 (index->close)(index);
181 fclose(text);
182 return (0);
183 } while ((c = (index->seq)(index, &key, &data, R_NEXT)) == 0);
185 if (c == 0)
187 /* An error. */
188 (index->close)(index);
189 fclose(text);
190 return (-1);
193 (index->close)(index);
194 fclose(text);
195 return (1);
199 * idx_delete_entry()
201 * Delete an entry from the index file.
203 * Input:
204 * file Name of database file (text version).
205 * track Last track's start time (database key).
206 * fuzz Fuzz factor (tolerance value).
207 * pos Position of CD in database file.
209 * Output:
210 * 1 No matching record found.
211 * 0 Record deleted.
212 * -1 Index file out of date or inaccessible, or another error.
214 * Note: it is the caller's responsibility to do locking, as it's assumed
215 * that this operation will accompany a modification of the main database
216 * file and will need to be atomic with that modification.
219 idx_delete_entry(char *file, int track, int fuzz, unsigned long pos )
221 unsigned long dbpos;
222 char *indexname = NULL, keyval[8];
223 int c, status;
224 DB *index;
225 DBT key, data;
226 BTREEINFO bti;
229 * Open the index file.
231 indexname = malloc(strlen(file) + sizeof(".ind"));
232 if (indexname == NULL)
233 return (-1);
235 strcpy(indexname, file);
236 strcat(indexname, ".ind");
238 bti.flags = 0;
239 bti.cachesize = 0;
240 bti.minkeypage = bti.maxkeypage = 0;
241 bti.psize = bti.lorder = 0;
242 bti.compare = NULL;
243 bti.prefix = NULL;
244 index = dbopen(indexname, O_RDWR, 0666, DB_BTREE, &bti);
245 free(indexname);
246 if (index == NULL)
247 return (-1);
250 * Search for the first matching entry.
252 sprintf(keyval, "%07d", track - fuzz);
253 key.data = keyval;
254 key.size = 7;
255 if (c = (index->seq)(index, &key, &data, R_CURSOR))
258 * Nothing matched!
260 (index->close)(index);
261 return (c);
265 * Look for the entry the user wants to delete.
267 do {
268 int val;
270 /* Hit the end of the valid entries? */
271 sscanf(key.data, "%d", &val);
272 if (val > track + fuzz)
273 break;
275 /* Is this the entry we want? */
276 if (pos == ntohl(*((unsigned long *) data.data)))
279 * Yep! Delete it.
281 status = (index->del)(index, &key, R_CURSOR);
282 (index->close)(index);
283 return (status);
285 } while ((c = (index->seq)(index, &key, &data, R_NEXT)) == 0);
287 if (c == 0)
289 /* An error. */
290 (index->close)(index);
291 return (-1);
294 (index->close)(index);
295 return (1);
299 * idx_write_entry()
301 * Write out an index file entry.
303 * Input:
304 * file Name of database file (text version).
305 * track Start time of last track (database key).
306 * pos Position of entry in text file.
308 * Output:
309 * 0 Record written.
310 * -1 Index file inaccessible, or another error.
312 * Note: it is the caller's responsibility to do locking, as it's assumed
313 * that this operation will accompany a modification of the main database
314 * file and will need to be atomic with that modification.
317 idx_write_entry( char *file, int track, unsigned long pos )
319 char *indexname, keyval[8];
320 int status;
321 DB *index;
322 DBT key, data;
323 BTREEINFO bti;
326 * Open the index file.
328 indexname = malloc(strlen(file) + sizeof(".ind"));
329 if (indexname == NULL)
330 return (-1);
332 strcpy(indexname, file);
333 strcat(indexname, ".ind");
335 bti.flags = R_DUP;
336 bti.cachesize = 0;
337 bti.minkeypage = 0;
338 bti.maxkeypage = 0;
339 bti.psize = 0;
340 bti.lorder = 4321; /* network byte order */
341 bti.compare = NULL;
342 bti.prefix = NULL;
343 index = dbopen(indexname, O_RDWR, 0666, DB_BTREE, &bti);
344 free(indexname);
345 if (index == NULL)
346 return (-1);
349 * Create a new key and value.
351 pos = htonl(pos);
352 data.data = &pos;
353 data.size = sizeof(pos);
354 key.data = keyval;
355 key.size = 7;
357 sprintf(keyval, "%07d", track);
359 status = (index->put)(index, &key, &data, 0);
361 (index->close)(index);
362 return (status);
365 #else /* LIBDB */
368 idx_find_entry()
370 return (1); /* no record found; text file will be searched. */
374 idx_delete_entry()
376 return (0);
380 idx_write_entry()
382 return (0);
385 #endif /* LIBDB */