Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rgw: make RGWEnv return a const ref. to its map #15269

Merged
merged 1 commit into from
Jun 14, 2017

Conversation

theanalyst
Copy link
Member

@theanalyst theanalyst commented May 24, 2017

We already have a public method set for setting values in the RGW env
map, making the map as a read only. In addition:

  • Added const to other methods in RGWEnv which are getters
  • req_info::init_meta also reused the same iter name for an internal
    find, changed the var name
  • add_grants_headers now accepts an RGWEnv instead of the map
  • use range based for loops wherever the code was changed\
  • req_info holds a ptr to a const RGWEnv, since we seem to only read the
    values from it

Signed-off-by: Abhishek Lekshmanan abhishek@suse.com

Copy link
Contributor

@rzarzynski rzarzynski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for bringing this up, @theanalyst! Please see my comments below.

@@ -201,7 +201,7 @@ static string get_abs_path(const string& request_uri) {
return request_uri.substr(beg_pos, len - beg_pos);
}

req_info::req_info(CephContext *cct, class RGWEnv *e) : env(e) {
req_info::req_info(CephContext *cct, class RGWEnv *_env) : env(_env) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The underscore in _env may be omitted:

req_info::req_info(CephContext *cct, class RGWEnv *env) : env(env) {

A bit more const-correct variant would look like:

req_info::req_info(CephContext* const cct, class RGWEnv* const env) : env(env) {

map<string, string, ltstr_nocase>& m = env->get_map();
map<string, string, ltstr_nocase>::iterator iter;
for (iter = m.begin(); iter != m.end(); ++iter) {
for (const auto& iter: env->get_map()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, technically it isn't an iterator anymore. Maybe just kv instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -427,8 +424,8 @@ void req_info::init_meta_info(bool *found_bad_meta)
}
}
}
for (iter = x_meta_map.begin(); iter != x_meta_map.end(); ++iter) {
dout(10) << "x>> " << iter->first << ":" << rgw::crypt_sanitize::x_meta_map{iter->first, iter->second} << dendl;
for (const auto& iter: x_meta_map) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same as above (I stop mentioning that).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -383,16 +383,16 @@ class RGWEnv {
void init(CephContext *cct);
void init(CephContext *cct, char **envp);
void set(const boost::string_ref& name, const boost::string_ref& val);
const char *get(const char *name, const char *def_val = NULL);
int get_int(const char *name, int def_val = 0);
const char *get(const char *name, const char *def_val = NULL) const;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we're already touching the line it might be worth to switch to nullptr as well.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm sure

string old = iter->second;
auto it = x_meta_map.find(name_low);
if (it != x_meta_map.end()) {
string old = it->second;
int pos = old.find_last_not_of(" \t"); /* get rid of any whitespaces after the value */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May we have size_t in place of int?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure

headers.push_back(pair<string, string>(iter->first, iter->second));
const auto & m = new_env.get_map();
for (const auto& iter: m) {
headers.push_back(pair<string, string>(iter.first, iter.second));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::make_pair could be helpful here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

headers.emplace_back(iter) works here as well

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack

string old = iter->second;
auto it = x_meta_map.find(name_low);
if (it != x_meta_map.end()) {
string old = it->second;
int pos = old.find_last_not_of(" \t"); /* get rid of any whitespaces after the value */
old = old.substr(0, pos + 1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it's not directly related to the proposed changes but we might have an issue here. AFAIK std::string::npos usually is the max of size_t, so adding 1 to it would give us 0. If so, the substr(0, 0) eradicates the old value. This isn't coherent with the comment above if my understanding is correct.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checking for pos != string::npos (or use boost::string::trim_right..)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I vote for trim_right. We're already using boost::algorithm::trim in couple of places.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -201,7 +201,7 @@ static string get_abs_path(const string& request_uri) {
return request_uri.substr(beg_pos, len - beg_pos);
}

req_info::req_info(CephContext *cct, class RGWEnv *e) : env(e) {
req_info::req_info(CephContext *cct, class RGWEnv *_env) : env(_env) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a suggestion: maybe req_info::env could be turned into a pointer to constant. If I see correctly the methods of req_info call only RGWEnv::get.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I thought of going that route, and got around to fixing all the places where we mutate the map without the methods. I also vote for this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@rzarzynski rzarzynski self-assigned this May 30, 2017
map<string, string, ltstr_nocase>& m = env->get_map();
map<string, string, ltstr_nocase>::iterator iter;
for (iter = m.begin(); iter != m.end(); ++iter) {
for (const auto& iter: env->get_map()) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack

string old = iter->second;
auto it = x_meta_map.find(name_low);
if (it != x_meta_map.end()) {
string old = it->second;
int pos = old.find_last_not_of(" \t"); /* get rid of any whitespaces after the value */
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure

for (iter = x_meta_map.begin(); iter != x_meta_map.end(); ++iter) {
dout(10) << "x>> " << iter->first << ":" << rgw::crypt_sanitize::x_meta_map{iter->first, iter->second} << dendl;
for (const auto& iter: x_meta_map) {
dout(10) << "x>> " << iter.first << ":" << rgw::crypt_sanitize::x_meta_map{iter.first, iter.second} << dendl;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also do the dout->ldout stuff while I'm here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unfortunately don't have a context, I just looked at the code in github's ui which folded the code when I made the comment

string old = iter->second;
auto it = x_meta_map.find(name_low);
if (it != x_meta_map.end()) {
string old = it->second;
int pos = old.find_last_not_of(" \t"); /* get rid of any whitespaces after the value */
old = old.substr(0, pos + 1);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checking for pos != string::npos (or use boost::string::trim_right..)

@@ -427,8 +424,8 @@ void req_info::init_meta_info(bool *found_bad_meta)
}
}
}
for (iter = x_meta_map.begin(); iter != x_meta_map.end(); ++iter) {
dout(10) << "x>> " << iter->first << ":" << rgw::crypt_sanitize::x_meta_map{iter->first, iter->second} << dendl;
for (const auto& iter: x_meta_map) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack

@@ -383,16 +383,16 @@ class RGWEnv {
void init(CephContext *cct);
void init(CephContext *cct, char **envp);
void set(const boost::string_ref& name, const boost::string_ref& val);
const char *get(const char *name, const char *def_val = NULL);
int get_int(const char *name, int def_val = 0);
const char *get(const char *name, const char *def_val = NULL) const;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm sure

const char *get(const char *name, const char *def_val = NULL);
int get_int(const char *name, int def_val = 0);
const char *get(const char *name, const char *def_val = NULL) const;
int get_int(const char *name, int def_val = 0) const;
bool get_bool(const char *name, bool def_val = 0);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should also be const if we go for const ptr

headers.push_back(pair<string, string>(iter->first, iter->second));
const auto & m = new_env.get_map();
for (const auto& iter: m) {
headers.push_back(pair<string, string>(iter.first, iter.second));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack

for (iter = m.begin(); iter != m.end(); ++iter) {
headers.push_back(pair<string, string>(iter->first, iter->second));
for (const auto& iter: new_env.get_map()) {
headers.push_back(pair<string, string>(iter.first, iter.second));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

emplace

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


/* add original headers that start with HTTP_X_AMZ_ */
#define SEARCH_AMZ_PREFIX "HTTP_X_AMZ_"
for (map<string, string>::iterator iter = orig_map.lower_bound(SEARCH_AMZ_PREFIX); iter != orig_map.end(); ++iter) {
const string& name = iter->first;
for (const auto& iter: orig_map) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm this doesn't look right, use the lower bound, and maybe #define -> constexpr?

if (iter == env_map.end())
return def_val;

const char *s = iter->second.c_str();
return atoll(s);
return atoll(s);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stol?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since stol throws have to catch the exceptions as well

@theanalyst theanalyst changed the title rgw: make RGWEnv return a const ref. to its map wip: rgw: make RGWEnv return a const ref. to its map Jun 1, 2017
@theanalyst
Copy link
Member Author

will squash the PRs after reviews

#define SEARCH_AMZ_PREFIX "HTTP_X_AMZ_"
for (const auto& iter: orig_map) {
const string& name = iter.first;
#define SEARCH_AMZ_PREFIX "HTTP_X_AMZ_"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about something like below?

static constexpr char SEARCH_AMZ_PREFIX[] = "HTTP_X_AMZ_";

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack

if (name == "HTTP_X_AMZ_DATE") /* dont forward date from original request */
continue;
if (name.compare(0, sizeof(SEARCH_AMZ_PREFIX) - 1, "HTTP_X_AMZ_") != 0)
if (name.compare(0, sizeof(SEARCH_AMZ_PREFIX) - 1, SEARCH_AMZ_PREFIX) != 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to use std::strlen() instead of the sizeof() - 1. A reasonable compiler should optimise it out while it's a bit more descriptive and consistent with the case of having \0 in the middle of a char array. Though, this cosmetics is less than a suggestion.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's make sure that compiler actually optimizes it correctly before changing it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test program:

#include <cstring>
#include <iostream>

int main () {
  static constexpr char test_string[] = "Just a test C\0string";
  std::cout << "the length is: " << std::strlen(test_string) << std::endl;
}

Verification with GCC 4.8.4 on AMD64:

$ g++ -std=c++11 /tmp/test.cc -o /tmp/test
$ /tmp/test 
the length is: 13
$ objdump -dC /tmp/test

...

000000000040089d <main>:
  40089d:	55                   	push   %rbp
  40089e:	48 89 e5             	mov    %rsp,%rbp
  4008a1:	be c1 09 40 00       	mov    $0x4009c1,%esi
  4008a6:	bf 80 10 60 00       	mov    $0x601080,%edi
  4008ab:	e8 c0 fe ff ff       	callq  400770 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)@plt>
  4008b0:	be 0d 00 00 00       	mov    $0xd,%esi
  4008b5:	48 89 c7             	mov    %rax,%rdi
  4008b8:	e8 c3 fe ff ff       	callq  400780 <std::ostream::operator<<(unsigned long)@plt>
  4008bd:	be a0 07 40 00       	mov    $0x4007a0,%esi
  4008c2:	48 89 c7             	mov    %rax,%rdi
  4008c5:	e8 c6 fe ff ff       	callq  400790 <std::ostream::operator<<(std::ostream& (*)(std::ostream&))@plt>
  4008ca:	b8 00 00 00 00       	mov    $0x0,%eax
  4008cf:	5d                   	pop    %rbp
  4008d0:	c3                   	retq 

...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

@theanalyst
Copy link
Member Author

test this please

@theanalyst theanalyst force-pushed the rgw/env-fix branch 2 times, most recently from 0579742 to 904c2d8 Compare June 6, 2017 14:13
@theanalyst theanalyst changed the title wip: rgw: make RGWEnv return a const ref. to its map rgw: make RGWEnv return a const ref. to its map Jun 9, 2017
@theanalyst
Copy link
Member Author

@rzarzynski updated

@@ -454,7 +450,7 @@ int RGWRESTStreamWriteRequest::put_obj_init(RGWAccessKey& key, rgw_obj& obj, uin
new_info.script_uri.append(resource);
new_info.request_uri = new_info.script_uri;

map<string, string, ltstr_nocase>& m = new_env.get_map();

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this empty line?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually the next line also can be squashed if go for a range based for loop, pushing the changeset. I can always push back the previous version if we feel this is not necessary

for (iter = m.begin(); iter != m.end(); ++iter) {
headers.push_back(pair<string, string>(iter->first, iter->second));
const auto & m = new_env.get_map();
for (const auto& iter: m) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iter might be a bit confusing here. Maybe:

  for (const auto& kv: new_env.get_map()) {
    headers.emplace_back(kv);
  }

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, more compact, did this in one other place, forgot here

}

map<string, string>& meta_map = new_info.x_meta_map;
for (iter = meta_map.begin(); iter != meta_map.end(); ++iter) {
headers.push_back(pair<string, string>(iter->first, iter->second));
for (const auto& iter: meta_map) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iter -> kv.

for (iter = meta_map.begin(); iter != meta_map.end(); ++iter) {
headers.push_back(pair<string, string>(iter->first, iter->second));
for (const auto& iter: meta_map) {
headers.push_back(pair<string, string>(iter.first, iter.second));
Copy link
Contributor

@rzarzynski rzarzynski Jun 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

    headers.emplace_back(kv);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch

map<string, string>::iterator iter;
for (iter = m.begin(); iter != m.end(); ++iter) {
headers.push_back(pair<string, string>(iter->first, iter->second));
for (const auto& iter: new_env.get_map()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iter -> kv.

map<string, string>::iterator iter;
for (iter = m.begin(); iter != m.end(); ++iter) {
headers.push_back(pair<string, string>(iter->first, iter->second));
for (const auto& iter: new_env.get_map()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iter -> kv.

const size_t put_prefix_len = strlen(put_prefix);
const size_t del_prefix_len = strlen(del_prefix);

for (iter = m.begin(); iter != m.end(); ++iter) {
for (const auto& iter : s->info.env->get_map()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iter -> kv.

@rzarzynski
Copy link
Contributor

@theanalyst: thanks for the update, Abhishek. I think this is the last iteration of review. The changes look good.

@theanalyst theanalyst force-pushed the rgw/env-fix branch 2 times, most recently from a2b36d4 to 51d7fd5 Compare June 12, 2017 12:38
@theanalyst
Copy link
Member Author

@rzarzynski thanks for the patient reviews, updated, also changed a for loop in rgw_rest_client.cc L453 to a range based for loop while i was at it, let me know if this is okay, or I can always fall back to the previous version

for (iter = meta_map.begin(); iter != meta_map.end(); ++iter) {
headers.push_back(pair<string, string>(iter->first, iter->second));
for (const auto& kv: meta_map) {
headers.emplace_back(pair<string, string>(kv.first, kv.second));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe:

  for (const auto& kv: meta_map) {
    headers.emplace_back(kv);
  }

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, silly me

for (bliter = attrs.begin(); bliter != attrs.end(); ++bliter) {
bufferlist& bl = bliter->second;
const string& name = bliter->first;
for (auto attr: attrs) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

auto&?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Contributor

@rzarzynski rzarzynski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks, @theanalyst! I'm scheduling a Teuthology run.

@rzarzynski
Copy link
Contributor

jenkins retest this please (Agent went offline during the build)

@rzarzynski
Copy link
Contributor

jenkins retest this please (cephtool-test-rados.sh)

@rzarzynski
Copy link
Contributor

@theanalyst: the Teuthology runs look clean:

Unfortunately, we've gotten a (trivial) merge conflict in rgw/rgw_crypt.cc. Could you please rebase?

We already have a public method `set` for setting values in the RGW env
map, making the map as a read only. In addition:

- Added const to other  methods in `RGWEnv` which are getters
- `req_info::init_meta` also reused the same `iter` name for an internal
  find, changed the var name
- `add_grants_headers` now accepts an RGWEnv instead of the map
- use range based for loops wherever the code was changed
- req_info holds a ptr to a const RGWEnv, since we seem to only read the
  values from it

Signed-off-by: Abhishek Lekshmanan <abhishek@suse.com>
@theanalyst
Copy link
Member Author

@rzarzynski thanks! done

@rzarzynski
Copy link
Contributor

jenkins retest this please (test_objectstore_memstore.sh)

@rzarzynski rzarzynski merged commit 04f9789 into ceph:master Jun 14, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants