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 osl::OslConfig::UsiMode osl::OslConfig::usi_mode = osl::OslConfig::NoUSI;
00051 volatile bool 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 osl::OslConfig::UsiMode osl::OslConfig::usiMode()
00150 {
00151   return usi_mode;
00152 }
00153 void osl::OslConfig::setUsiMode(UsiMode 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 int osl::OslConfig::resignThreshold()
00264 {
00265   static const int value = getenv("OSL_RESIGN_VALUE") 
00266     ? atoi(getenv("OSL_RESIGN_VALUE")) : 0;
00267   return (value > 0) ? value : 10000;
00268 }
00269 
00270 const std::string osl::OslConfig::makeTest()
00271 {
00272   std::string result;
00273   if (const char *env = getenv("OSL_TEST"))
00274     trySetDir(result, env);
00275 
00276   if (result.empty())
00277     result = home() + "/data";  // 今はdata内に混在
00278 
00279   std::cerr << "using " << result << " as OSL_TEST" << std::endl;
00280   return result;
00281 }
00282 
00283 const std::string osl::OslConfig::makeTestPublic()
00284 {
00285   std::string result;
00286   if (const char *env = getenv("OSL_TEST_PUBLIC"))
00287     trySetDir(result, env);
00288 
00289   if (result.empty())
00290     result = home() + "/public-domain";
00291 
00292   std::cerr << "using " << result << " as OSL_TEST_PUBLIC" << std::endl;
00293   return result;
00294 }
00295 
00296 const std::string osl::OslConfig::testPrivate()
00297 {
00298   static const std::string test_directory = makeTest();
00299   return test_directory;
00300 }
00301 
00302 const std::string osl::OslConfig::testPublic()
00303 {
00304   static const std::string test_directory = makeTestPublic();
00305   return test_directory;
00306 }
00307 
00308 namespace 
00309 {
00310   struct NameHolder : std::map<std::string,std::string>
00311   {
00312     std::string directory;
00313 
00314     NameHolder(const std::string& d) : directory(d)
00315     {
00316       directory += "/";
00317     }
00318 
00319     iterator add(const std::string& key, const std::string& value)
00320     {
00321       return insert(std::make_pair(key, value)).first;
00322     }
00323     iterator addRelative(const std::string& key, const std::string& filename)
00324     {
00325       std::string value = directory + filename;
00326       return add(key, value);
00327     }
00328     iterator addRelative(const std::string& filename)
00329     {
00330       return addRelative(filename, filename);
00331     }
00332   };
00333 }
00334 
00335 const char * osl::OslConfig::testPrivateFile(const std::string& filename)
00336 {
00337   static NameHolder table(testPrivate());
00338   NameHolder::iterator p=table.find(filename);
00339   if (p == table.end()) {
00340     p = table.addRelative(filename);
00341   }
00342   return p->second.c_str();
00343 }
00344 
00345 const char * osl::OslConfig::testPublicFile(const std::string& filename)
00346 {
00347   static NameHolder table(testPublic());
00348   NameHolder::iterator p=table.find(filename);
00349   if (p == table.end()) {
00350     p = table.addRelative(filename);
00351   }
00352   return p->second.c_str();
00353 }
00354 
00355 const char * osl::OslConfig::testCsaFile(const std::string& filename)
00356 {
00357   static NameHolder table(testPublic()+"/floodgate2010");
00358   NameHolder::iterator p=table.find(filename);
00359   if (p == table.end()) {
00360     p = table.addRelative(filename);
00361   }
00362   return p->second.c_str();
00363 }
00364 
00365 const char *osl::OslConfig::openingBook(const std::string& filename)
00366 {
00367   static NameHolder table(home()+"/data");
00368   NameHolder::iterator p=table.find(filename);
00369   if (p == table.end()) {
00370     if (! filename.empty() && filename[0] == '/') {
00371       // absolute path
00372       p = table.add(filename, filename);
00373     }
00374     else {
00375       // relative path
00376       p = table.addRelative(filename, 
00377                             (filename == "" ? "joseki.dat" : filename));
00378     }
00379   }
00380   return p->second.c_str();
00381 }
00382 
00383 
00384 size_t osl::OslConfig::residentMemoryUse()
00385 {
00386 #if defined(_WIN32)
00387   static const DWORD process_id = GetCurrentProcessId();
00388   HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
00389                                 FALSE, process_id);
00390   if (NULL == hProcess)
00391   {
00392     std::cerr << "Failed to get residentMemoryUse()\n";
00393     return 0;
00394   }
00395 
00396   size_t working_set = 0;
00397   PROCESS_MEMORY_COUNTERS pmc;
00398   if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) {
00399     working_set = pmc.WorkingSetSize; // in bytes
00400   }
00401   CloseHandle(hProcess);
00402   return working_set;
00403 #else
00404   // see proc(5)
00405   // note: < 40000 cycles @macpro2
00406   std::ifstream is("/proc/self/statm");
00407   size_t total, resident;
00408   if (is >> total >> resident)
00409     return resident*getpagesize();
00410 #ifdef __APPLE__
00411   mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT;
00412   task_basic_info_64 ti;
00413   if (task_info(current_task(), TASK_BASIC_INFO_64, (task_info_t)&ti, &count)
00414       == KERN_SUCCESS)
00415     return ti.resident_size;
00416 #endif
00417 #ifdef __FreeBSD__
00418   static kvm_t *kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "osl kvm_open");
00419   int nproc;
00420   kinfo_proc *pp = kvm_getprocs(kd, KERN_PROC_PID, getpid(), &nproc);
00421   if (pp)
00422     return pp->ki_rssize * getpagesize();
00423 #endif  
00424 #endif
00425   return 0;
00426 }
00427 
00428 #ifndef DFPNSTATONE
00429 void osl::OslConfig::setUp()
00430 {
00431   eval::ml::OpenMidEndingEval::setUp();
00432   progress::ml::NewProgress::setUp();
00433 }
00434 #endif
00435 
00436 bool osl::OslConfig::healthCheck()
00437 {
00438   bool old_verbose = verbose();
00439   setVerbose(true);
00440   std::cerr << "health check\n";
00441   showOslHome(home());
00442 #ifndef DFPNSTATONE
00443   {
00444     std::string filename = eval::ml::OpenMidEndingEval::defaultFilename();
00445     std::cerr << "loading " << filename << ' ';
00446     bool success = eval::ml::OpenMidEndingEval::setUp(filename.c_str());
00447     std::cerr << (success ? "success" : "failed\a") << "\n";
00448     if (! success) {
00449       std::cerr << "exists?  " << boost::filesystem::exists(filename.c_str()) << "\n";
00450       std::cerr << "regular? " << boost::filesystem::is_regular_file(filename.c_str()) << "\n";
00451       return false;
00452     }
00453   }
00454   {
00455     std::string filename = progress::ml::NewProgress::defaultFilename();
00456     std::cerr << "loading " << filename << ' ';
00457     bool success = progress::ml::NewProgress::setUp(filename.c_str());
00458     std::cerr << (success ? "success" : "failed\a") << "\n";
00459     if (! success) {
00460       std::cerr << "exists?  " << boost::filesystem::exists(filename.c_str()) << "\n";
00461       std::cerr << "regular? " << boost::filesystem::is_regular_file(filename.c_str()) << "\n";
00462       return false;
00463     }
00464   }
00465 #endif
00466   setVerbose(old_verbose);
00467   return true;
00468 }
00469 
00470 int osl::OslConfig::dfpnMaxDepth()
00471 {
00472   return dfpn_max_depth;
00473 }
00474 void osl::OslConfig::setDfpnMaxDepth(int new_depth)
00475 {
00476   dfpn_max_depth = new_depth;
00477 }
00478 
00479 /* ------------------------------------------------------------------------- */
00480 // ;;; Local Variables:
00481 // ;;; mode:c++
00482 // ;;; c-basic-offset:2
00483 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines