diff --git a/ASyncRedis.cpp b/ASyncRedis.cpp deleted file mode 100644 index 823a341..0000000 --- a/ASyncRedis.cpp +++ /dev/null @@ -1,198 +0,0 @@ -#pragma once - -#include "ASyncRedis.h" - -#include -#include - -struct QueryCb -{ - ASyncRedis::CommandCallback cb; - const ASyncRedis *ac; - void *data; -}; - -static void cmdCallback(redisAsyncContext *c, void *r, void *privdata) -{ - redisReply *reply = (redisReply *)r; - QueryCb *cb = (QueryCb *)privdata; - if (cb) { - if (cb->cb) { - cb->cb(cb->ac, r, cb->data); - } - delete cb; - } -} - -static void connectCallback(const redisAsyncContext *c, int status) -{ - if (c && c->data) { - ((ASyncRedis *)c->data)->ConnectCallback(status); - } -} - -static void disconnectCallback(const redisAsyncContext *c, int status) -{ - if (c && c->data) { - ((ASyncRedis *)c->data)->DisconnectCallback(status); - } -} - -static int timeEventCallback(aeEventLoop *eventLoop, PORT_LONGLONG id, void *clientData) -{ - auto ac = (ASyncRedis *)clientData; - return ac->EventMain(); -} - -ASyncRedis::ASyncRedis(int _intval, int cache) -{ - connected = false; - disconnected = false; - ac = nullptr; - - interval = _intval; - cache_size = cache; - - loop = aeCreateEventLoop(1024 * 10); - aeCreateTimeEvent(loop, interval, timeEventCallback, this, nullptr); - - evMain = std::thread([this] { - aeMain(loop); - }); - - std::this_thread::yield(); -} - -ASyncRedis::~ASyncRedis() -{ - if (loop) { - aeStop(loop); - } - - if (evMain.joinable()) { - evMain.join(); - } - - if (loop) { - aeDeleteEventLoop(loop); - } - - if (!connected && ac) { - redisAsyncDisconnect(ac); - } -} - -bool ASyncRedis::WaitForConnected() -{ - std::unique_lock lk(lock); - cv_connect.wait(lk, [this] {return connected; }); - return connected; -} - -bool ASyncRedis::WaitForDisconnected() -{ - std::unique_lock lk(lock); - cv_disconnect.wait(lk, [this] {return disconnected; }); - return disconnected; -} - -bool ASyncRedis::Connect(const std::string &ip, int port) -{ - connected = false; - disconnected = false; - ac = redisAsyncConnect(ip.c_str(), port); - if (ac->err) { - disconnected = true; - return false; - } - return Attach(); -} - -bool ASyncRedis::ConnectBind(const std::string &ip, int port, const std::string &source_addr) -{ - connected = false; - disconnected = false; - ac = redisAsyncConnectBind(ip.c_str(), port, source_addr.c_str()); - if (ac->err) { - disconnected = true; - return false; - } - return Attach(); -} - -bool ASyncRedis::Attach() -{ - ac->data = this; - - if (redisAeAttach(loop, ac) != REDIS_OK) { - return false; - } - - if (redisAsyncSetConnectCallback(ac, connectCallback) != REDIS_OK) { - return false; - } - - if (redisAsyncSetDisconnectCallback(ac, disconnectCallback) != REDIS_OK) { - return false; - } - - return true; -} - -bool ASyncRedis::Command(const std::string &cmd) -{ - if (!disconnected) { - return cmdlist.try_enqueue({ cmd, nullptr }); - } - return false; -} - -bool ASyncRedis::Command(const std::string &cmd, CommandCallback cb, void *data) -{ - if (!disconnected) { - QueryCb *p = new QueryCb{ cb, this, data }; - return cmdlist.try_enqueue({ cmd, p }); - } - return false; -} - -void ASyncRedis::ConnectCallback(int status) -{ - std::unique_lock lck(lock); - connected = true; - cv_connect.notify_all(); - - if (status != REDIS_OK) { - aeStop(loop); - return; - } -} - -void ASyncRedis::DisconnectCallback(int status) -{ - std::unique_lock lck(lock); - disconnected = true; - cv_disconnect.notify_all(); - - if (status != REDIS_OK) { - aeStop(loop); - return; - } -} - -int ASyncRedis::EventMain() -{ - if (cmdlist.size_approx()) { - std::vector cmds(cache_size); - int n = cmdlist.try_dequeue_bulk(cmds.begin(), cmds.size()); - for (int i = 0; i < n; ++i) { - auto[cmd, cb] = cmds[i]; - if (cb) { - redisAsyncCommand(ac, cmdCallback, cb, cmd.c_str()); - } else { - redisAsyncCommand(ac, nullptr, nullptr, cmd.c_str()); - } - } - } - return interval; -} diff --git a/ASyncRedis.h b/ASyncRedis.h deleted file mode 100644 index ea9380d..0000000 --- a/ASyncRedis.h +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include "concurrentqueue.h" - -#include -#include -extern "C" { -#include "adapters/ae.h" -} - -class ASyncRedis -{ -public: - using CommandCallback = std::function; - - ASyncRedis(int intval = 1000, int cache_size = 32); - ~ASyncRedis(); - - bool Connect(const std::string &ip, int port); - bool ConnectBind(const std::string &ip, int port, const std::string &source_addr); - - bool WaitForConnected(); - bool WaitForDisconnected(); - - bool Command(const std::string &cmd); - bool Command(const std::string &cmd, CommandCallback cb, void *data); - - virtual void ConnectCallback(int status); - virtual void DisconnectCallback(int status); - - int EventMain(); - - const redisAsyncContext* GetContext() const - { - return ac; - } - - int GetError() const - { - return ac->err; - } - - const char *GetErrorStr() const - { - return ac->errstr; - } - -private: - using QueryOp = std::tuple; - using QueryOps = moodycamel::ConcurrentQueue; - - bool Attach(); - - int interval; - int cache_size; - - aeEventLoop *loop; - redisAsyncContext *ac; - std::thread evMain; - - std::mutex lock; - std::condition_variable cv_connect; - std::condition_variable cv_disconnect; - - bool connected; - bool disconnected; - - QueryOps cmdlist; -}; diff --git a/RedisDB.h b/RedisDB.h deleted file mode 100644 index ff26a46..0000000 --- a/RedisDB.h +++ /dev/null @@ -1,343 +0,0 @@ -#pragma once - -#include "TQueue.h" -#include "ASyncRedis.h" - -#include - -#include - -class RedisReply -{ -public: - RedisReply(RedisReply && t) - { - this->type = t.type; - this->integer = t.integer; - this->elements = t.elements; - - if (!t.str.empty()) { - this->str = std::move(t.str); - } - - if (!t.reply_array.empty()) { - this->reply_array = std::move(t.reply_array); - } - } - - RedisReply(redisReply *reply = nullptr) - { - if (reply == nullptr) { - return; - } - - type = reply->type; - integer = reply->integer; - - if (reply->len > 0 && reply->str != nullptr) { - str = reply->str; - } - - if (reply->type == REDIS_REPLY_ARRAY && reply->element != nullptr) { - for (size_t i = 0; i < reply->elements; ++i) { - reply_array.emplace_back(reply->element[i]); - } - } - } - - int type = 0; - long long integer = 0; - size_t elements = 0; - - std::string str; - std::vector reply_array; -}; - -class RedisDB -{ -public: - static RedisDB *GetRedisDB(std::string host, int port, int maxTimeout, std::string pass) - { - if (host.empty()) { - return nullptr; - } - - auto db = new RedisDB(); - if (db->Connect(host, port, maxTimeout, pass) && db->Alive()) { - return db; - } - - delete db; - return nullptr; - } - - RedisDB() - { - this->ctx = nullptr; - } - - RedisDB(std::string host, int port, int maxTimeout, std::string pass) - { - RedisDB(); - Connect(host, port, maxTimeout, pass); - } - - ~RedisDB() - { - Close(); - } - - bool Connect(std::string host, int port, int maxTimeout, std::string pass) - { - struct timeval timeout = { maxTimeout, 0 }; - - if (maxTimeout > 0) - timeout.tv_sec = maxTimeout; - else timeout.tv_sec = 30; - - auto ctx = redisConnectWithTimeout(host.c_str(), port, timeout); - - if (ctx == nullptr || ctx->err) { - if (ctx) { - printf("Connection error: %s\n", ctx->errstr); - redisFree(ctx); - } else { - printf("Connection error: can't allocate redis context\n"); - } - return false; - } - - this->ctx = ctx; - - if (pass.empty()) { - return true; - } - - auto reply = this->Run("AUTH %s", pass.c_str()); - if (reply.type != REDIS_REPLY_STATUS || reply.str != "OK") { - printf("Redis Password error: %s\n", reply.str.c_str()); - redisFree(ctx); - - this->ctx = nullptr; - return false; - } - - return true; - } - - int ConnectAsync(std::string host, int port, std::string pass) - { - if (async) { - delete async; - } - - async = new ASyncRedis(); - if (!async->Connect(host.c_str(), port)) { - return async->GetError(); - } - - async->WaitForConnected(); - async->Command(("AUTH " + pass).c_str(), [this](const ASyncRedis *c, void *r, void *privdata) { - redisReply *reply = (redisReply *)r; - if (reply->type == REDIS_REPLY_STATUS && c->GetError() == REDIS_OK) { - this->canAsync = true; - } else { - this->canAsync = false; - } - }, nullptr); - - return async->GetError(); - } - - bool SELECT_DBID(int dbid) - { - if (this->ctx == nullptr) { - return false; - } - - auto reply = this->Run("SELECT %d", dbid); - if (reply.type != REDIS_REPLY_STATUS || reply.str != "OK") { - return false; - } - - if (canAsync && async) { - char buf[32]; - sprintf(buf, "SELECT %d", dbid); - async->Command(buf); - } - return true; - } - - bool Alive() - { - if (this->ctx == nullptr) { - return false; - } - - auto reply = this->Run("PING"); - if (reply.type != REDIS_REPLY_STATUS || ctx->err != REDIS_OK) { - return false; - } - - if (canAsync && async) { - async->Command("PING"); - return async->GetError() == REDIS_OK; - } - return true; - } - - bool Command(const char *format, ...) - { - if (this->ctx == nullptr) { - return false; - } - - va_list ap; - va_start(ap, format); - auto res = redisvAppendCommand(ctx, format, ap); - va_end(ap); - return res == REDIS_OK; - } - - bool CommandAsync(const char *format, ...) - { - if (!canAsync || !async) { - return false; - } - - char buf[1024]; - va_list arglist; - va_start(arglist, format); - _vsnprintf(buf, 1024, format, arglist); - va_end(arglist); - - return async->Command(buf); - } - - bool Execute(const char *format, ...) - { - if (this->ctx == nullptr) { - return false; - } - - va_list ap; - va_start(ap, format); - redisReply *res = (redisReply *)redisvCommand(ctx, format, ap); - va_end(ap); - - if (res == nullptr) { - return false; - } - - bool success = res->type != REDIS_REPLY_ERROR && ctx->err == REDIS_OK; - freeReplyObject(res); - - return success; - } - - RedisReply Run(const char *format, ...) - { - if (this->ctx == nullptr) { - return RedisReply(); - } - - va_list ap; - va_start(ap, format); - auto reply = redisvCommand(ctx, format, ap); - va_end(ap); - - auto res = RedisReply((redisReply *)reply); - - if (reply != nullptr) { - freeReplyObject(reply); - } - - return res; - } - - RedisReply GetReply(bool block = false) - { - if (this->ctx == nullptr) { - return RedisReply(); - } - - redisReply *reply; - redisGetReply(ctx, (void **)&reply); - - auto res = RedisReply(reply); - if (reply != nullptr) { - freeReplyObject(reply); - } - - return std::move(res); - } - - std::vector GetReplies(int count) - { - std::vector res; - if (this->ctx == nullptr) { - return{}; - } - - while (res.size() != count) { - auto reply = GetReply(false); - if (reply.type == 0) { - continue; - } - - res.emplace_back(std::move(reply)); - } - - return res; - } - - bool Close() - { - if (this->ctx != nullptr) { - redisFree(this->ctx); - } - - if (async) { - delete async; - } - - return true; - } - - int GetErrorCode() const - { - return ctx->err; - } - - const char *GetErrorStr() const - { - return ctx->errstr; - } - - const char *GetASyncErrorStr() const - { - return async->GetErrorStr(); - } - - //void LockForFullAtomicOperation() - //{ - // lock.Lock(); - //} - - //void UnlockFromFullAtomicOperation() - //{ - // lock.Unlock(); - //} - - bool CanAsync() const - { - return canAsync; - } - -private: - // std::mutex lock; - redisContext *ctx; - - bool canAsync = false; - ASyncRedis *async = nullptr; -}; diff --git a/adapters/ae.h b/adapters/ae.h deleted file mode 100644 index 269e1c3..0000000 --- a/adapters/ae.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIREDIS_AE_H__ -#define __HIREDIS_AE_H__ -#include -#ifdef _WIN32 -#include "../ae.h" -#else -#include -#endif -#include -#include - -typedef struct redisAeEvents { - redisAsyncContext *context; - aeEventLoop *loop; - int fd; - int reading, writing; -} redisAeEvents; - -static void redisAeReadEvent(aeEventLoop *el, int fd, void *privdata, int mask) { - ((void)el); ((void)fd); ((void)mask); - - redisAeEvents *e = (redisAeEvents*)privdata; - redisAsyncHandleRead(e->context); -} - -static void redisAeWriteEvent(aeEventLoop *el, int fd, void *privdata, int mask) { - ((void)el); ((void)fd); ((void)mask); - - redisAeEvents *e = (redisAeEvents*)privdata; - redisAsyncHandleWrite(e->context); -} - -static void redisAeAddRead(void *privdata) { - redisAeEvents *e = (redisAeEvents*)privdata; - aeEventLoop *loop = e->loop; - if (!e->reading) { - e->reading = 1; - aeCreateFileEvent(loop,e->fd,AE_READABLE,redisAeReadEvent,e); - } -} - -#ifdef _WIN32 -static void redisAeForceAddRead(void *privdata) { - redisAeEvents *e = (redisAeEvents*)privdata; - aeEventLoop *loop = e->loop; - e->reading = 1; - aeCreateFileEvent(loop, e->fd, AE_READABLE, redisAeReadEvent, e); -} -#endif - -static void redisAeDelRead(void *privdata) { - redisAeEvents *e = (redisAeEvents*)privdata; - aeEventLoop *loop = e->loop; - if (e->reading) { - e->reading = 0; - aeDeleteFileEvent(loop,e->fd,AE_READABLE); - } -} - -static void redisAeAddWrite(void *privdata) { - redisAeEvents *e = (redisAeEvents*)privdata; - aeEventLoop *loop = e->loop; - if (!e->writing) { - e->writing = 1; - aeCreateFileEvent(loop,e->fd,AE_WRITABLE,redisAeWriteEvent,e); - } -} - -static void redisAeDelWrite(void *privdata) { - redisAeEvents *e = (redisAeEvents*)privdata; - aeEventLoop *loop = e->loop; - if (e->writing) { - e->writing = 0; - aeDeleteFileEvent(loop,e->fd,AE_WRITABLE); - } -} - -static void redisAeCleanup(void *privdata) { - redisAeEvents *e = (redisAeEvents*)privdata; - redisAeDelRead(privdata); - redisAeDelWrite(privdata); - free(e); -} - -static int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac) { - redisContext *c = &(ac->c); - redisAeEvents *e; - - /* Nothing should be attached when something is already attached */ - if (ac->ev.data != NULL) - return REDIS_ERR; - - /* Create container for context and r/w events */ - e = (redisAeEvents*)malloc(sizeof(*e)); - e->context = ac; - e->loop = loop; - e->fd = c->fd; - e->reading = e->writing = 0; - - /* Register functions to start/stop listening for events */ - ac->ev.addRead = redisAeAddRead; -#ifdef _WIN32 - ac->ev.forceAddRead = redisAeForceAddRead; -#endif - ac->ev.delRead = redisAeDelRead; - ac->ev.addWrite = redisAeAddWrite; - ac->ev.delWrite = redisAeDelWrite; - ac->ev.cleanup = redisAeCleanup; - ac->ev.data = e; - - return REDIS_OK; -} -#endif diff --git a/addons/sourcemod/configs/databases.cfg b/addons/sourcemod/configs/databases.cfg index 330544c..4325960 100644 --- a/addons/sourcemod/configs/databases.cfg +++ b/addons/sourcemod/configs/databases.cfg @@ -36,6 +36,7 @@ { "driver" "redis" "host" "127.0.0.1" + "database" "0" "pass" "foobared233" } } diff --git a/addons/sourcemod/extensions/.gitkeep b/addons/sourcemod/extensions/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/adlist.c b/adlist.c deleted file mode 100644 index eb361dc..0000000 --- a/adlist.c +++ /dev/null @@ -1,344 +0,0 @@ -/* adlist.c - A generic doubly linked list implementation - * - * Copyright (c) 2006-2010, Salvatore Sanfilippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#ifdef _WIN32 -#include "Win32_Interop/Win32_Portability.h" -#include "Win32_Interop/win32_types.h" -#endif - -#include -#include "adlist.h" -#include - - /* Create a new list. The created list can be freed with - * AlFreeList(), but private value of every node need to be freed - * by the user before to call AlFreeList(). - * - * On error, NULL is returned. Otherwise the pointer to the new list. */ -list *listCreate(void) -{ - struct list *list; - - if ((list = zmalloc(sizeof(*list))) == NULL) - return NULL; - list->head = list->tail = NULL; - list->len = 0; - list->dup = NULL; - list->free = NULL; - list->match = NULL; - return list; -} - -/* Free the whole list. - * - * This function can't fail. */ -void listRelease(list *list) -{ - PORT_ULONG len; - listNode *current, *next; - - current = list->head; - len = list->len; - while (len--) { - next = current->next; - if (list->free) list->free(current->value); - zfree(current); - current = next; - } - zfree(list); -} - -/* Add a new node to the list, to head, containing the specified 'value' - * pointer as value. - * - * On error, NULL is returned and no operation is performed (i.e. the - * list remains unaltered). - * On success the 'list' pointer you pass to the function is returned. */ -list *listAddNodeHead(list *list, void *value) -{ - listNode *node; - - if ((node = zmalloc(sizeof(*node))) == NULL) - return NULL; - node->value = value; - if (list->len == 0) { - list->head = list->tail = node; - node->prev = node->next = NULL; - } else { - node->prev = NULL; - node->next = list->head; - list->head->prev = node; - list->head = node; - } - list->len++; - return list; -} - -/* Add a new node to the list, to tail, containing the specified 'value' - * pointer as value. - * - * On error, NULL is returned and no operation is performed (i.e. the - * list remains unaltered). - * On success the 'list' pointer you pass to the function is returned. */ -list *listAddNodeTail(list *list, void *value) -{ - listNode *node; - - if ((node = zmalloc(sizeof(*node))) == NULL) - return NULL; - node->value = value; - if (list->len == 0) { - list->head = list->tail = node; - node->prev = node->next = NULL; - } else { - node->prev = list->tail; - node->next = NULL; - list->tail->next = node; - list->tail = node; - } - list->len++; - return list; -} - -list *listInsertNode(list *list, listNode *old_node, void *value, int after) -{ - listNode *node; - - if ((node = zmalloc(sizeof(*node))) == NULL) - return NULL; - node->value = value; - if (after) { - node->prev = old_node; - node->next = old_node->next; - if (list->tail == old_node) { - list->tail = node; - } - } else { - node->next = old_node; - node->prev = old_node->prev; - if (list->head == old_node) { - list->head = node; - } - } - if (node->prev != NULL) { - node->prev->next = node; - } - if (node->next != NULL) { - node->next->prev = node; - } - list->len++; - return list; -} - -/* Remove the specified node from the specified list. - * It's up to the caller to free the private value of the node. - * - * This function can't fail. */ -void listDelNode(list *list, listNode *node) -{ - if (node->prev) - node->prev->next = node->next; - else - list->head = node->next; - if (node->next) - node->next->prev = node->prev; - else - list->tail = node->prev; - if (list->free) list->free(node->value); - zfree(node); - list->len--; -} - -/* Returns a list iterator 'iter'. After the initialization every - * call to listNext() will return the next element of the list. - * - * This function can't fail. */ -listIter *listGetIterator(list *list, int direction) -{ - listIter *iter; - - if ((iter = zmalloc(sizeof(*iter))) == NULL) return NULL; - if (direction == AL_START_HEAD) - iter->next = list->head; - else - iter->next = list->tail; - iter->direction = direction; - return iter; -} - -/* Release the iterator memory */ -void listReleaseIterator(listIter *iter) -{ - zfree(iter); -} - -/* Create an iterator in the list private iterator structure */ -void listRewind(list *list, listIter *li) -{ - li->next = list->head; - li->direction = AL_START_HEAD; -} - -void listRewindTail(list *list, listIter *li) -{ - li->next = list->tail; - li->direction = AL_START_TAIL; -} - -/* Return the next element of an iterator. - * It's valid to remove the currently returned element using - * listDelNode(), but not to remove other elements. - * - * The function returns a pointer to the next element of the list, - * or NULL if there are no more elements, so the classical usage patter - * is: - * - * iter = listGetIterator(list,); - * while ((node = listNext(iter)) != NULL) { - * doSomethingWith(listNodeValue(node)); - * } - * - * */ -listNode *listNext(listIter *iter) -{ - listNode *current = iter->next; - - if (current != NULL) { - if (iter->direction == AL_START_HEAD) - iter->next = current->next; - else - iter->next = current->prev; - } - return current; -} - -/* Duplicate the whole list. On out of memory NULL is returned. - * On success a copy of the original list is returned. - * - * The 'Dup' method set with listSetDupMethod() function is used - * to copy the node value. Otherwise the same pointer value of - * the original node is used as value of the copied node. - * - * The original list both on success or error is never modified. */ -list *listDup(list *orig) -{ - list *copy; - listIter iter; - listNode *node; - - if ((copy = listCreate()) == NULL) - return NULL; - copy->dup = orig->dup; - copy->free = orig->free; - copy->match = orig->match; - listRewind(orig, &iter); - while ((node = listNext(&iter)) != NULL) { - void *value; - - if (copy->dup) { - value = copy->dup(node->value); - if (value == NULL) { - listRelease(copy); - return NULL; - } - } else - value = node->value; - if (listAddNodeTail(copy, value) == NULL) { - listRelease(copy); - return NULL; - } - } - return copy; -} - -/* Search the list for a node matching a given key. - * The match is performed using the 'match' method - * set with listSetMatchMethod(). If no 'match' method - * is set, the 'value' pointer of every node is directly - * compared with the 'key' pointer. - * - * On success the first matching node pointer is returned - * (search starts from head). If no matching node exists - * NULL is returned. */ -listNode *listSearchKey(list *list, void *key) -{ - listIter iter; - listNode *node; - - listRewind(list, &iter); - while ((node = listNext(&iter)) != NULL) { - if (list->match) { - if (list->match(node->value, key)) { - return node; - } - } else { - if (key == node->value) { - return node; - } - } - } - return NULL; -} - -/* Return the element at the specified zero-based index - * where 0 is the head, 1 is the element next to head - * and so on. Negative integers are used in order to count - * from the tail, -1 is the last element, -2 the penultimate - * and so on. If the index is out of range NULL is returned. */ -listNode *listIndex(list *list, PORT_LONG index) -{ - listNode *n; - - if (index < 0) { - index = (-index) - 1; - n = list->tail; - while (index-- && n) n = n->prev; - } else { - n = list->head; - while (index-- && n) n = n->next; - } - return n; -} - -/* Rotate the list removing the tail node and inserting it to the head. */ -void listRotate(list *list) -{ - listNode *tail = list->tail; - - if (listLength(list) <= 1) return; - - /* Detach current tail */ - list->tail = tail->prev; - list->tail->next = NULL; - /* Move it as head */ - list->head->prev = tail; - tail->prev = NULL; - tail->next = list->head; - list->head = tail; -} diff --git a/adlist.h b/adlist.h deleted file mode 100644 index 2745f5c..0000000 --- a/adlist.h +++ /dev/null @@ -1,96 +0,0 @@ -/* adlist.h - A generic doubly linked list implementation - * - * Copyright (c) 2006-2012, Salvatore Sanfilippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#ifdef _WIN32 -#include "Win32_Interop/Win32_Portability.h" -#endif - -#ifndef __ADLIST_H__ -#define __ADLIST_H__ - -/* Node, List, and Iterator are the only data structures used currently. */ - -typedef struct listNode { - struct listNode *prev; - struct listNode *next; - void *value; -} listNode; - -typedef struct listIter { - listNode *next; - int direction; -} listIter; - -typedef struct list { - listNode *head; - listNode *tail; - void *(*dup)(void *ptr); - void (*free)(void *ptr); - int (*match)(void *ptr, void *key); - PORT_ULONG len; -} list; - -/* Functions implemented as macros */ -#define listLength(l) ((l)->len) -#define listFirst(l) ((l)->head) -#define listLast(l) ((l)->tail) -#define listPrevNode(n) ((n)->prev) -#define listNextNode(n) ((n)->next) -#define listNodeValue(n) ((n)->value) - -#define listSetDupMethod(l,m) ((l)->dup = (m)) -#define listSetFreeMethod(l,m) ((l)->free = (m)) -#define listSetMatchMethod(l,m) ((l)->match = (m)) - -#define listGetDupMethod(l) ((l)->dup) -#define listGetFree(l) ((l)->free) -#define listGetMatchMethod(l) ((l)->match) - -/* Prototypes */ -list *listCreate(void); -void listRelease(list *list); -list *listAddNodeHead(list *list, void *value); -list *listAddNodeTail(list *list, void *value); -list *listInsertNode(list *list, listNode *old_node, void *value, int after); -void listDelNode(list *list, listNode *node); -listIter *listGetIterator(list *list, int direction); -listNode *listNext(listIter *iter); -void listReleaseIterator(listIter *iter); -list *listDup(list *orig); -listNode *listSearchKey(list *list, void *key); -listNode *listIndex(list *list, PORT_LONG index); -void listRewind(list *list, listIter *li); -void listRewindTail(list *list, listIter *li); -void listRotate(list *list); - -/* Directions for iterators */ -#define AL_START_HEAD 0 -#define AL_START_TAIL 1 - -#endif /* __ADLIST_H__ */ diff --git a/ae.c b/ae.c deleted file mode 100644 index 4b3047c..0000000 --- a/ae.c +++ /dev/null @@ -1,505 +0,0 @@ -/* A simple event-driven programming library. Originally I wrote this code - * for the Jim's event-loop (Jim is a Tcl interpreter) but later translated - * it in form of a library for easy reuse. - * - * Copyright (c) 2006-2010, Salvatore Sanfilippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include - //#include -#ifdef _WIN32 -//#include -#include -#include -#include -#else -#include -#include -#include -#endif -#include -#include -#include -#include - -#include "ae.h" -#include - // #include "config.h" - - /* Include the best multiplexing layer supported by this system. - * The following should be ordered by performances, descending. */ -#ifdef _WIN32 -#include "ae_wsiocp.c" -#else -#ifdef HAVE_EVPORT -#include "ae_evport.c" -#else -#ifdef HAVE_EPOLL -#include "ae_epoll.c" -#else -#ifdef HAVE_KQUEUE -#include "ae_kqueue.c" -#else -#include "ae_select.c" -#endif -#endif -#endif -#endif - -aeEventLoop *aeCreateEventLoop(int setsize) -{ - aeEventLoop *eventLoop; - int i; - - if ((eventLoop = zmalloc(sizeof(*eventLoop))) == NULL) goto err; - eventLoop->events = zmalloc(sizeof(aeFileEvent)*setsize); - eventLoop->fired = zmalloc(sizeof(aeFiredEvent)*setsize); - if (eventLoop->events == NULL || eventLoop->fired == NULL) goto err; - eventLoop->setsize = setsize; - eventLoop->lastTime = time(NULL); - eventLoop->timeEventHead = NULL; - eventLoop->timeEventNextId = 0; - eventLoop->stop = 0; - eventLoop->maxfd = -1; - eventLoop->beforesleep = NULL; - if (aeApiCreate(eventLoop) == -1) goto err; - /* Events with mask == AE_NONE are not set. So let's initialize the - * vector with it. */ - for (i = 0; i < setsize; i++) - eventLoop->events[i].mask = AE_NONE; - return eventLoop; - -err: - if (eventLoop) { - zfree(eventLoop->events); - zfree(eventLoop->fired); - zfree(eventLoop); - } - return NULL; -} - -/* Return the current set size. */ -int aeGetSetSize(aeEventLoop *eventLoop) -{ - return eventLoop->setsize; -} - -/* Resize the maximum set size of the event loop. - * If the requested set size is smaller than the current set size, but - * there is already a file descriptor in use that is >= the requested - * set size minus one, AE_ERR is returned and the operation is not - * performed at all. - * - * Otherwise AE_OK is returned and the operation is successful. */ -int aeResizeSetSize(aeEventLoop *eventLoop, int setsize) -{ - int i; - - if (setsize == eventLoop->setsize) return AE_OK; - if (eventLoop->maxfd >= setsize) return AE_ERR; - if (aeApiResize(eventLoop, setsize) == -1) return AE_ERR; - - eventLoop->events = zrealloc(eventLoop->events, sizeof(aeFileEvent)*setsize); - eventLoop->fired = zrealloc(eventLoop->fired, sizeof(aeFiredEvent)*setsize); - eventLoop->setsize = setsize; - - /* Make sure that if we created new slots, they are initialized with - * an AE_NONE mask. */ - for (i = eventLoop->maxfd + 1; i < setsize; i++) - eventLoop->events[i].mask = AE_NONE; - return AE_OK; -} - -void aeDeleteEventLoop(aeEventLoop *eventLoop) -{ - aeApiFree(eventLoop); - zfree(eventLoop->events); - zfree(eventLoop->fired); - zfree(eventLoop); -} - -void aeStop(aeEventLoop *eventLoop) -{ - eventLoop->stop = 1; -} - -int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask, - aeFileProc *proc, void *clientData) -{ - if (fd >= eventLoop->setsize) { - errno = ERANGE; - return AE_ERR; - } - aeFileEvent *fe = &eventLoop->events[fd]; - - if (aeApiAddEvent(eventLoop, fd, mask) == -1) - return AE_ERR; - fe->mask |= mask; - if (mask & AE_READABLE) fe->rfileProc = proc; - if (mask & AE_WRITABLE) fe->wfileProc = proc; - fe->clientData = clientData; - if (fd > eventLoop->maxfd) - eventLoop->maxfd = fd; - return AE_OK; -} - -void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask) -{ - if (fd >= eventLoop->setsize) return; - aeFileEvent *fe = &eventLoop->events[fd]; - if (fe->mask == AE_NONE) return; - - aeApiDelEvent(eventLoop, fd, mask); - fe->mask = fe->mask & (~mask); - if (fd == eventLoop->maxfd && fe->mask == AE_NONE) { - /* Update the max fd */ - int j; - - for (j = eventLoop->maxfd - 1; j >= 0; j--) - if (eventLoop->events[j].mask != AE_NONE) break; - eventLoop->maxfd = j; - } -} - -int aeGetFileEvents(aeEventLoop *eventLoop, int fd) -{ - if (fd >= eventLoop->setsize) return 0; - aeFileEvent *fe = &eventLoop->events[fd]; - - return fe->mask; -} - -static void aeGetTime(PORT_LONG *seconds, PORT_LONG *milliseconds) -{ -#ifdef _WIN32 - struct _timeb tb; - - memset(&tb, 0, sizeof(struct _timeb)); - _ftime_s(&tb); - (*seconds) = tb.time; - (*milliseconds) = tb.millitm; -#else - struct timeval tv; - - gettimeofday(&tv, NULL); - *seconds = tv.tv_sec; - *milliseconds = tv.tv_usec / 1000; -#endif -} - -static void aeAddMillisecondsToNow(PORT_LONGLONG milliseconds, PORT_LONG *sec, PORT_LONG *ms) -{ - PORT_LONG cur_sec, cur_ms, when_sec, when_ms; - - aeGetTime(&cur_sec, &cur_ms); - when_sec = (PORT_LONG)(cur_sec + milliseconds / 1000); - when_ms = cur_ms + milliseconds % 1000; - if (when_ms >= 1000) { - when_sec++; - when_ms -= 1000; - } - *sec = when_sec; - *ms = when_ms; -} - -PORT_LONGLONG aeCreateTimeEvent(aeEventLoop *eventLoop, PORT_LONGLONG milliseconds, - aeTimeProc *proc, void *clientData, - aeEventFinalizerProc *finalizerProc) -{ - PORT_LONGLONG id = eventLoop->timeEventNextId++; - aeTimeEvent *te; - - te = zmalloc(sizeof(*te)); - if (te == NULL) return AE_ERR; - te->id = id; - aeAddMillisecondsToNow(milliseconds, &te->when_sec, &te->when_ms); - te->timeProc = proc; - te->finalizerProc = finalizerProc; - te->clientData = clientData; - te->next = eventLoop->timeEventHead; - eventLoop->timeEventHead = te; - return id; -} - -int aeDeleteTimeEvent(aeEventLoop *eventLoop, PORT_LONGLONG id) -{ - aeTimeEvent *te = eventLoop->timeEventHead; - while (te) { - if (te->id == id) { - te->id = AE_DELETED_EVENT_ID; - return AE_OK; - } - te = te->next; - } - return AE_ERR; /* NO event with the specified ID found */ -} - -/* Search the first timer to fire. - * This operation is useful to know how many time the select can be - * put in sleep without to delay any event. - * If there are no timers NULL is returned. - * - * Note that's O(N) since time events are unsorted. - * Possible optimizations (not needed by Redis so far, but...): - * 1) Insert the event in order, so that the nearest is just the head. - * Much better but still insertion or deletion of timers is O(N). - * 2) Use a skiplist to have this operation as O(1) and insertion as O(log(N)). - */ -static aeTimeEvent *aeSearchNearestTimer(aeEventLoop *eventLoop) -{ - aeTimeEvent *te = eventLoop->timeEventHead; - aeTimeEvent *nearest = NULL; - - while (te) { - if (!nearest || te->when_sec < nearest->when_sec || - (te->when_sec == nearest->when_sec && - te->when_ms < nearest->when_ms)) - nearest = te; - te = te->next; - } - return nearest; -} - -/* Process time events */ -static int processTimeEvents(aeEventLoop *eventLoop) -{ - int processed = 0; - aeTimeEvent *te, *prev; - PORT_LONGLONG maxId; - time_t now = time(NULL); - - /* If the system clock is moved to the future, and then set back to the - * right value, time events may be delayed in a random way. Often this - * means that scheduled operations will not be performed soon enough. - * - * Here we try to detect system clock skews, and force all the time - * events to be processed ASAP when this happens: the idea is that - * processing events earlier is less dangerous than delaying them - * indefinitely, and practice suggests it is. */ - if (now < eventLoop->lastTime) { - te = eventLoop->timeEventHead; - while (te) { - te->when_sec = 0; - te = te->next; - } - } - eventLoop->lastTime = now; - - prev = NULL; - te = eventLoop->timeEventHead; - maxId = eventLoop->timeEventNextId - 1; - while (te) { - PORT_LONG now_sec, now_ms; - PORT_LONGLONG id; - - /* Remove events scheduled for deletion. */ - if (te->id == AE_DELETED_EVENT_ID) { - aeTimeEvent *next = te->next; - if (prev == NULL) - eventLoop->timeEventHead = te->next; - else - prev->next = te->next; - if (te->finalizerProc) - te->finalizerProc(eventLoop, te->clientData); - zfree(te); - te = next; - continue; - } - - /* Make sure we don't process time events created by time events in - * this iteration. Note that this check is currently useless: we always - * add new timers on the head, however if we change the implementation - * detail, this check may be useful again: we keep it here for future - * defense. */ - if (te->id > maxId) { - te = te->next; - continue; - } - aeGetTime(&now_sec, &now_ms); - if (now_sec > te->when_sec || - (now_sec == te->when_sec && now_ms >= te->when_ms)) { - int retval; - - id = te->id; - retval = te->timeProc(eventLoop, id, te->clientData); - processed++; - if (retval != AE_NOMORE) { - aeAddMillisecondsToNow(retval, &te->when_sec, &te->when_ms); - } else { - te->id = AE_DELETED_EVENT_ID; - } - } - prev = te; - te = te->next; - } - return processed; -} - -/* Process every pending time event, then every pending file event - * (that may be registered by time event callbacks just processed). - * Without special flags the function sleeps until some file event - * fires, or when the next time event occurs (if any). - * - * If flags is 0, the function does nothing and returns. - * if flags has AE_ALL_EVENTS set, all the kind of events are processed. - * if flags has AE_FILE_EVENTS set, file events are processed. - * if flags has AE_TIME_EVENTS set, time events are processed. - * if flags has AE_DONT_WAIT set the function returns ASAP until all - * the events that's possible to process without to wait are processed. - * - * The function returns the number of events processed. */ -int aeProcessEvents(aeEventLoop *eventLoop, int flags) -{ - int processed = 0, numevents; - - /* - #ifdef _WIN32 - if (ServiceStopIssued() == TRUE) { - aeStop(eventLoop); - } - #endif - */ - - /* Nothing to do? return ASAP */ - if (!(flags & AE_TIME_EVENTS) && !(flags & AE_FILE_EVENTS)) return 0; - - /* Note that we want call select() even if there are no - * file events to process as PORT_LONG as we want to process time - * events, in order to sleep until the next time event is ready - * to fire. */ - if (eventLoop->maxfd != -1 || - ((flags & AE_TIME_EVENTS) && !(flags & AE_DONT_WAIT))) { - int j; - aeTimeEvent *shortest = NULL; - struct timeval tv, *tvp; - - if (flags & AE_TIME_EVENTS && !(flags & AE_DONT_WAIT)) - shortest = aeSearchNearestTimer(eventLoop); - if (shortest) { - PORT_LONG now_sec, now_ms; - - aeGetTime(&now_sec, &now_ms); - tvp = &tv; - - /* How many milliseconds we need to wait for the next - * time event to fire? */ - PORT_LONGLONG ms = - (shortest->when_sec - now_sec) * 1000 + - shortest->when_ms - now_ms; - - if (ms > 0) { - tvp->tv_sec = ms / 1000; - tvp->tv_usec = (ms % 1000) * 1000; - } else { - tvp->tv_sec = 0; - tvp->tv_usec = 0; - } - } else { - /* If we have to check for events but need to return - * ASAP because of AE_DONT_WAIT we need to set the timeout - * to zero */ - if (flags & AE_DONT_WAIT) { - tv.tv_sec = tv.tv_usec = 0; - tvp = &tv; - } else { - /* Otherwise we can block */ - tvp = NULL; /* wait forever */ - } - } - - numevents = aeApiPoll(eventLoop, tvp); - for (j = 0; j < numevents; j++) { - aeFileEvent *fe = &eventLoop->events[eventLoop->fired[j].fd]; - int mask = eventLoop->fired[j].mask; - int fd = eventLoop->fired[j].fd; - int rfired = 0; - - /* note the fe->mask & mask & ... code: maybe an already processed - * event removed an element that fired and we still didn't - * processed, so we check if the event is still valid. */ - if (fe->mask & mask & AE_READABLE) { - rfired = 1; - fe->rfileProc(eventLoop, fd, fe->clientData, mask); - } - if (fe->mask & mask & AE_WRITABLE) { - if (!rfired || fe->wfileProc != fe->rfileProc) - fe->wfileProc(eventLoop, fd, fe->clientData, mask); - } - processed++; - } - } - /* Check time events */ - if (flags & AE_TIME_EVENTS) - processed += processTimeEvents(eventLoop); - - return processed; /* return the number of processed file/time events */ -} - -/* Wait for milliseconds until the given file descriptor becomes - * writable/readable/exception */ -int aeWait(int fd, int mask, PORT_LONGLONG milliseconds) -{ - struct pollfd pfd; - int retmask = 0, retval; - - memset(&pfd, 0, sizeof(pfd)); - pfd.fd = fd; - if (mask & AE_READABLE) pfd.events |= POLLIN; - if (mask & AE_WRITABLE) pfd.events |= POLLOUT; - - if ((retval = poll(&pfd, 1, (int)milliseconds)) == 1) { - WIN_PORT_FIX /* cast (int) */ - if (pfd.revents & POLLIN) retmask |= AE_READABLE; - if (pfd.revents & POLLOUT) retmask |= AE_WRITABLE; - if (pfd.revents & POLLERR) retmask |= AE_WRITABLE; - if (pfd.revents & POLLHUP) retmask |= AE_WRITABLE; - return retmask; - } else { - return retval; - } -} - -void aeMain(aeEventLoop *eventLoop) -{ - eventLoop->stop = 0; - while (!eventLoop->stop) { - if (eventLoop->beforesleep != NULL) - eventLoop->beforesleep(eventLoop); - aeProcessEvents(eventLoop, AE_ALL_EVENTS); - } -} - -char *aeGetApiName(void) -{ - return aeApiName(); -} - -void aeSetBeforeSleepProc(aeEventLoop *eventLoop, aeBeforeSleepProc *beforesleep) -{ - eventLoop->beforesleep = beforesleep; -} diff --git a/ae.h b/ae.h deleted file mode 100644 index 964244a..0000000 --- a/ae.h +++ /dev/null @@ -1,127 +0,0 @@ -/* A simple event-driven programming library. Originally I wrote this code - * for the Jim's event-loop (Jim is a Tcl interpreter) but later translated - * it in form of a library for easy reuse. - * - * Copyright (c) 2006-2012, Salvatore Sanfilippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __AE_H__ -#define __AE_H__ - -#include - -#define AE_OK 0 -#define AE_ERR -1 - -#define AE_NONE 0 -#define AE_READABLE 1 -#define AE_WRITABLE 2 - -#define AE_FILE_EVENTS 1 -#define AE_TIME_EVENTS 2 -#define AE_ALL_EVENTS (AE_FILE_EVENTS|AE_TIME_EVENTS) -#define AE_DONT_WAIT 4 - -#define AE_NOMORE -1 -#define AE_DELETED_EVENT_ID -1 - - /* Macros */ -#define AE_NOTUSED(V) ((void) V) - -struct aeEventLoop; - -/* Types and data structures */ -typedef void aeFileProc(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask); -typedef int aeTimeProc(struct aeEventLoop *eventLoop, PORT_LONGLONG id, void *clientData); -typedef void aeEventFinalizerProc(struct aeEventLoop *eventLoop, void *clientData); -typedef void aeBeforeSleepProc(struct aeEventLoop *eventLoop); - -/* File event structure */ -typedef struct aeFileEvent -{ - int mask; /* one of AE_(READABLE|WRITABLE) */ - aeFileProc *rfileProc; - aeFileProc *wfileProc; - void *clientData; -} aeFileEvent; - -/* Time event structure */ -typedef struct aeTimeEvent -{ - PORT_LONGLONG id; /* time event identifier. */ - PORT_LONG when_sec; /* seconds */ - PORT_LONG when_ms; /* milliseconds */ - aeTimeProc *timeProc; - aeEventFinalizerProc *finalizerProc; - void *clientData; - struct aeTimeEvent *next; -} aeTimeEvent; - -/* A fired event */ -typedef struct aeFiredEvent -{ - int fd; - int mask; -} aeFiredEvent; - -/* State of an event based program */ -typedef struct aeEventLoop -{ - int maxfd; /* highest file descriptor currently registered */ - int setsize; /* max number of file descriptors tracked */ - PORT_LONGLONG timeEventNextId; - time_t lastTime; /* Used to detect system clock skew */ - aeFileEvent *events; /* Registered events */ - aeFiredEvent *fired; /* Fired events */ - aeTimeEvent *timeEventHead; - int stop; - void *apidata; /* This is used for polling API specific data */ - aeBeforeSleepProc *beforesleep; -} aeEventLoop; - -/* Prototypes */ -aeEventLoop *aeCreateEventLoop(int setsize); -void aeDeleteEventLoop(aeEventLoop *eventLoop); -void aeStop(aeEventLoop *eventLoop); -int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask, - aeFileProc *proc, void *clientData); -void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask); -int aeGetFileEvents(aeEventLoop *eventLoop, int fd); -PORT_LONGLONG aeCreateTimeEvent(aeEventLoop *eventLoop, PORT_LONGLONG milliseconds, - aeTimeProc *proc, void *clientData, - aeEventFinalizerProc *finalizerProc); -int aeDeleteTimeEvent(aeEventLoop *eventLoop, PORT_LONGLONG id); -int aeProcessEvents(aeEventLoop *eventLoop, int flags); -int aeWait(int fd, int mask, PORT_LONGLONG milliseconds); -void aeMain(aeEventLoop *eventLoop); -char *aeGetApiName(void); -void aeSetBeforeSleepProc(aeEventLoop *eventLoop, aeBeforeSleepProc *beforesleep); -int aeGetSetSize(aeEventLoop *eventLoop); -int aeResizeSetSize(aeEventLoop *eventLoop, int setsize); - -#endif diff --git a/ae_wsiocp.c b/ae_wsiocp.c deleted file mode 100644 index c129ca3..0000000 --- a/ae_wsiocp.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright (c), Microsoft Open Technologies, Inc. - * All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - /* IOCP-based ae.c module */ - -#include "win32_Interop/win32fixes.h" -#include "adlist.h" -#include "win32_Interop/win32_wsiocp.h" - -#define MAX_COMPLETE_PER_POLL 100 -#define MAX_SOCKET_LOOKUP 65535 - -/* Use GetQueuedCompletionStatusEx if possible. - * Try to load the function pointer dynamically. - * If it is not available, use GetQueuedCompletionStatus */ -typedef BOOL(WINAPI *sGetQueuedCompletionStatusEx) -(HANDLE CompletionPort, - LPOVERLAPPED_ENTRY lpCompletionPortEntries, - ULONG ulCount, - PULONG ulNumEntriesRemoved, - DWORD dwMilliseconds, - BOOL fAlertable); -sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx; - -/* Structure that keeps state of sockets and Completion port handle */ -typedef struct aeApiState -{ - HANDLE iocp; - int setsize; - OVERLAPPED_ENTRY entries[MAX_COMPLETE_PER_POLL]; -} aeApiState; - -/* Find matching value in list and remove. If found return TRUE */ -BOOL removeMatchFromList(list *requestlist, void *value) -{ - listNode *node; - if (requestlist == NULL) { - return FALSE; - } - node = listFirst(requestlist); - while (node != NULL) { - if (listNodeValue(node) == value) { - listDelNode(requestlist, node); - return TRUE; - } - node = listNextNode(node); - } - return FALSE; -} - -/* Called by ae to initialize state */ -static int aeApiCreate(aeEventLoop *eventLoop) -{ - HMODULE kernel32_module; - aeApiState *state = (aeApiState *)CallocMemoryNoCOW(sizeof(aeApiState)); - - if (!state) return -1; - - // Create a single IOCP to be shared by all sockets - state->iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, - NULL, - 0, - 1); - if (state->iocp == NULL) { - FreeMemoryNoCOW(state); - return -1; - } - - pGetQueuedCompletionStatusEx = NULL; - kernel32_module = GetModuleHandleA("kernel32.dll"); - if (kernel32_module != NULL) { - pGetQueuedCompletionStatusEx = (sGetQueuedCompletionStatusEx)GetProcAddress( - kernel32_module, - "GetQueuedCompletionStatusEx"); - } - - state->setsize = eventLoop->setsize; - eventLoop->apidata = state; - WSIOCP_Init(state->iocp); - return 0; -} - -static int aeApiResize(aeEventLoop *eventLoop, int setsize) -{ - ((aeApiState *)(eventLoop->apidata))->setsize = setsize; - return 0; -} - -/* Termination */ -static void aeApiFree(aeEventLoop *eventLoop) -{ - aeApiState *state = (aeApiState *)eventLoop->apidata; - CloseHandle(state->iocp); - FreeMemoryNoCOW(state); - WSIOCP_Cleanup(); -} - -/* Monitor state changes for a socket */ -static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) -{ - iocpSockState *sockstate = WSIOCP_GetSocketState(fd); - if (sockstate == NULL) { - errno = WSAEINVAL; - return -1; - } - - if (mask & AE_READABLE) { - sockstate->masks |= AE_READABLE; - if ((sockstate->masks & CONNECT_PENDING) == 0) { - if (sockstate->masks & LISTEN_SOCK) { - // Actually a listen. Do not treat as read - } else { - if ((sockstate->masks & READ_QUEUED) == 0) { - // Queue up a 0 byte read - WSIOCP_QueueNextRead(fd); - } - } - } - } - if (mask & AE_WRITABLE) { - sockstate->masks |= AE_WRITABLE; - if ((sockstate->masks & CONNECT_PENDING) == 0) { - // If no write active, then need to queue write ready - if (sockstate->wreqs == 0) { - asendreq *areq = (asendreq *)CallocMemoryNoCOW(sizeof(asendreq)); - aeApiState *state = (aeApiState *)eventLoop->apidata; - if (PostQueuedCompletionStatus(state->iocp, - 0, - fd, - &areq->ov) == 0) { - errno = GetLastError(); - FreeMemoryNoCOW(areq); - return -1; - } - sockstate->wreqs++; - listAddNodeTail(&sockstate->wreqlist, areq); - } - } - } - return 0; -} - -/* Stop monitoring state changes for a socket */ -static void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int mask) -{ - iocpSockState *sockstate = WSIOCP_GetExistingSocketState(fd); - if (sockstate == NULL) { - errno = WSAEINVAL; - return; - } - - if (mask & AE_READABLE) sockstate->masks &= ~AE_READABLE; - if (mask & AE_WRITABLE) sockstate->masks &= ~AE_WRITABLE; -} - -/* Return array of sockets that are ready for read or write - * depending on the mask for each socket */ -static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) -{ - aeApiState *state = (aeApiState *)eventLoop->apidata; - iocpSockState *sockstate; - ULONG j; - int numevents = 0; - ULONG numComplete = 0; - BOOL rc; - int mswait = (tvp == NULL) ? 100 : (tvp->tv_sec * 1000) + (tvp->tv_usec / 1000); - - if (pGetQueuedCompletionStatusEx != NULL) { - // First get an array of completion notifications - rc = pGetQueuedCompletionStatusEx(state->iocp, - state->entries, - MAX_COMPLETE_PER_POLL, - &numComplete, - mswait, - FALSE); - } else { - // Need to get one at a time. Use first array element - rc = GetQueuedCompletionStatus(state->iocp, - &state->entries[0].dwNumberOfBytesTransferred, - &state->entries[0].lpCompletionKey, - &state->entries[0].lpOverlapped, - mswait); - if (!rc && state->entries[0].lpOverlapped == NULL) { - // Timeout. Return. - return 0; - } else { - // Check if more completions are ready - BOOL lrc = TRUE; - rc = TRUE; - numComplete = 1; - - while (numComplete < MAX_COMPLETE_PER_POLL) { - lrc = GetQueuedCompletionStatus(state->iocp, - &state->entries[numComplete].dwNumberOfBytesTransferred, - &state->entries[numComplete].lpCompletionKey, - &state->entries[numComplete].lpOverlapped, - 0); - if (lrc) { - numComplete++; - } else { - if (state->entries[numComplete].lpOverlapped == NULL) break; - } - } - } - } - - if (rc && numComplete > 0) { - LPOVERLAPPED_ENTRY entry = state->entries; - for (j = 0; j < numComplete && numevents < state->setsize; j++, entry++) { - // The competion key is the rfd identifying the socket - int rfd = (int)entry->lpCompletionKey; - sockstate = WSIOCP_GetExistingSocketState(rfd); - if (sockstate == NULL) { - continue; - } - - if ((sockstate->masks & CLOSE_PENDING) == FALSE) { - if ((sockstate->masks & LISTEN_SOCK) && entry->lpOverlapped != NULL) { - // Need to set event for listening - aacceptreq *areq = (aacceptreq *)entry->lpOverlapped; - areq->next = sockstate->reqs; - sockstate->reqs = areq; - sockstate->masks &= ~ACCEPT_PENDING; - if (sockstate->masks & AE_READABLE) { - eventLoop->fired[numevents].fd = rfd; - eventLoop->fired[numevents].mask = AE_READABLE; - numevents++; - } - } else if (sockstate->masks & CONNECT_PENDING) { - // Check if connect complete - if (entry->lpOverlapped == &sockstate->ov_read) { - sockstate->masks &= ~CONNECT_PENDING; - // Enable read and write events for this connection - aeApiAddEvent(eventLoop, rfd, sockstate->masks); - } - } else { - BOOL matched = FALSE; - // Check if event is read complete (may be 0 length read) - if (entry->lpOverlapped == &sockstate->ov_read) { - matched = TRUE; - sockstate->masks &= ~READ_QUEUED; - if (sockstate->masks & AE_READABLE) { - eventLoop->fired[numevents].fd = rfd; - eventLoop->fired[numevents].mask = AE_READABLE; - numevents++; - } - } else if (sockstate->wreqs > 0 && entry->lpOverlapped != NULL) { - // Should be write complete. Get results - asendreq *areq = (asendreq *)entry->lpOverlapped; - matched = removeMatchFromList(&sockstate->wreqlist, areq); - if (matched == TRUE) { - // Call write complete callback so buffers can be freed - if (areq->proc != NULL) { - DWORD written = 0; - DWORD flags; - FDAPI_WSAGetOverlappedResult(rfd, &areq->ov, &written, FALSE, &flags); - areq->proc(areq->eventLoop, rfd, &areq->req, (int)written); - } - sockstate->wreqs--; - FreeMemoryNoCOW(areq); - // If no active write requests, set ready to write - if (sockstate->wreqs == 0 && sockstate->masks & AE_WRITABLE) { - eventLoop->fired[numevents].fd = rfd; - eventLoop->fired[numevents].mask = AE_WRITABLE; - numevents++; - } - } - } - if (matched == 0 && sockstate->unknownComplete == 0) { - sockstate->unknownComplete = 1; - close(rfd); - } - } - } else { - if (sockstate->masks & CONNECT_PENDING) { - // Check if connect complete - if (entry->lpOverlapped == &sockstate->ov_read) { - sockstate->masks &= ~CONNECT_PENDING; - } - } else if (entry->lpOverlapped == &sockstate->ov_read) { - // Read complete - sockstate->masks &= ~READ_QUEUED; - } else { - // Check pending writes - asendreq *areq = (asendreq *)entry->lpOverlapped; - if (removeMatchFromList(&sockstate->wreqlist, areq)) { - sockstate->wreqs--; - FreeMemoryNoCOW(areq); - } - } - if (sockstate->wreqs == 0 && - (sockstate->masks & (CONNECT_PENDING | READ_QUEUED | SOCKET_ATTACHED)) == 0) { - sockstate->masks &= ~(CLOSE_PENDING); - if (WSIOCP_CloseSocketState(sockstate)) { - FDAPI_ClearSocketInfo(rfd); - } - } - } - } - } - return numevents; -} - -/* Name of this event handler */ -static char *aeApiName(void) -{ - return "WinSock_IOCP"; -} diff --git a/client.cpp b/client.cpp new file mode 100644 index 0000000..1225beb --- /dev/null +++ b/client.cpp @@ -0,0 +1,197 @@ +extern "C" { +#ifdef _WIN32 +#define WIN32_INTEROP_APIS_H +#define NO_QFORKIMPL +#include + +#pragma comment(lib, "hiredis.lib") +#pragma comment(lib, "Win32_Interop.lib") +#endif +} + +#include + +#include +#include +using namespace std::chrono_literals; + +#include "client.h" + +namespace async_redis +{ +client::client(size_t _piped_cache, uint32_t pipeline_timeout) : + cache_size(_piped_cache), pipe_timeout(pipeline_timeout), ctx(nullptr) +{ + stopped = true; +} + +client::~client() +{ + Disconnect(); +} + +bool client::Connect(const std::string & host, int port, uint32_t timeout_ms) +{ + if (IsConnected()) { + Disconnect(); + } + + if (timeout_ms > 0) { + struct timeval timeout; + timeout.tv_sec = (timeout_ms / 1000); + timeout.tv_usec = ((timeout_ms - (timeout.tv_sec * 1000)) * 1000); + ctx = redisConnectWithTimeout(host.c_str(), port, timeout); + } else { + ctx = redisConnect(host.c_str(), port); + } + + if (ctx == nullptr || ctx->err) { + if (ctx) { + redisFree(ctx); + ctx = nullptr; + } + return false; + } + + stopped = false; + worker = std::thread([this] { + std::vector reqs; + while (!stopped) { + if (!ctx || ctx->err) { + stopped = true; + return; + } + + auto send = [&] { + size_t queue_size = m_commands.size_approx(); + if (!queue_size) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + return; + } + queue_size = cache_size < queue_size ? queue_size : cache_size; + + reqs.clear(); + reqs.resize(queue_size); + + size_t dequeued = 0; + if (pipe_timeout) { + dequeued = m_commands.wait_dequeue_bulk_timed(reqs.begin(), reqs.size(), std::chrono::milliseconds(pipe_timeout)); + } else { + do { + dequeued += m_commands.wait_dequeue_bulk_timed(reqs.begin(), reqs.size() - dequeued, std::chrono::milliseconds(100)); + } while (!stopped && dequeued < queue_size && !flush_pipeline); + } + + if (!dequeued) { + return; + } + + flush_pipeline = false; + + std::vector appended; + for (size_t i = 0; i < dequeued; ++i) { + auto &req = reqs[i]; + appended.emplace_back( + redisAppendFormattedCommand(ctx, req.command.c_str(), req.command.size()) == REDIS_OK + ); + } + + for (size_t i = 0; i < dequeued; ++i) { + auto &req = reqs[i]; + redisReply *rawReply = nullptr; + + bool success = appended[i]; + if (success) { + success &= redisGetReply(ctx, (void **)&rawReply) == REDIS_OK; + } + + if (req.callback) { + if (success) { + req.callback(new reply(rawReply)); + } else { + req.callback(nullptr); + } + } + + if (rawReply) { + freeReplyObject(rawReply); + } + } + }; + + if (cache_size == 0) { + if (!pipeline_sem.wait(100 * 1000)) { + continue; + } + } + + { + send(); + } + } + }); + + return true; +} + +bool client::IsConnected() const +{ + return ctx && ctx->err == 0 && !stopped; +} + +void client::Disconnect() +{ + stopped = true; + + if (worker.joinable()) { + worker.join(); + } + + if (ctx) { + redisFree(ctx); + ctx = nullptr; + } +} + +client & client::Append(const std::vector &redis_cmd, const reply_callback & callback) +{ + m_commands.enqueue({ formatCommand(redis_cmd), callback }); + return *this; +} + +client & client::Commit() +{ + flush_pipeline = true; + if (IsConnected() && cache_size == 0) { + pipeline_sem.signal(); + } + return *this; +} + +int client::GetError() const +{ + if (ctx) { + return ctx->err; + } + + return -1; +} + +const char *client::GetErrorString() const +{ + if (ctx) { + return ctx->errstr; + } + return nullptr; +} + +inline std::string client::formatCommand(const std::vector& redis_cmd) +{ + std::stringstream ss; + ss << "*" << redis_cmd.size() << "\r\n"; + for (const auto &cmd_part : redis_cmd) { + ss << "$" << cmd_part.length() << "\r\n" << cmd_part << "\r\n"; + } + return ss.str(); +} +} diff --git a/client.h b/client.h new file mode 100644 index 0000000..7480ce8 --- /dev/null +++ b/client.h @@ -0,0 +1,86 @@ +#pragma once + +#include "concurrentqueue.h" +#include "blockingconcurrentqueue.h" + +#include +#include +#include +#include +#include + +#include "reply.h" + +struct redisContext; + +namespace async_redis +{ +class client +{ +public: + /** + * Create a new redis client + * + * @param piped_cache The number of command put to pipeline before commit + * 0: manully commit, 1: disable pipeline (commit when available) + * + * @param pipeline_timeout The maximum time to spend waiting for pipeline to be filled in ms + * 0: wait for piped_cache number of command to be filled. + * DONT recommend set time to 0, since the worker will wait forever + * until receive enough command (if you use future you will get a deadlock) + * + */ + client(size_t piped_cache = 0, uint32_t pipeline_timeout = 0); + ~client(); + + bool Connect(const std::string &host, int port, uint32_t timeout_ms); + + bool IsConnected() const; + + void Disconnect(); + + // bool: if successfully sent and receive, reply: actual reply content + typedef std::function reply_callback; + + client &Append(const std::vector &redis_cmd, const reply_callback &callback = nullptr); + + std::future> Command(const std::vector &redis_cmd, bool commit = true) + { + auto prms = std::make_shared>>(); + Append(redis_cmd, [prms](auto r) { prms->set_value(std::unique_ptr(r)); }); + if (commit) { + Commit(); + } + return prms->get_future(); + } + + // This function will do nothing when auto pipeline enabled + // If pipeline was enable, it will force worker to commit existing command + client &Commit(); + + int GetError() const; + const char *GetErrorString() const; + +private: + struct command_request + { + std::string command; + reply_callback callback; + }; + + static std::string formatCommand(const std::vector &redis_cmd); + + moodycamel::BlockingConcurrentQueue m_commands; + + moodycamel::details::mpmc_sema::LightweightSemaphore pipeline_sem; + + size_t cache_size; + uint32_t pipe_timeout; + + std::atomic flush_pipeline; + std::atomic stopped; + std::thread worker; + + redisContext *ctx; +}; +} diff --git a/extension.cpp b/extension.cpp index b21ea54..46e2b5c 100644 --- a/extension.cpp +++ b/extension.cpp @@ -98,52 +98,57 @@ bool ClientPrefs::SDK_OnLoad(char *error, size_t maxlength, bool late) const char *num_worker = smutils->GetCoreConfigValue("RedisQueryThread"); if (num_worker == NULL) { - worker = 4; + worker = 1; } else { worker = atoi(num_worker); } - bool noasync = false; - const char *_noasync = smutils->GetCoreConfigValue("RedisDBNoASync"); - if (_noasync) { - noasync = atoi(_noasync) != 0; - } - smutils->LogMessage(myself, "Connecting to %s:%d %s password using %d query thread(s).", host.c_str(), port, pass.empty() ? "without" : "with", worker); for (int i = 0; i < worker; ++i) { - std::thread([this, i, noasync] { - RedisDB *db = nullptr; + std::thread([this, i] { + async_redis::client *db = nullptr; auto connectDb = [&]() { - while (db == nullptr) { - Sleep(3000); + while (!db || !db->IsConnected()) { + db = new async_redis::client(); - std::unique_lock _(connectLock); - db = RedisDB::GetRedisDB(host, port, maxTimeout, pass); - if (noasync || !db) { - continue; + Sleep(3000); + if (db->Connect(host, port, maxTimeout)) { + break; } - if (int err = db->ConnectAsync(host, port, pass)) { - fprintf(stderr, "[%d] Cannot use async connection: %d (error: %s).\n", - i, err, db->GetASyncErrorStr()); - } else { - // Async connection is available - fprintf(stderr, "[%d] Connected to %s:%d with non-blocking context.\n", - i, host.c_str(), port); - } + delete db; + db = nullptr; } - }; - { - connectDb(); - auto reply = db->Run("SCRIPT LOAD %s", GET_CLIENT_COOKIES); - if (reply.str != GET_CLIENT_COOKIES_SHA) { - fprintf(stderr, "Lua script sha dose not match: except:%s actual:%s", - GET_CLIENT_COOKIES_SHA, reply.str.c_str()); + auto reply = db->Command({ "AUTH", "foobared233" }).get(); + if (!reply || !reply->IsStatus()) { + fprintf(stderr, "REDIS ERROR: %s\n", reply->Status()); + return; } - } + + db->Append({ "SELECT", std::to_string(dbid) }); + + reply = db->Command({ "SCRIPT", "LOAD", GET_CLIENT_COOKIES }).get(); + if (!reply) { + fprintf(stderr, "Invalid reply when loading lua script\n"); + return; + } + + if (!reply->IsString()) { + fprintf(stderr, "Load lua script error: %s\n", reply->Status()); + return; + } + + if (reply->GetString() != GET_CLIENT_COOKIES_SHA) { + fprintf(stderr, "Lua script sha dose not match: except:%s actual:%s\n", + GET_CLIENT_COOKIES_SHA, reply->GetString().c_str()); + return; + } + }; + + connectDb(); while (true) { auto op = tqq->GetQuery(); @@ -152,13 +157,14 @@ bool ClientPrefs::SDK_OnLoad(char *error, size_t maxlength, bool late) break; } - if (db == nullptr || !db->Alive()) { + if (db == nullptr || !db->IsConnected()) { delete db; db = nullptr; connectDb(); } - db->SELECT_DBID(dbid); + db->Commit(); + op->SetDatabase(db); op->RunThreadPart(); tqq->PutResult(op); diff --git a/extension.h b/extension.h index b0b9a90..6a7eb25 100644 --- a/extension.h +++ b/extension.h @@ -38,13 +38,14 @@ extern "C" { #define NO_QFORKIMPL #include -#pragma comment(lib,"hiredis.lib") -#pragma comment(lib,"Win32_Interop.lib") +#pragma comment(lib, "hiredis.lib") +#pragma comment(lib, "Win32_Interop.lib") #endif } #include "TQueue.h" -#include "RedisDB.h" +#include "client.h" +#include "reply.h" #include #include diff --git a/include/Win32_Interop/EventLog.h b/include/Win32_Interop/EventLog.h deleted file mode 100644 index 1d0f03c..0000000 --- a/include/Win32_Interop/EventLog.h +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once -// -// Values are 32 bit values laid out as follows: -// -// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 -// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 -// +---+-+-+-----------------------+-------------------------------+ -// |Sev|C|R| Facility | Code | -// +---+-+-+-----------------------+-------------------------------+ -// -// where -// -// Sev - is the severity code -// -// 00 - Success -// 01 - Informational -// 10 - Warning -// 11 - Error -// -// C - is the Customer code flag -// -// R - is a reserved bit -// -// Facility - is the facility code -// -// Code - is the facility's status code -// -// -// Define the facility codes -// - - -// -// Define the severity codes -// - - -// -// MessageId: MSG_INFO_1 -// -// MessageText: -// -// %1 -// -#define MSG_INFO_1 0x60000000L - -// -// MessageId: MSG_WARNING_1 -// -// MessageText: -// -// %1 -// -#define MSG_WARNING_1 0xA0000001L - -// -// MessageId: MSG_ERROR_1 -// -// MessageText: -// -// %1 -// -#define MSG_ERROR_1 0xE0000002L - -// -// MessageId: MSG_SUCCESS_1 -// -// MessageText: -// -// %1 -// -#define MSG_SUCCESS_1 0x20000003L - diff --git a/include/Win32_Interop/Win32_ANSI.h b/include/Win32_Interop/Win32_ANSI.h deleted file mode 100644 index 853fd3d..0000000 --- a/include/Win32_Interop/Win32_ANSI.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -* Copyright (c), Microsoft Open Technologies, Inc. -* All rights reserved. -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* - Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#ifndef WIN32_INTEROPA_ANSI_H -#define WIN32_INTEROPA_ANSI_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - - BOOL ParseAndPrintANSIString(HANDLE hDev, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten); - void ANSI_printf(char *format, ...); - - // include this file after stdio.h in order to redirect printf to the one that supports ANSI escape sequences -#define printf ANSI_printf - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/Win32_Interop/Win32_Assert.h b/include/Win32_Interop/Win32_Assert.h deleted file mode 100644 index 9109566..0000000 --- a/include/Win32_Interop/Win32_Assert.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c), Microsoft Open Technologies, Inc. - * All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef WIN32_INTEROP_ASSERT_H -#define WIN32_INTEROP_ASSERT_H - -#ifdef _DEBUG -#define ASSERT(condition) do { if(!(condition)){ fprintf(stderr, "Assertion failed: %s @ %s::%s (%d)\n", #condition , __FILE__, __FUNCTION__, __LINE__); DebugBreak();} } while(0) -#else -#define ASSERT(condition) -#endif - -#endif \ No newline at end of file diff --git a/include/Win32_Interop/Win32_CommandLine.h b/include/Win32_Interop/Win32_CommandLine.h deleted file mode 100644 index c7aed6e..0000000 --- a/include/Win32_Interop/Win32_CommandLine.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -* Copyright (c), Microsoft Open Technologies, Inc. -* All rights reserved. -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* - Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef WIN32_INTEROPA_COMMANDLINE_H -#define WIN32_INTEROPA_COMMANDLINE_H - -#include -#include -#include - -using namespace std; - -// A map of arguments encountered to the set of parameters for those arguments, in the order in which they -// were encountered. If 'maxmemory' is encountered 3 times, ArgumentMap["maxmemory"] will return a vector -// of an array of values, with the first being the value od the first 'maxmemory' instance enountered. -// Order of encounter is command line, conf file, nested conf file #1 (via include statement), ... -typedef map>> ArgumentMap; -extern ArgumentMap g_argMap; - -void ParseConfFile(string confFile, string cwd, ArgumentMap& argMap); -void ParseCommandLineArguments(int argc, char** argv); -vector GetAccessPaths(); - -const string cQFork = "qfork"; -const string cServiceRun = "service-run"; -const string cServiceInstall = "service-install"; -const string cServiceUninstall = "service-uninstall"; -const string cServiceStart = "service-start"; -const string cServiceStop = "service-stop"; -const string cServiceName = "service-name"; -const string cSyslogEnabled = "syslog-enabled"; -const string cSyslogIdent= "syslog-ident"; -const string cLogfile = "logfile"; -const string cInclude = "include"; -const string cDir = "dir"; -const string cPersistenceAvailable = "persistence-available"; -const string cMaxMemory = "maxmemory"; -const string cSentinel = "sentinel"; - -const string cYes = "yes"; -const string cNo = "no"; -const string cDefaultSyslogIdent = "redis"; -const string cDefaultLogfile = "stdout"; - -/* List of -- command arguments to be passed to redis::main() unaltered */ -const vector cRedisArgsForMainC = {"help", "version", "test-memory"}; - -#endif diff --git a/include/Win32_Interop/Win32_Common.h b/include/Win32_Interop/Win32_Common.h deleted file mode 100644 index 5451fdb..0000000 --- a/include/Win32_Interop/Win32_Common.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -* Copyright (c), Microsoft Open Technologies, Inc. -* All rights reserved. -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* - Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef WIN32_INTEROP_COMMON_H -#define WIN32_INTEROP_COMMON_H - -#include - -namespace Globals { - // forward declarations only - extern size_t pageSize; -} - -void EnsureMemoryIsMapped(const void *buffer, size_t size); -bool IsWindowsVersionAtLeast(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor); - -class WindowsVersion { -private: - bool isAtLeast_6_0; - bool isAtLeast_6_2; - - WindowsVersion() { - isAtLeast_6_0 = IsWindowsVersionAtLeast(6, 0, 0); - isAtLeast_6_2 = IsWindowsVersionAtLeast(6, 2, 0); - } - - WindowsVersion(WindowsVersion const&); // Don't implement to guarantee singleton semantics - void operator=(WindowsVersion const&); // Don't implement to guarantee singleton semantics - -public: - static WindowsVersion& getInstance() { - static WindowsVersion instance; // Instantiated on first use. Guaranteed to be destroyed. - return instance; - } - - bool IsAtLeast_6_0() { - return isAtLeast_6_0; - } - - bool IsAtLeast_6_2() { - return isAtLeast_6_2; - } -}; -#endif \ No newline at end of file diff --git a/include/Win32_Interop/Win32_Error.h b/include/Win32_Interop/Win32_Error.h deleted file mode 100644 index f7130fd..0000000 --- a/include/Win32_Interop/Win32_Error.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c), Microsoft Open Technologies, Inc. - * All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WIN32_INTEROP_ERROR_H -#define WIN32_INTEROP_ERROR_H - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Converts error codes returned by GetLastError/WSAGetLastError to errno codes */ -int translate_sys_error(int sys_error); -void set_errno_from_last_error(); - -int strerror_r(int err, char* buf, size_t buflen); -char *wsa_strerror(int err); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/include/Win32_Interop/Win32_EventLog.h b/include/Win32_Interop/Win32_EventLog.h deleted file mode 100644 index 6cdf38e..0000000 --- a/include/Win32_Interop/Win32_EventLog.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -* Copyright (c), Microsoft Open Technologies, Inc. -* All rights reserved. -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* - Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#pragma once - -#ifdef __cplusplus -#include -using namespace std; - -typedef class RedisEventLog { -public: - ~RedisEventLog() {} - - void InstallEventLogSource(string appPath); - void UninstallEventLogSource(); - - void SetEventLogIdentity(const char* identity); - - void LogMessage(LPCSTR msg, const WORD type); - void LogError(string msg); - - string GetEventLogIdentity(); - void EnableEventLog(bool enabled); - bool IsEventLogEnabled(); - -private: - const string eventLogName = "redis"; - const string cEventLogPath = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\"; - const string cEventLogApplicitonPath = cEventLogPath + "Application\\"; - const string cRedis = "redis"; - const string cEventMessageFile = "EventMessageFile"; - const string cRedisServer = "redis-server"; - const string cTypesSupported = "TypesSupported"; - const string cApplication = "Application"; -} RedisEventLog; - -extern "C" { -#endif - - void setSyslogEnabled(int enabled); - void setSyslogIdent(char* identity); - int IsEventLogEnabled(); - void WriteEventLog(const char* msg); - -#ifdef __cplusplus -} -#endif - diff --git a/include/Win32_Interop/Win32_FDAPI.h b/include/Win32_Interop/Win32_FDAPI.h index 8fae9c7..ce2442b 100644 --- a/include/Win32_Interop/Win32_FDAPI.h +++ b/include/Win32_Interop/Win32_FDAPI.h @@ -119,8 +119,8 @@ typedef int (*fdapi_fcntl)(int fd, int cmd, int flags); typedef int (*fdapi_poll)(struct pollfd *fds, nfds_t nfds, int timeout); typedef int (*fdapi_getsockopt)(int sockfd, int level, int optname, void *optval, socklen_t *optlen); typedef int (*fdapi_connect)(int sockfd, const struct sockaddr *addr, size_t addrlen); -typedef ssize_t (*fdapi_read)(int fd, void *buf, size_t count); -typedef ssize_t (*fdapi_write)(int fd, const void *buf, size_t count); +typedef _ssize_t (*fdapi_read)(int fd, void *buf, size_t count); +typedef _ssize_t (*fdapi_write)(int fd, const void *buf, size_t count); typedef int (*fdapi_fsync)(int fd); typedef int (*fdapi_listen)(int sockfd, int backlog); typedef int (*fdapi_ftruncate)(int fd, PORT_LONGLONG length); diff --git a/include/Win32_Interop/Win32_PThread.h b/include/Win32_Interop/Win32_PThread.h deleted file mode 100644 index e7c3669..0000000 --- a/include/Win32_Interop/Win32_PThread.h +++ /dev/null @@ -1,53 +0,0 @@ - - -#include -#include - -#ifndef _SIGSET_T_ -#define _SIGSET_T_ -typedef size_t _sigset_t; -#define sigset_t _sigset_t -#endif /* _SIGSET_T_ */ - -#ifndef SIG_SETMASK -#define SIG_SETMASK (0) -#define SIG_BLOCK (1) -#define SIG_UNBLOCK (2) -#endif /* SIG_SETMASK */ - -/* threads avoiding pthread.h */ -#define pthread_mutex_t CRITICAL_SECTION -#define pthread_attr_t ssize_t - -#define pthread_mutex_init(a,b) (InitializeCriticalSectionAndSpinCount((a), 0x80000400),0) -#define pthread_mutex_destroy(a) DeleteCriticalSection((a)) -#define pthread_mutex_lock EnterCriticalSection -#define pthread_mutex_unlock LeaveCriticalSection - -#define pthread_equal(t1, t2) ((t1) == (t2)) - -#define pthread_attr_init(x) (*(x) = 0) -#define pthread_attr_getstacksize(x, y) (*(y) = *(x)) -#define pthread_attr_setstacksize(x, y) (*(x) = y) - -#define pthread_t unsigned int - -int pthread_create(pthread_t *thread, const void *unused, void *(*start_routine)(void*), void *arg); - -pthread_t pthread_self(void); - -typedef struct { - CRITICAL_SECTION waiters_lock; - LONG waiters; - int was_broadcast; - HANDLE sema; - HANDLE continue_broadcast; -} pthread_cond_t; - -int pthread_cond_init(pthread_cond_t *cond, const void *unused); -int pthread_cond_destroy(pthread_cond_t *cond); -int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); -int pthread_cond_signal(pthread_cond_t *cond); - -int pthread_detach(pthread_t thread); -int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset); diff --git a/include/Win32_Interop/Win32_Portability.h b/include/Win32_Interop/Win32_Portability.h deleted file mode 100644 index 7fcb1a6..0000000 --- a/include/Win32_Interop/Win32_Portability.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -* Copyright (c), Microsoft Open Technologies, Inc. -* All rights reserved. -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* - Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef WIN32_INTEROPA_PORTABILITY_H -#define WIN32_INTEROPA_PORTABILITY_H - - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Sometimes in the Windows port we make changes from: - antirez_redis_statement(); - to: - #ifdef _WIN32 - windows_redis_statement(); - #else - antirez_redis_statement(); - #endif - - If subsequently antirez changed that code, we might not detect the change during the next merge. - The INDUCE_MERGE_CONFLICT macro expands to nothing, but it is used to make sure that the original line - is modified with respect to the antirez version, so that any subsequent modifications will trigger a conflict - during the next merge. - - Sample usage: - #ifdef _WIN32 - windows_redis_statement(); - #else - antirez_redis_statement(); INDUCE_MERGE_CONFLICT - #endif - - Don't use any parenthesis or semi-colon after INDUCE_MERGE_CONFLICT. - Use it at the end of a line to preserve the original indentation. -*/ -#define INDUCE_MERGE_CONFLICT - -/* Use WIN_PORT_FIX at the end of a line to mark places where we make changes to the code - without using #ifdefs. Useful to keep the code more legible. Mainly intended for replacing - the use of long (which is 64-bit on 64-bit Unix and 32-bit on 64-bit Windows) to portable types. - In order to be eligible for an inline fix (without #ifdef), the change should be portable back to the Posix version. -*/ -#define WIN_PORT_FIX - -#ifdef _WIN32 -#define IF_WIN32(x, y) x -#define WIN32_ONLY(x) x -#define POSIX_ONLY(x) -#define inline __inline -#else -#define IF_WIN32(x, y) y -#define WIN32_ONLY(x) -#define POSIX_ONLY(x) x -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/Win32_Interop/Win32_QFork.h b/include/Win32_Interop/Win32_QFork.h deleted file mode 100644 index 4b13767..0000000 --- a/include/Win32_Interop/Win32_QFork.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c), Microsoft Open Technologies, Inc. - * All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -BOOL g_IsForkedProcess; - -typedef enum operationType { - otINVALID = 0, - otRDB = 1, - otAOF = 2, - otSocket = 3 -} OperationType; - -typedef enum operationStatus { - osUNSTARTED = 0, - osINPROGRESS = 1, - osCOMPLETE = 2, - osFAILED = 3 -} OperationStatus; - -typedef enum startupStatus { - ssFAILED = 0, // Something went wrong, exit program with error. - ssCONTINUE_AS_PARENT = 1, // Parent qfork initialization complete, continue as parent instance. Call QForkShutdown when exiting. - ssCHILD_EXIT = 2 // Child completed operation. Call QForkShutdown and exit. -} StartupStatus; - -// For parent process use only -pid_t BeginForkOperation_Rdb( - char* fileName, - LPVOID redisData, - int sizeOfRedisData, - uint32_t dictHashSeed); - -pid_t BeginForkOperation_Aof( - int aof_pipe_write_ack_to_parent, - int aof_pipe_read_ack_from_parent, - int aof_pipe_read_data_from_parent, - char* fileName, - LPVOID redisData, - int sizeOfRedisData, - uint32_t dictHashSeed); - -pid_t BeginForkOperation_Socket( - int *fds, - int numfds, - uint64_t *clientids, - int pipe_write_fd, - LPVOID redisData, - int sizeOfRedisData, - uint32_t dictHashSeed); - -void BeginForkOperation_Socket_Duplicate(DWORD dwProcessId); - -OperationStatus GetForkOperationStatus(); -BOOL EndForkOperation(int * pExitCode); -BOOL AbortForkOperation(); - -#ifdef USE_DLMALLOC - LPVOID AllocHeapBlock(size_t size, BOOL allocateHigh); - // for no persistence optimization/feature when using dlmalloc - extern void*(*g_malloc)(size_t); - extern void*(*g_calloc)(size_t, size_t); - extern void*(*g_realloc)(void*, size_t); - extern void(*g_free)(void*); - extern size_t(*g_msize)(void*); -#elif USE_JEMALLOC - LPVOID AllocHeapBlock(LPVOID addr, size_t size, BOOL zero); - BOOL PurgePages(LPVOID addr, size_t length); -#endif -BOOL FreeHeapBlock(LPVOID addr, size_t size); - -#ifndef NO_QFORKIMPL -#ifdef QFORK_MAIN_IMPL -int redis_main(int argc, char** argv); -#else -#define main redis_main -#endif -#endif - -#ifdef __cplusplus -} -#endif diff --git a/include/Win32_Interop/Win32_QFork_impl.h b/include/Win32_Interop/Win32_QFork_impl.h deleted file mode 100644 index 167a8e7..0000000 --- a/include/Win32_Interop/Win32_QFork_impl.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c), Microsoft Open Technologies, Inc. - * All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - - void SetupRedisGlobals(LPVOID redisData, size_t redisDataSize, uint32_t dictHashKey); - int do_rdbSave(char* filename); - int do_aofSave(char* filename, int aof_pipe_read_ack, int aof_pipe_read_data, int aof_pipe_write_ack); - int do_socketSave(int *fds, int numfds, uint64_t *clientids, int pipe_write_fd); - -#ifdef __cplusplus -} -#endif diff --git a/include/Win32_Interop/Win32_RedisLog.h b/include/Win32_Interop/Win32_RedisLog.h deleted file mode 100644 index cdc75f1..0000000 --- a/include/Win32_Interop/Win32_RedisLog.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -* Copyright (c), Microsoft Open Technologies, Inc. -* All rights reserved. -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* - Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#pragma once - -/* Log levels */ -#define LL_DEBUG 0 -#define LL_VERBOSE 1 -#define LL_NOTICE 2 -#define LL_WARNING 3 -#define LL_RAW (1<<10) /* Modifier to log without timestamp */ -#define CONFIG_DEFAULT_VERBOSITY LL_NOTICE -/* - * Default maximum length of syslog messages. - * Empirical results show that 1024 is also the maximum size that WriteFile can - * write atomically. - */ -#define LOG_MAX_LEN 1024 - -#ifdef __cplusplus -extern "C" { -#endif - -void setLogVerbosityLevel(int level); -void setLogFile(const char* filename); -const char* getLogFilename(); -void serverLogRaw(int level, const char *msg); -void serverLog(int level, const char *fmt, ...); -void serverLogFromHandler(int level, const char *msg); - -#ifdef __cplusplus -} -#endif - diff --git a/include/Win32_Interop/Win32_Service.h b/include/Win32_Interop/Win32_Service.h deleted file mode 100644 index 8f99f4d..0000000 --- a/include/Win32_Interop/Win32_Service.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -* Copyright (c), Microsoft Open Technologies, Inc. -* All rights reserved. -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* - Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#pragma once - -#ifdef __cplusplus -extern "C" -{ -#endif - - BOOL RunningAsService(); - const char* GetServiceName(); - BOOL HandleServiceCommands(int argc, char **argv); - BOOL ServiceStopIssued(); - -#ifdef __cplusplus -} -#endif diff --git a/include/Win32_Interop/Win32_Signal_Process.h b/include/Win32_Interop/Win32_Signal_Process.h deleted file mode 100644 index 72d5bb9..0000000 --- a/include/Win32_Interop/Win32_Signal_Process.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c), Microsoft Open Technologies, Inc. - * All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WIN32_INTEROP_SIGNALPROCESS_H -#define WIN32_INTEROP_SIGNALPROCESS_H - -#include "win32_types.h" -#include -#include -#include -#include - -/* rusage */ -#define RUSAGE_SELF 0 -#define RUSAGE_CHILDREN (-1) - -#ifndef _RUSAGE_T_ -#define _RUSAGE_T_ -struct rusage { - struct timeval ru_utime; /* user time used */ - struct timeval ru_stime; /* system time used */ -}; -#endif - -int getrusage(int who, struct rusage * rusage); - -/* Signals */ -#define SIGNULL 0 /* Null Check access to pid*/ -#define SIGHUP 1 /* Hangup Terminate; can be trapped*/ -#define SIGINT 2 /* Interrupt Terminate; can be trapped */ -#define SIGQUIT 3 /* Quit Terminate with core dump; can be trapped */ -#define SIGTRAP 5 -#define SIGBUS 7 -#define SIGKILL 9 /* Kill Forced termination; cannot be trapped */ -#define SIGPIPE 13 -#define SIGALRM 14 -#define SIGTERM 15 /* Terminate Terminate; can be trapped */ -#define SIGSTOP 17 -#define SIGTSTP 18 -#define SIGCONT 19 -#define SIGCHLD 20 -#define SIGTTIN 21 -#define SIGTTOU 22 -#define SIGABRT 22 -/* #define SIGSTOP 24 /*Pause the process; cannot be trapped*/ -/* #define SIGTSTP 25 /*Terminal stop Pause the process; can be trapped*/ -/* #define SIGCONT 26 /* */ -#define SIGWINCH 28 -#define SIGUSR1 30 -#define SIGUSR2 31 - -#define SA_NOCLDSTOP 0x00000001u -#define SA_NOCLDWAIT 0x00000002u -#define SA_SIGINFO 0x00000004u -#define SA_ONSTACK 0x08000000u -#define SA_RESTART 0x10000000u -#define SA_NODEFER 0x40000000u -#define SA_RESETHAND 0x80000000u -#define SA_NOMASK SA_NODEFER -#define SA_ONESHOT SA_RESETHAND -#define SA_RESTORER 0x04000000 - -#define sigemptyset(pset) (*(pset) = 0) -#define sigfillset(pset) (*(pset) = (unsigned int)-1) -#define sigaddset(pset, num) (*(pset) |= (1L<<(num))) -#define sigdelset(pset, num) (*(pset) &= ~(1L<<(num))) -#define sigismember(pset, num) (*(pset) & (1L<<(num))) - -typedef void(*__p_sig_fn_t)(int); - -#ifndef _SIGSET_T_ -#define _SIGSET_T_ -typedef size_t _sigset_t; -#define sigset_t _sigset_t -#endif /* _SIGSET_T_ */ - -struct sigaction { - int sa_flags; - sigset_t sa_mask; - __p_sig_fn_t sa_handler; - __p_sig_fn_t sa_sigaction; -}; - -int sigaction(int sig, struct sigaction *in, struct sigaction *out); - -#endif \ No newline at end of file diff --git a/include/Win32_Interop/Win32_SmartHandle.h b/include/Win32_Interop/Win32_SmartHandle.h deleted file mode 100644 index 19b2aa0..0000000 --- a/include/Win32_Interop/Win32_SmartHandle.h +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Copyright (c), Microsoft Open Technologies, Inc. - * All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include -#include -#include -#include -#include -using namespace std; - -typedef class SmartHandle -{ -private: - HANDLE m_handle; - -public: - HANDLE Assign(HANDLE h) - { - Close(); - m_handle = h; - if (Invalid()) - throw std::runtime_error("invalid handle passed to constructor"); - return h; - } - - SmartHandle() - { - m_handle = NULL; - } - - SmartHandle(HANDLE handle) - { - m_handle = handle; - if (Invalid()) - throw std::runtime_error("invalid handle passed to constructor"); - } - - HANDLE Assign(HANDLE h, string errorToReport) - { - Close(); - m_handle = h; - if (Invalid()) - throw std::runtime_error(errorToReport); - return h; - } - - SmartHandle(HANDLE handle, string errorToReport) - { - Close(); - m_handle = handle; - if (Invalid()) - throw std::runtime_error(errorToReport); - } - - HANDLE Assign(HANDLE parentProcess, HANDLE parentHandleToDuplicate) - { - Close(); - if (!DuplicateHandle(parentProcess, parentHandleToDuplicate, GetCurrentProcess(), &m_handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) - throw std::system_error(GetLastError(), system_category(), "handle duplication failed"); - return m_handle; - } - - SmartHandle(HANDLE parentProcess, HANDLE parentHandleToDuplicate) - { - if (!DuplicateHandle(parentProcess, parentHandleToDuplicate, GetCurrentProcess(), &m_handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) - throw std::system_error(GetLastError(), system_category(), "handle duplication failed"); - } - - operator PHANDLE() { - return &m_handle; - } - - operator HANDLE() - { - return m_handle; - } - - BOOL Valid() - { - return (m_handle != INVALID_HANDLE_VALUE) && (m_handle != NULL); - } - - BOOL Invalid() - { - return (m_handle == INVALID_HANDLE_VALUE) || (m_handle == NULL); - } - - void Close() - { - if (Valid()) - { - CloseHandle(m_handle); - m_handle = INVALID_HANDLE_VALUE; - } - } - - ~SmartHandle() - { - Close(); - } -} SmartHandle; - -template -class SmartFileView -{ -private: - T* m_viewPtr; - -public: - T* operator->() - { - return m_viewPtr; - } - - operator T* () - { - return m_viewPtr; - } - - SmartFileView() - { - m_viewPtr = NULL; - } - - T* Assign(HANDLE fileMapHandle, DWORD desiredAccess, string errorToReport) - { - UnmapViewOfFile(); - m_viewPtr = (T*) MapViewOfFile(fileMapHandle, desiredAccess, 0, 0, sizeof(T)); - if (Invalid()) { - if (IsDebuggerPresent()) DebugBreak(); - throw std::system_error(GetLastError(), system_category(), errorToReport.c_str()); - } - return m_viewPtr; - } - - SmartFileView(HANDLE fileMapHandle, DWORD desiredAccess, string errorToReport) - { - m_viewPtr = (T*) MapViewOfFile(fileMapHandle, desiredAccess, 0, 0, sizeof(T)); - if (Invalid()) { - throw std::system_error(GetLastError(), system_category(), errorToReport.c_str()); - } - } - - T* Assign(HANDLE fileMapHandle, DWORD desiredAccess, DWORD fileOffsetHigh, DWORD fileOffsetLow, SIZE_T bytesToMap, string errorToReport) - { - UnmapViewOfFile(); - m_viewPtr = (T*) MapViewOfFile(fileMapHandle, desiredAccess, fileOffsetHigh, fileOffsetLow, bytesToMap); - if (Invalid()) { - if (IsDebuggerPresent()) DebugBreak(); - throw std::system_error(GetLastError(), system_category(), errorToReport.c_str()); - } - return m_viewPtr; - } - - SmartFileView(HANDLE fileMapHandle, DWORD desiredAccess, DWORD fileOffsetHigh, DWORD fileOffsetLow, SIZE_T bytesToMap, string errorToReport) - { - m_viewPtr = (T*) MapViewOfFile(fileMapHandle, desiredAccess, fileOffsetHigh, fileOffsetLow, bytesToMap); - if (Invalid()) { - throw std::system_error(GetLastError(), system_category(), errorToReport.c_str()); - } - } - - T* Assign(HANDLE fileMapHandle, DWORD desiredAccess, DWORD fileOffsetHigh, DWORD fileOffsetLow, SIZE_T bytesToMap, LPVOID baseAddress, string errorToReport) - { - UnmapViewOfFile(); - m_viewPtr = (T*) MapViewOfFileEx(fileMapHandle, desiredAccess, fileOffsetHigh, fileOffsetLow, bytesToMap, baseAddress); - if (Invalid()) { - if (IsDebuggerPresent()) DebugBreak(); - throw std::system_error(GetLastError(), system_category(), errorToReport.c_str()); - } - return m_viewPtr; - } - - SmartFileView(HANDLE fileMapHandle, DWORD desiredAccess, DWORD fileOffsetHigh, DWORD fileOffsetLow, SIZE_T bytesToMap, LPVOID baseAddress, string errorToReport) - { - m_viewPtr = (T*) MapViewOfFileEx(fileMapHandle, desiredAccess, fileOffsetHigh, fileOffsetLow, bytesToMap, baseAddress); - if (Invalid()) { - throw std::system_error(GetLastError(), system_category(), errorToReport.c_str()); - } - } - - void Remap(HANDLE fileMapHandle, DWORD desiredAccess, DWORD fileOffsetHigh, DWORD fileOffsetLow, SIZE_T bytesToMap, LPVOID baseAddress, string errorToReport) - { - if (Valid()) - throw new invalid_argument("m_viewPtr still valid"); - m_viewPtr = (T*) MapViewOfFileEx(fileMapHandle, desiredAccess, fileOffsetHigh, fileOffsetLow, bytesToMap, baseAddress); - if (Invalid()) { - throw std::system_error(GetLastError(), system_category(), errorToReport.c_str()); - } - } - - BOOL Valid() - { - return (m_viewPtr != NULL); - } - - BOOL Invalid() - { - return (m_viewPtr == NULL); - } - - void UnmapViewOfFile() - { - if (m_viewPtr != NULL) - { - if (!::UnmapViewOfFile(m_viewPtr)) - throw system_error(GetLastError(), system_category(), "UnmapViewOfFile failed"); - - m_viewPtr = NULL; - } - } - - ~SmartFileView() - { - UnmapViewOfFile(); - } -}; - -typedef class SmartFileMapHandle -{ -private: - HANDLE m_handle; - DWORD systemAllocationGranularity; - -public: - operator HANDLE() - { - return m_handle; - } - - SmartFileMapHandle() - { - m_handle = INVALID_HANDLE_VALUE; - } - - HANDLE Assign(HANDLE mmFile, DWORD protectionFlags, DWORD maxSizeHigh, DWORD maxSizeLow, string errorToReport) - { - Unmap(); - m_handle = CreateFileMapping(mmFile, NULL, protectionFlags, maxSizeHigh, maxSizeLow, NULL); - if (Invalid()) { - if (IsDebuggerPresent()) DebugBreak(); - throw std::system_error(GetLastError(), system_category(), errorToReport); - } - - SYSTEM_INFO si; - GetSystemInfo(&si); - systemAllocationGranularity = si.dwAllocationGranularity; - return m_handle; - } - - SmartFileMapHandle(HANDLE mmFile, DWORD protectionFlags, DWORD maxSizeHigh, DWORD maxSizeLow, string errorToReport) - { - m_handle = CreateFileMapping(mmFile, NULL, protectionFlags, maxSizeHigh, maxSizeLow, NULL); - if (Invalid()) { - throw std::system_error(GetLastError(), system_category(), errorToReport); - } - - SYSTEM_INFO si; - GetSystemInfo(&si); - systemAllocationGranularity = si.dwAllocationGranularity; - } - - void Unmap() - { - if (Valid()) { - CloseHandle(m_handle); - } - m_handle = NULL; - } - - void Remap(HANDLE mmFile, DWORD protectionFlags, DWORD maxSizeHigh, DWORD maxSizeLow, string errorToReport) - { - m_handle = CreateFileMapping(mmFile, NULL, protectionFlags, maxSizeHigh, maxSizeLow, NULL); - if (Invalid()) { - throw std::system_error(GetLastError(), system_category(), errorToReport); - } - } - - BOOL Valid() - { - return (m_handle != INVALID_HANDLE_VALUE) && (m_handle != NULL); - } - - BOOL Invalid() - { - return (m_handle == INVALID_HANDLE_VALUE) || (m_handle == NULL); - } - - ~SmartFileMapHandle() - { - CloseHandle(m_handle); - m_handle = INVALID_HANDLE_VALUE; - } - -} SmartFileMapHandle; - - -typedef class SmartServiceHandle -{ -private: - SC_HANDLE m_handle; - -public: - operator SC_HANDLE() - { - return m_handle; - } - - SmartServiceHandle & operator= (const SC_HANDLE handle) - { - m_handle = handle; - return *this; - } - - SmartServiceHandle() - { - m_handle = NULL; - } - - SmartServiceHandle(const SC_HANDLE handle) - { - m_handle = handle; - } - - BOOL Valid() - { - return (m_handle != NULL); - } - - BOOL Invalid() - { - return (m_handle == NULL); - } - - ~SmartServiceHandle() - { - CloseServiceHandle(m_handle); - m_handle = NULL; - } -} SmartServiceHandle; - -typedef class SmartRegistryHandle { -private: - HKEY m_handle; - -public: - operator HKEY() { - return m_handle; - } - - operator HKEY* () { - return &m_handle; - } - - SmartRegistryHandle & operator= (const HKEY handle) { - m_handle = handle; - return *this; - } - - SmartRegistryHandle() { - m_handle = NULL; - } - - SmartRegistryHandle(const HKEY handle) { - m_handle = handle; - } - - BOOL Valid() { - return (m_handle != NULL); - } - - BOOL Invalid() { - return (m_handle == NULL); - } - - ~SmartRegistryHandle() { - RegCloseKey(m_handle); - m_handle = NULL; - } -} SmartRegistryHandle; diff --git a/include/Win32_Interop/Win32_StackTrace.h b/include/Win32_Interop/Win32_StackTrace.h deleted file mode 100644 index 36638d5..0000000 --- a/include/Win32_Interop/Win32_StackTrace.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -* Copyright (c), Microsoft Open Technologies, Inc. -* All rights reserved. -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* - Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#pragma once - -#include "win32_types.h" -#include - -void StackTraceInit(void); - -extern "C" typedef char *sds; -extern "C" sds genRedisInfoString(char *section); -extern "C" void bugReportStart(void); \ No newline at end of file diff --git a/include/Win32_Interop/Win32_ThreadControl.h b/include/Win32_Interop/Win32_ThreadControl.h deleted file mode 100644 index d79d5e1..0000000 --- a/include/Win32_Interop/Win32_ThreadControl.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c), Microsoft Open Technologies, Inc. - * All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - - -void InitThreadControl(); -void IncrementWorkerThreadCount(); -void DecrementWorkerThreadCount(); -void RequestSuspension(); -BOOL SuspensionCompleted(); -void ResumeFromSuspension(); - -void WorkerThread_EnterSafeMode(); -void WorkerThread_ExitSafeMode(); - - -#ifdef __cplusplus -} -#endif diff --git a/include/Win32_Interop/Win32_Time.h b/include/Win32_Interop/Win32_Time.h deleted file mode 100644 index 1d4b9a7..0000000 --- a/include/Win32_Interop/Win32_Time.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c), Microsoft Open Technologies, Inc. - * All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* Credits Henry Rawas (henryr@schakra.com) */ - -#ifndef WIN32_INTEROP_TIME_H -#define WIN32_INTEROP_TIME_H - -#if (_MSC_VER > 1800) -#include -#endif -#include - -#define gettimeofday gettimeofday_highres - -void InitTimeFunctions(); -uint64_t GetHighResRelativeTime(double scale); -time_t gettimeofdaysecs(unsigned int *usec); -int gettimeofday_highres(struct timeval *tv, struct timezone *tz); -char* ctime_r(const time_t *clock, char *buf); - -#endif diff --git a/include/Win32_Interop/Win32_dlmalloc.h b/include/Win32_Interop/Win32_dlmalloc.h deleted file mode 100644 index 10bd768..0000000 --- a/include/Win32_Interop/Win32_dlmalloc.h +++ /dev/null @@ -1,655 +0,0 @@ -/* -* Copyright (c), Microsoft Open Technologies, Inc. -* All rights reserved. -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* - Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -/* - Default header file for malloc-2.8.x, written by Doug Lea - and released to the public domain, as explained at - http://creativecommons.org/publicdomain/zero/1.0/ - - This header is for ANSI C/C++ only. You can set any of - the following #defines before including: - - * If USE_DL_PREFIX is defined, it is assumed that malloc.c - was also compiled with this option, so all routines - have names starting with "dl". - - * If HAVE_USR_INCLUDE_MALLOC_H is defined, it is assumed that this - file will be #included AFTER . This is needed only if - your system defines a struct mallinfo that is incompatible with the - standard one declared here. Otherwise, you can include this file - INSTEAD of your system system . At least on ANSI, all - declarations should be compatible with system versions - - * If MSPACES is defined, declarations for mspace versions are included. -*/ - -#ifdef USE_DLMALLOC -#ifndef MALLOC_280_H -#define MALLOC_280_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include /* for size_t */ - -#ifndef ONLY_MSPACES -#define ONLY_MSPACES 0 /* define to a value */ -#elif ONLY_MSPACES != 0 -#define ONLY_MSPACES 1 -#endif /* ONLY_MSPACES */ -#ifndef NO_MALLINFO -#define NO_MALLINFO 0 -#endif /* NO_MALLINFO */ - -#ifndef MSPACES -#if ONLY_MSPACES -#define MSPACES 1 -#else /* ONLY_MSPACES */ -#define MSPACES 0 -#endif /* ONLY_MSPACES */ -#endif /* MSPACES */ - -#if !ONLY_MSPACES - -#ifndef USE_DL_PREFIX -#define dlcalloc calloc -#define dlfree free -#define dlmalloc malloc -#define dlmemalign memalign -#define dlposix_memalign posix_memalign -#define dlrealloc realloc -#define dlvalloc valloc -#define dlpvalloc pvalloc -#define dlmallinfo mallinfo -#define dlmallopt mallopt -#define dlmalloc_trim malloc_trim -#define dlmalloc_stats malloc_stats -#define dlmalloc_usable_size malloc_usable_size -#define dlmalloc_footprint malloc_footprint -#define dlmalloc_max_footprint malloc_max_footprint -#define dlmalloc_footprint_limit malloc_footprint_limit -#define dlmalloc_set_footprint_limit malloc_set_footprint_limit -#define dlmalloc_inspect_all malloc_inspect_all -#define dlindependent_calloc independent_calloc -#define dlindependent_comalloc independent_comalloc -#define dlbulk_free bulk_free -#endif /* USE_DL_PREFIX */ - -#if !NO_MALLINFO -#ifndef HAVE_USR_INCLUDE_MALLOC_H -#ifndef _MALLOC_H -#ifndef MALLINFO_FIELD_TYPE -#define MALLINFO_FIELD_TYPE size_t -#endif /* MALLINFO_FIELD_TYPE */ -#ifndef STRUCT_MALLINFO_DECLARED -#define STRUCT_MALLINFO_DECLARED 1 -struct mallinfo { - MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */ - MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */ - MALLINFO_FIELD_TYPE smblks; /* always 0 */ - MALLINFO_FIELD_TYPE hblks; /* always 0 */ - MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */ - MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */ - MALLINFO_FIELD_TYPE fsmblks; /* always 0 */ - MALLINFO_FIELD_TYPE uordblks; /* total allocated space */ - MALLINFO_FIELD_TYPE fordblks; /* total free space */ - MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */ -}; -#endif /* STRUCT_MALLINFO_DECLARED */ -#endif /* _MALLOC_H */ -#endif /* HAVE_USR_INCLUDE_MALLOC_H */ -#endif /* !NO_MALLINFO */ - -/* -Stuffs the global malloc_params and malloc_state data into a buffer. Calling with an incorrect buffer size -or a NULL buffer pointer will cause this call to return EINVAL and update the bufferSize argument. -*/ -int GetDLMallocGlobalState(size_t* bufferSize, void* buffer); - -/* -Copies the supplied data over the global malloc_params and malloc_state variables. This is done to -support the QFork implementation in the forked process. -*/ -int SetDLMallocGlobalState(size_t bufferSize, void* buffer); - -/* - malloc(size_t n) - Returns a pointer to a newly allocated chunk of at least n bytes, or - null if no space is available, in which case errno is set to ENOMEM - on ANSI C systems. - - If n is zero, malloc returns a minimum-sized chunk. (The minimum - size is 16 bytes on most 32bit systems, and 32 bytes on 64bit - systems.) Note that size_t is an unsigned type, so calls with - arguments that would be negative if signed are interpreted as - requests for huge amounts of space, which will often fail. The - maximum supported value of n differs across systems, but is in all - cases less than the maximum representable value of a size_t. -*/ -void* dlmalloc(size_t); - -/* - free(void* p) - Releases the chunk of memory pointed to by p, that had been previously - allocated using malloc or a related routine such as realloc. - It has no effect if p is null. If p was not malloced or already - freed, free(p) will by default cuase the current program to abort. -*/ -void dlfree(void*); - -/* - calloc(size_t n_elements, size_t element_size); - Returns a pointer to n_elements * element_size bytes, with all locations - set to zero. -*/ -void* dlcalloc(size_t, size_t); - -/* - realloc(void* p, size_t n) - Returns a pointer to a chunk of size n that contains the same data - as does chunk p up to the minimum of (n, p's size) bytes, or null - if no space is available. - - The returned pointer may or may not be the same as p. The algorithm - prefers extending p in most cases when possible, otherwise it - employs the equivalent of a malloc-copy-free sequence. - - If p is null, realloc is equivalent to malloc. - - If space is not available, realloc returns null, errno is set (if on - ANSI) and p is NOT freed. - - if n is for fewer bytes than already held by p, the newly unused - space is lopped off and freed if possible. realloc with a size - argument of zero (re)allocates a minimum-sized chunk. - - The old unix realloc convention of allowing the last-free'd chunk - to be used as an argument to realloc is not supported. -*/ -void* dlrealloc(void*, size_t); - -/* - realloc_in_place(void* p, size_t n) - Resizes the space allocated for p to size n, only if this can be - done without moving p (i.e., only if there is adjacent space - available if n is greater than p's current allocated size, or n is - less than or equal to p's size). This may be used instead of plain - realloc if an alternative allocation strategy is needed upon failure - to expand space; for example, reallocation of a buffer that must be - memory-aligned or cleared. You can use realloc_in_place to trigger - these alternatives only when needed. - - Returns p if successful; otherwise null. -*/ -void* dlrealloc_in_place(void*, size_t); - -/* - memalign(size_t alignment, size_t n); - Returns a pointer to a newly allocated chunk of n bytes, aligned - in accord with the alignment argument. - - The alignment argument should be a power of two. If the argument is - not a power of two, the nearest greater power is used. - 8-byte alignment is guaranteed by normal malloc calls, so don't - bother calling memalign with an argument of 8 or less. - - Overreliance on memalign is a sure way to fragment space. -*/ -void* dlmemalign(size_t, size_t); - -/* - int posix_memalign(void** pp, size_t alignment, size_t n); - Allocates a chunk of n bytes, aligned in accord with the alignment - argument. Differs from memalign only in that it (1) assigns the - allocated memory to *pp rather than returning it, (2) fails and - returns EINVAL if the alignment is not a power of two (3) fails and - returns ENOMEM if memory cannot be allocated. -*/ -int dlposix_memalign(void**, size_t, size_t); - -/* - valloc(size_t n); - Equivalent to memalign(pagesize, n), where pagesize is the page - size of the system. If the pagesize is unknown, 4096 is used. -*/ -void* dlvalloc(size_t); - -/* - mallopt(int parameter_number, int parameter_value) - Sets tunable parameters The format is to provide a - (parameter-number, parameter-value) pair. mallopt then sets the - corresponding parameter to the argument value if it can (i.e., so - long as the value is meaningful), and returns 1 if successful else - 0. SVID/XPG/ANSI defines four standard param numbers for mallopt, - normally defined in malloc.h. None of these are use in this malloc, - so setting them has no effect. But this malloc also supports other - options in mallopt: - - Symbol param # default allowed param values - M_TRIM_THRESHOLD -1 2*1024*1024 any (-1U disables trimming) - M_GRANULARITY -2 page size any power of 2 >= page size - M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support) -*/ -int dlmallopt(int, int); - -#define M_TRIM_THRESHOLD (-1) -#define M_GRANULARITY (-2) -#define M_MMAP_THRESHOLD (-3) - - -/* - malloc_footprint(); - Returns the number of bytes obtained from the system. The total - number of bytes allocated by malloc, realloc etc., is less than this - value. Unlike mallinfo, this function returns only a precomputed - result, so can be called frequently to monitor memory consumption. - Even if locks are otherwise defined, this function does not use them, - so results might not be up to date. -*/ -size_t dlmalloc_footprint(void); - -/* - malloc_max_footprint(); - Returns the maximum number of bytes obtained from the system. This - value will be greater than current footprint if deallocated space - has been reclaimed by the system. The peak number of bytes allocated - by malloc, realloc etc., is less than this value. Unlike mallinfo, - this function returns only a precomputed result, so can be called - frequently to monitor memory consumption. Even if locks are - otherwise defined, this function does not use them, so results might - not be up to date. -*/ -size_t dlmalloc_max_footprint(void); - -/* - malloc_footprint_limit(); - Returns the number of bytes that the heap is allowed to obtain from - the system, returning the last value returned by - malloc_set_footprint_limit, or the maximum size_t value if - never set. The returned value reflects a permission. There is no - guarantee that this number of bytes can actually be obtained from - the system. -*/ -size_t dlmalloc_footprint_limit(void); - -/* - malloc_set_footprint_limit(); - Sets the maximum number of bytes to obtain from the system, causing - failure returns from malloc and related functions upon attempts to - exceed this value. The argument value may be subject to page - rounding to an enforceable limit; this actual value is returned. - Using an argument of the maximum possible size_t effectively - disables checks. If the argument is less than or equal to the - current malloc_footprint, then all future allocations that require - additional system memory will fail. However, invocation cannot - retroactively deallocate existing used memory. -*/ -size_t dlmalloc_set_footprint_limit(size_t bytes); - -/* - malloc_inspect_all(void(*handler)(void *start, - void *end, - size_t used_bytes, - void* callback_arg), - void* arg); - Traverses the heap and calls the given handler for each managed - region, skipping all bytes that are (or may be) used for bookkeeping - purposes. Traversal does not include include chunks that have been - directly memory mapped. Each reported region begins at the start - address, and continues up to but not including the end address. The - first used_bytes of the region contain allocated data. If - used_bytes is zero, the region is unallocated. The handler is - invoked with the given callback argument. If locks are defined, they - are held during the entire traversal. It is a bad idea to invoke - other malloc functions from within the handler. - - For example, to count the number of in-use chunks with size greater - than 1000, you could write: - static int count = 0; - void count_chunks(void* start, void* end, size_t used, void* arg) { - if (used >= 1000) ++count; - } - then: - malloc_inspect_all(count_chunks, NULL); - - malloc_inspect_all is compiled only if MALLOC_INSPECT_ALL is defined. -*/ -void dlmalloc_inspect_all(void(*handler)(void*, void *, size_t, void*), - void* arg); - -#if !NO_MALLINFO -/* - mallinfo() - Returns (by copy) a struct containing various summary statistics: - - arena: current total non-mmapped bytes allocated from system - ordblks: the number of free chunks - smblks: always zero. - hblks: current number of mmapped regions - hblkhd: total bytes held in mmapped regions - usmblks: the maximum total allocated space. This will be greater - than current total if trimming has occurred. - fsmblks: always zero - uordblks: current total allocated space (normal or mmapped) - fordblks: total free space - keepcost: the maximum number of bytes that could ideally be released - back to system via malloc_trim. ("ideally" means that - it ignores page restrictions etc.) - - Because these fields are ints, but internal bookkeeping may - be kept as longs, the reported values may wrap around zero and - thus be inaccurate. -*/ - -struct mallinfo dlmallinfo(void); -#endif /* NO_MALLINFO */ - -/* - independent_calloc(size_t n_elements, size_t element_size, void* chunks[]); - - independent_calloc is similar to calloc, but instead of returning a - single cleared space, it returns an array of pointers to n_elements - independent elements that can hold contents of size elem_size, each - of which starts out cleared, and can be independently freed, - realloc'ed etc. The elements are guaranteed to be adjacently - allocated (this is not guaranteed to occur with multiple callocs or - mallocs), which may also improve cache locality in some - applications. - - The "chunks" argument is optional (i.e., may be null, which is - probably the most typical usage). If it is null, the returned array - is itself dynamically allocated and should also be freed when it is - no longer needed. Otherwise, the chunks array must be of at least - n_elements in length. It is filled in with the pointers to the - chunks. - - In either case, independent_calloc returns this pointer array, or - null if the allocation failed. If n_elements is zero and "chunks" - is null, it returns a chunk representing an array with zero elements - (which should be freed if not wanted). - - Each element must be freed when it is no longer needed. This can be - done all at once using bulk_free. - - independent_calloc simplifies and speeds up implementations of many - kinds of pools. It may also be useful when constructing large data - structures that initially have a fixed number of fixed-sized nodes, - but the number is not known at compile time, and some of the nodes - may later need to be freed. For example: - - struct Node { int item; struct Node* next; }; - - struct Node* build_list() { - struct Node** pool; - int n = read_number_of_nodes_needed(); - if (n <= 0) return 0; - pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0); - if (pool == 0) die(); - // organize into a linked list... - struct Node* first = pool[0]; - for (i = 0; i < n-1; ++i) - pool[i]->next = pool[i+1]; - free(pool); // Can now free the array (or not, if it is needed later) - return first; - } -*/ -void** dlindependent_calloc(size_t, size_t, void**); - -/* - independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]); - - independent_comalloc allocates, all at once, a set of n_elements - chunks with sizes indicated in the "sizes" array. It returns - an array of pointers to these elements, each of which can be - independently freed, realloc'ed etc. The elements are guaranteed to - be adjacently allocated (this is not guaranteed to occur with - multiple callocs or mallocs), which may also improve cache locality - in some applications. - - The "chunks" argument is optional (i.e., may be null). If it is null - the returned array is itself dynamically allocated and should also - be freed when it is no longer needed. Otherwise, the chunks array - must be of at least n_elements in length. It is filled in with the - pointers to the chunks. - - In either case, independent_comalloc returns this pointer array, or - null if the allocation failed. If n_elements is zero and chunks is - null, it returns a chunk representing an array with zero elements - (which should be freed if not wanted). - - Each element must be freed when it is no longer needed. This can be - done all at once using bulk_free. - - independent_comallac differs from independent_calloc in that each - element may have a different size, and also that it does not - automatically clear elements. - - independent_comalloc can be used to speed up allocation in cases - where several structs or objects must always be allocated at the - same time. For example: - - struct Head { ... } - struct Foot { ... } - - void send_message(char* msg) { - int msglen = strlen(msg); - size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) }; - void* chunks[3]; - if (independent_comalloc(3, sizes, chunks) == 0) - die(); - struct Head* head = (struct Head*)(chunks[0]); - char* body = (char*)(chunks[1]); - struct Foot* foot = (struct Foot*)(chunks[2]); - // ... - } - - In general though, independent_comalloc is worth using only for - larger values of n_elements. For small values, you probably won't - detect enough difference from series of malloc calls to bother. - - Overuse of independent_comalloc can increase overall memory usage, - since it cannot reuse existing noncontiguous small chunks that - might be available for some of the elements. -*/ -void** dlindependent_comalloc(size_t, size_t*, void**); - -/* - bulk_free(void* array[], size_t n_elements) - Frees and clears (sets to null) each non-null pointer in the given - array. This is likely to be faster than freeing them one-by-one. - If footers are used, pointers that have been allocated in different - mspaces are not freed or cleared, and the count of all such pointers - is returned. For large arrays of pointers with poor locality, it - may be worthwhile to sort this array before calling bulk_free. -*/ -size_t dlbulk_free(void**, size_t n_elements); - -/* - pvalloc(size_t n); - Equivalent to valloc(minimum-page-that-holds(n)), that is, - round up n to nearest pagesize. - */ -void* dlpvalloc(size_t); - -/* - malloc_trim(size_t pad); - - If possible, gives memory back to the system (via negative arguments - to sbrk) if there is unused memory at the `high' end of the malloc - pool or in unused MMAP segments. You can call this after freeing - large blocks of memory to potentially reduce the system-level memory - requirements of a program. However, it cannot guarantee to reduce - memory. Under some allocation patterns, some large free blocks of - memory will be locked between two used chunks, so they cannot be - given back to the system. - - The `pad' argument to malloc_trim represents the amount of free - trailing space to leave untrimmed. If this argument is zero, only - the minimum amount of memory to maintain internal data structures - will be left. Non-zero arguments can be supplied to maintain enough - trailing space to service future expected allocations without having - to re-obtain memory from the system. - - Malloc_trim returns 1 if it actually released any memory, else 0. -*/ -int dlmalloc_trim(size_t); - -/* - malloc_stats(); - Prints on stderr the amount of space obtained from the system (both - via sbrk and mmap), the maximum amount (which may be more than - current if malloc_trim and/or munmap got called), and the current - number of bytes allocated via malloc (or realloc, etc) but not yet - freed. Note that this is the number of bytes allocated, not the - number requested. It will be larger than the number requested - because of alignment and bookkeeping overhead. Because it includes - alignment wastage as being in use, this figure may be greater than - zero even when no user-level chunks are allocated. - - The reported current and maximum system memory can be inaccurate if - a program makes other calls to system memory allocation functions - (normally sbrk) outside of malloc. - - malloc_stats prints only the most commonly interesting statistics. - More information can be obtained by calling mallinfo. - - malloc_stats is not compiled if NO_MALLOC_STATS is defined. -*/ -void dlmalloc_stats(void); - -#endif /* !ONLY_MSPACES */ - -/* - malloc_usable_size(void* p); - - Returns the number of bytes you can actually use in - an allocated chunk, which may be more than you requested (although - often not) due to alignment and minimum size constraints. - You can use this many bytes without worrying about - overwriting other allocated objects. This is not a particularly great - programming practice. malloc_usable_size can be more useful in - debugging and assertions, for example: - - p = malloc(n); - assert(malloc_usable_size(p) >= 256); -*/ -size_t dlmalloc_usable_size(const void*); - -#if MSPACES - -/* - mspace is an opaque type representing an independent - region of space that supports mspace_malloc, etc. -*/ -typedef void* mspace; - -/* - create_mspace creates and returns a new independent space with the - given initial capacity, or, if 0, the default granularity size. It - returns null if there is no system memory available to create the - space. If argument locked is non-zero, the space uses a separate - lock to control access. The capacity of the space will grow - dynamically as needed to service mspace_malloc requests. You can - control the sizes of incremental increases of this space by - compiling with a different DEFAULT_GRANULARITY or dynamically - setting with mallopt(M_GRANULARITY, value). -*/ -mspace create_mspace(size_t capacity, int locked); - -/* - destroy_mspace destroys the given space, and attempts to return all - of its memory back to the system, returning the total number of - bytes freed. After destruction, the results of access to all memory - used by the space become undefined. -*/ -size_t destroy_mspace(mspace msp); - -/* - create_mspace_with_base uses the memory supplied as the initial base - of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this - space is used for bookkeeping, so the capacity must be at least this - large. (Otherwise 0 is returned.) When this initial space is - exhausted, additional memory will be obtained from the system. - Destroying this space will deallocate all additionally allocated - space (if possible) but not the initial base. -*/ -mspace create_mspace_with_base(void* base, size_t capacity, int locked); - -/* - mspace_track_large_chunks controls whether requests for large chunks - are allocated in their own untracked mmapped regions, separate from - others in this mspace. By default large chunks are not tracked, - which reduces fragmentation. However, such chunks are not - necessarily released to the system upon destroy_mspace. Enabling - tracking by setting to true may increase fragmentation, but avoids - leakage when relying on destroy_mspace to release all memory - allocated using this space. The function returns the previous - setting. -*/ -int mspace_track_large_chunks(mspace msp, int enable); - -#if !NO_MALLINFO -/* - mspace_mallinfo behaves as mallinfo, but reports properties of - the given space. -*/ -struct mallinfo mspace_mallinfo(mspace msp); -#endif /* NO_MALLINFO */ - -/* - An alias for mallopt. -*/ -int mspace_mallopt(int, int); - -/* - The following operate identically to their malloc counterparts - but operate only for the given mspace argument -*/ -void* mspace_malloc(mspace msp, size_t bytes); -void mspace_free(mspace msp, void* mem); -void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size); -void* mspace_realloc(mspace msp, void* mem, size_t newsize); -void* mspace_realloc_in_place(mspace msp, void* mem, size_t newsize); -void* mspace_memalign(mspace msp, size_t alignment, size_t bytes); -void** mspace_independent_calloc(mspace msp, size_t n_elements, - size_t elem_size, void* chunks[]); -void** mspace_independent_comalloc(mspace msp, size_t n_elements, - size_t sizes[], void* chunks[]); -size_t mspace_bulk_free(mspace msp, void**, size_t n_elements); -size_t mspace_usable_size(const void* mem); -void mspace_malloc_stats(mspace msp); -int mspace_trim(mspace msp, size_t pad); -size_t mspace_footprint(mspace msp); -size_t mspace_max_footprint(mspace msp); -size_t mspace_footprint_limit(mspace msp); -size_t mspace_set_footprint_limit(mspace msp, size_t bytes); -void mspace_inspect_all(mspace msp, - void(*handler)(void *, void *, size_t, void*), - void* arg); -#endif /* MSPACES */ - -#ifdef __cplusplus -}; /* end of extern "C" */ -#endif - -#endif /* MALLOC_280_H */ -#endif /* USE_DLMALLOC */ \ No newline at end of file diff --git a/include/Win32_Interop/Win32_fdapi_crt.h b/include/Win32_Interop/Win32_fdapi_crt.h deleted file mode 100644 index 0e941f9..0000000 --- a/include/Win32_Interop/Win32_fdapi_crt.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -* Copyright (c), Microsoft Open Technologies, Inc. -* All rights reserved. -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* - Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#pragma once - -#include -#include - -int crt_pipe(int *pfds, unsigned int psize, int textmode); -int crt_close(int fd); -int crt_read(int fd, void *buffer, unsigned int count); -int crt_write(int fd, const void *buffer, unsigned int count); -int crt_open(const char *filename, int oflag, int pmode); -int crt_open_osfhandle(intptr_t osfhandle, int flags); -intptr_t crt_get_osfhandle(int fd); -int crt_setmode(int fd, int mode); -size_t crt_fwrite(const void *buffer, size_t size, size_t count, FILE *file); -int crt_fclose(FILE* file); -int crt_fileno(FILE* file); -int crt_isatty(int fd); -int crt_access(const char *pathname, int mode); -__int64 crt_lseek64(int fd, __int64 offset, int origin); diff --git a/include/Win32_Interop/Win32_variadicFunctor.h b/include/Win32_Interop/Win32_variadicFunctor.h deleted file mode 100644 index a40ea72..0000000 --- a/include/Win32_Interop/Win32_variadicFunctor.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -* Copyright (c), Microsoft Open Technologies, Inc. -* All rights reserved. -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* - Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#pragma once - -#include -#include -#include -using namespace std; - -class DLLMap : map { -public: - static DLLMap& getInstance(); - -private: - DLLMap(); - DLLMap(DLLMap const&); // Don't implement to guarantee singleton semantics - void operator=(DLLMap const&); // Don't implement to guarantee singleton semantics - -public: - LPVOID getProcAddress(string dll, string functionName); - virtual ~DLLMap(); -}; - - -template -class dllfunctor_stdcall { -public: - dllfunctor_stdcall(string dll, string function) - { - _f = (R(__stdcall *)(T...))DLLMap::getInstance().getProcAddress(dll, function.c_str()); - } - R operator()(T... args) { return _f(args...); } - -private: - R(__stdcall *_f)(T...); -}; diff --git a/include/Win32_Interop/win32_rfdmap.h b/include/Win32_Interop/win32_rfdmap.h deleted file mode 100644 index facc125..0000000 --- a/include/Win32_Interop/win32_rfdmap.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c), Microsoft Open Technologies, Inc. - * All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include -#define INCL_WINSOCK_API_PROTOTYPES 0 // Important! Do not include Winsock API definitions to avoid conflicts with API entry points defined below. -#include -#include "ws2tcpip.h" -#include -#include - -using namespace std; - -/* In UNIX File Descriptors increment by one for each new one. Windows handles - * do not follow the same rule. Additionally UNIX uses a 32-bit int to - * represent a FD while Windows_x64 uses a 64-bit value to represent a handle. - * There is no documented guarantee that a Windows SOCKET value will be - * entirely constrained in 32-bits (though it seems to be currently). SOCKETs - * should be treated as an opaque value and not be cast to a 32-bit int. In - * order to not break existing code that relies on the maximum FD value to - * indicate the number of handles that have been created (and other UNIXisms), - * this code maps SOCKET handles to a virtual FD number starting at 3 (0,1 and - * 2 are reserved for stdin, stdout and stderr). - */ - -#define INVALID_FD -1 -typedef int RFD; // Redis File Descriptor - -typedef struct { - SOCKET socket; - void* state; - int flags; - SOCKADDR_STORAGE socketAddrStorage; -} SocketInfo; - -class RFDMap { -public: - static RFDMap& getInstance(); - -private: - RFDMap(); - RFDMap(RFDMap const&); // Don't implement to guarantee singleton semantics - void operator=(RFDMap const&); // Don't implement to guarantee singleton semantics - -private: - map SocketToRFDMap; - map CrtFDToRFDMap; - map RFDToSocketInfoMap; - map RFDToCrtFDMap; - queue RFDRecyclePool; - -private: - CRITICAL_SECTION mutex; - const static int FIRST_RESERVED_RFD_INDEX = 0; - const static int LAST_RESERVED_RFD_INDEX = 2; - int next_available_rfd = LAST_RESERVED_RFD_INDEX + 1; - -private: - /* Gets the next available Redis File Descriptor. Redis File Descriptors - * are always non-negative integers, with the first three being reserved - * for stdin(0), stdout(1) and stderr(2). */ - RFD getNextRFDAvailable(); - -public: - /* Adds a socket to SocketToRFDMap and to RFDToSocketInfoMap. - * Returns the RFD value for the socket. - * Returns INVALID_RFD if the socket is already added to the collection. */ - RFD addSocket(SOCKET socket); - - /* Removes a socket from SocketToRFDMap. */ - void removeSocketToRFD(SOCKET socket); - - /* Removes a RFD from RFDToSocketInfoMap. - * It frees the associated RFD adding it to RFDRecyclePool. */ - void removeRFDToSocketInfo(RFD rfd); - - /* Adds a CRT fd (used with low-level CRT posix file functions) to RFDToCrtFDMap. - * Returns the RFD value for the crt_fd. - * Returns the existing RFD if the crt_fd is already present in the collection. */ - RFD addCrtFD(int crt_fd); - - /* Removes a socket from RFDToCrtFDMap. - * It frees the associated RFD adding it to RFDRecyclePool. */ - void removeCrtFD(int crt_fd); - - /* Returns the socket associated with a RFD. - * Returns INVALID_SOCKET if the socket is not found. */ - SOCKET lookupSocket(RFD rfd); - - /* Returns a pointer to the socket info structure associated with a RFD. - * Return NULL if the info socket info structure is not found. */ - SocketInfo* lookupSocketInfo(RFD rfd); - - /* Returns the crt_fd associated with a RFD. - * Returns INVALID_FD if the crt_fd is not found. */ - int lookupCrtFD(RFD rfd); -}; diff --git a/include/Win32_Interop/win32_types_hiredis.h b/include/Win32_Interop/win32_types_hiredis.h index 2c83a3a..fca74bc 100644 --- a/include/Win32_Interop/win32_types_hiredis.h +++ b/include/Win32_Interop/win32_types_hiredis.h @@ -37,11 +37,11 @@ typedef unsigned __int64 PORT_ULONGLONG; typedef double PORT_LONGDOUBLE; #ifdef _WIN64 -typedef __int64 ssize_t; +typedef __int64 _ssize_t; typedef __int64 PORT_LONG; typedef unsigned __int64 PORT_ULONG; #else -typedef long ssize_t; +typedef long _ssize_t; typedef long PORT_LONG; typedef unsigned long PORT_ULONG; #endif diff --git a/include/Win32_Interop/win32_winapifamily.h b/include/Win32_Interop/win32_winapifamily.h deleted file mode 100644 index d12170b..0000000 --- a/include/Win32_Interop/win32_winapifamily.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - -Copyright (c) Microsoft Corporation. All rights reserved. - -Module Name: - -winapifamily.h - -Abstract: - -Master include file for API family partitioning. - -*/ - -#ifndef _INC_WINAPIFAMILY -#define _INC_WINAPIFAMILY - -#if defined(_MSC_VER) && !defined(MOFCOMP_PASS) -#pragma once -#endif // defined(_MSC_VER) && !defined(MOFCOMP_PASS) - -/* -* When compiling C and C++ code using SDK header files, the development -* environment can specify a target platform by #define-ing the -* pre-processor symbol WINAPI_FAMILY to one of the following values. -* Each FAMILY value denotes an application family for which a different -* subset of the total set of header-file-defined APIs are available. -* Setting the WINAPI_FAMILY value will effectively hide from the -* editing and compilation environments the existence of APIs that -* are not applicable to the family of applications targeting a -* specific platform. -*/ - -/* -* The WINAPI_FAMILY values of 0 and 1 are reserved to ensure that -* an error will occur if WINAPI_FAMILY is set to any -* WINAPI_PARTITION value (which must be 0 or 1, see below). -*/ -#define WINAPI_FAMILY_PC_APP 2 /* Windows Store Applications */ -#define WINAPI_FAMILY_PHONE_APP 3 /* Windows Phone Applications */ -#define WINAPI_FAMILY_DESKTOP_APP 100 /* Windows Desktop Applications */ -/* The value of WINAPI_FAMILY_DESKTOP_APP may change in future SDKs. */ -/* Additional WINAPI_FAMILY values may be defined in future SDKs. */ - -/* -* For compatibility with Windows 8 header files, the following -* synonym for WINAPI_FAMILY_PC_APP is temporarily #define'd. -* Use of this symbol should be considered deprecated. -*/ -#define WINAPI_FAMILY_APP WINAPI_FAMILY_PC_APP - -/* -* If no WINAPI_FAMILY value is specified, then all APIs available to -* Windows desktop applications are exposed. -*/ -#ifndef WINAPI_FAMILY -#define WINAPI_FAMILY WINAPI_FAMILY_DESKTOP_APP -#endif - -/* -* API PARTITONs are part of an indirection mechanism for mapping between -* individual APIs and the FAMILYs to which they apply. -* Each PARTITION is a category or subset of named APIs. PARTITIONs -* are permitted to have overlapping membership -- some single API -* might be part of more than one PARTITION. In support of new -* FAMILYs that might be added in future SDKs, any single current -* PARTITION might in that future SDK be split into two or more new PARTITIONs. -* Accordingly, application developers should avoid taking dependencies on -* PARTITION names; developers' only dependency upon the symbols defined -* in this file should be their reliance on the WINAPI_FAMILY names and values. -*/ - -/* -* Current PARTITIONS are each #undef'ed below, and then will be #define-ed -* to be either 1 or 0 or depending on the active WINAPI_FAMILY. -*/ - -#undef WINAPI_PARTITION_DESKTOP /* usable for PC desktop apps (but not store apps) */ -#undef WINAPI_PARTITION_APP /* usable for most platforms' store apps */ -#undef WINAPI_PARTITION_PC_APP /* specific to PC store apps */ -#undef WINAPI_PARTITION_PHONE_APP /* specific to phone store apps */ - - -/* -* The mapping between families and partitions is summarized here. -* An X indicates that the given partition is active for the given -* platform/family. -* -* +---------------+ -* | *Partition* | -* +---+---+---+---+ -* | | | | P | -* | | | | H | -* | D | | | O | -* | E | | P | N | -* | S | | C | E | -* | K | | _ | _ | -* | T | A | A | A | -* +-------------------------+-+ O | P | P | P | -* | *Platform/Family* \| P | P | P | P | -* +---------------------------+---+---+---+---+ -* | WINAPI_FAMILY_DESKTOP_APP | X | X | X | | -* +---------------------------+---+---+---+---+ -* | WINAPI_FAMILY_PC_APP | | X | X | | -* +---------------------------+---+---+---+---+ -* | WINAPI_FAMILY_PHONE_APP | | X | | X | -* +---------------------------+---+---+---+---+ -* -* The table above is encoded in the following expressions, -* each of which evaluates to 1 or 0. -* -* Whenever a new family is added, all of these expressions -* need to be reconsidered. -*/ -#if WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP && WINAPI_FAMILY != WINAPI_FAMILY_PC_APP && WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP -# error Unknown WINAPI_FAMILY value. Was it defined in terms of a WINAPI_PARTITION_* value? -#endif -#define WINAPI_PARTITION_DESKTOP (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP) -#define WINAPI_PARTITION_APP 1 /* active for all current families */ -#define WINAPI_PARTITION_PC_APP (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP || WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) -#define WINAPI_PARTITION_PHONE_APP (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) - -/* -* For compatibility with Windows Phone 8 header files, the following -* synonym for WINAPI_PARTITION_PHONE_APP is temporarily #define'd. -* Use of this symbol should be regarded as deprecated. -*/ -#define WINAPI_PARTITION_PHONE WINAPI_PARTITION_PHONE_APP - -/* -* Header files use the WINAPI_FAMILY_PARTITION macro to assign one or -* more declarations to some group of partitions. The macro chooses -* whether the preprocessor will emit or omit a sequence of declarations -* bracketed by an #if/#endif pair. All header file references to the -* WINAPI_PARTITION_* values should be in the form of occurrences of -* WINAPI_FAMILY_PARTITION(...). -* -* For example, the following usage of WINAPI_FAMILY_PARTITION identifies -* a sequence of declarations that are part of both the Windows Desktop -* Partition and the Windows-Phone-Specific Store Partition: -* -* #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_PHONE_APP) -* ... -* #endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_PHONE_APP) -* -* The comment on the closing #endif allow tools as well as people to find the -* matching #ifdef properly. -* -* Usages of WINAPI_FAMILY_PARTITION may be combined, when the partitition definitions are -* related. In particular one might use declarations like -* -* #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -* -* or -* -* #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) -* -* Direct references to WINAPI_PARTITION_ values (eg #if !WINAPI_FAMILY_PARTITION_...) -* should not be used. -*/ -#define WINAPI_FAMILY_PARTITION(Partitions) (Partitions) - -/* -* Macro used to #define or typedef a symbol used for selective deprecation -* of individual methods of a COM interfaces that are otherwise available -* for a given set of partitions. -*/ -#define _WINAPI_DEPRECATED_DECLARATION __declspec(deprecated("This API cannot be used in the context of the caller's application type.")) - -/* -* For compatibility with Windows 8 header files, the following -* symbol is temporarily conditionally #define'd. Additional symbols -* like this should be not defined in winapifamily.h, but rather should be -* introduced locally to the header files of the component that needs them. -*/ -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -# define APP_DEPRECATED_HRESULT HRESULT _WINAPI_DEPRECATED_DECLARATION -#endif // WINAPIFAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - -#endif /* !_INC_WINAPIFAMILY */ diff --git a/include/Win32_Interop/win32_wsiocp.h b/include/Win32_Interop/win32_wsiocp.h deleted file mode 100644 index 729cbc7..0000000 --- a/include/Win32_Interop/win32_wsiocp.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c), Microsoft Open Technologies, Inc. - * All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WIN32_INTEROP_WSIOCP_H -#define WIN32_INTEROP_WSIOCP_H - -#include "win32_wsiocp2.h" - -/* structs and functions for using IOCP with windows sockets */ - -/* structure used for async write requests. - * contains overlapped, WSABuf, and callback info - * NOTE: OVERLAPPED must be first member */ -typedef struct asendreq { - OVERLAPPED ov; - WSABUF wbuf; - WSIOCP_Request req; - aeFileProc *proc; - aeEventLoop *eventLoop; -} asendreq; - -/* structure used for async accept requests. - * contains overlapped, accept socket, accept buffer - * NOTE: OVERLAPPED must be first member */ -typedef struct aacceptreq { - OVERLAPPED ov; - SOCKET accept; - void *buf; - struct aacceptreq *next; -} aacceptreq; - - -/* per socket information */ -typedef struct iocpSockState { - int masks; - int fd; - aacceptreq *reqs; - int wreqs; - OVERLAPPED ov_read; - list wreqlist; - int unknownComplete; -} iocpSockState; - -#define READ_QUEUED 0x000100 -#define SOCKET_ATTACHED 0x000400 -#define ACCEPT_PENDING 0x000800 -#define LISTEN_SOCK 0x001000 -#define CONNECT_PENDING 0x002000 -#define CLOSE_PENDING 0x004000 - -void WSIOCP_Init(HANDLE iocp); -void WSIOCP_Cleanup(); -iocpSockState* WSIOCP_GetExistingSocketState(int fd); -iocpSockState* WSIOCP_GetSocketState(int fd); -BOOL WSIOCP_CloseSocketState(iocpSockState* pSocketState); - -void* CallocMemoryNoCOW(size_t size); -void FreeMemoryNoCOW(void * ptr); - -#endif diff --git a/include/Win32_Interop/win32_wsiocp2.h b/include/Win32_Interop/win32_wsiocp2.h deleted file mode 100644 index 5983e1b..0000000 --- a/include/Win32_Interop/win32_wsiocp2.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c), Microsoft Open Technologies, Inc. - * All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WIN32_INTEROP_WSIOCP2_H -#define WIN32_INTEROP_WSIOCP2_H - -#include // For SOCKADDR_STORAGE -#include "WS2tcpip.h" // For socklen_t - -/* need callback on write complete. WSIOCP_Request is used to pass parameters */ -typedef struct WSIOCP_Request { - void *client; - void *data; - char *buf; - int len; -} WSIOCP_Request; - -int WSIOCP_QueueNextRead(int rfd); -int WSIOCP_SocketSend(int rfd, char *buf, int len, void *eventLoop, void *client, void *data, void *proc); -int WSIOCP_Listen(int rfd, int backlog); -int WSIOCP_Accept(int rfd, struct sockaddr *sa, socklen_t *len); -int WSIOCP_SocketConnect(int rfd, const SOCKADDR_STORAGE *ss); -int WSIOCP_SocketConnectBind(int rfd, const SOCKADDR_STORAGE *ss, const char* source_addr); - -#endif \ No newline at end of file diff --git a/include/hiredis/async.h b/include/hiredis/async.h deleted file mode 100644 index 6c08a52..0000000 --- a/include/hiredis/async.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2009-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIREDIS_ASYNC_H -#define __HIREDIS_ASYNC_H -#include "hiredis.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct redisAsyncContext; /* need forward declaration of redisAsyncContext */ -struct dict; /* dictionary header is included in async.c */ - -/* Reply callback prototype and container */ -typedef void (redisCallbackFn)(struct redisAsyncContext*, void*, void*); -typedef struct redisCallback { - struct redisCallback *next; /* simple singly linked list */ - redisCallbackFn *fn; - void *privdata; -} redisCallback; - -/* List of callbacks for either regular replies or pub/sub */ -typedef struct redisCallbackList { - redisCallback *head, *tail; -} redisCallbackList; - -/* Connection callback prototypes */ -typedef void (redisDisconnectCallback)(const struct redisAsyncContext*, int status); -typedef void (redisConnectCallback)(const struct redisAsyncContext*, int status); - -/* Context for an async connection to Redis */ -typedef struct redisAsyncContext { - /* Hold the regular context, so it can be realloc'ed. */ - redisContext c; - - /* Setup error flags so they can be used directly. */ - int err; - char *errstr; - - /* Not used by hiredis */ - void *data; - - /* Event library data and hooks */ - struct { - void *data; - - /* Hooks that are called when the library expects to start - * reading/writing. These functions should be idempotent. */ - void (*addRead)(void *privdata); -#ifdef _WIN32 - void (*forceAddRead)(void *privdata); -#endif - void (*delRead)(void *privdata); - void (*addWrite)(void *privdata); - void (*delWrite)(void *privdata); - void (*cleanup)(void *privdata); - } ev; - - /* Called when either the connection is terminated due to an error or per - * user request. The status is set accordingly (C_OK, C_ERR). */ - redisDisconnectCallback *onDisconnect; - - /* Called when the first write event was received. */ - redisConnectCallback *onConnect; - - /* Regular command callbacks */ - redisCallbackList replies; - - /* Subscription callbacks */ - struct { - redisCallbackList invalid; - struct dict *channels; - struct dict *patterns; - } sub; -} redisAsyncContext; - -/* Functions that proxy to hiredis */ -redisAsyncContext *redisAsyncConnect(const char *ip, int port); -redisAsyncContext *redisAsyncConnectBind(const char *ip, int port, const char *source_addr); -redisAsyncContext *redisAsyncConnectUnix(const char *path); -int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn); -int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn); -void redisAsyncDisconnect(redisAsyncContext *ac); -void redisAsyncFree(redisAsyncContext *ac); - -/* Handle read/write events */ -void redisAsyncHandleRead(redisAsyncContext *ac); -void redisAsyncHandleWrite(redisAsyncContext *ac); -#ifdef _WIN32 -int redisAsyncHandleWritePrep(redisAsyncContext *ac); -int redisAsyncHandleWriteComplete(redisAsyncContext *ac, int written); -#endif - -/* Command functions for an async context. Write the command to the - * output buffer and register the provided callback. */ -int redisvAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, va_list ap); -int redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...); -int redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/hiredis/dict.h b/include/hiredis/dict.h deleted file mode 100644 index e4e8a29..0000000 --- a/include/hiredis/dict.h +++ /dev/null @@ -1,126 +0,0 @@ -/* Hash table implementation. - * - * This file implements in memory hash tables with insert/del/replace/find/ - * get-random-element operations. Hash tables will auto resize if needed - * tables of power of two in size are used, collisions are handled by - * chaining. See the source code for more information... :) - * - * Copyright (c) 2006-2010, Salvatore Sanfilippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __DICT_H -#define __DICT_H - -#define DICT_OK 0 -#define DICT_ERR 1 - -/* Unused arguments generate annoying warnings... */ -#define DICT_NOTUSED(V) ((void) V) - -typedef struct dictEntry { - void *key; - void *val; - struct dictEntry *next; -} dictEntry; - -typedef struct dictType { - unsigned int (*hashFunction)(const void *key); - void *(*keyDup)(void *privdata, const void *key); - void *(*valDup)(void *privdata, const void *obj); - int (*keyCompare)(void *privdata, const void *key1, const void *key2); - void (*keyDestructor)(void *privdata, void *key); - void (*valDestructor)(void *privdata, void *obj); -} dictType; - -typedef struct dict { - dictEntry **table; - dictType *type; - PORT_ULONG size; - PORT_ULONG sizemask; - PORT_ULONG used; - void *privdata; -} dict; - -typedef struct dictIterator { - dict *ht; - int index; - dictEntry *entry, *nextEntry; -} dictIterator; - -/* This is the initial size of every hash table */ -#define DICT_HT_INITIAL_SIZE 4 - -/* ------------------------------- Macros ------------------------------------*/ -#define dictFreeEntryVal(ht, entry) \ - if ((ht)->type->valDestructor) \ - (ht)->type->valDestructor((ht)->privdata, (entry)->val) - -#define dictSetHashVal(ht, entry, _val_) do { \ - if ((ht)->type->valDup) \ - entry->val = (ht)->type->valDup((ht)->privdata, _val_); \ - else \ - entry->val = (_val_); \ -} while(0) - -#define dictFreeEntryKey(ht, entry) \ - if ((ht)->type->keyDestructor) \ - (ht)->type->keyDestructor((ht)->privdata, (entry)->key) - -#define dictSetHashKey(ht, entry, _key_) do { \ - if ((ht)->type->keyDup) \ - entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \ - else \ - entry->key = (_key_); \ -} while(0) - -#define dictCompareHashKeys(ht, key1, key2) \ - (((ht)->type->keyCompare) ? \ - (ht)->type->keyCompare((ht)->privdata, key1, key2) : \ - (key1) == (key2)) - -#define dictHashKey(ht, key) (ht)->type->hashFunction(key) - -#define dictGetEntryKey(he) ((he)->key) -#define dictGetEntryVal(he) ((he)->val) -#define dictSlots(ht) ((ht)->size) -#define dictSize(ht) ((ht)->used) - -/* API */ -static unsigned int dictGenHashFunction(const unsigned char *buf, int len); -static dict *dictCreate(dictType *type, void *privDataPtr); -static int dictExpand(dict *ht, PORT_ULONG size); -static int dictAdd(dict *ht, void *key, void *val); -static int dictReplace(dict *ht, void *key, void *val); -static int dictDelete(dict *ht, const void *key); -static void dictRelease(dict *ht); -static dictEntry * dictFind(dict *ht, const void *key); -static dictIterator *dictGetIterator(dict *ht); -static dictEntry *dictNext(dictIterator *iter); -static void dictReleaseIterator(dictIterator *iter); - -#endif /* __DICT_H */ diff --git a/include/hiredis/fmacros.h b/include/hiredis/fmacros.h deleted file mode 100644 index 6a41aa1..0000000 --- a/include/hiredis/fmacros.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef __HIREDIS_FMACRO_H -#define __HIREDIS_FMACRO_H - -#if !defined(_BSD_SOURCE) -#define _BSD_SOURCE -#endif - -#if defined(_AIX) -#define _ALL_SOURCE -#endif - -#if defined(__sun__) -#define _POSIX_C_SOURCE 200112L -#elif defined(__linux__) || defined(__OpenBSD__) || defined(__NetBSD__) -#define _XOPEN_SOURCE 600 -#else -#define _XOPEN_SOURCE -#endif - -#if __APPLE__ && __MACH__ -#define _OSX -#endif - -#endif diff --git a/include/hiredis/net.h b/include/hiredis/net.h deleted file mode 100644 index 3763ab0..0000000 --- a/include/hiredis/net.h +++ /dev/null @@ -1,51 +0,0 @@ -/* Extracted from anet.c to work properly with Hiredis error reporting. - * - * Copyright (c) 2006-2011, Salvatore Sanfilippo - * Copyright (c) 2010-2011, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __NET_H -#define __NET_H - -#include "hiredis.h" - -#if defined(__sun) || defined(_AIX) -#define AF_LOCAL AF_UNIX -#endif - -int redisCheckSocketError(redisContext *c); -int redisContextSetTimeout(redisContext *c, const struct timeval tv); -int redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout); -int redisContextConnectBindTcp(redisContext *c, const char *addr, int port, - const struct timeval *timeout, - const char *source_addr); -int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout); -int redisKeepAlive(redisContext *c, int interval); - -#endif diff --git a/include/hiredis/sds.h b/include/hiredis/sds.h deleted file mode 100644 index e6d8f54..0000000 --- a/include/hiredis/sds.h +++ /dev/null @@ -1,321 +0,0 @@ -/* SDSLib 2.0 -- A C dynamic strings library - * - * Copyright (c) 2006-2015, Salvatore Sanfilippo - * Copyright (c) 2015, Oran Agra - * Copyright (c) 2015, Redis Labs, Inc - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __SDS_H -#define __SDS_H - -#define SDS_MAX_PREALLOC (1024*1024) - -#ifdef _WIN32 -#include "../../src/Win32_Interop/Win32_Portability.h" -#include "../../src/Win32_Interop/win32_types_hiredis.h" -#endif -#include -#include -#include - -typedef char *sds; - -#ifdef _WIN32 -#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) ) - -/* Note: sdshdr5 is never used, we just access the flags byte directly. -* However is here to document the layout of type 5 SDS strings. */ -PACK( -struct sdshdr5{ - unsigned char flags; /* 3 lsb of type, and 5 msb of string length */ - char buf[]; -};) -PACK( -struct sdshdr8 { - uint8_t len; /* used */ - uint8_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -};) -PACK( -struct sdshdr16 { - uint16_t len; /* used */ - uint16_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -};) -PACK( -struct sdshdr32 { - uint32_t len; /* used */ - uint32_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -};) -PACK( -struct sdshdr64 { - uint64_t len; /* used */ - uint64_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -};) -#else -/* Note: sdshdr5 is never used, we just access the flags byte directly. - * However is here to document the layout of type 5 SDS strings. */ -struct __attribute__ ((__packed__)) sdshdr5 { - unsigned char flags; /* 3 lsb of type, and 5 msb of string length */ - char buf[]; -}; -struct __attribute__ ((__packed__)) sdshdr8 { - uint8_t len; /* used */ - uint8_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -}; -struct __attribute__ ((__packed__)) sdshdr16 { - uint16_t len; /* used */ - uint16_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -}; -struct __attribute__ ((__packed__)) sdshdr32 { - uint32_t len; /* used */ - uint32_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -}; -struct __attribute__ ((__packed__)) sdshdr64 { - uint64_t len; /* used */ - uint64_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; -}; -#endif - -#define SDS_TYPE_5 0 -#define SDS_TYPE_8 1 -#define SDS_TYPE_16 2 -#define SDS_TYPE_32 3 -#define SDS_TYPE_64 4 -#define SDS_TYPE_MASK 7 -#define SDS_TYPE_BITS 3 -#define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (void*)((s)-(sizeof(struct sdshdr##T))); -#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T)))) -#define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS) - -#ifdef _WIN32 -#define inline __inline -#endif - -static inline size_t sdslen(const sds s) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - return SDS_TYPE_5_LEN(flags); - case SDS_TYPE_8: - return SDS_HDR(8,s)->len; - case SDS_TYPE_16: - return SDS_HDR(16,s)->len; - case SDS_TYPE_32: - return SDS_HDR(32,s)->len; - case SDS_TYPE_64: - return SDS_HDR(64,s)->len; - } - return 0; -} - -static inline size_t sdsavail(const sds s) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: { - return 0; - } - case SDS_TYPE_8: { - SDS_HDR_VAR(8,s); - return sh->alloc - sh->len; - } - case SDS_TYPE_16: { - SDS_HDR_VAR(16,s); - return sh->alloc - sh->len; - } - case SDS_TYPE_32: { - SDS_HDR_VAR(32,s); - return sh->alloc - sh->len; - } - case SDS_TYPE_64: { - SDS_HDR_VAR(64,s); - return sh->alloc - sh->len; - } - } - return 0; -} - -static inline void sdssetlen(sds s, size_t newlen) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - { - unsigned char *fp = ((unsigned char*)s)-1; - *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS); - } - break; - case SDS_TYPE_8: - SDS_HDR(8,s)->len = newlen; - break; - case SDS_TYPE_16: - SDS_HDR(16,s)->len = newlen; - break; - case SDS_TYPE_32: - SDS_HDR(32,s)->len = newlen; - break; - case SDS_TYPE_64: - SDS_HDR(64,s)->len = newlen; - break; - } -} - -static inline void sdsinclen(sds s, size_t inc) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - { - unsigned char *fp = ((unsigned char*)s)-1; - unsigned char newlen = SDS_TYPE_5_LEN(flags)+inc; - *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS); - } - break; - case SDS_TYPE_8: - SDS_HDR(8,s)->len += inc; - break; - case SDS_TYPE_16: - SDS_HDR(16,s)->len += inc; - break; - case SDS_TYPE_32: - SDS_HDR(32,s)->len += inc; - break; - case SDS_TYPE_64: - SDS_HDR(64,s)->len += inc; - break; - } -} - -/* sdsalloc() = sdsavail() + sdslen() */ -static inline size_t sdsalloc(const sds s) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - return SDS_TYPE_5_LEN(flags); - case SDS_TYPE_8: - return SDS_HDR(8,s)->alloc; - case SDS_TYPE_16: - return SDS_HDR(16,s)->alloc; - case SDS_TYPE_32: - return SDS_HDR(32,s)->alloc; - case SDS_TYPE_64: - return SDS_HDR(64,s)->alloc; - } - return 0; -} - -static inline void sdssetalloc(sds s, size_t newlen) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - /* Nothing to do, this type has no total allocation info. */ - break; - case SDS_TYPE_8: - SDS_HDR(8,s)->alloc = newlen; - break; - case SDS_TYPE_16: - SDS_HDR(16,s)->alloc = newlen; - break; - case SDS_TYPE_32: - SDS_HDR(32,s)->alloc = newlen; - break; - case SDS_TYPE_64: - SDS_HDR(64,s)->alloc = newlen; - break; - } -} - -sds sdsnewlen(const void *init, size_t initlen); -sds sdsnew(const char *init); -sds sdsempty(void); -sds sdsdup(const sds s); -void sdsfree(sds s); -sds sdsgrowzero(sds s, size_t len); -sds sdscatlen(sds s, const void *t, size_t len); -sds sdscat(sds s, const char *t); -sds sdscatsds(sds s, const sds t); -sds sdscpylen(sds s, const char *t, size_t len); -sds sdscpy(sds s, const char *t); - -sds sdscatvprintf(sds s, const char *fmt, va_list ap); -#ifdef __GNUC__ -sds sdscatprintf(sds s, const char *fmt, ...) - __attribute__((format(printf, 2, 3))); -#else -sds sdscatprintf(sds s, const char *fmt, ...); -#endif - -sds sdscatfmt(sds s, char const *fmt, ...); -sds sdstrim(sds s, const char *cset); -void sdsrange(sds s, int start, int end); -void sdsupdatelen(sds s); -void sdsclear(sds s); -int sdscmp(const sds s1, const sds s2); -sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count); -void sdsfreesplitres(sds *tokens, int count); -void sdstolower(sds s); -void sdstoupper(sds s); -sds sdsfromlonglong(PORT_LONGLONG value); -sds sdscatrepr(sds s, const char *p, size_t len); -sds *sdssplitargs(const char *line, int *argc); -sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen); -sds sdsjoin(char **argv, int argc, char *sep); -sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen); - -/* Low level functions exposed to the user API */ -sds sdsMakeRoomFor(sds s, size_t addlen); -void sdsIncrLen(sds s, int incr); -sds sdsRemoveFreeSpace(sds s); -size_t sdsAllocSize(sds s); -void *sdsAllocPtr(sds s); - -/* Export the allocator used by SDS to the program using SDS. - * Sometimes the program SDS is linked to, may use a different set of - * allocators, but may want to allocate or free things that SDS will - * respectively free or allocate. */ -void *sds_malloc(size_t size); -void *sds_realloc(void *ptr, size_t size); -void sds_free(void *ptr); - -#ifdef REDIS_TEST -int sdsTest(int argc, char *argv[]); -#endif - -#endif diff --git a/include/hiredis/sdsalloc.h b/include/hiredis/sdsalloc.h deleted file mode 100644 index 531d419..0000000 --- a/include/hiredis/sdsalloc.h +++ /dev/null @@ -1,42 +0,0 @@ -/* SDSLib 2.0 -- A C dynamic strings library - * - * Copyright (c) 2006-2015, Salvatore Sanfilippo - * Copyright (c) 2015, Redis Labs, Inc - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* SDS allocator selection. - * - * This file is used in order to change the SDS allocator at compile time. - * Just define the following defines to what you want to use. Also add - * the include of your alternate allocator if needed (not needed in order - * to use the default libc allocator). */ - -#include "zmalloc.h" -#define s_malloc zmalloc -#define s_realloc zrealloc -#define s_free zfree diff --git a/include/hiredis/win32_hiredis.h b/include/hiredis/win32_hiredis.h deleted file mode 100644 index 556fe91..0000000 --- a/include/hiredis/win32_hiredis.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c), Microsoft Open Technologies, Inc. - * All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WIN32_HIREDIS_H -#define WIN32_HIREDIS_H - -#include "../../src/Win32_Interop/Win32_Portability.h" -#include "../../src/Win32_Interop/Win32_types_hiredis.h" -#include "../../src/Win32_Interop/Win32_Error.h" -#include "../../src/Win32_Interop/Win32_FDAPI.h" -#define INCL_WINSOCK_API_PROTOTYPES 0 // Important! Do not include Winsock API definitions to avoid conflicts with API entry points defined below. -#include // For SOCKADDR_STORAGE - -#include "hiredis.h" - -#define snprintf _snprintf -#ifndef va_copy -#define va_copy(d,s) d = (s) -#endif - -redisContext *redisPreConnectNonBlock(const char *ip, int port, SOCKADDR_STORAGE *sa); -int redisBufferReadDone(redisContext *c, char *buf, ssize_t nread); -int redisBufferWriteDone(redisContext *c, int nwritten, int *done); - -int redisContextPreConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout, SOCKADDR_STORAGE *ss); - -#endif diff --git a/include/hiredis/zmalloc.h b/include/hiredis/zmalloc.h deleted file mode 100644 index 99b87ac..0000000 --- a/include/hiredis/zmalloc.h +++ /dev/null @@ -1,13 +0,0 @@ -/* Drop in replacement for zmalloc.h in order to just use libc malloc without - * any wrappering. */ - -#ifndef ZMALLOC_H -#define ZMALLOC_H - -#define zmalloc malloc -#define zrealloc realloc -#define zcalloc(x) calloc(x,1) -#define zfree free -#define zstrdup strdup - -#endif diff --git a/lib/Win32/Debug/Win32_Interop.lib b/lib/Win32/Debug/Win32_Interop.lib index 0c30148..6c3ead1 100644 Binary files a/lib/Win32/Debug/Win32_Interop.lib and b/lib/Win32/Debug/Win32_Interop.lib differ diff --git a/lib/Win32/Debug/Win32_Interop.pdb b/lib/Win32/Debug/Win32_Interop.pdb index fbce33c..319873c 100644 Binary files a/lib/Win32/Debug/Win32_Interop.pdb and b/lib/Win32/Debug/Win32_Interop.pdb differ diff --git a/lib/Win32/Release/Win32_Interop.lib b/lib/Win32/Release/Win32_Interop.lib index b0472da..711ca6a 100644 Binary files a/lib/Win32/Release/Win32_Interop.lib and b/lib/Win32/Release/Win32_Interop.lib differ diff --git a/lib/Win32/Release/hiredis.lib b/lib/Win32/Release/hiredis.lib index a88a6b7..4834dbb 100644 Binary files a/lib/Win32/Release/hiredis.lib and b/lib/Win32/Release/hiredis.lib differ diff --git a/msvc12/sdk.vcxproj b/msvc12/sdk.vcxproj index 237f94d..51de403 100644 --- a/msvc12/sdk.vcxproj +++ b/msvc12/sdk.vcxproj @@ -110,7 +110,7 @@ {B3E797CF-4E77-4C9D-B8A8-7589B6902206} sdk Win32Proj - 10.0.17763.0 + 10.0.16299.0 @@ -246,7 +246,7 @@ DynamicLibrary MultiByte - true + false v141 @@ -522,7 +522,7 @@ $(ProjectDir)..\lib\Win32;$(LibraryPath) - D:\alliedmodders\sourcemod\sourcepawn\include;D:\alliedmodders\sourcemod\public\amtl;D:\alliedmodders\sourcemod\public\amtl\amtl;D:\alliedmodders\mmsource-1.10\core\sourcehook;D:\alliedmodders\sourcemod\public;$(ProjectDir)..\include;$(IncludePath) + E:\am\alliedmodders\sourcemod\sourcepawn\include;E:\am\alliedmodders\sourcemod\public\amtl;E:\am\alliedmodders\sourcemod\public\amtl\amtl;E:\am\alliedmodders\mmsource-1.10\core\sourcehook;E:\am\alliedmodders\sourcemod\public;$(ProjectDir)..\include;$(IncludePath) $(ProjectDir)..\lib\Win32\Release;$(LibraryPath) diff --git a/query.cpp b/query.cpp index 4b64ab8..e8343ad 100644 --- a/query.cpp +++ b/query.cpp @@ -86,7 +86,7 @@ void TQueryOp::RunThreadPart() if (!BindParamsAndRun()) { g_pSM->LogError(myself, "Failed Redis Query, Error: \"%s\" (Query id %i - serial %i)", - m_database->GetErrorStr(), + m_database->GetErrorString(), m_type, m_serial); } @@ -131,7 +131,7 @@ TQueryOp::TQueryOp(enum querytype type, Cookie *cookie) void TQueryOp::SetDatabase(void *db) { - m_database = (RedisDB *)db; + m_database = (async_redis::client *)db; } bool TQueryOp::BindParamsAndRun() @@ -142,53 +142,26 @@ bool TQueryOp::BindParamsAndRun() std::string safe_name = m_params.cookie->name; std::string safe_desc = m_params.cookie->description; - std::hash h; - int id = h(safe_name) & 0x7FFFFFFF; - assert(id > 0); - - auto rep = m_database->Run("GET %s", "cookies.id." + safe_name); // check if we have that cookie - if (rep.type == REDIS_REPLY_STRING) { - m_database->Execute("SADD cookies.list %s", safe_name.c_str()); - m_insertId = std::stoi(rep.str); - return true; - } - - std::string key_name = "cookies.access." + safe_name; - std::string key_desc = "cookies.desc." + safe_name; - std::string key_id = "cookies.id." + safe_name; - - if (m_database->CanAsync()) { - m_database->CommandAsync("SADD cookies.list %s", safe_name.c_str()); - m_database->CommandAsync("SET %s %d", key_name.c_str(), (int)m_params.cookie->access); // access - m_database->CommandAsync("SET %s %s", key_desc.c_str(), safe_desc.c_str()); // description - m_database->CommandAsync("SET %s %d", key_id.c_str(), id); // id - m_insertId = id; - return true; - } - - if (!m_database->Execute("SADD cookies.list %s", safe_name.c_str())) { - g_pSM->LogError(myself, "Cannot add \"%s\" to cookies.list", safe_name.c_str()); + // check if we have that cookie + { + auto reply = m_database->Command({ "GET", "cookies.id." + safe_name }).get(); + if (reply->IsString()) { + m_database->Append({ "SADD", "cookies.list", safe_name }); + m_insertId = std::stoi(reply->GetString()); + return true; + } } - m_database->Command("SET %s %d", key_name.c_str(), (int)m_params.cookie->access); // access - m_database->Command("SET %s %s", key_desc.c_str(), safe_desc.c_str()); // description - m_database->Command("SET %s %d", key_id.c_str(), id); // id - auto replies = m_database->GetReplies(3); - if (replies.size() != 3) { - g_pSM->LogError(myself, "Expect 3 replies but got %d", replies.size()); - } + std::hash h; + m_insertId = h(safe_name) & 0x7FFFFFFF; - bool bsucc = true; - for (const auto &reply : replies) { - if (reply.type != REDIS_REPLY_STATUS) { - g_pSM->LogError(myself, "Expect REDIS_REPLY_STATUS reply but got %d", reply.type); - } else if (reply.str != "OK") { - bsucc = false; - } - } + auto &client = *m_database; + client.Append({ "SADD", "cookies.list", safe_name }) + .Append({ "SET", "cookies.access." + safe_name, std::to_string((int)m_params.cookie->access) }) + .Append({ "SET", "cookies.desc." + safe_name, safe_desc }) + .Append({ "SET", "cookies.id." + safe_name, std::to_string(m_insertId) }); - m_insertId = id; - return bsucc; + return true; } case Query_SelectData: @@ -198,29 +171,29 @@ bool TQueryOp::BindParamsAndRun() auto luaquery = [&] { // Try to use cached Lua query first - auto cookies = m_database->Run("EVALSHA %s %d %s", GET_CLIENT_COOKIES_SHA, 1, steamId.c_str()); - if (cookies.type == REDIS_REPLY_ARRAY && cookies.reply_array.size() > 0) { - for (const auto &cookieData : cookies.reply_array) { - if (cookieData.type != REDIS_REPLY_ARRAY || cookieData.reply_array.size() != 4) { + auto cookies = m_database->Command({ "EVALSHA", GET_CLIENT_COOKIES_SHA, "1", steamId }).get(); + + if (cookies->IsArrays()) { + for (const auto &cookieData : cookies->GetArray()) { + if (cookieData.IsArrays() || cookieData.GetArray().size() != 4) { break; } - const auto &cookie = cookieData.reply_array; + const auto &cookie = cookieData.GetArray(); CookieAccess acce; try { - acce = (CookieAccess)std::stoi(cookie[CookieAcce].str); + acce = (CookieAccess)std::stoi(cookie[CookieAcce].GetString()); } catch (const std::exception&) { acce = CookieAccess_Public; } m_results.push_back({ Cookie( - cookie[CookieName].str.data(), - cookie[CookieDesc].str.data(), + cookie[CookieName].GetString().c_str(), + cookie[CookieDesc].GetString().c_str(), acce - ), - cookie[CookieValue].str.data() + ), cookie[CookieValue].GetString().c_str() }); } } @@ -230,38 +203,44 @@ bool TQueryOp::BindParamsAndRun() return true; } - // Use normal and slow method - auto keys = m_database->Run("KEYS cookies.id.*"); - for (const auto &item : keys.reply_array) { - std::string cookieName = item.str.substr(11); + // Use normal and slow method, if you have too many cookies (>= 10M), you should use the lua method + auto keys = m_database->Command({ "KEYS", "cookies.id.*" }).get(); + for (const auto &item : keys->GetArray()) { + std::string cookieName = item.GetString().substr(11); - auto cookie_id = m_database->Run("GET %s", item.str.c_str()); - if (cookie_id.type != REDIS_REPLY_STRING) { - g_pSM->LogError(myself, "Expect %s to be REDIS_REPLY_STRING but got %d", item.str.c_str(), cookie_id.type); + auto cookie_id = m_database->Command({ "GET", item.GetString() }).get(); + if (!cookie_id->IsString()) { + g_pSM->LogError(myself, "Expect %s to be REDIS_REPLY_STRING but got %d", item.GetString().c_str(), cookie_id->Type()); + continue; } - std::string key_name = steamId + "." + cookie_id.str; + std::string key_name = steamId + "." + cookie_id->GetString(); std::string key_desc = "cookies.desc." + cookieName; std::string key_id = "cookies.access." + cookieName; - auto value = m_database->Run("GET %s", key_name.c_str()); - auto desc = m_database->Run("GET %s", key_desc.c_str()); - auto access = m_database->Run("GET %s", key_id.c_str()); + auto _value = m_database->Command({ "GET", key_name }, false); + auto _desc = m_database->Command({ "GET", key_desc }, false); + auto _access = m_database->Command({ "GET", key_id }, false); + m_database->Commit(); + + auto value = _value.get(); + auto desc = _desc.get(); + auto access = _access.get(); - if (value.type == REDIS_REPLY_STRING) { + if (value->IsString()) { CookieAccess acce; try { - acce = (CookieAccess)std::stoi(access.str); + acce = (CookieAccess)std::stoi(access->GetString()); } catch (const std::exception&) { acce = CookieAccess_Public; } m_results.push_back({ Cookie( - cookieName.data(), - desc.str.data(), + cookieName.c_str(), + desc->GetString().c_str(), acce - ), value.str + ), value->GetString() }); } } @@ -277,10 +256,8 @@ bool TQueryOp::BindParamsAndRun() int cookieId = m_params.cookieId; safe_id = safe_id + "." + std::to_string(cookieId); - if (m_database->CanAsync()) { - return m_database->CommandAsync("SET %s %s EX %d", safe_id.c_str(), safe_val.c_str(), 14 * 24 * 3600); // Set this key expire in 2 weeks - } - return m_database->Execute("SET %s %s EX %d", safe_id.c_str(), safe_val.c_str(), 14 * 24 * 3600); // Set this key expire in 2 weeks + m_database->Append({ "SET", safe_id, safe_val, "EX", "1209600" }); // Set this key expire in 2 weeks + return true; } case Query_SelectId: @@ -290,12 +267,12 @@ bool TQueryOp::BindParamsAndRun() std::hash h; int id = h(safe_name) & 0x7FFFFFFF; - auto rep = m_database->Run("GET %s", ("cookies.id." + safe_name).c_str()); - if (rep.type != REDIS_REPLY_STRING) { + auto rep = m_database->Command({ "GET", "cookies.id." + safe_name }).get(); + if (rep->IsString()) { return false; } - m_insertId = std::stoi(rep.str); + m_insertId = std::stoi(rep->GetString()); if (id != m_insertId) { g_pSM->LogError(myself, "Cookies ID does not match %d vs %d", id, m_insertId); } diff --git a/query.h b/query.h index bd98fb3..9187144 100644 --- a/query.h +++ b/query.h @@ -116,7 +116,7 @@ class TQueryOp : public IThreadQuery /* Params to be bound */ ParamData m_params; - inline RedisDB *GetDB() + inline async_redis::client *GetDB() { return m_database; } @@ -126,7 +126,7 @@ class TQueryOp : public IThreadQuery int PullQuerySerial(); private: - RedisDB *m_database; + async_redis::client *m_database; // IDBDriver *m_driver; // IQuery *m_pResult; std::vector> m_results; diff --git a/reply.cpp b/reply.cpp new file mode 100644 index 0000000..07ee041 --- /dev/null +++ b/reply.cpp @@ -0,0 +1,102 @@ +#include "reply.h" + +#include + +#include + +namespace async_redis +{ +reply::reply(void *raw_reply) +{ + reply_type = type::invalid; + if (raw_reply == nullptr) { + return; + } + + redisReply *r = (redisReply *)raw_reply; + reply_type = (type)r->type; + + int_val = r->integer; + + if (r->len && r->str) { + str_val = std::string(r->str); + } + + if (reply_type == type::arrays && r->elements && r->element) { + for (size_t i = 0; i < r->elements; ++i) { + rows.emplace_back(r->element[i]); + } + } +} + +//reply::reply(reply &&other) noexcept +//{ +// reply_type = other.reply_type; +// rows = std::move(other.rows); +// str_val = std::move(other.str_val); +// int_val = other.int_val; +//} +// +//reply &reply::operator=(reply &&other) noexcept +//{ +// if (this != &other) { +// reply_type = other.reply_type; +// rows = std::move(other.rows); +// str_val = std::move(other.str_val); +// int_val = other.int_val; +// } +// return *this; +//} + +reply::operator bool() const +{ + return reply_type == type::invalid; +} + +reply::type reply::Type() const +{ + return reply_type; +} + +bool reply::Ok() const +{ + return reply_type != type::invalid && reply_type != type::error; +} + +const char *reply::Status() const +{ + if (reply_type == type::invalid) { + return "reply is invalid"; + } + + if (reply_type == type::status || reply_type == type::error) { + return str_val.c_str(); + } + + return nullptr; +} + +const std::vector &reply::GetArray() const +{ + if (reply_type != type::arrays) { + throw std::invalid_argument("Redis reply type does not match"); + } + return rows; +} + +int64_t reply::GetInt() const +{ + if (reply_type != type::integer) { + throw std::invalid_argument("Redis reply type does not match"); + } + return int_val; +} + +const std::string &reply::GetString() const +{ + if (reply_type != type::string) { + throw std::invalid_argument("Redis reply type does not match"); + } + return str_val; +} +} diff --git a/reply.h b/reply.h new file mode 100644 index 0000000..1c8a1b3 --- /dev/null +++ b/reply.h @@ -0,0 +1,82 @@ +#pragma once + +#include +#include + +namespace async_redis +{ +class reply +{ +public: + enum type + { + invalid, + string, + arrays, + integer, + nil, + status, + error, + }; + + reply(void *raw_reply); + + //reply(reply &&other) noexcept; + //reply &operator=(reply &&other) noexcept; + + operator bool() const; + + ~reply() = default; + + type Type() const; + + bool Ok() const; + const char * Status() const; + + const std::vector &GetArray() const; + int64_t GetInt() const; + const std::string &GetString() const; + + bool IsVaild() const + { + return reply_type != type::invalid; + } + + bool IsString() const + { + return reply_type == type::string; + } + + bool IsArrays() const + { + return reply_type == type::arrays; + } + + bool IsInt() const + { + return reply_type == type::integer; + } + + bool IsNIL() const + { + return reply_type == type::nil; + } + + bool IsStatus() const + { + return reply_type == type::status; + } + + bool IsError() const + { + return reply_type == type::error; + } + +private: + type reply_type; + + std::vector rows; + std::string str_val; + int64_t int_val; +}; +} diff --git a/version.aps b/version.aps deleted file mode 100644 index 4e6765c..0000000 Binary files a/version.aps and /dev/null differ