KUDU-2395 (part 1): cache logged-in user

The name of the current logged-in user is not expected to change over
time once the process is running. If it did change this could cause
strange effects with ACL enforcement, for one, or result in outbound RPC
connections switching credentials during the process lifetime.

Additionally, as pointed at in KUDU-2395, the lookup of the user name
from the UID sometimes needs to go to external services which may be
slow and incur lock contention.

This patch switches to computing the local username only once and
reusing the result on all subsequent lookups.

Change-Id: Ib4500d89dd91e8eed6e4ae0661b886ab3c105130
Reviewed-on: http://gerrit.cloudera.org:8080/9895
Tested-by: Kudu Jenkins
Reviewed-by: Todd Lipcon <t...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/kudu/repo
Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/52b50b7a
Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/52b50b7a
Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/52b50b7a

Branch: refs/heads/master
Commit: 52b50b7a91c61925a7bc42992fe1001e74425d4d
Parents: 161c25c
Author: Todd Lipcon <t...@apache.org>
Authored: Mon Apr 2 16:12:33 2018 -0700
Committer: Todd Lipcon <t...@apache.org>
Committed: Wed Apr 4 00:21:27 2018 +0000

----------------------------------------------------------------------
 src/kudu/util/user.cc | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kudu/blob/52b50b7a/src/kudu/util/user.cc
----------------------------------------------------------------------
diff --git a/src/kudu/util/user.cc b/src/kudu/util/user.cc
index 1b73e53..2d12267 100644
--- a/src/kudu/util/user.cc
+++ b/src/kudu/util/user.cc
@@ -22,19 +22,23 @@
 
 #include <cerrno>
 #include <cstdlib>
+#include <mutex>
 #include <string>
+#include <utility>
 
 #include <glog/logging.h>
 
 #include "kudu/gutil/gscoped_ptr.h"
+#include "kudu/util/debug/leakcheck_disabler.h"
 #include "kudu/util/errno.h"
 #include "kudu/util/status.h"
 
 using std::string;
 
 namespace kudu {
+namespace {
 
-Status GetLoggedInUser(string* user_name) {
+Status DoGetLoggedInUser(string* user_name) {
   DCHECK(user_name != nullptr);
 
   struct passwd pwd;
@@ -59,9 +63,26 @@ Status GetLoggedInUser(string* user_name) {
       return Status::RuntimeError("Error calling getpwuid_r()", 
ErrnoToString(ret), ret);
     }
   }
-
   *user_name = pwd.pw_name;
+  return Status::OK();
+}
+
+} // anonymous namespace
+
+Status GetLoggedInUser(string* user_name) {
+  static std::once_flag once;
+  static string* once_user_name;
+  static Status* once_status;
+  std::call_once(once, [](){
+      string u;
+      Status s = DoGetLoggedInUser(&u);
+      debug::ScopedLeakCheckDisabler ignore_leaks;
+      once_status = new Status(std::move(s));
+      once_user_name = new string(std::move(u));
+    });
 
+  RETURN_NOT_OK(*once_status);
+  *user_name = *once_user_name;
   return Status::OK();
 }
 

Reply via email to