]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_tools.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / rgw / rgw_tools.cc
CommitLineData
7c673cae
FG
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
19static std::map<std::string, std::string>* ext_mime_map;
20
21int 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
41int 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)
44{
45 struct rgw_err err;
46 bufferlist::iterator iter;
47 int request_len = READ_CHUNK_LEN;
48 rgw_raw_obj obj(pool, key);
49
50 obj_version original_readv;
51 if (objv_tracker && !objv_tracker->read_version.empty()) {
52 original_readv = objv_tracker->read_version;
53 }
54
55 do {
56 RGWRados::SystemObject source(rgwstore, obj_ctx, obj);
57 RGWRados::SystemObject::Read rop(&source);
58
59 rop.stat_params.attrs = pattrs;
60 rop.stat_params.lastmod = pmtime;
61 rop.stat_params.perr = &err;
62
63 int ret = rop.stat(objv_tracker);
64 if (ret < 0)
65 return ret;
66
67 rop.read_params.cache_info = cache_info;
68
69 ret = rop.read(0, request_len - 1, bl, objv_tracker);
70 if (ret == -ECANCELED) {
71 /* raced, restart */
72 if (!original_readv.empty()) {
73 /* we were asked to read a specific obj_version, failed */
74 return ret;
75 }
76 if (objv_tracker) {
77 objv_tracker->read_version.clear();
78 }
79 source.invalidate_state();
80 continue;
81 }
82 if (ret < 0)
83 return ret;
84
85 if (ret < request_len)
86 break;
87 bl.clear();
88 request_len *= 2;
89 } while (true);
90
91 return 0;
92}
93
94int rgw_delete_system_obj(RGWRados *rgwstore, const rgw_pool& pool, const string& oid,
95 RGWObjVersionTracker *objv_tracker)
96{
97 rgw_raw_obj obj(pool, oid);
98 return rgwstore->delete_system_obj(obj, objv_tracker);
99}
100
101void parse_mime_map_line(const char *start, const char *end)
102{
103 char line[end - start + 1];
104 strncpy(line, start, end - start);
105 line[end - start] = '\0';
106 char *l = line;
107#define DELIMS " \t\n\r"
108
109 while (isspace(*l))
110 l++;
111
112 char *mime = strsep(&l, DELIMS);
113 if (!mime)
114 return;
115
116 char *ext;
117 do {
118 ext = strsep(&l, DELIMS);
119 if (ext && *ext) {
120 (*ext_mime_map)[ext] = mime;
121 }
122 } while (ext);
123}
124
125
126void parse_mime_map(const char *buf)
127{
128 const char *start = buf, *end = buf;
129 while (*end) {
130 while (*end && *end != '\n') {
131 end++;
132 }
133 parse_mime_map_line(start, end);
134 end++;
135 start = end;
136 }
137}
138
139static int ext_mime_map_init(CephContext *cct, const char *ext_map)
140{
141 int fd = open(ext_map, O_RDONLY);
142 char *buf = NULL;
143 int ret;
144 if (fd < 0) {
145 ret = -errno;
146 ldout(cct, 0) << __func__ << " failed to open file=" << ext_map
147 << " : " << cpp_strerror(-ret) << dendl;
148 return ret;
149 }
150
151 struct stat st;
152 ret = fstat(fd, &st);
153 if (ret < 0) {
154 ret = -errno;
155 ldout(cct, 0) << __func__ << " failed to stat file=" << ext_map
156 << " : " << cpp_strerror(-ret) << dendl;
157 goto done;
158 }
159
160 buf = (char *)malloc(st.st_size + 1);
161 if (!buf) {
162 ret = -ENOMEM;
163 ldout(cct, 0) << __func__ << " failed to allocate buf" << dendl;
164 goto done;
165 }
166
167 ret = safe_read(fd, buf, st.st_size + 1);
168 if (ret != st.st_size) {
169 // huh? file size has changed?
170 ldout(cct, 0) << __func__ << " raced! will retry.." << dendl;
171 free(buf);
172 close(fd);
173 return ext_mime_map_init(cct, ext_map);
174 }
175 buf[st.st_size] = '\0';
176
177 parse_mime_map(buf);
178 ret = 0;
179done:
180 free(buf);
181 close(fd);
182 return ret;
183}
184
185const char *rgw_find_mime_by_ext(string& ext)
186{
187 map<string, string>::iterator iter = ext_mime_map->find(ext);
188 if (iter == ext_mime_map->end())
189 return NULL;
190
191 return iter->second.c_str();
192}
193
194int rgw_tools_init(CephContext *cct)
195{
196 ext_mime_map = new std::map<std::string, std::string>;
197 int ret = ext_mime_map_init(cct, cct->_conf->rgw_mime_types_file.c_str());
198 if (ret < 0)
199 return ret;
200
201 return 0;
202}
203
204void rgw_tools_cleanup()
205{
206 delete ext_mime_map;
207 ext_mime_map = nullptr;
208}