Commit 7eca5297 authored by Greg Williams's avatar Greg Williams
Browse files

Refactored internals to support overlapped IO. Still need to update client API...

Refactored internals to support overlapped IO. Still need to update client API layer in order to bring back to life.
parent 328be836
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -10,7 +10,7 @@ PUB_INC = ./include
#===============================================================================
CC ?= gcc
OPTIMIZE = -O3
WARN = -Wall -Wextra -pedantic
WARN = -Wall -Wextra -Wstrict-prototypes -Wcast-align -pedantic
CDEFS += -D_POSIX_C_SOURCE=1 -D_C99_SOURCE=1
CFLAGS += -std=c99 -fPIC -g $(WARN) $(CDEFS) $(OPTIMIZE)
LDFLAGS += -lm -l crypto -l ssl -l pthread
+5 −1
Original line number Diff line number Diff line
@@ -88,6 +88,8 @@
      - -g
      - -Wall
      - -Wextra
      - -Wstrict-prototypes
      - -Wcast-align
      - -pedantic
      - -D_POSIX_C_SOURCE=1
      - -D_C99_SOURCE=1
@@ -103,7 +105,9 @@
      - -g
      - -Wall
      - -Wextra
      - -pedantic
      # - -pedantic
      - -Wstrict-prototypes
      # - -Wcast-align
      - -D_POSIX_C_SOURCE=1
      - -D_C99_SOURCE=1
      - -Wno-nonnull
+10 −1
Original line number Diff line number Diff line
@@ -157,7 +157,16 @@ typedef enum {

const char* Kinetic_GetStatusDescription(KineticStatus status);

typedef void (*KineticCompletionCallback)(KineticStatus status);
typedef struct _KineticCompletionData {
    KineticStatus status;
} KineticCompletionData;

typedef void (*KineticCompletionCallback)(KineticCompletionData* kinetic_data, void* client_data);

typedef struct _KineticCompletionClosure {
    KineticCompletionCallback callback;
    void* clientData;
} KineticCompletionClosure;

// KineticEntry - byte arrays need to be preallocated by the client
typedef struct _KineticEntry {
+189 −84
Original line number Diff line number Diff line
@@ -23,26 +23,59 @@
#include <stdlib.h>
#include <pthread.h>

static inline void KineticAllocator_LockList(KineticList* const list)

//==============================================================================
// Generic List Support (INTERNAL)
//==============================================================================

#define KINETIC_LIST_LOCK(_list) { \
    /*LOG_LOCATION; LOGF3("Locking list! (list_addr=0x%llX)", (_list));*/ \
    assert(!((_list)->locked)); \
    pthread_mutex_lock(&((_list)->mutex)); \
    ((_list)->locked) = true; \
}

#define KINETIC_LIST_UNLOCK(_list) { \
    /*LOG_LOCATION; LOGF3("Unlocking list! (list_addr=0x%llX)", (_list));*/ \
    assert(((_list)->locked)); \
    pthread_mutex_unlock(&((_list)->mutex)); \
    ((_list)->locked) = false; \
}

void KineticAllocator_InitLists(KineticConnection* connection)
{
    assert(!list->locked);
    pthread_mutex_lock(&list->mutex);
    list->locked = true;
    assert(connection != NULL);
    connection->pdus = KINETIC_LIST_INITIALIZER;
    connection->operations = KINETIC_LIST_INITIALIZER;
}

static inline void KineticAllocator_UnlockList(KineticList* const list)
static void* KineticAllocator_GetFirstListItem(KineticList* list)
{
    // assert(list->locked);
    pthread_mutex_unlock(&list->mutex);
    list->locked = false;
    assert(list != NULL);
    if (list->start == NULL) {
        return NULL;
    }
    return list->start->data;
}

void KineticAllocator_InitList(KineticList* const list)
static void* KineticAllocator_GetNextListItem(KineticList* list, void* item_data)
{
    *list = (KineticList) {
        .mutex = PTHREAD_MUTEX_INITIALIZER,
        .locked = false,
    };
    assert(list != NULL);
    void* nextData = NULL;
    KINETIC_LIST_LOCK(list);
    KineticListItem* current = list->start;
    while (current != NULL) {
        void* currData = current->data;
        if (currData == item_data) {
            if (current->next != NULL) {
                nextData = current->next->data;
            }
            break;
        }
        current = current->next;
    }
    KINETIC_LIST_UNLOCK(list);
    return nextData;
}

static void* KineticAllocator_NewItem(KineticList* const list, size_t size)
@@ -61,7 +94,7 @@ static void* KineticAllocator_NewItem(KineticList* const list, size_t size)
    memset(newItem->data, 0, size);

    // Add the new item to the list
    KineticAllocator_LockList(list);
    KINETIC_LIST_LOCK(list);
    if (list->start == NULL) {
        list->start = newItem;
    }
@@ -70,9 +103,9 @@ static void* KineticAllocator_NewItem(KineticList* const list, size_t size)
        list->last->next = newItem;
    }
    list->last = newItem;
    KineticAllocator_UnlockList(list);
    KINETIC_LIST_UNLOCK(list);

    LOGF3("Allocated new list item @ 0x%0llX w/data @ 0x%0llX",
    LOGF3("  Allocated new list item (0x%0llX) w/data (0x%0llX)",
         (long long)newItem, (long long)newItem->data);

    return newItem->data;
@@ -80,12 +113,12 @@ static void* KineticAllocator_NewItem(KineticList* const list, size_t size)

static void KineticAllocator_FreeItem(KineticList* const list, void* item)
{
    KineticAllocator_LockList(list);
    KINETIC_LIST_LOCK(list);
    KineticListItem* cur = list->start;
    while (cur->data != item) {
        if (cur->next == NULL) {
            LOG1("  Reached end of list before finding item to free!");
            KineticAllocator_UnlockList(list);
            KINETIC_LIST_UNLOCK(list);
            return;
        }
        else {
@@ -117,13 +150,13 @@ static void KineticAllocator_FreeItem(KineticList* const list, void* item)
            if (cur->previous->next != NULL) {
                LOG3("  Relinking previous to next");
                if (cur->next != NULL) {
                    LOG3("    next being reset!");
                    LOG3("    Next being reset!");
                    cur->previous->next = cur->next;
                }
                else {
                    list->last = cur->previous;
                    list->last->next = NULL;
                    LOGF3("    next is NULL. End of list now @ 0x%0llX",
                    LOGF3("    Next is NULL. End of list now @ 0x%0llX",
                         (long long)list->last);
                }
            }
@@ -133,21 +166,20 @@ static void KineticAllocator_FreeItem(KineticList* const list, void* item)
            }
        }

        LOGF3("  Freeing item @ 0x%0llX, item @ 0x%0llX",
             (long long)cur, (long long)&cur->data);
        LOGF3("  Freeing item (0x%0llX) w/data (0x%0llX)", cur, &cur->data);
        free(cur->data);
        cur->data = NULL;
        free(cur);
        cur = NULL;
    }
    KineticAllocator_UnlockList(list);
    KINETIC_LIST_UNLOCK(list);
}

static void KineticAllocator_FreeList(KineticList* const list)
{
    if (list != NULL) {
        LOG3("Freeing list of all items");
        KineticAllocator_LockList(list);
        LOGF3("  Freeing list (0x%0llX) of all items...", list);
        KINETIC_LIST_LOCK(list);
        KineticListItem* current = list->start;

        while (current->next != NULL) {
@@ -156,119 +188,192 @@ static void KineticAllocator_FreeList(KineticList* const list)
        }

        while (current != NULL) {
            LOG2("  Current item not freed!");
            LOGF3("  DEALLOCATING item: 0x%0llX, data: 0x%llX, prev: 0x%0llX",
                (long long)current,
                (long long)&current->data,
                (long long)current->previous);
            KineticListItem* curItem = current;
            KineticListItem* prevItem = current->previous;
            if (curItem != NULL) {
                LOG3("  Freeing list item");
                LOGF3("  Freeing list item (0x%0llX) w/ data (0x%llX)",
                    (long long)current,
                    (long long)&current->data,
                    (long long)current->previous);
                if (curItem->data != NULL) {
                    free(curItem->data);
                }
                free(curItem);
            }
            current = prevItem;
            LOGF3("  on to prev=0x%llX", (long long)current);
            LOGF3("  on to previous list item (0x%llX)...", current);
        }

        *list = (KineticList) {
            .start = NULL, .last = NULL
        };

        KineticAllocator_UnlockList(list);
        // Make list empty, but leave mutex alone so the state is retained!
        list->start = NULL;
        list->last = NULL;
        KINETIC_LIST_UNLOCK(list);
    }
    else {
        LOG1("  Nothing to free!");
        LOGF3("  Nothing to free from list (0x%0llX)", list);
    }

}

KineticPDU* KineticAllocator_NewPDU(KineticList* const list, KineticConnection* connection)

//==============================================================================
// PDU List Support
//==============================================================================

KineticPDU* KineticAllocator_NewPDU(KineticConnection* connection)
{
    assert(connection != NULL);
    LOGF3("Allocating new PDU on connection (0x%0llX)", connection);
    KineticPDU* newPDU = (KineticPDU*)KineticAllocator_NewItem(
                             list, sizeof(KineticPDU));
                             &connection->pdus, sizeof(KineticPDU));
    if (newPDU == NULL) {
        LOG0("Failed allocating new PDU!");
        return NULL;
    }
    assert(newPDU->proto == NULL);
    KINETIC_PDU_INIT(newPDU, connection);
    LOGF3("Allocated new PDU @ 0x%0llX", (long long)newPDU);
    LOGF3("Allocated new PDU (0x%0llX) on connection", newPDU, connection);
    return newPDU;
}

void KineticAllocator_FreePDU(KineticList* const list, KineticPDU* pdu)
void KineticAllocator_FreePDU(KineticConnection* connection, KineticPDU* pdu)
{
    KineticAllocator_LockList(list);
    LOGF3("Freeing PDU (0x%0llX) on connection (0x%0llX)", pdu, connection);
    KINETIC_LIST_LOCK(&connection->pdus);
    if ((pdu->proto != NULL) && pdu->protobufDynamicallyExtracted) {
        LOG3("Freeing dynamically allocated protobuf");
        KineticProto_Message__free_unpacked(pdu->proto, NULL);
    };
    KineticAllocator_UnlockList(list);
    KineticAllocator_FreeItem(list, (void*)pdu);
    KINETIC_LIST_UNLOCK(&connection->pdus);
    KineticAllocator_FreeItem(&connection->pdus, (void*)pdu);
    LOGF3("Freed PDU (0x%0llX) on connection (0x%0llX)", pdu, connection);
}

KineticPDU* KineticAllocator_GetFirstPDU(KineticList* const list)
KineticPDU* KineticAllocator_GetFirstPDU(KineticConnection* connection)
{
    assert(list != NULL);
    if (list->start == NULL) {
        return NULL;
    }
    return (KineticPDU*)list->start->data;
    assert(connection != NULL);
    return (KineticPDU*)KineticAllocator_GetFirstListItem(&connection->pdus);
}

KineticPDU* KineticAllocator_GetNextPDU(KineticList* const list, KineticPDU* pdu)
KineticPDU* KineticAllocator_GetNextPDU(KineticConnection* connection, KineticPDU* pdu)
{
    assert(list != NULL);
    KineticPDU* next = NULL;
    assert(connection != NULL);
    return (KineticPDU*)KineticAllocator_GetNextListItem(&connection->pdus, pdu);
}

    KineticAllocator_LockList(list);
    KineticListItem* current = list->start;
void KineticAllocator_FreeAllPDUs(KineticConnection* connection)
{
    assert(connection != NULL);
    if (connection->pdus.start != NULL) {
        LOG3("Freeing all PDUs...");
        KINETIC_LIST_LOCK(&connection->pdus);
        KineticListItem* current = connection->pdus.start;
        while (current != NULL) {
        KineticPDU* currPDU = (KineticPDU*)current->data;
        if (currPDU == pdu) {
            if (current->next != NULL) {
                next = (KineticPDU*)current->next->data;
            }
            break;
            KineticPDU* pdu = (KineticPDU*)current->data;
            if (pdu != NULL && pdu->proto != NULL
                && pdu->protobufDynamicallyExtracted) {
                KineticProto_Message__free_unpacked(pdu->proto, NULL);
            }
            current = current->next;
        }
    KineticAllocator_UnlockList(list);
        KINETIC_LIST_UNLOCK(&connection->pdus);
        KineticAllocator_FreeList(&connection->pdus);
    }
    else {
        LOG1("  Nothing to free!");
    }
}

    return next;

//==============================================================================
// Operation List Support
//==============================================================================

KineticOperation* KineticAllocator_NewOperation(KineticConnection* const connection)
{
    assert(connection != NULL);
    LOGF3("Allocating new operation on connection (0x%0llX)", connection);
    KineticOperation* newOperation =
        (KineticOperation*)KineticAllocator_NewItem(&connection->operations, sizeof(KineticOperation));
    if (newOperation == NULL) {
        LOGF0("Failed allocating new operation on connection (0x%0llX)!", connection);
        return NULL;
    }
    KINETIC_OPERATION_INIT(newOperation, connection);
    newOperation->request = KineticAllocator_NewPDU(connection);
    KINETIC_PDU_INIT_WITH_COMMAND(newOperation->request, connection);
    LOGF3("Allocated new operation (0x%0llX) on connection (0x%0llX)", newOperation, connection);
    return newOperation;
}

void KineticAllocator_FreeAllPDUs(KineticList* const list)
void KineticAllocator_FreeOperation(KineticConnection* const connection, KineticOperation* operation)
{
    if (list->start != NULL) {
        LOG3("Freeing all PDUs...");
        KineticAllocator_LockList(list);
        KineticListItem* current = list->start;
    assert(connection != NULL);
    assert(operation != NULL);
    LOGF3("Freeing operation (0x%0llX) on connection (0x%0llX)", operation, connection);
    if (operation->request != NULL) {
        LOGF3("Freeing request PDU (0x%0llX) from operation (0x%0llX) on connection (0x%0llX)",
            operation->request, operation, connection);
        KineticAllocator_FreePDU(connection, operation->request);
    }
    if (operation->response != NULL) {
        LOGF3("Freeing response PDU (0x%0llX) from operation (0x%0llX) on connection (0x%0llX)",
            operation->response, operation, connection);
        KineticAllocator_FreePDU(connection, operation->response);
    }
    KineticAllocator_FreeItem(&connection->operations, (void*)operation);
    LOGF3("Freed operation (0x%0llX) on connection (0x%0llX)", operation, connection);
}

KineticOperation* KineticAllocator_GetFirstOperation(KineticConnection* const connection)
{
    assert(connection != NULL);
    return (KineticOperation*)KineticAllocator_GetFirstListItem(&connection->operations);
}

KineticOperation* KineticAllocator_GetNextOperation(KineticConnection* const connection, KineticOperation* operation)
{
    assert(connection != NULL);
    return (KineticOperation*)KineticAllocator_GetNextListItem(&connection->operations, operation);
}

void KineticAllocator_FreeAllOperations(KineticConnection* const connection)
{
    assert(connection != NULL);
    if (connection->operations.start != NULL) {
        LOGF3("Freeing all operations in list (0x%0llX) from connection (0x%0llX)...",
            &connection->operations, connection);
        KINETIC_LIST_LOCK(&connection->operations);
        KineticListItem* current = connection->operations.start;
        while (current != NULL) {
            KineticPDU* pdu = (KineticPDU*)current->data;
            if (pdu != NULL && pdu->proto != NULL
                && pdu->protobufDynamicallyExtracted) {
                KineticProto_Message__free_unpacked(pdu->proto, NULL);
            KineticOperation* operation = (KineticOperation*)current->data;
            if (operation->request != NULL) {
                KineticAllocator_FreePDU(connection, operation->request);
            }
            if (operation->response != NULL) {
                KineticAllocator_FreePDU(connection, operation->response);
            }
            current = current->next;
        }
        KineticAllocator_UnlockList(list);
        KineticAllocator_FreeList(list);
        KINETIC_LIST_UNLOCK(&connection->operations);
        KineticAllocator_FreeList(&connection->operations);
    }
    else {
        LOG1("  Nothing to free!");
    }
}

bool KineticAllocator_ValidateAllMemoryFreed(KineticList* const list)

bool KineticAllocator_ValidateAllMemoryFreed(KineticConnection* const connection)
{
    bool empty = (list->start == NULL);
    LOGF3("  PDUList: 0x%0llX, empty=%s",
        (long long)list->start, empty ? "true" : "false");
    assert(connection != NULL);
    LOGF3("Checking to see if all memory has been freed from connection (0x%0llX)...",
        connection);
    bool empty = true;
    LOGF3("  Operations: 0x%0llX, empty=%s",connection->operations.start,
        BOOL_TO_STRING(connection->operations.start == NULL));
    if (connection->operations.start != NULL) {empty = false;}
    LOGF3("  PDUs: 0x%0llX, empty=%s", connection->pdus.start,
        BOOL_TO_STRING(connection->pdus.start == NULL));
    if (connection->pdus.start != NULL) {empty = false;}
    return empty;
}
+15 −7
Original line number Diff line number Diff line
@@ -23,12 +23,20 @@

#include "kinetic_types_internal.h"

void KineticAllocator_InitList(KineticList* const list);
KineticPDU* KineticAllocator_NewPDU(KineticList* const list, KineticConnection* connection);
void KineticAllocator_FreePDU(KineticList* const list, KineticPDU* pdu);
KineticPDU* KineticAllocator_GetFirstPDU(KineticList* const list);
KineticPDU* KineticAllocator_GetNextPDU(KineticList* const list, KineticPDU* pdu);
void KineticAllocator_FreeAllPDUs(KineticList* const list);
bool KineticAllocator_ValidateAllMemoryFreed(KineticList* const list);
void KineticAllocator_InitLists(KineticConnection* connection);

KineticPDU* KineticAllocator_NewPDU(KineticConnection* connection);
void KineticAllocator_FreePDU(KineticConnection* connection, KineticPDU* pdu);
KineticPDU* KineticAllocator_GetFirstPDU(KineticConnection* connection);
KineticPDU* KineticAllocator_GetNextPDU(KineticConnection* connection, KineticPDU* pdu);
void KineticAllocator_FreeAllPDUs(KineticConnection* connection);

KineticOperation* KineticAllocator_NewOperation(KineticConnection* connection);
void KineticAllocator_FreeOperation(KineticConnection* connection, KineticOperation* operation);
KineticOperation* KineticAllocator_GetFirstOperation(KineticConnection* connection);
KineticOperation* KineticAllocator_GetNextOperation(KineticConnection* connection, KineticOperation* operation);
void KineticAllocator_FreeAllOperations(KineticConnection* connection);

bool KineticAllocator_ValidateAllMemoryFreed(KineticConnection* connection);

#endif // _KINETIC_ALLOCATOR
Loading