Support a direction prefix on SORT
[xapian.git] / xapian-applications / omega / cdb_init.cc
blob81aa1661a36e9f991581d33241d07b8b8232395a
1 /* $Id: cdb_init.c,v 1.9 2003/11/03 21:42:20 mjt Exp $
2 * cdb_init, cdb_free and cdb_read routines
4 * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
5 * Public domain.
6 */
8 #include <config.h>
10 #include <sys/types.h>
11 #ifdef HAVE_MMAP
12 # include <sys/mman.h>
13 #else
14 # include "safeunistd.h"
15 # include <cstdlib>
16 #endif
17 #ifdef __WIN32__
18 # include "safewindows.h"
19 #endif
20 #include "safesysstat.h"
21 #include "cdb_int.h"
22 #include <cstring>
24 using namespace std;
26 int
27 cdb_init(struct cdb *cdbp, int fd)
29 struct stat st;
30 unsigned char *mem;
31 unsigned fsize, dend;
32 #ifndef HAVE_MMAP
33 #ifdef _WIN32
34 HANDLE hFile, hMapping;
35 #else
36 size_t size;
37 unsigned char *p;
38 #endif
39 #endif
41 /* get file size */
42 if (fstat(fd, &st) < 0)
43 return -1;
44 /* trivial sanity check: at least toc should be here */
45 if (st.st_size < 2048)
46 return errno = EPROTO, -1;
47 fsize = (unsigned)(st.st_size & 0xffffffffu);
48 /* memory-map file */
49 #ifndef HAVE_MMAP
50 #ifdef _WIN32
51 hFile = (HANDLE) _get_osfhandle(fd);
52 if(hFile == (HANDLE) -1) return -1;
53 hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
54 if (!hMapping) return -1;
55 mem = (unsigned char *)MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
56 if (!mem) return -1;
57 #else
58 // No mmap, so take the very crude approach of malloc and read the whole file in!
59 if ((mem = (unsigned char *)malloc(fsize)) == NULL)
60 return -1;
61 size = fsize;
62 p = mem;
63 while (size > 0) {
64 ssize_t n = read(fd, (void*)p, size);
65 if (n == -1)
66 return -1;
67 p += n;
68 size -= n;
70 #endif
71 #else
72 mem = (unsigned char *)mmap(NULL, fsize, PROT_READ, MAP_SHARED, fd, 0);
73 if (mem == (unsigned char *)-1)
74 return -1;
75 #endif /* _WIN32 */
77 cdbp->cdb_fd = fd;
78 cdbp->cdb_fsize = fsize;
79 cdbp->cdb_mem = mem;
81 #if 0
82 /* XXX don't know well about madvise syscall -- is it legal
83 to set different options for parts of one mmap() region?
84 There is also posix_madvise() exist, with POSIX_MADV_RANDOM etc...
86 #ifdef MADV_RANDOM
87 /* set madvise() parameters. Ignore errors for now if system
88 doesn't support it */
89 madvise(mem, 2048, MADV_WILLNEED);
90 madvise(mem + 2048, cdbp->cdb_fsize - 2048, MADV_RANDOM);
91 #endif
92 #endif
94 cdbp->cdb_vpos = cdbp->cdb_vlen = 0;
95 cdbp->cdb_kpos = cdbp->cdb_klen = 0;
96 dend = cdb_unpack(mem);
97 if (dend < 2048) dend = 2048;
98 else if (dend >= fsize) dend = fsize;
99 cdbp->cdb_dend = dend;
101 return 0;
104 #ifdef __cplusplus
105 class VoidStarOrCharStar {
106 void *p;
107 public:
108 VoidStarOrCharStar(const void *p_) : p(const_cast<void*>(p_)) { }
109 VoidStarOrCharStar(const char *p_) : p(const_cast<char*>(p_)) { }
110 operator void*() { return p; }
111 operator char*() { return static_cast<char*>(p); }
113 #endif
115 void
116 cdb_free(struct cdb *cdbp)
118 if (cdbp->cdb_mem) {
119 #ifdef _WIN32
120 HANDLE hFile, hMapping;
121 #endif
123 #ifndef HAVE_MMAP
124 #ifdef __cplusplus
125 void * p = const_cast<void*>((const void*)cdbp->cdb_mem);
126 #else
127 void * p = (void*)cdbp->cdb_mem;
128 #endif
129 #ifdef _WIN32
130 hFile = (HANDLE) _get_osfhandle(cdbp->cdb_fd);
131 hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
132 UnmapViewOfFile(p);
133 CloseHandle(hMapping);
134 #else
135 free(p);
136 #endif
137 #else
138 #ifdef __cplusplus
139 /* Solaris sys/mman.h defines munmap as taking char* unless __STDC__ is
140 * defined (which it isn't in C++).
142 VoidStarOrCharStar p(cdbp->cdb_mem);
143 #else
144 void * p = (void*)cdbp->cdb_mem;
145 #endif
146 munmap(p, cdbp->cdb_fsize);
147 #endif /* _WIN32 */
148 cdbp->cdb_mem = NULL;
150 cdbp->cdb_fsize = 0;
153 const void *
154 cdb_get(const struct cdb *cdbp, unsigned len, unsigned pos)
156 if (pos > cdbp->cdb_fsize || cdbp->cdb_fsize - pos < len) {
157 errno = EPROTO;
158 return NULL;
160 return cdbp->cdb_mem + pos;
164 cdb_read(const struct cdb *cdbp, void *buf, unsigned len, unsigned pos)
166 const void *data = cdb_get(cdbp, len, pos);
167 if (!data) return -1;
168 memcpy(buf, data, len);
169 return 0;