Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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)
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);
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   int ret = ext_mime_map_init(cct, cct->_conf->rgw_mime_types_file.c_str());
196   if (ret < 0)
197     return ret;
198
199   return 0;
200 }
201
202 void rgw_tools_cleanup()
203 {
204   delete ext_mime_map;
205   ext_mime_map = nullptr;
206 }