]> mj.ucw.cz Git - libucw.git/blob - lib/fb-param.c
Merge with git+ssh://git.ucw.cz/projects/sherlock/GIT/sherlock.git
[libucw.git] / lib / fb-param.c
1 /*
2  *      UCW Library -- FastIO on files with run-time parametrization
3  *
4  *      (c) 2007 Pavel Charvat <pchar@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #include "lib/lib.h"
11 #include "lib/conf.h"
12 #include "lib/lfs.h"
13 #include "lib/fastbuf.h"
14
15 #include <fcntl.h>
16 #include <stdio.h>
17
18 struct fb_params fbpar_def = {
19   .buffer_size = 65536,
20   .read_ahead = 1,
21   .write_back = 1,
22 }; 
23
24 struct cf_section fbpar_cf = {
25 # define F(x) PTR_TO(struct fb_params, x)
26   CF_TYPE(struct fb_params),
27   CF_ITEMS {
28     CF_LOOKUP("Type", (int *)F(type), ((char *[]){"std", "direct", "mmap", NULL})),
29     CF_UNS("BufSize", F(buffer_size)),
30     CF_UNS("KeepBackBuf", F(keep_back_buf)),
31     CF_UNS("ReadAhead", F(read_ahead)),
32     CF_UNS("WriteBack", F(write_back)),
33     CF_END
34   }
35 # undef F
36 };
37
38 static struct cf_section fbpar_global_cf = {
39   CF_ITEMS {
40     CF_SECTION("Defaults", &fbpar_def, &fbpar_cf),
41     CF_END
42   }
43 };
44
45 static void CONSTRUCTOR
46 fbpar_global_init(void)
47 {
48   cf_declare_section("FBParam", &fbpar_global_cf, 0);
49 }
50
51 static struct fastbuf *
52 bopen_fd_internal(int fd, struct fb_params *params, uns mode, const byte *name)
53 {
54   byte buf[32];
55   if (!name)
56     {
57       sprintf(buf, "fd%d", fd);
58       name = buf;
59     }
60   struct fastbuf *fb;
61   switch (params->type)
62     {
63       case FB_STD:
64         fb = bfdopen_internal(fd, name,
65             params->buffer_size ? : fbpar_def.buffer_size);
66         if (params->keep_back_buf)
67           bconfig(fb, BCONFIG_KEEP_BACK_BUF, 1);
68         return fb;
69       case FB_DIRECT:
70         fb = fbdir_open_fd_internal(fd, name, params->asio,
71             params->buffer_size ? : fbpar_def.buffer_size,
72             params->read_ahead ? : fbpar_def.read_ahead,
73             params->write_back ? : fbpar_def.write_back);
74         if (!~mode && !fbdir_cheat && ((int)(mode = fcntl(fd, F_GETFL)) < 0 || fcntl(fd, F_SETFL, mode | O_DIRECT)) < 0)
75           msg(L_WARN, "Cannot set O_DIRECT on fd %d: %m", fd);
76         return fb;
77       case FB_MMAP:
78         if (!~mode && (int)(mode = fcntl(fd, F_GETFL)) < 0)
79           die("Cannot get flags of fd %d: %m", fd);
80         return bfmmopen_internal(fd, name, mode);
81       default:
82         ASSERT(0);
83     }
84 }
85
86 static struct fastbuf *
87 bopen_file_internal(const byte *name, int mode, struct fb_params *params, int try)
88 {
89   if (params->type == FB_DIRECT && !fbdir_cheat)
90     mode |= O_DIRECT;
91   if (params->type == FB_MMAP && (mode & O_ACCMODE) == O_WRONLY)
92     mode = (mode & ~O_ACCMODE) | O_RDWR;
93   int fd = sh_open(name, mode, 0666);
94   if (fd < 0)
95     if (try)
96       return NULL;
97     else
98       die("Unable to %s file %s: %m", (mode & O_CREAT) ? "create" : "open", name);
99   struct fastbuf *fb = bopen_fd_internal(fd, params, mode, name);
100   ASSERT(fb);
101   if (mode & O_APPEND)
102     bseek(fb, 0, SEEK_END);
103   return fb;
104 }
105
106 struct fastbuf *
107 bopen_file(const char *name, int mode, struct fb_params *params)
108 {
109   return bopen_file_internal(name, mode, params ? : &fbpar_def, 0);
110 }
111
112 struct fastbuf *
113 bopen_file_try(const char *name, int mode, struct fb_params *params)
114 {
115   return bopen_file_internal(name, mode, params ? : &fbpar_def, 1);
116 }
117
118 struct fastbuf *
119 bopen_fd(int fd, struct fb_params *params)
120 {
121   return bopen_fd_internal(fd, params ? : &fbpar_def, ~0U, NULL);
122 }
123
124 struct fastbuf *
125 bopen_tmp_file(struct fb_params *params)
126 {
127   byte buf[TEMP_FILE_NAME_LEN];
128   temp_file_name(buf);
129   struct fastbuf *fb = bopen_file_internal(buf, O_RDWR | O_CREAT | O_TRUNC, params, 0);
130   bconfig(fb, BCONFIG_IS_TEMP_FILE, 1);
131   return fb;
132 }