]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_tools.cc
import 12.2.13 release
[ceph.git] / ceph / src / rgw / rgw_tools.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include <errno.h>
5
6 #include "common/errno.h"
7 #include "common/safe_io.h"
8
9 #include "include/types.h"
10
11 #include "rgw_common.h"
12 #include "rgw_rados.h"
13 #include "rgw_tools.h"
14
15 #define dout_subsys ceph_subsys_rgw
16
17 #define READ_CHUNK_LEN (512 * 1024)
18
19 static std::map<std::string, std::string>* ext_mime_map;
20
21 int rgw_put_system_obj(RGWRados *rgwstore, const rgw_pool& pool, const string& oid, const char *data, size_t size, bool exclusive,
22 RGWObjVersionTracker *objv_tracker, real_time set_mtime, map<string, bufferlist> *pattrs)
23 {
24 map<string,bufferlist> no_attrs;
25 if (!pattrs)
26 pattrs = &no_attrs;
27
28 rgw_raw_obj obj(pool, oid);
29
30 int ret = rgwstore->put_system_obj(NULL, obj, data, size, exclusive, NULL, *pattrs, objv_tracker, set_mtime);
31
32 if (ret == -ENOENT) {
33 ret = rgwstore->create_pool(pool);
34 if (ret >= 0)
35 ret = rgwstore->put_system_obj(NULL, obj, data, size, exclusive, NULL, *pattrs, objv_tracker, set_mtime);
36 }
37
38 return ret;
39 }
40
41 int rgw_get_system_obj(RGWRados *rgwstore, RGWObjectCtx& obj_ctx, const rgw_pool& pool, const string& key, bufferlist& bl,
42 RGWObjVersionTracker *objv_tracker, real_time *pmtime, map<string, bufferlist> *pattrs,
43 rgw_cache_entry_info *cache_info, boost::optional<obj_version> refresh_version)
44 {
45 bufferlist::iterator iter;
46 int request_len = READ_CHUNK_LEN;
47 rgw_raw_obj obj(pool, key);
48
49 obj_version original_readv;
50 if (objv_tracker && !objv_tracker->read_version.empty()) {
51 original_readv = objv_tracker->read_version;
52 }
53
54 do {
55 RGWRados::SystemObject source(rgwstore, obj_ctx, obj);
56 RGWRados::SystemObject::Read rop(&source);
57
58 rop.stat_params.attrs = pattrs;
59 rop.stat_params.lastmod = pmtime;
60
61 int ret = rop.stat(objv_tracker);
62 if (ret < 0)
63 return ret;
64
65 rop.read_params.cache_info = cache_info;
66
67 ret = rop.read(0, request_len - 1, bl, objv_tracker, refresh_version);
68 if (ret == -ECANCELED) {
69 /* raced, restart */
70 if (!original_readv.empty()) {
71 /* we were asked to read a specific obj_version, failed */
72 return ret;
73 }
74 if (objv_tracker) {
75 objv_tracker->read_version.clear();
76 }
77 source.invalidate_state();
78 continue;
79 }
80 if (ret < 0)
81 return ret;
82
83 if (ret < request_len)
84 break;
85 bl.clear();
86 request_len *= 2;
87 } while (true);
88
89 return 0;
90 }
91
92 int rgw_delete_system_obj(RGWRados *rgwstore, const rgw_pool& pool, const string& oid,
93 RGWObjVersionTracker *objv_tracker)
94 {
95 rgw_raw_obj obj(pool, oid);
96 return rgwstore->delete_system_obj(obj, objv_tracker);
97 }
98
99 void parse_mime_map_line(const char *start, const char *end)
100 {
101 char line[end - start + 1];
102 strncpy(line, start, end - start);
103 line[end - start] = '\0';
104 char *l = line;
105 #define DELIMS " \t\n\r"
106
107 while (isspace(*l))
108 l++;
109
110 char *mime = strsep(&l, DELIMS);
111 if (!mime)
112 return;
113
114 char *ext;
115 do {
116 ext = strsep(&l, DELIMS);
117 if (ext && *ext) {
118 (*ext_mime_map)[ext] = mime;
119 }
120 } while (ext);
121 }
122
123
124 void parse_mime_map(const char *buf)
125 {
126 const char *start = buf, *end = buf;
127 while (*end) {
128 while (*end && *end != '\n') {
129 end++;
130 }
131 parse_mime_map_line(start, end);
132 end++;
133 start = end;
134 }
135 }
136
137 static int ext_mime_map_init(CephContext *cct, const char *ext_map)
138 {
139 int fd = open(ext_map, O_RDONLY);
140 char *buf = NULL;
141 int ret;
142 if (fd < 0) {
143 ret = -errno;
144 ldout(cct, 0) << __func__ << " failed to open file=" << ext_map
145 << " : " << cpp_strerror(-ret) << dendl;
146 return ret;
147 }
148
149 struct stat st;
150 ret = fstat(fd, &st);
151 if (ret < 0) {
152 ret = -errno;
153 ldout(cct, 0) << __func__ << " failed to stat file=" << ext_map
154 << " : " << cpp_strerror(-ret) << dendl;
155 goto done;
156 }
157
158 buf = (char *)malloc(st.st_size + 1);
159 if (!buf) {
160 ret = -ENOMEM;
161 ldout(cct, 0) << __func__ << " failed to allocate buf" << dendl;
162 goto done;
163 }
164
165 ret = safe_read(fd, buf, st.st_size + 1);
166 if (ret != st.st_size) {
167 // huh? file size has changed?
168 ldout(cct, 0) << __func__ << " raced! will retry.." << dendl;
169 free(buf);
170 close(fd);
171 return ext_mime_map_init(cct, ext_map);
172 }
173 buf[st.st_size] = '\0';
174
175 parse_mime_map(buf);
176 ret = 0;
177 done:
178 free(buf);
179 close(fd);
180 return ret;
181 }
182
183 const char *rgw_find_mime_by_ext(string& ext)
184 {
185 map<string, string>::iterator iter = ext_mime_map->find(ext);
186 if (iter == ext_mime_map->end())
187 return NULL;
188
189 return iter->second.c_str();
190 }
191
192 int rgw_tools_init(CephContext *cct)
193 {
194 ext_mime_map = new std::map<std::string, std::string>;
195 ext_mime_map_init(cct, cct->_conf->rgw_mime_types_file.c_str());
196 // ignore errors; missing mime.types is not fatal
197 return 0;
198 }
199
200 void rgw_tools_cleanup()
201 {
202 delete ext_mime_map;
203 ext_mime_map = nullptr;
204 }