2015-07-02 01:13:49 +02:00
|
|
|
// Copyright (c) 2013, Facebook, Inc. All rights reserved.
|
|
|
|
// This source code is licensed under the BSD-style license found in the
|
|
|
|
// LICENSE file in the root directory of this source tree. An additional grant
|
|
|
|
// of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
//
|
|
|
|
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
|
|
|
//
|
|
|
|
// See port_example.h for documentation for the following types/functions.
|
|
|
|
|
|
|
|
#ifndef STORAGE_LEVELDB_PORT_PORT_WIN_H_
|
|
|
|
#define STORAGE_LEVELDB_PORT_PORT_WIN_H_
|
|
|
|
|
|
|
|
// Always want minimum headers
|
|
|
|
#ifndef WIN32_LEAN_AND_MEAN
|
2015-07-13 21:11:05 +02:00
|
|
|
#define WIN32_LEAN_AND_MEAN
|
2015-07-02 01:13:49 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Assume that for everywhere
|
|
|
|
#undef PLATFORM_IS_LITTLE_ENDIAN
|
|
|
|
#define PLATFORM_IS_LITTLE_ENDIAN true
|
|
|
|
|
|
|
|
#include <windows.h>
|
|
|
|
#include <string>
|
|
|
|
#include <string.h>
|
|
|
|
#include <mutex>
|
|
|
|
#include <condition_variable>
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
#include "rocksdb/options.h"
|
|
|
|
|
2015-07-16 21:10:16 +02:00
|
|
|
#undef min
|
|
|
|
#undef max
|
|
|
|
#undef DeleteFile
|
|
|
|
#undef GetCurrentTime
|
|
|
|
|
|
|
|
|
2015-07-02 01:13:49 +02:00
|
|
|
#ifndef strcasecmp
|
|
|
|
#define strcasecmp _stricmp
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// defined in stdio.h
|
|
|
|
#ifndef snprintf
|
|
|
|
#define snprintf _snprintf
|
|
|
|
#endif
|
|
|
|
|
2015-07-16 21:10:16 +02:00
|
|
|
#undef GetCurrentTime
|
|
|
|
#undef DeleteFile
|
|
|
|
|
2015-07-02 01:13:49 +02:00
|
|
|
typedef SSIZE_T ssize_t;
|
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
// size_t printf formatting named in the manner of C99 standard formatting
|
|
|
|
// strings such as PRIu64
|
2015-07-02 01:13:49 +02:00
|
|
|
// in fact, we could use that one
|
2015-07-16 21:10:16 +02:00
|
|
|
#ifndef ROCKSDB_PRIszt
|
2015-07-02 01:13:49 +02:00
|
|
|
#define ROCKSDB_PRIszt "Iu"
|
2015-07-16 21:10:16 +02:00
|
|
|
#endif
|
2015-07-02 01:13:49 +02:00
|
|
|
|
2015-08-26 01:34:39 +02:00
|
|
|
#define ROCKSDB_NOEXCEPT
|
2015-08-26 00:17:14 +02:00
|
|
|
|
2015-07-02 01:13:49 +02:00
|
|
|
#define __attribute__(A)
|
|
|
|
|
|
|
|
#ifdef ZLIB
|
|
|
|
#include <zlib.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef BZIP2
|
|
|
|
#include <bzlib.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(LZ4)
|
|
|
|
#include <lz4.h>
|
|
|
|
#include <lz4hc.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef SNAPPY
|
2015-07-08 01:58:20 +02:00
|
|
|
#include <snappy.h>
|
2015-07-02 01:13:49 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Thread local storage on Linux
|
|
|
|
// There is thread_local in C++11
|
2015-07-16 21:10:16 +02:00
|
|
|
#ifndef __thread
|
2015-07-02 01:13:49 +02:00
|
|
|
#define __thread __declspec(thread)
|
2015-07-16 21:10:16 +02:00
|
|
|
#endif
|
2015-07-02 01:13:49 +02:00
|
|
|
|
|
|
|
#ifndef PLATFORM_IS_LITTLE_ENDIAN
|
|
|
|
#define PLATFORM_IS_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
namespace rocksdb {
|
|
|
|
|
|
|
|
#define PREFETCH(addr, rw, locality)
|
2015-08-27 03:51:18 +02:00
|
|
|
std::string GetWindowsErrSz(DWORD err);
|
2015-07-02 01:13:49 +02:00
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
namespace port {
|
2015-07-02 01:13:49 +02:00
|
|
|
|
2015-07-08 01:58:20 +02:00
|
|
|
// For use at db/file_indexer.h kLevelMaxIndex
|
2015-07-11 18:54:33 +02:00
|
|
|
const int kMaxInt32 = INT32_MAX;
|
|
|
|
const uint64_t kMaxUint64 = UINT64_MAX;
|
2015-09-22 19:34:21 +02:00
|
|
|
// std::numeric_limits<size_t>::max() is not constexpr just yet
|
|
|
|
// therefore, use the same limits
|
|
|
|
#ifdef _WIN64
|
|
|
|
const size_t kMaxSizet = UINT64_MAX;
|
|
|
|
#else
|
|
|
|
const size_t kMaxSizet = UINT_MAX;
|
|
|
|
#endif
|
2015-07-08 01:58:20 +02:00
|
|
|
|
2015-07-02 01:13:49 +02:00
|
|
|
const bool kLittleEndian = true;
|
|
|
|
|
|
|
|
class CondVar;
|
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
class Mutex {
|
|
|
|
public:
|
2015-10-13 00:41:20 +02:00
|
|
|
|
2015-10-13 23:28:11 +02:00
|
|
|
/* implicit */ Mutex(bool adaptive = false)
|
|
|
|
#ifndef NDEBUG
|
|
|
|
: locked_(false)
|
|
|
|
#endif
|
|
|
|
{ }
|
2015-10-13 00:41:20 +02:00
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
~Mutex();
|
|
|
|
|
2015-10-13 00:41:20 +02:00
|
|
|
void Lock() {
|
|
|
|
mutex_.lock();
|
|
|
|
#ifndef NDEBUG
|
|
|
|
locked_ = true;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void Unlock() {
|
|
|
|
#ifndef NDEBUG
|
|
|
|
locked_ = false;
|
|
|
|
#endif
|
|
|
|
mutex_.unlock();
|
|
|
|
}
|
2015-07-13 21:11:05 +02:00
|
|
|
|
|
|
|
// this will assert if the mutex is not locked
|
|
|
|
// it does NOT verify that mutex is held by a calling thread
|
2015-10-13 00:41:20 +02:00
|
|
|
void AssertHeld() {
|
|
|
|
#ifndef NDEBUG
|
|
|
|
assert(locked_);
|
|
|
|
#endif
|
|
|
|
}
|
2015-07-02 01:13:49 +02:00
|
|
|
|
2015-10-13 00:41:20 +02:00
|
|
|
// Mutex is move only with lock ownership transfer
|
|
|
|
Mutex(const Mutex&) = delete;
|
|
|
|
void operator=(const Mutex&) = delete;
|
2015-07-13 21:11:05 +02:00
|
|
|
|
|
|
|
private:
|
2015-10-13 00:41:20 +02:00
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
friend class CondVar;
|
2015-10-13 00:41:20 +02:00
|
|
|
|
|
|
|
std::mutex& getLock() {
|
|
|
|
return mutex_;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::mutex mutex_;
|
2015-07-02 01:13:49 +02:00
|
|
|
#ifndef NDEBUG
|
2015-07-13 21:11:05 +02:00
|
|
|
bool locked_;
|
2015-07-02 01:13:49 +02:00
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
class RWMutex {
|
|
|
|
public:
|
|
|
|
RWMutex() { InitializeSRWLock(&srwLock_); }
|
2015-07-02 01:13:49 +02:00
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
void ReadLock() { AcquireSRWLockShared(&srwLock_); }
|
2015-07-02 01:13:49 +02:00
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
void WriteLock() { AcquireSRWLockExclusive(&srwLock_); }
|
2015-07-02 01:13:49 +02:00
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
void ReadUnlock() { ReleaseSRWLockShared(&srwLock_); }
|
2015-07-02 01:13:49 +02:00
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
void WriteUnlock() { ReleaseSRWLockExclusive(&srwLock_); }
|
2015-07-02 01:13:49 +02:00
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
// Empty as in POSIX
|
|
|
|
void AssertHeld() {}
|
2015-07-02 01:13:49 +02:00
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
private:
|
2015-07-08 01:58:20 +02:00
|
|
|
SRWLOCK srwLock_;
|
|
|
|
// No copying allowed
|
|
|
|
RWMutex(const RWMutex&);
|
|
|
|
void operator=(const RWMutex&);
|
2015-07-02 01:13:49 +02:00
|
|
|
};
|
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
class CondVar {
|
|
|
|
public:
|
2015-10-13 00:41:20 +02:00
|
|
|
explicit CondVar(Mutex* mu) : mu_(mu) {
|
|
|
|
}
|
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
~CondVar();
|
|
|
|
void Wait();
|
|
|
|
bool TimedWait(uint64_t expiration_time);
|
|
|
|
void Signal();
|
|
|
|
void SignalAll();
|
|
|
|
|
2015-10-13 00:41:20 +02:00
|
|
|
// Condition var is not copy/move constructible
|
|
|
|
CondVar(const CondVar&) = delete;
|
|
|
|
CondVar& operator=(const CondVar&) = delete;
|
|
|
|
|
|
|
|
CondVar(CondVar&&) = delete;
|
|
|
|
CondVar& operator=(CondVar&&) = delete;
|
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
private:
|
|
|
|
std::condition_variable cv_;
|
|
|
|
Mutex* mu_;
|
2015-07-02 01:13:49 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::once_flag OnceType;
|
|
|
|
#define LEVELDB_ONCE_INIT std::once_flag::once_flag();
|
|
|
|
extern void InitOnce(OnceType* once, void (*initializer)());
|
|
|
|
|
|
|
|
#define CACHE_LINE_SIZE 64U
|
|
|
|
|
|
|
|
#ifdef min
|
|
|
|
#undef min
|
|
|
|
#endif
|
|
|
|
#ifdef max
|
|
|
|
#undef max
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// For Thread Local Storage abstraction
|
|
|
|
typedef DWORD pthread_key_t;
|
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
inline int pthread_key_create(pthread_key_t* key, void (*destructor)(void*)) {
|
|
|
|
// Not used
|
|
|
|
(void)destructor;
|
2015-07-02 01:13:49 +02:00
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
pthread_key_t k = TlsAlloc();
|
|
|
|
if (TLS_OUT_OF_INDEXES == k) {
|
|
|
|
return ENOMEM;
|
|
|
|
}
|
2015-07-02 01:13:49 +02:00
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
*key = k;
|
|
|
|
return 0;
|
2015-07-02 01:13:49 +02:00
|
|
|
}
|
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
inline int pthread_key_delete(pthread_key_t key) {
|
|
|
|
if (!TlsFree(key)) {
|
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
return 0;
|
2015-07-02 01:13:49 +02:00
|
|
|
}
|
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
inline int pthread_setspecific(pthread_key_t key, const void* value) {
|
|
|
|
if (!TlsSetValue(key, const_cast<void*>(value))) {
|
|
|
|
return ENOMEM;
|
|
|
|
}
|
|
|
|
return 0;
|
2015-07-02 01:13:49 +02:00
|
|
|
}
|
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
inline void* pthread_getspecific(pthread_key_t key) {
|
|
|
|
void* result = TlsGetValue(key);
|
|
|
|
if (!result) {
|
|
|
|
if (GetLastError() != ERROR_SUCCESS) {
|
|
|
|
errno = EINVAL;
|
|
|
|
} else {
|
|
|
|
errno = NOERROR;
|
2015-07-02 01:13:49 +02:00
|
|
|
}
|
2015-07-13 21:11:05 +02:00
|
|
|
}
|
|
|
|
return result;
|
2015-07-02 01:13:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// UNIX equiv although errno numbers will be off
|
|
|
|
// using C-runtime to implement. Note, this does not
|
|
|
|
// feel space with zeros in case the file is extended.
|
|
|
|
int truncate(const char* path, int64_t length);
|
2015-07-22 02:20:57 +02:00
|
|
|
void Crash(const std::string& srcfile, int srcline);
|
2015-09-10 19:49:28 +02:00
|
|
|
extern int GetMaxOpenFiles();
|
2015-07-02 01:13:49 +02:00
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
} // namespace port
|
2015-07-02 01:13:49 +02:00
|
|
|
|
|
|
|
using port::pthread_key_t;
|
|
|
|
using port::pthread_key_create;
|
|
|
|
using port::pthread_key_delete;
|
|
|
|
using port::pthread_setspecific;
|
|
|
|
using port::pthread_getspecific;
|
|
|
|
using port::truncate;
|
|
|
|
|
2015-07-13 21:11:05 +02:00
|
|
|
} // namespace rocksdb
|
2015-07-02 01:13:49 +02:00
|
|
|
|
|
|
|
#endif // STORAGE_LEVELDB_PORT_PORT_POSIX_H_
|