35 #define GRN_IO_IDSTR "GROONGA:IO:00001"
39 #define MAX_REQUEST (64*1024)
41 #define MEM_ALIGN grn_cache_block
47 # define O_BINARY _O_BINARY
57 grn_critical_section cs;
65 #define IO_HEADER_SIZE 64
67 inline static grn_rc grn_open(
grn_ctx *ctx,
fileinfo *fi,
const char *path,
int flags,
size_t maxsize);
68 inline static void grn_fileinfo_init(
fileinfo *fis,
int nfis);
69 inline static int grn_opened(
fileinfo *fi);
71 #if defined(WIN32) && defined(WIN32_FMO_EACH)
73 off_t offset,
size_t length);
74 inline static int grn_munmap(
grn_ctx *ctx, HANDLE *fmo,
void *start,
size_t length);
75 #define GRN_MMAP(ctx,fmo,fi,offset,length)\
76 (grn_mmap((ctx), (fmo), (fi), (offset), (length)))
77 #define GRN_MUNMAP(ctx,fmo,start,length) (grn_munmap((ctx), (fmo), (start), (length)))
79 inline static void * grn_mmap(
grn_ctx *ctx,
fileinfo *fi, off_t offset,
size_t length);
80 inline static int grn_munmap(
grn_ctx *ctx,
void *start,
size_t length);
81 #define GRN_MUNMAP(ctx,fmo,start,length) (grn_munmap((ctx), (start), (length)))
82 #ifdef USE_FAIL_MALLOC
84 off_t offset,
size_t length,
85 const char* file,
int line,
const char *func);
86 #define GRN_MMAP(ctx,fmo,fi,offset,length) \
87 (grn_fail_mmap((ctx), (fi), (offset), (length), __FILE__, __LINE__, __FUNCTION__))
89 #define GRN_MMAP(ctx,fmo,fi,offset,length) (grn_mmap((ctx), (fi), (offset), (length)))
92 inline static int grn_msync(
grn_ctx *ctx,
void *start,
size_t length);
110 uint32_t max_segment,
grn_io_mode mode, uint32_t flags)
114 uint32_t total_header_size;
155 grn_io_register(
grn_io *io)
162 (
void **)&io, NULL)) {
168 "grn_io_register(%s) failed", io->
path);
174 grn_io_unregister(
grn_io *io)
187 "grn_io_unregister(%s) failed", io->
path);
198 unsigned int b, max_nfiles;
199 uint32_t bs, total_header_size;
204 if (!*path || (strlen(path) >
PATH_MAX - 4)) {
return NULL; }
207 bs = (b + segment_size - 1) / segment_size;
208 max_nfiles = (
unsigned int)(
212 grn_fileinfo_init(fis, max_nfiles);
222 grn_msync(ctx, header, b);
279 hp +=
sizeof(uint32_t) * array_specs[i].max_n_segments;
280 mp +=
sizeof(
void *) * array_specs[i].max_n_segments;
287 array_init(
grn_io *io,
int n_arrays)
295 hsize +=
sizeof(uint32_t) * array_specs[i].max_n_segments;
296 msize +=
sizeof(
void *) * array_specs[i].max_n_segments;
298 return array_init_(io, n_arrays, hsize, msize);
317 hsize +=
sizeof(uint32_t) * array_specs[i].max_n_segments;
318 msize +=
sizeof(
void *) * array_specs[i].max_n_segments;
326 if (!array_init_(io, n_arrays, hsize, msize)) {
336 inline static uint32_t
349 if (!used) {
return 0; }
377 if ((*sp = segment_alloc(io))) {
383 uint32_t pseg = *sp - 1;
405 if (fstat(fd, &s) != -1 && s.st_size >=
sizeof(
struct _grn_io_header)) {
432 unsigned int b, max_nfiles;
433 uint32_t total_header_size;
434 uint32_t header_size = 0, segment_size = 0, max_segment = 0, bs;
435 if (!path || !*path || (strlen(path) >
PATH_MAX - 4)) {
return NULL; }
439 if (fd == -1) {
SERR(path);
return NULL; }
440 if (fstat(fd, &s) != -1 && s.st_size >=
sizeof(
struct _grn_io_header)) {
458 max_nfiles = (
unsigned int)(
462 grn_fileinfo_init(fis, max_nfiles);
511 unsigned int max_nfiles = (
unsigned int)(
514 grn_io_unregister(io);
517 for (mi = io->
maps, i = max_segment; i; mi++, i--) {
537 for (fi = io->
fis, i = max_nfiles; i; fi++, i--) { grn_close(ctx, fi); }
580 gen_pathname(
const char *path,
char *
buffer,
int fno)
582 size_t len = strlen(path);
583 memcpy(buffer, path, len);
587 buffer[len + 4] =
'\0';
607 nfiles = (uint32_t) (((uint64_t)segment_size * (max_segment + bs) +
GRN_IO_FILE_SIZE - 1)
610 for (fno = 0; fno < nfiles; fno++) {
611 gen_pathname(io->
path, buffer, fno);
612 if (stat(buffer, &s)) {
626 if (stat(path, &s)) {
629 }
else if (unlink(path)) {
635 for (fno = 1; ; fno++) {
636 gen_pathname(path, buffer, fno);
637 if (!stat(buffer, &s)) {
638 if (unlink(buffer)) {
SERR(buffer); }
651 if (stat(old_name, &s)) {
654 }
else if (rename(old_name, new_name)) {
661 for (fno = 1; ; fno++) {
662 gen_pathname(old_name, old_buffer, fno);
663 if (!stat(old_buffer, &s)) {
664 gen_pathname(new_name, new_buffer, fno);
665 if (rename(old_buffer, new_buffer)) {
SERR(old_buffer); }
682 uint32_t segment, uint32_t offset,
void **value, uint32_t *value_len)
687 uint32_t bseg = segment + io->
base_seg;
688 int fno = bseg / segments_per_file;
690 off_t base = fno ? 0 : io->
base - (uint64_t)segment_size * io->
base_seg;
691 off_t pos = (uint64_t)segment_size * (bseg % segments_per_file) + offset + base;
700 size = GRN_IO_FILE_SIZE - pos;
702 if (!grn_opened(fi)) {
704 gen_pathname(io->
path, path, fno);
712 if (grn_pread(ctx, fi, v, size, pos)) {
718 if (einfo->
pos != epos) {
725 if (einfo->
size != *value_len) {
732 if (v->head.key != key) {
739 if (v->head.size != *value_len) {
749 fi = &io->
fis[++fno];
750 if (!grn_opened(fi)) {
752 gen_pathname(io->
path, path, fno);
761 if (grn_pread(ctx, fi, vr, size, 0)) {
777 uint32_t segment, uint32_t offset,
void *value, uint32_t value_len)
783 uint32_t bseg = segment + io->
base_seg;
784 int fno = bseg / segments_per_file;
786 off_t base = fno ? 0 : io->
base - (uint64_t)segment_size * io->
base_seg;
787 off_t pos = (uint64_t)segment_size * (bseg % segments_per_file) + offset + base;
790 size = GRN_IO_FILE_SIZE - pos;
792 if (!grn_opened(fi)) {
794 gen_pathname(io->
path, path, fno);
795 if ((rc = grn_open(ctx, fi, path, O_RDWR|O_CREAT,
GRN_IO_FILE_SIZE))) {
return rc; }
797 if (value_len <= 256) {
801 memcpy(je.
body, value, value_len);
802 rc = grn_pwrite(ctx, fi, &je, size, pos);
807 if ((rc = grn_pwrite(ctx, fi, &eh,
sizeof(
grn_io_ja_ehead), pos))) {
return rc; }
811 if (rc) {
return rc; }
815 fi = &io->
fis[++fno];
816 if (!grn_opened(fi)) {
818 gen_pathname(io->
path, path, fno);
819 if ((rc = grn_open(ctx, fi, path, O_RDWR|O_CREAT,
GRN_IO_FILE_SIZE))) {
return rc; }
822 if ((rc = grn_pwrite(ctx, fi, vr, size, 0))) {
return rc; }
832 uint32_t segment, uint32_t offset, uint32_t value_len)
837 uint32_t bseg = segment + io->
base_seg;
838 int fno = bseg / segments_per_file;
840 off_t base = fno ? 0 : io->
base - (uint64_t)segment_size + io->
base_seg;
841 off_t pos = (uint64_t)segment_size * (bseg % segments_per_file) + offset + base;
842 if (!grn_opened(fi)) {
844 gen_pathname(io->
path, path, fno);
845 if ((rc = grn_open(ctx, fi, path, O_RDWR|O_CREAT,
GRN_IO_FILE_SIZE))) {
return rc; }
867 if (offset >= segment_size) {
868 segment += offset / segment_size;
869 offset = offset % segment_size;
871 nseg = (offset + size + segment_size - 1) / segment_size;
873 fno = bseg / segments_per_file;
874 base = fno ? 0 : io->
base - (uint64_t)segment_size * io->
base_seg;
875 pos = (uint64_t)segment_size * (bseg % segments_per_file) + offset + base;
877 fno != (bseg + nseg - 1) / segments_per_file) {
884 if (!grn_opened(fi)) {
886 gen_pathname(io->
path, path, fno);
892 if (grn_pread(ctx, fi, p, size, pos)) {
903 if (!grn_opened(fi)) {
905 gen_pathname(io->
path, path, fno);
910 if (!(p =
GRN_MMAP(&
grn_gctx, &iw->fmo, fi, pos, (uint64_t)segment_size * nseg))) {
914 uint64_t tail = io->
base + (uint64_t)segment_size * segment + offset + size;
918 GRN_LOG(ctx,
GRN_LOG_ALERT,
"nseg == 0! in grn_io_win_map(%p, %u, %u, %u)", io, segment, offset, size);
922 iw->
addr = p + offset;
958 for (i = 0; i < nent; i++) {
972 if (offset >= segment_size) {
973 segment += offset / segment_size;
974 offset = offset % segment_size;
976 nseg = (offset + size + segment_size - 1) / segment_size;
978 fno = bseg / segments_per_file;
979 base = fno ? 0 : io->
base - (uint64_t)segment_size * io->
base_seg;
980 pos = (uint64_t)segment_size * (bseg % segments_per_file) + offset + base;
982 fno != (bseg + nseg - 1) / segments_per_file) {
986 if (!grn_opened(fi)) {
988 gen_pathname(io->
path, path, fno);
998 uint32_t vsize = pos + size;
1001 vsize = vsize - voffset;
1004 iw->
diff = pos - voffset;
1006 dp (
"pos: %lu, allocate: %d, really needed: %d\n", voffset, vsize, size);
1007 memset(&oper[count], 0,
sizeof(CacheIOOper));
1008 memset(&iocb[count], 0,
sizeof(
struct aiocb));
1009 oper[count].iocb = &iocb[count];
1010 iocb[count].aio_fildes = fi->
fd;
1011 iocb[count].aio_lio_opcode = LIO_READ;
1014 (p = grn_cache_read (&oper[count], fi->
dev, fi->
inode, voffset, vsize)) != NULL) {
1016 iw->
cached = oper[count].cd->num;
1020 if (oper[count].read == 1) {
1021 iocbs[count] = &iocb[count];
1023 }
else if (oper[count].cd->flag == CACHE_READ) {
1030 dp (
"Wont use cache offset=%lu size=%u\n", voffset, vsize);
1033 if (posix_memalign(&p,
MEM_ALIGN, vsize) != 0) {
1034 SERR(
"posix_memalign");
1037 iocb[count].aio_buf = p;
1038 iocb[count].aio_nbytes = vsize;
1039 iocb[count].aio_offset = voffset;
1040 iocbs[count] = &iocb[count];
1043 oper[count].cd = NULL;
1063 if (grn_aio_enabled) {
1068 if (lio_listio (LIO_WAIT, iocbs, count, NULL) < 0) {
1072 for (c=0;c<count;c++) {
1074 if (oper[c].cd) oper[c].cd->flag = CACHE_VALID;
1082 dp (
"-- Validate Reading state CacheData (%d) --\n", cl);
1091 dp(
"-- No Reading state CacheData. --\n");
1105 int nseg = iw->
nseg;
1111 else if (iw->
cached >= 0){
1113 grn_cache_data_unref (iw->
cached);
1133 if (grn_aio_enabled) {
1146 if (!grn_opened(fi)) {
1148 gen_pathname(io->
path, path, fno);
1152 if (!(rc = grn_pwrite(ctx, fi, iw->
addr, iw->
size, iw->
pos))) {
1161 if (grn_aio_enabled) {
1179 if (offset >= segment_size) {
1180 segment += offset / segment_size;
1181 offset = offset % segment_size;
1183 nseg = (offset + size + segment_size - 1) / segment_size;
1197 if (!addr) {
return NULL; }
1199 iw->
addr = addr + offset;
1209 for (p = iw->
addr, r = size; r; p += s, r -= s, segment++, offset = 0) {
1215 s = (offset + r > segment_size) ? segment_size - offset : r;
1216 memcpy(p, q + offset, s);
1252 for (p = iw->
addr, r = iw->
size; r; p += s, r -= s, segment++, offset = 0) {
1255 s = (offset + r > segment_size) ? segment_size - offset : r;
1256 memcpy(q + offset, p, s);
1268 #define DO_MAP(io,fmo,fi,pos,size,segno,res) do {\
1269 if (((res) = GRN_MMAP(&grn_gctx, (fmo), (fi), (pos), (size)))) {\
1271 if (io->max_map_seg < segno) { io->max_map_seg = segno; }\
1272 GRN_ATOMIC_ADD_EX(&io->nmaps, 1, nmaps);\
1274 uint64_t tail = io->base + (uint64_t)(size) * ((segno) + 1);\
1275 if (tail > io->header->curr_size) { io->header->curr_size = tail; }\
1280 #define SEG_MAP(io,segno,info) do {\
1281 uint32_t segment_size = io->header->segment_size;\
1282 if ((io->flags & GRN_IO_TEMPORARY)) {\
1283 DO_MAP(io, &info->fmo, NULL, 0, segment_size, segno, info->map);\
1285 uint32_t segments_per_file = GRN_IO_FILE_SIZE / segment_size;\
1286 uint32_t bseg = segno + io->base_seg;\
1287 uint32_t fno = bseg / segments_per_file;\
1288 off_t base = fno ? 0 : io->base - (uint64_t)segment_size * io->base_seg;\
1289 off_t pos = (uint64_t)segment_size * (bseg % segments_per_file) + base;\
1290 fileinfo *fi = &io->fis[fno];\
1291 if (!grn_opened(fi)) {\
1292 char path[PATH_MAX];\
1293 gen_pathname(io->path, path, fno);\
1294 if (!grn_open(ctx, fi, path, O_RDWR|O_CREAT, GRN_IO_FILE_SIZE)) { \
1295 DO_MAP(io, &info->fmo, fi, pos, segment_size, segno, info->map);\
1298 DO_MAP(io, &info->fmo, fi, pos, segment_size, segno, info->map);\
1312 uint32_t retry, *pnref;
1315 info = &io->
maps[segno];
1317 pnref = &info->
nref;
1318 for (retry = 0;; retry++) {
1320 GRN_ATOMIC_ADD_EX(pnref, 1, nref);
1322 GRN_ATOMIC_ADD_EX(pnref, -1, nref);
1324 GRN_LOG(ctx,
GRN_LOG_CRIT,
"deadlock detected! in grn_io_seg_expire(%p, %u, %u)", io, segno, nref);
1342 GRN_ATOMIC_ADD_EX(&io->
nmaps, -1, nmaps);
1355 uint32_t m, n = 0, ln = io->
nmaps;
1359 uint32_t nref, nmaps, *pnref = &io->
nref;
1360 GRN_ATOMIC_ADD_EX(pnref, 1, nref);
1374 GRN_ATOMIC_ADD_EX(&io->
nmaps, -1, nmaps);
1379 GRN_ATOMIC_ADD_EX(pnref, -1, nref);
1390 for (m = io->
max_map_seg; n < limit && m; info++, m--) {
1392 uint32_t nmaps, nref, *pnref = &info->
nref;
1393 GRN_ATOMIC_ADD_EX(pnref, 1, nref);
1396 GRN_ATOMIC_ADD_EX(&io->
nmaps, -1, nmaps);
1401 GRN_ATOMIC_ADD_EX(pnref, -1, nref);
1415 grn_expire_(
grn_ctx *ctx,
int count_thresh, uint32_t limit)
1422 if (n >= limit) {
break; }
1437 n = grn_expire_(ctx, count_thresh, limit);
1453 return (mi->
map =
GRN_MMAP(ctx, &mi->fmo, NULL, 0, length));
1469 static int _ncalls = 0, _ncolls = 0;
1470 uint32_t count, count_log_border = 1000;
1473 for (count = 0;; count++) {
1475 GRN_ATOMIC_ADD_EX(io->
lock, 1, lock);
1477 GRN_ATOMIC_ADD_EX(io->
lock, -1, lock);
1478 if (count == count_log_border) {
1480 "io(%s) collisions(%d/%d): lock failed %d times",
1481 io->
path, _ncolls, _ncalls, count_log_border);
1483 if (!timeout || (timeout > 0 && timeout == count)) {
1485 "[DB Locked] time out(%d): io(%s) collisions(%d/%d)",
1486 timeout, io->
path, _ncolls, _ncalls);
1489 if (!(++_ncolls % 1000000) && (_ncolls > _ncalls)) {
1490 if (_ncolls < 0 || _ncalls < 0) {
1491 _ncolls = 0; _ncalls = 0;
1494 "io(%s) collisions(%d/%d)", io->
path, _ncolls, _ncalls);
1511 GRN_ATOMIC_ADD_EX(io->
lock, -1, lock);
1518 if (io) { *io->
lock = 0; }
1524 return io ? *io->
lock : 0;
1529 static size_t mmap_size = 0;
1533 #ifdef WIN32_FMO_EACH
1536 grn_open(
grn_ctx *ctx,
fileinfo *fi,
const char *path,
int flags,
size_t maxsize)
1538 if ((flags & O_CREAT)) {
1539 DWORD dwCreationDisposition;
1540 if (flags & O_EXCL) {
1541 dwCreationDisposition = CREATE_NEW;
1543 dwCreationDisposition = OPEN_ALWAYS;
1545 fi->fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE,
1546 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1547 dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, 0);
1548 if (fi->fh == INVALID_HANDLE_VALUE) {
1554 if ((flags & O_TRUNC)) {
1555 CloseHandle(fi->fh);
1556 fi->fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE,
1557 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1558 TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
1559 if (fi->fh == INVALID_HANDLE_VALUE) {
1566 fi->fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE,
1567 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1568 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
1569 if (fi->fh == INVALID_HANDLE_VALUE) {
1574 CRITICAL_SECTION_INIT(fi->cs);
1578 inline static void *
1579 grn_mmap(
grn_ctx *ctx, HANDLE *fmo,
fileinfo *fi, off_t offset,
size_t length)
1590 *fmo = CreateFileMapping(fi->fh, NULL, PAGE_READWRITE, 0, offset + length, NULL);
1591 if (!*fmo) {
return NULL; }
1592 res = MapViewOfFile(*fmo, FILE_MAP_WRITE, 0, (DWORD)offset, (SIZE_T)length);
1594 MERR(
"MapViewOfFile failed #%d <%zu>", GetLastError(), mmap_size);
1598 mmap_size += length;
1603 grn_munmap(
grn_ctx *ctx, HANDLE *fmo,
void *start,
size_t length)
1610 if (UnmapViewOfFile(start)) {
1611 mmap_size -= length;
1613 SERR(
"UnmapViewOfFile");
1617 if (!CloseHandle(*fmo)) {
1618 SERR(
"CloseHandle");
1631 if (fi->fmo != NULL) {
1634 if (fi->fh != INVALID_HANDLE_VALUE) {
1635 CloseHandle(fi->fh);
1636 CRITICAL_SECTION_FIN(fi->cs);
1637 fi->fh = INVALID_HANDLE_VALUE;
1644 grn_open(
grn_ctx *ctx,
fileinfo *fi,
const char *path,
int flags,
size_t maxsize)
1647 if ((flags & O_CREAT)) {
1648 DWORD dwCreationDisposition;
1649 if (flags & O_EXCL) {
1650 dwCreationDisposition = CREATE_NEW;
1652 dwCreationDisposition = OPEN_ALWAYS;
1654 fi->fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE,
1655 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1656 dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, 0);
1657 if (fi->fh == INVALID_HANDLE_VALUE) {
1663 if ((flags & O_TRUNC)) {
1664 CloseHandle(fi->fh);
1666 fi->fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE,
1667 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1668 TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
1669 if (fi->fh == INVALID_HANDLE_VALUE) {
1676 fi->fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE,
1677 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1678 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
1679 if (fi->fh == INVALID_HANDLE_VALUE) {
1685 fi->fmo = OpenFileMapping(FILE_MAP_ALL_ACCESS,
FALSE, NULL);
1687 if (fi->fmo == NULL) {
1690 fi->fmo = OpenFileMapping(FILE_MAP_ALL_ACCESS,
FALSE, NULL);
1692 if (fi->fmo == NULL) {
1694 fi->fmo = CreateFileMapping(fi->fh, NULL, PAGE_READWRITE, 0,
GRN_IO_FILE_SIZE, NULL);
1698 if (fi->fmo != NULL) {
1699 if (GetLastError() != ERROR_ALREADY_EXISTS ) {
1700 CRITICAL_SECTION_INIT(fi->cs);
1704 CloseHandle(fi->fmo);
1709 CloseHandle(fi->fh);
1710 SERR(
"OpenFileMapping");
1714 inline static void *
1735 res = MapViewOfFile(fi->fmo, FILE_MAP_WRITE, 0, (DWORD)offset, (SIZE_T)length);
1737 MERR(
"MapViewOfFile failed #%d <%zu>", GetLastError(), mmap_size);
1740 mmap_size += length;
1745 grn_munmap(
grn_ctx *ctx,
void *start,
size_t length)
1747 if (UnmapViewOfFile(start)) {
1748 mmap_size -= length;
1751 SERR(
"UnmapViewOfFile");
1760 if (fi->fmo != NULL) {
1761 CloseHandle(fi->fmo);
1764 if (fi->fh != INVALID_HANDLE_VALUE) {
1765 CloseHandle(fi->fh);
1766 CRITICAL_SECTION_FIN(fi->cs);
1767 fi->fh = INVALID_HANDLE_VALUE;
1774 grn_fileinfo_init(
fileinfo *fis,
int nfis)
1776 for (; nfis--; fis++) {
1777 fis->fh = INVALID_HANDLE_VALUE;
1785 return fi->fh != INVALID_HANDLE_VALUE;
1789 grn_msync(
grn_ctx *ctx,
void *start,
size_t length)
1792 return FlushViewOfFile(start, length);
1796 grn_pread(
grn_ctx *ctx,
fileinfo *fi,
void *buf,
size_t count, off_t offset)
1799 CRITICAL_SECTION_ENTER(fi->cs);
1800 r = SetFilePointer(fi->fh, offset, NULL, FILE_BEGIN);
1801 if (r == INVALID_SET_FILE_POINTER) {
1802 SERR(
"SetFilePointer");
1804 if (!ReadFile(fi->fh, buf, (DWORD)count, &len, NULL)) {
1806 }
else if (len != count) {
1811 CRITICAL_SECTION_LEAVE(fi->cs);
1816 grn_pwrite(
grn_ctx *ctx,
fileinfo *fi,
void *buf,
size_t count, off_t offset)
1819 CRITICAL_SECTION_ENTER(fi->cs);
1820 r = SetFilePointer(fi->fh, offset, NULL, FILE_BEGIN);
1821 if (r == INVALID_SET_FILE_POINTER) {
1822 SERR(
"SetFilePointer");
1824 if (!WriteFile(fi->fh, buf, (DWORD)count, &len, NULL)) {
1826 }
else if (len != count) {
1831 CRITICAL_SECTION_LEAVE(fi->cs);
1838 grn_open(
grn_ctx *ctx,
fileinfo *fi,
const char *path,
int flags,
size_t maxsize)
1841 if ((fi->
fd =
GRN_OPEN(path, flags, 0666)) == -1) {
1845 if (fstat(fi->
fd, &st) == -1) {
1849 fi->
dev = st.st_dev;
1850 fi->
inode = st.st_ino;
1855 grn_fileinfo_init(
fileinfo *fis,
int nfis)
1857 for (; nfis--; fis++) { fis->
fd = -1; }
1863 return fi->
fd != -1;
1879 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
1880 #define MAP_ANONYMOUS MAP_ANON
1883 #include <sys/mman.h>
1885 inline static void *
1892 off_t tail = offset + length;
1894 if ((fstat(fd, &s) == -1) || (s.st_size < tail && ftruncate(fd, tail) == -1)) {
1901 flags = MAP_PRIVATE|MAP_ANONYMOUS;
1903 res = mmap(NULL, length, PROT_READ|PROT_WRITE, flags, fd, offset);
1904 if (MAP_FAILED == res) {
1906 (
unsigned long long int)length, fd, (
long long int)offset, strerror(errno),
1907 (
unsigned long long int)mmap_size);
1910 mmap_size += length;
1914 #ifdef USE_FAIL_MALLOC
1915 inline static void *
1916 grn_fail_mmap(
grn_ctx *ctx,
fileinfo *fi, off_t offset,
size_t length,
1917 const char* file,
int line,
const char *func)
1919 if (grn_fail_malloc_check(length, file, line, func)) {
1920 return grn_mmap(ctx, fi, offset, length);
1922 MERR(
"fail_mmap(%zu,%d,%" GRN_FMT_LLU
") (%s:%d@%s) <%zu>",
1923 length, fi ? fi->
fd : 0, offset, file, line, func, mmap_size);
1930 grn_msync(
grn_ctx *ctx,
void *start,
size_t length)
1932 int r = msync(start, length, MS_SYNC);
1933 if (r == -1) {
SERR(
"msync"); }
1938 grn_munmap(
grn_ctx *ctx,
void *start,
size_t length)
1941 res = munmap(start, length);
1945 start, (
unsigned long long int)length, (
unsigned long long int)mmap_size);
1947 mmap_size -= length;
1953 grn_pread(
grn_ctx *ctx,
fileinfo *fi,
void *buf,
size_t count, off_t offset)
1955 ssize_t r = pread(fi->
fd, buf, count, offset);
1962 (
long long int)r, (
unsigned long long int)count);
1970 grn_pwrite(
grn_ctx *ctx,
fileinfo *fi,
void *buf,
size_t count, off_t offset)
1972 ssize_t r = pwrite(fi->
fd, buf, count, offset);
1979 (
long long int)r, (
unsigned long long int)count);