Return correct reply size: data+binary, not data+event
[elliptics.git] / library / compat.c
blobc8958ebed4ddef6d5e9fc0c6acb85f38224849ff
1 /*
2 * 2008+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
3 * All rights reserved.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <sys/socket.h>
19 #include <sys/mman.h>
20 #include <sys/wait.h>
22 #include <fcntl.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
27 #include "elliptics.h"
30 * Supported in Linux only so far
32 #ifdef HAVE_SENDFILE4_SUPPORT
33 #include <sys/prctl.h>
35 int dnet_set_name(char *n)
37 char str[] = "dnet-";
38 char name[16];
39 int len = strlen(n);
40 int rest = sizeof(name) - sizeof(str);
41 int offset = 0;
43 if (len >= rest)
44 offset = len - rest - 1;
46 snprintf(name, sizeof(name), "%s%s", str, n + offset);
47 return prctl(PR_SET_NAME, name);
50 #include <sys/syscall.h>
51 long dnet_get_id(void)
53 return syscall(SYS_gettid);
55 #else
56 int dnet_set_name(char *name __attribute__ ((unused))) { return 0; }
58 long dnet_get_id(void)
60 return pthread_self();
62 #endif
64 #ifdef HAVE_SENDFILE4_SUPPORT
65 #include <sys/sendfile.h>
66 int dnet_sendfile(struct dnet_net_state *st, int fd, uint64_t *offset, uint64_t size)
68 int err;
70 err = sendfile(st->write_s, fd, (off_t *)offset, size);
71 if (err < 0)
72 return -errno;
74 return err;
76 #elif HAVE_SENDFILE7_SUPPORT
77 #include <sys/uio.h>
78 int dnet_sendfile(struct dnet_net_state *st, int fd, uint64_t *offset, uint64_t size)
80 int err;
82 err = sendfile(fd, st->write_s, *offset, size, NULL, &size, 0);
83 if (err && errno != EAGAIN)
84 return -errno;
86 if (size) {
87 *offset += size;
88 return size;
91 return -EAGAIN;
93 #elif HAVE_SENDFILE6_SUPPORT
94 #include <sys/uio.h>
95 int dnet_sendfile(struct dnet_net_state *st, int fd, uint64_t *offset, uint64_t size)
97 int err;
99 err = sendfile(fd, st->write_s, *offset, &size, NULL, 0);
100 if (err && errno != EAGAIN)
101 return -errno;
103 if (size) {
104 *offset += size;
105 return size;
108 return -EAGAIN;
110 #else
111 int dnet_sendfile(struct dnet_net_state *st, int fd, uint64_t *offset, uint64_t size)
113 char buf[4096];
114 suint64_t err;
115 uint64_t total = 0;
117 err = lseek(fd, *offset, SEEK_SET);
118 if (err < 0) {
119 err = -errno;
120 dnet_log_err(st->n, "failed to seek to %llu",
121 (unsigned long long)*offset);
122 return err;
125 while (size) {
126 uint64_t sz = size;
128 if (sz > sizeof(buf))
129 sz = sizeof(buf);
131 err = read(fd, buf, sz);
132 if (err < 0) {
133 if (errno == EAGAIN || errno == EINTR)
134 break;
135 err = -errno;
136 dnet_log_err(st->n, "failed to read %zu bytes at %llu",
137 sz, (unsigned long long)*offset);
138 return err;
141 if (!err)
142 break;
144 sz = err;
146 while (sz) {
147 err = send(st->write_s, buf, sz, 0);
148 if (err < 0) {
149 if (errno == EAGAIN || errno == EINTR)
150 break;
151 return err;
153 if (!err)
154 return -ECONNRESET;
156 *offset += err;
157 size -= err;
158 total += err;
159 sz -= err;
160 err = 0;
163 if (err)
164 break;
167 if (total)
168 return total;
170 return -EAGAIN;
172 #endif
174 #ifdef HAVE_IOPRIO_SUPPORT
176 enum {
177 IOPRIO_CLASS_NONE,
178 IOPRIO_CLASS_RT,
179 IOPRIO_CLASS_BE,
180 IOPRIO_CLASS_IDLE,
183 enum {
184 IOPRIO_WHO_PROCESS = 1,
185 IOPRIO_WHO_PGRP,
186 IOPRIO_WHO_USER,
190 * Gives us 8 prio classes with 13-bits of data for each class
192 #define IOPRIO_BITS (16)
193 #define IOPRIO_CLASS_SHIFT (13)
194 #define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)
196 #define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT)
197 #define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK)
198 #define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data)
200 #define ioprio_valid(mask) (IOPRIO_PRIO_CLASS((mask)) != IOPRIO_CLASS_NONE)
202 int dnet_ioprio_set(long pid, int class, int prio)
204 return syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, pid, IOPRIO_PRIO_VALUE(class, prio));
207 int dnet_ioprio_get(long pid)
209 return syscall(SYS_ioprio_get, IOPRIO_WHO_PROCESS, pid);
211 #else
212 int dnet_ioprio_set(long pid __attribute__ ((unused)), int class __attribute__ ((unused)), int prio __attribute__ ((unused))) { return 0; }
213 int dnet_ioprio_get(long pid __attribute__ ((unused))) { return 0; }
214 #endif