oslConfig.cc
Go to the documentation of this file.
00001 /* oslConfig.cc
00002  */
00003 #include "osl/oslConfig.h"
00004 #include "osl/config.h"
00005 #include "osl/misc/ncores.h"
00006 #include "osl/eval/ml/openMidEndingEval.h"
00007 #include "osl/progress/ml/newProgress.h"
00008 #include <boost/filesystem/operations.hpp>
00009 #include <boost/static_assert.hpp>
00010 #include <map>
00011 #include <limits>
00012 #include <iostream>
00013 #include <fstream>
00014 #include <cstdlib>
00015 #ifndef _MSC_VER
00016 #  include <unistd.h>
00017 #endif
00018 #ifdef _WIN32
00019 #  include <windows.h>
00020 #  include <psapi.h>
00021 #else
00022 #include <sys/resource.h>
00023 #ifdef __FreeBSD__
00024 #  include <kvm.h>
00025 #  include <sys/param.h>
00026 #  include <sys/sysctl.h>
00027 #  include <sys/user.h>
00028 #  include <paths.h>
00029 #  include <fcntl.h>
00030 #endif
00031 #ifdef __APPLE__
00032 #  include <sys/types.h>
00033 #  include <sys/sysctl.h>
00034 #  include <mach/task.h>
00035 #  include <mach/mach_init.h>
00036 #endif
00037 #endif
00038 
00039 const int osl::OslConfig::MaxThreads; // define
00040 unsigned int osl::OslConfig::eval_random = 0;
00041 
00042 bool osl::OslConfig::is_verbose = false;
00043 #ifndef OSL_NCPUS
00044 const int osl::OslConfig::default_ncpus = osl::misc::ncores();
00045 #else
00046 BOOST_STATIC_ASSERT(OSL_NCPUS <= osl::OslConfig::MaxThreads);
00047 const int osl::OslConfig::default_ncpus = OSL_NCPUS;
00048 #endif
00049 int osl::OslConfig::num_cpu = default_ncpus;
00050 volatile bool osl::OslConfig::usi_mode = false, 
00051   osl::OslConfig::usi_mode_silent = false, 
00052   osl::OslConfig::force_root_window = false;
00053 int osl::OslConfig::usi_output_pawn_value = 100; 
00054 volatile int osl::OslConfig::root_window_alpha = 0; 
00055 volatile int osl::OslConfig::root_window_beta = 0; 
00056 volatile int osl::OslConfig::in_unit_test = 0;
00057 int osl::OslConfig::dfpn_max_depth = 256;
00058 bool osl::OslConfig::search_exact_value_in_one_reply = false;
00059 bool osl::OslConfig::has_byoyomi = false;
00060 boost::mutex osl::OslConfig::lock_io;
00061 
00062 namespace
00063 {
00064   size_t system_memory_use_limit() 
00065   {
00066 #ifdef _WIN32
00067     MEMORYSTATUSEX statex;
00068     statex.dwLength = sizeof(statex);
00069     GlobalMemoryStatusEx(&statex);
00070     return statex.ullTotalPhys; // in bytes
00071 #else
00072     size_t limit_by_rlimit = std::numeric_limits<size_t>::max();
00073     {
00074       rlimit rlp;
00075       if (getrlimit(RLIMIT_AS, &rlp) == 0
00076           && rlp.rlim_cur != std::numeric_limits<rlim_t>::max()) {
00077         limit_by_rlimit = rlp.rlim_cur;
00078 #ifdef __APPLE__
00079         limit_by_rlimit *= 1024;
00080 #endif
00081         std::cerr << "rlimit " << limit_by_rlimit << "\n";
00082       }
00083     }
00084 #ifdef __APPLE__
00085     {
00086       int mib[2];
00087       unsigned int usermem;
00088       size_t len=sizeof(usermem);
00089       mib[0] = CTL_HW;
00090       mib[1] = HW_USERMEM;
00091       if (sysctl(mib, 2, &usermem, &len, NULL, 0) == 0
00092           && len == sizeof(usermem)) {
00093         std::cerr << "usermem " << usermem << std::endl;
00094         return std::min((size_t)usermem, limit_by_rlimit);
00095       }
00096     }
00097 #endif
00098     {
00099       std::string name, unit;
00100       size_t value;
00101       std::ifstream is("/proc/meminfo");
00102       if (is >> name >> value >> unit
00103           && name == "MemTotal:" && unit == "kB")
00104         return std::min(value * 1024, limit_by_rlimit);
00105     }
00106 #if (defined __FreeBSD__)
00107     const long mem = sysconf(_SC_PHYS_PAGES);
00108     if (mem != -1) 
00109       return std::min(mem * getpagesize(), limit_by_rlimit);
00110 #endif
00111     return std::min((rlim_t)limit_by_rlimit, std::numeric_limits<rlim_t>::max());
00112 #endif
00113   }
00114 }
00115 
00116 size_t osl::OslConfig::memory_use_limit = system_memory_use_limit();
00117 const size_t osl::OslConfig::memory_use_limit_system_max = 
00118 #ifdef _WIN32
00119   3000000000; // 3GB
00120 #else
00121   std::numeric_limits<rlim_t>::max();
00122 #endif
00123 double osl::OslConfig::memory_use_percent = 100.0;
00124 
00125 void osl::OslConfig::setNumCPUs(int ncpu)
00126 {
00127   if (ncpu > MaxThreads) {
00128     std::cerr << "ncpu " << ncpu << " > " << "MaxThreads " << MaxThreads << "\n";
00129     ncpu = MaxThreads;
00130   }
00131   num_cpu = ncpu;
00132 }
00133 
00134 int osl::OslConfig::numCPUs()
00135 {
00136   return num_cpu;
00137 }
00138 
00139 void osl::OslConfig::setVerbose(bool v)
00140 {
00141   is_verbose = v;
00142 }
00143 
00144 bool osl::OslConfig::verbose()
00145 {
00146   return is_verbose;
00147 }
00148 
00149 bool osl::OslConfig::usiMode()
00150 {
00151   return usi_mode;
00152 }
00153 void osl::OslConfig::setUsiMode(bool enable)
00154 {
00155   usi_mode = enable;
00156 }
00157 bool osl::OslConfig::usiModeInSilent()
00158 {
00159   return usi_mode_silent;
00160 }
00161 void osl::OslConfig::setUsiSilent(bool enable)
00162 {
00163   usi_mode_silent = enable;
00164 }
00165 bool osl::OslConfig::searchExactValueInOneReply()
00166 {
00167   return search_exact_value_in_one_reply;
00168 }
00169 void osl::OslConfig::setSearchExactValueInOneReply(bool enable)
00170 {
00171   search_exact_value_in_one_reply = enable;
00172 }
00173 
00174 bool osl::OslConfig::hasByoyomi()
00175 {
00176   return has_byoyomi;
00177 }
00178 
00179 void osl::OslConfig::setHasByoyomi(bool value)
00180 {
00181   has_byoyomi = value;
00182 }
00183 
00184 void osl::OslConfig::showOslHome(const std::string& home)
00185 {
00186   std::cerr << "using " << home << " as OSL_HOME, word size "
00187             << OSL_WORDSIZE << std::endl;
00188 }
00189 
00190 void osl::OslConfig::showOslHome()
00191 {
00192   showOslHome(home());
00193 }
00194 
00195 bool osl::OslConfig::isGoodDir(const std::string& dir)
00196 {
00197   return boost::filesystem::exists(dir)
00198     && boost::filesystem::is_directory(dir);
00199 }
00200 
00201 void osl::OslConfig::trySetDir(std::string& dir, const std::string& candidate)
00202 {
00203   if (isGoodDir(candidate))
00204   {
00205     dir = candidate;
00206     return;
00207   }
00208   if (verbose())
00209     std::cerr << "skipping " << candidate << std::endl;
00210 }
00211 
00212 const std::string osl::OslConfig::makeHome()
00213 {
00214   std::string result;
00215   if (const char *env = getenv("GPSSHOGI_HOME"))
00216     trySetDir(result, env);
00217   
00218 #if defined GPSSHOGI_HOME
00219   if (result.empty())
00220     trySetDir(result, GPSSHOGI_HOME);
00221 #endif
00222 
00223   if (result.empty())
00224     if (const char *env = getenv("OSL_HOME"))
00225       trySetDir(result, env);
00226 
00227   if (result.empty())
00228     result = OSL_HOME;
00229 
00230   if (verbose())
00231     showOslHome(result);
00232   return result;
00233 }
00234 
00235 const std::string& osl::OslConfig::home()
00236 {
00237   static const std::string home_directory = makeHome();
00238   return home_directory;
00239 }
00240 
00241 const char * osl::OslConfig::home_c_str()
00242 {
00243   return home().c_str();
00244 }
00245 
00246 const std::string osl::OslConfig::gpsusiConf()
00247 {
00248   // issue:
00249   // - 開発者には $HOME ではなく OSL_HOME の方が使い分ける都合が良い
00250   // - 一方、配布版では OSL_HOME は共有ディレクトリで書き込めないかもしれない
00251 #ifdef OSL_PUBLIC_RELEASE
00252   // for personal users
00253   if (const char *env = getenv("HOME"))
00254     return std::string(env) + "/gpsusi.conf";
00255   if (const char *env = getenv("USERPROFILE"))
00256     return std::string(env) + "/gpsusi.conf";
00257 #endif
00258   // for developpers
00259   static const std::string home_directory = makeHome();
00260   return home_directory + "/gpsusi.conf";
00261 }
00262 
00263 const std::string osl::OslConfig::makeTest()
00264 {
00265   std::string result;
00266   if (const char *env = getenv("OSL_TEST"))
00267     trySetDir(result, env);
00268 
00269   if (result.empty())
00270     result = home() + "/data";  // 今はdata内に混在
00271 
00272   std::cerr << "using " << result << " as OSL_TEST" << std::endl;
00273   return result;
00274 }
00275 
00276 const std::string osl::OslConfig::makeTestPublic()
00277 {
00278   std::string result;
00279   if (const char *env = getenv("OSL_TEST_PUBLIC"))
00280     trySetDir(result, env);
00281 
00282   if (result.empty())
00283     result = home() + "/public-domain";
00284 
00285   std::cerr << "using " << result << " as OSL_TEST_PUBLIC" << std::endl;
00286   return result;
00287 }
00288 
00289 const std::string osl::OslConfig::testPrivate()
00290 {
00291   static const std::string test_directory = makeTest();
00292   return test_directory;
00293 }
00294 
00295 const std::string osl::OslConfig::testPublic()
00296 {
00297   static const std::string test_directory = makeTestPublic();
00298   return test_directory;
00299 }
00300 
00301 namespace 
00302 {
00303   struct NameHolder : std::map<std::string,std::string>
00304   {
00305     std::string directory;
00306 
00307     NameHolder(const std::string& d) : directory(d)
00308     {
00309       directory += "/";
00310     }
00311 
00312     iterator add(const std::string& key, const std::string& value)
00313     {
00314       return insert(std::make_pair(key, value)).first;
00315     }
00316     iterator addRelative(const std::string& key, const std::string& filename)
00317     {
00318       std::string value = directory + filename;
00319       return add(key, value);
00320     }
00321     iterator addRelative(const std::string& filename)
00322     {
00323       return addRelative(filename, filename);
00324     }
00325   };
00326 }
00327 
00328 const char * osl::OslConfig::testPrivateFile(const std::string& filename)
00329 {
00330   static NameHolder table(testPrivate());
00331   NameHolder::iterator p=table.find(filename);
00332   if (p == table.end()) {
00333     p = table.addRelative(filename);
00334   }
00335   return p->second.c_str();
00336 }
00337 
00338 const char * osl::OslConfig::testPublicFile(const std::string& filename)
00339 {
00340   static NameHolder table(testPublic());
00341   NameHolder::iterator p=table.find(filename);
00342   if (p == table.end()) {
00343     p = table.addRelative(filename);
00344   }
00345   return p->second.c_str();
00346 }
00347 
00348 const char * osl::OslConfig::testCsaFile(const std::string& filename)
00349 {
00350   static NameHolder table(testPublic()+"/floodgate2010");
00351   NameHolder::iterator p=table.find(filename);
00352   if (p == table.end()) {
00353     p = table.addRelative(filename);
00354   }
00355   return p->second.c_str();
00356 }
00357 
00358 const char *osl::OslConfig::openingBook(const std::string& filename)
00359 {
00360   static NameHolder table(home()+"/data");
00361   NameHolder::iterator p=table.find(filename);
00362   if (p == table.end()) {
00363     if (! filename.empty() && filename[0] == '/') {
00364       // absolute path
00365       p = table.add(filename, filename);
00366     }
00367     else {
00368       // relative path
00369       p = table.addRelative(filename, 
00370                             (filename == "" ? "joseki.dat" : filename));
00371     }
00372   }
00373   return p->second.c_str();
00374 }
00375 
00376 
00377 size_t osl::OslConfig::residentMemoryUse()
00378 {
00379 #if defined(_WIN32)
00380   static const DWORD process_id = GetCurrentProcessId();
00381   HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
00382                                 FALSE, process_id);
00383   if (NULL == hProcess)
00384   {
00385     std::cerr << "Failed to get residentMemoryUse()\n";
00386     return 0;
00387   }
00388 
00389   size_t working_set = 0;
00390   PROCESS_MEMORY_COUNTERS pmc;
00391   if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) {
00392     working_set = pmc.WorkingSetSize; // in bytes
00393   }
00394   CloseHandle(hProcess);
00395   return working_set;
00396 #else
00397   // see proc(5)
00398   // note: < 40000 cycles @macpro2
00399   std::ifstream is("/proc/self/statm");
00400   size_t total, resident;
00401   if (is >> total >> resident)
00402     return resident*getpagesize();
00403 #ifdef __APPLE__
00404   mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT;
00405   task_basic_info_64 ti;
00406   if (task_info(current_task(), TASK_BASIC_INFO_64, (task_info_t)&ti, &count)
00407       == KERN_SUCCESS)
00408     return ti.resident_size;
00409 #endif
00410 #ifdef __FreeBSD__
00411   static kvm_t *kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "osl kvm_open");
00412   int nproc;
00413   kinfo_proc *pp = kvm_getprocs(kd, KERN_PROC_PID, getpid(), &nproc);
00414   if (pp)
00415     return pp->ki_rssize * getpagesize();
00416 #endif  
00417 #endif
00418   return 0;
00419 }
00420 
00421 #ifndef DFPNSTATONE
00422 void osl::OslConfig::setUp()
00423 {
00424   eval::ml::OpenMidEndingEval::setUp();
00425   progress::ml::NewProgress::setUp();
00426 }
00427 #endif
00428 
00429 bool osl::OslConfig::healthCheck()
00430 {
00431   bool old_verbose = verbose();
00432   setVerbose(true);
00433   std::cerr << "health check\n";
00434   showOslHome(home());
00435 #ifndef DFPNSTATONE
00436   {
00437     std::string filename = eval::ml::OpenMidEndingEval::defaultFilename();
00438     std::cerr << "loading " << filename << ' ';
00439     bool success = eval::ml::OpenMidEndingEval::setUp(filename.c_str());
00440     std::cerr << (success ? "success" : "failed\a") << "\n";
00441     if (! success) {
00442       std::cerr << "exists?  " << boost::filesystem::exists(filename.c_str()) << "\n";
00443       std::cerr << "regular? " << boost::filesystem::is_regular_file(filename.c_str()) << "\n";
00444       return false;
00445     }
00446   }
00447   {
00448     std::string filename = progress::ml::NewProgress::defaultFilename();
00449     std::cerr << "loading " << filename << ' ';
00450     bool success = progress::ml::NewProgress::setUp(filename.c_str());
00451     std::cerr << (success ? "success" : "failed\a") << "\n";
00452     if (! success) {
00453       std::cerr << "exists?  " << boost::filesystem::exists(filename.c_str()) << "\n";
00454       std::cerr << "regular? " << boost::filesystem::is_regular_file(filename.c_str()) << "\n";
00455       return false;
00456     }
00457   }
00458 #endif
00459   setVerbose(old_verbose);
00460   return true;
00461 }
00462 
00463 int osl::OslConfig::dfpnMaxDepth()
00464 {
00465   return dfpn_max_depth;
00466 }
00467 void osl::OslConfig::setDfpnMaxDepth(int new_depth)
00468 {
00469   dfpn_max_depth = new_depth;
00470 }
00471 
00472 /* ------------------------------------------------------------------------- */
00473 // ;;; Local Variables:
00474 // ;;; mode:c++
00475 // ;;; c-basic-offset:2
00476 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines