1 /*
2  * ServerREnvironment.cpp
3  *
4  * Copyright (C) 2021 by RStudio, PBC
5  *
6  * Unless you have received this program directly from RStudio pursuant
7  * to the terms of a commercial license agreement with RStudio, then
8  * this program is licensed to you under the terms of version 3 of the
9  * GNU Affero General Public License. This program is distributed WITHOUT
10  * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
11  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
12  * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
13  *
14  */
15 
16 #include "ServerREnvironment.hpp"
17 
18 #include <shared_core/Error.hpp>
19 #include <core/Log.hpp>
20 #include <core/Thread.hpp>
21 #include <core/r_util/REnvironment.hpp>
22 
23 #include <server_core/RVersionsScanner.hpp>
24 
25 #include <server/ServerOptions.hpp>
26 #include <server/ServerUriHandlers.hpp>
27 
28 using namespace rstudio::core;
29 
30 namespace rstudio {
31 namespace server {
32 namespace r_environment {
33 
34 namespace {
35 
36 boost::mutex s_versionMutex;
37 
38 // R version detected during initialization (either the system
39 // R version or the provided fallback)
40 core::r_util::RVersion s_rVersion;
41 
42 boost::shared_ptr<RVersionsScanner> s_scanner;
43 
44 } // anonymous namespace
45 
initializeScanner()46 void initializeScanner()
47 {
48    s_scanner.reset(
49             new RVersionsScanner(true,
50                                  options().rsessionWhichR(),
51                                  options().rldpathPath(),
52                                  options().rsessionLdLibraryPath()));
53 }
54 
initialize(std::string * pErrMsg)55 bool initialize(std::string* pErrMsg)
56 {
57    if (!s_scanner)
58       initializeScanner();
59 
60    // if we already have a cached version (such as multi version setting it)
61    // then simply return success
62    if (!s_rVersion.empty())
63    {
64       return true;
65    }
66 
67    // otherwise, we have no cached version (no multi version)
68    // detect it ourselves
69    bool detected = s_scanner->detectSystemRVersion(&s_rVersion, pErrMsg);
70    return detected;
71 }
72 
rVersion()73 core::r_util::RVersion rVersion()
74 {
75    LOCK_MUTEX(s_versionMutex)
76    {
77       return s_rVersion;
78    }
79    END_LOCK_MUTEX
80 
81    // mutex related error
82    return r_util::RVersion();
83 }
84 
setRVersion(const r_util::RVersion & version)85 void setRVersion(const r_util::RVersion& version)
86 {
87    LOCK_MUTEX(s_versionMutex)
88    {
89       s_rVersion = version;
90    }
91    END_LOCK_MUTEX
92 }
93 
detectRVersion(const core::FilePath & rScriptPath,core::r_util::RVersion * pVersion,std::string * pErrMsg)94 bool detectRVersion(const core::FilePath& rScriptPath,
95                     core::r_util::RVersion* pVersion,
96                     std::string* pErrMsg)
97 {
98    if (!s_scanner)
99       initializeScanner();
100 
101    return s_scanner->detectRVersion(rScriptPath, pVersion, pErrMsg);
102 }
103 
104 } // namespace r_environment
105 } // namespace server
106 } // namespace rstudio
107 
108