1// Protocol Buffers - Google's data interchange format 2// Copyright 2008 Google Inc. All rights reserved. 3// http://code.google.com/p/protobuf/ 4// 5// Redistribution and use in source and binary forms, with or without 6// modification, are permitted provided that the following conditions are 7// met: 8// 9// * Redistributions of source code must retain the above copyright 10// notice, this list of conditions and the following disclaimer. 11// * Redistributions in binary form must reproduce the above 12// copyright notice, this list of conditions and the following disclaimer 13// in the documentation and/or other materials provided with the 14// distribution. 15// * Neither the name of Google Inc. nor the names of its 16// contributors may be used to endorse or promote products derived from 17// this software without specific prior written permission. 18// 19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31// Author: kenton@google.com (Kenton Varda) 32 33#include <google/protobuf/stubs/common.h> 34#include <google/protobuf/stubs/once.h> 35#include <stdio.h> 36#include <errno.h> 37#include <vector> 38 39#include "config.h" 40 41#ifdef _WIN32 42#define WIN32_LEAN_AND_MEAN // We only need minimal includes 43#include <windows.h> 44#define snprintf _snprintf // see comment in strutil.cc 45#elif defined(HAVE_PTHREAD) 46#include <pthread.h> 47#else 48#error "No suitable threading library available." 49#endif 50 51namespace google { 52namespace protobuf { 53 54namespace internal { 55 56void VerifyVersion(int headerVersion, 57 int minLibraryVersion, 58 const char* filename) { 59 if (GOOGLE_PROTOBUF_VERSION < minLibraryVersion) { 60 // Library is too old for headers. 61 GOOGLE_LOG(FATAL) 62 << "This program requires version " << VersionString(minLibraryVersion) 63 << " of the Protocol Buffer runtime library, but the installed version " 64 "is " << VersionString(GOOGLE_PROTOBUF_VERSION) << ". Please update " 65 "your library. If you compiled the program yourself, make sure that " 66 "your headers are from the same version of Protocol Buffers as your " 67 "link-time library. (Version verification failed in \"" 68 << filename << "\".)"; 69 } 70 if (headerVersion < kMinHeaderVersionForLibrary) { 71 // Headers are too old for library. 72 GOOGLE_LOG(FATAL) 73 << "This program was compiled against version " 74 << VersionString(headerVersion) << " of the Protocol Buffer runtime " 75 "library, which is not compatible with the installed version (" 76 << VersionString(GOOGLE_PROTOBUF_VERSION) << "). Contact the program " 77 "author for an update. If you compiled the program yourself, make " 78 "sure that your headers are from the same version of Protocol Buffers " 79 "as your link-time library. (Version verification failed in \"" 80 << filename << "\".)"; 81 } 82} 83 84string VersionString(int version) { 85 int major = version / 1000000; 86 int minor = (version / 1000) % 1000; 87 int micro = version % 1000; 88 89 // 128 bytes should always be enough, but we use snprintf() anyway to be 90 // safe. 91 char buffer[128]; 92 snprintf(buffer, sizeof(buffer), "%d.%d.%d", major, minor, micro); 93 94 // Guard against broken MSVC snprintf(). 95 buffer[sizeof(buffer)-1] = '\0'; 96 97 return buffer; 98} 99 100} // namespace internal 101 102// =================================================================== 103// emulates google3/base/logging.cc 104 105namespace internal { 106 107void DefaultLogHandler(LogLevel level, const char* filename, int line, 108 const string& message) { 109 static const char* level_names[] = { "INFO", "WARNING", "ERROR", "FATAL" }; 110 111 // We use fprintf() instead of cerr because we want this to work at static 112 // initialization time. 113 fprintf(stderr, "[libprotobuf %s %s:%d] %s\n", 114 level_names[level], filename, line, message.c_str()); 115 fflush(stderr); // Needed on MSVC. 116} 117 118void NullLogHandler(LogLevel level, const char* filename, int line, 119 const string& message) { 120 // Nothing. 121} 122 123static LogHandler* log_handler_ = &DefaultLogHandler; 124static int log_silencer_count_ = 0; 125 126static Mutex* log_silencer_count_mutex_ = NULL; 127GOOGLE_PROTOBUF_DECLARE_ONCE(log_silencer_count_init_); 128 129void DeleteLogSilencerCount() { 130 delete log_silencer_count_mutex_; 131 log_silencer_count_mutex_ = NULL; 132} 133void InitLogSilencerCount() { 134 log_silencer_count_mutex_ = new Mutex; 135 OnShutdown(&DeleteLogSilencerCount); 136} 137void InitLogSilencerCountOnce() { 138 GoogleOnceInit(&log_silencer_count_init_, &InitLogSilencerCount); 139} 140 141LogMessage& LogMessage::operator<<(const string& value) { 142 message_ += value; 143 return *this; 144} 145 146LogMessage& LogMessage::operator<<(const char* value) { 147 message_ += value; 148 return *this; 149} 150 151// Since this is just for logging, we don't care if the current locale changes 152// the results -- in fact, we probably prefer that. So we use snprintf() 153// instead of Simple*toa(). 154#undef DECLARE_STREAM_OPERATOR 155#define DECLARE_STREAM_OPERATOR(TYPE, FORMAT) \ 156 LogMessage& LogMessage::operator<<(TYPE value) { \ 157 /* 128 bytes should be big enough for any of the primitive */ \ 158 /* values which we print with this, but well use snprintf() */ \ 159 /* anyway to be extra safe. */ \ 160 char buffer[128]; \ 161 snprintf(buffer, sizeof(buffer), FORMAT, value); \ 162 /* Guard against broken MSVC snprintf(). */ \ 163 buffer[sizeof(buffer)-1] = '\0'; \ 164 message_ += buffer; \ 165 return *this; \ 166 } 167 168DECLARE_STREAM_OPERATOR(char , "%c" ) 169DECLARE_STREAM_OPERATOR(int , "%d" ) 170DECLARE_STREAM_OPERATOR(uint , "%u" ) 171DECLARE_STREAM_OPERATOR(long , "%ld") 172DECLARE_STREAM_OPERATOR(unsigned long, "%lu") 173DECLARE_STREAM_OPERATOR(double , "%g" ) 174#undef DECLARE_STREAM_OPERATOR 175 176LogMessage::LogMessage(LogLevel level, const char* filename, int line) 177 : level_(level), filename_(filename), line_(line) {} 178LogMessage::~LogMessage() {} 179 180void LogMessage::Finish() { 181 bool suppress = false; 182 183 if (level_ != LOGLEVEL_FATAL) { 184 InitLogSilencerCountOnce(); 185 MutexLock lock(log_silencer_count_mutex_); 186 suppress = log_silencer_count_ > 0; 187 } 188 189 if (!suppress) { 190 log_handler_(level_, filename_, line_, message_); 191 } 192 193 if (level_ == LOGLEVEL_FATAL) { 194#if PROTOBUF_USE_EXCEPTIONS 195 throw FatalException(filename_, line_, message_); 196#else 197 abort(); 198#endif 199 } 200} 201 202void LogFinisher::operator=(LogMessage& other) { 203 other.Finish(); 204} 205 206} // namespace internal 207 208LogHandler* SetLogHandler(LogHandler* new_func) { 209 LogHandler* old = internal::log_handler_; 210 if (old == &internal::NullLogHandler) { 211 old = NULL; 212 } 213 if (new_func == NULL) { 214 internal::log_handler_ = &internal::NullLogHandler; 215 } else { 216 internal::log_handler_ = new_func; 217 } 218 return old; 219} 220 221LogSilencer::LogSilencer() { 222 internal::InitLogSilencerCountOnce(); 223 MutexLock lock(internal::log_silencer_count_mutex_); 224 ++internal::log_silencer_count_; 225}; 226 227LogSilencer::~LogSilencer() { 228 internal::InitLogSilencerCountOnce(); 229 MutexLock lock(internal::log_silencer_count_mutex_); 230 --internal::log_silencer_count_; 231}; 232 233// =================================================================== 234// emulates google3/base/callback.cc 235 236Closure::~Closure() {} 237 238namespace internal { FunctionClosure0::~FunctionClosure0() {} } 239 240void DoNothing() {} 241 242// =================================================================== 243// emulates google3/base/mutex.cc 244 245#ifdef _WIN32 246 247struct Mutex::Internal { 248 CRITICAL_SECTION mutex; 249#ifndef NDEBUG 250 // Used only to implement AssertHeld(). 251 DWORD thread_id; 252#endif 253}; 254 255Mutex::Mutex() 256 : mInternal(new Internal) { 257 InitializeCriticalSection(&mInternal->mutex); 258} 259 260Mutex::~Mutex() { 261 DeleteCriticalSection(&mInternal->mutex); 262 delete mInternal; 263} 264 265void Mutex::Lock() { 266 EnterCriticalSection(&mInternal->mutex); 267#ifndef NDEBUG 268 mInternal->thread_id = GetCurrentThreadId(); 269#endif 270} 271 272void Mutex::Unlock() { 273#ifndef NDEBUG 274 mInternal->thread_id = 0; 275#endif 276 LeaveCriticalSection(&mInternal->mutex); 277} 278 279void Mutex::AssertHeld() { 280#ifndef NDEBUG 281 GOOGLE_DCHECK_EQ(mInternal->thread_id, GetCurrentThreadId()); 282#endif 283} 284 285#elif defined(HAVE_PTHREAD) 286 287struct Mutex::Internal { 288 pthread_mutex_t mutex; 289}; 290 291Mutex::Mutex() 292 : mInternal(new Internal) { 293 pthread_mutex_init(&mInternal->mutex, NULL); 294} 295 296Mutex::~Mutex() { 297 pthread_mutex_destroy(&mInternal->mutex); 298 delete mInternal; 299} 300 301void Mutex::Lock() { 302 int result = pthread_mutex_lock(&mInternal->mutex); 303 if (result != 0) { 304 GOOGLE_LOG(FATAL) << "pthread_mutex_lock: " << strerror(result); 305 } 306} 307 308void Mutex::Unlock() { 309 int result = pthread_mutex_unlock(&mInternal->mutex); 310 if (result != 0) { 311 GOOGLE_LOG(FATAL) << "pthread_mutex_unlock: " << strerror(result); 312 } 313} 314 315void Mutex::AssertHeld() { 316 // pthreads dosn't provide a way to check which thread holds the mutex. 317 // TODO(kenton): Maybe keep track of locking thread ID like with WIN32? 318} 319 320#endif 321 322// =================================================================== 323// emulates google3/util/endian/endian.h 324// 325// TODO(xiaofeng): PROTOBUF_LITTLE_ENDIAN is unfortunately defined in 326// google/protobuf/io/coded_stream.h and therefore can not be used here. 327// Maybe move that macro definition here in the furture. 328uint32 ghtonl(uint32 x) { 329 union { 330 uint32 result; 331 uint8 result_array[4]; 332 }; 333 result_array[0] = static_cast<uint8>(x >> 24); 334 result_array[1] = static_cast<uint8>((x >> 16) & 0xFF); 335 result_array[2] = static_cast<uint8>((x >> 8) & 0xFF); 336 result_array[3] = static_cast<uint8>(x & 0xFF); 337 return result; 338} 339 340// =================================================================== 341// Shutdown support. 342 343namespace internal { 344 345typedef void OnShutdownFunc(); 346vector<void (*)()>* shutdown_functions = NULL; 347Mutex* shutdown_functions_mutex = NULL; 348GOOGLE_PROTOBUF_DECLARE_ONCE(shutdown_functions_init); 349 350void InitShutdownFunctions() { 351 shutdown_functions = new vector<void (*)()>; 352 shutdown_functions_mutex = new Mutex; 353} 354 355inline void InitShutdownFunctionsOnce() { 356 GoogleOnceInit(&shutdown_functions_init, &InitShutdownFunctions); 357} 358 359void OnShutdown(void (*func)()) { 360 InitShutdownFunctionsOnce(); 361 MutexLock lock(shutdown_functions_mutex); 362 shutdown_functions->push_back(func); 363} 364 365} // namespace internal 366 367void ShutdownProtobufLibrary() { 368 internal::InitShutdownFunctionsOnce(); 369 370 // We don't need to lock shutdown_functions_mutex because it's up to the 371 // caller to make sure that no one is using the library before this is 372 // called. 373 374 // Make it safe to call this multiple times. 375 if (internal::shutdown_functions == NULL) return; 376 377 for (int i = 0; i < internal::shutdown_functions->size(); i++) { 378 internal::shutdown_functions->at(i)(); 379 } 380 delete internal::shutdown_functions; 381 internal::shutdown_functions = NULL; 382 delete internal::shutdown_functions_mutex; 383 internal::shutdown_functions_mutex = NULL; 384} 385 386#if PROTOBUF_USE_EXCEPTIONS 387FatalException::~FatalException() throw() {} 388 389const char* FatalException::what() const throw() { 390 return message_.c_str(); 391} 392#endif 393 394} // namespace protobuf 395} // namespace google 396