Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3c1e29a7 authored by Jakub Pawlowski's avatar Jakub Pawlowski
Browse files

Get rid of counter

This patch removes counter. We were never using those values,
except for increasing them.

Bug: 27324326
Change-Id: I3122a36fa0435a36a8401792267cb5ebff5ab269
parent 1465ac4c
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ LOCAL_PATH := $(call my-dir)
# ========================================================
btcoreCommonSrc := \
    src/bdaddr.c \
    src/counter.c \
    src/device_class.c \
    src/hal_util.c \
    src/module.c \
@@ -32,7 +31,6 @@ btcoreCommonSrc := \

btcoreCommonTestSrc := \
    ./test/bdaddr_test.cpp \
    ./test/counter_test.cpp \
    ./test/device_class_test.cpp \
    ./test/property_test.cpp \
    ./test/uuid_test.cpp \
+0 −2
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
static_library("btcore") {
  sources = [
    "src/bdaddr.c",
    "src/counter.c",
    "src/device_class.c",
    "src/hal_util.c",
    "src/module.c",
@@ -35,7 +34,6 @@ executable("net_test_btcore") {
  testonly = true
  sources = [
    "test/bdaddr_test.cpp",
    "test/counter_test.cpp",
    "test/device_class_test.cpp",
    "test/property_test.cpp",
    "test/uuid_test.cpp",

system/btcore/include/counter.h

deleted100644 → 0
+0 −36
Original line number Diff line number Diff line
/******************************************************************************
 *
 *  Copyright (C) 2014 Google, Inc.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at:
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 ******************************************************************************/

#pragma once

#include <stdbool.h>
#include <stdint.h>

static const char COUNTER_MODULE[] = "counter_module";

typedef int64_t counter_data_t;

// Used to iterate across all counters.
typedef bool (*counter_iter_cb)(const char *name, counter_data_t val, void *context);

// Mutators.
void counter_set(const char *name, counter_data_t val);
void counter_add(const char *name, counter_data_t val);

// Iteration.
bool counter_foreach(counter_iter_cb, void *context);

system/btcore/src/counter.c

deleted100644 → 0
+0 −420
Original line number Diff line number Diff line
/******************************************************************************
 *
 *  Copyright (C) 2014 Google, Inc.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at:
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 ******************************************************************************/

#define LOG_TAG "bt_core_counter"

#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdarg.h>
#include <stdatomic.h>
#include <string.h>
#include <sys/eventfd.h>

#include "btcore/include/counter.h"
#include "btcore/include/module.h"
#include "osi/include/allocator.h"
#include "osi/include/hash_functions.h"
#include "osi/include/hash_map.h"
#include "osi/include/list.h"
#include "osi/include/log.h"
#include "osi/include/osi.h"
#include "osi/include/socket.h"
#include "osi/include/thread.h"

typedef int (*handler_t)(socket_t * socket);

typedef struct counter_t {
  _Atomic(int64_t) val;
} counter_t;

typedef struct hash_element_t {
  const char *key;
  counter_t *val;
} hash_element_t;

typedef struct counter_data_cb_t {
  counter_iter_cb counter_iter_cb;
  void *user_context;
} counter_data_cb_t;

typedef struct {
  socket_t *socket;
  uint8_t buffer[256];
  size_t buffer_size;
} client_t;

typedef struct {
  const char *name;
  const char *help;
  handler_t handler;
} command_t;

// Counter core
static hash_map_t *hash_map_counter_;
static pthread_mutex_t hash_map_lock_;
static int counter_cnt_;

// Counter port access
static socket_t *listen_socket_;
static thread_t *thread_;
static list_t *clients_;

static void accept_ready(socket_t *socket, void *context);
static void read_ready(socket_t *socket, void *context);
static void client_free(void *ptr);
static const command_t *find_command(const char *name);
static void output(socket_t *socket, const char* format, ...);

// Commands
static int help(socket_t *socket);
static int show(socket_t *socket);
static int set(socket_t *socket);
static int quit(socket_t *socket);

static const command_t commands[] = {
  { "help", "<command> - show help text for <command>", help},
  { "quit", "<command> - Quit and exit", quit},
  { "set", "<counter> - Set something", set},
  { "show", "<counter> - Show counters", show},
};

static counter_t *counter_new_(counter_data_t initial_val);
static void counter_free_(counter_t *counter);

static hash_element_t *hash_element_new_(void);
// NOTE: The parameter datatype is void in order to satisfy the hash
// data free function signature
static void hash_element_free_(void *data);

static struct counter_t *name_to_counter_(const char *name);
static bool counter_foreach_cb_(hash_map_entry_t *hash_map_entry, void *context);

static bool counter_socket_open(void);
static void counter_socket_close(void);

static const int COUNTER_NUM_BUCKETS = 53;

// TODO(cmanton) Friendly interface, but may remove for automation
const char *WELCOME = "Welcome to counters\n";
const char *PROMPT = "\n> ";
const char *GOODBYE = "Quitting... Bye !!";

// TODO(cmanton) Develop port strategy; or multiplex all bt across single port
static const port_t LISTEN_PORT = 8879;

static future_t *counter_init(void) {
  assert(hash_map_counter_ == NULL);
  pthread_mutex_init(&hash_map_lock_, NULL);
  hash_map_counter_ = hash_map_new(COUNTER_NUM_BUCKETS, hash_function_string,
      NULL, hash_element_free_, NULL);
  if (hash_map_counter_ == NULL) {
    LOG_ERROR(LOG_TAG, "%s unable to allocate resources", __func__);
    return future_new_immediate(FUTURE_FAIL);
  }

  if (!counter_socket_open()) {
    LOG_ERROR(LOG_TAG, "%s unable to open counter port", __func__);
    return future_new_immediate(FUTURE_FAIL);
  }
  return future_new_immediate(FUTURE_SUCCESS);
}

static future_t *counter_clean_up(void) {
  counter_socket_close();
  hash_map_free(hash_map_counter_);
  pthread_mutex_destroy(&hash_map_lock_);
  hash_map_counter_ = NULL;
  return future_new_immediate(FUTURE_SUCCESS);
}

EXPORT_SYMBOL module_t counter_module = {
  .name = COUNTER_MODULE,
  .init = counter_init,
  .start_up = NULL,
  .shut_down = NULL,
  .clean_up = counter_clean_up,
  .dependencies = {NULL},
};

void counter_set(const char *name, counter_data_t val) {
  assert(name != NULL);
  counter_t *counter = name_to_counter_(name);
  if (counter)
    atomic_store(&counter->val, val);
}

void counter_add(const char *name, counter_data_t val) {
  assert(name != NULL);
  counter_t *counter = name_to_counter_(name);
  if (counter) {
    atomic_fetch_add(&counter->val, val);
  }
}

bool counter_foreach(counter_iter_cb cb, void *context) {
  assert(cb != NULL);
  counter_data_cb_t counter_cb_data = {
    cb,
    context
  };

  hash_map_foreach(hash_map_counter_, counter_foreach_cb_, &counter_cb_data);
  return true;
}

static counter_t *counter_new_(counter_data_t initial_val) {
  counter_t *counter = (counter_t *)osi_calloc(sizeof(counter_t));

  atomic_store(&counter->val, initial_val);
  return counter;
}

static void counter_free_(counter_t *counter) {
  osi_free(counter);
}

static hash_element_t *hash_element_new_(void) {
  return (hash_element_t *)osi_calloc(sizeof(hash_element_t));
}

static void hash_element_free_(void *data) {
  hash_element_t *hash_element = (hash_element_t *)data;
  // We don't own the key
  counter_free_(hash_element->val);
  osi_free(hash_element);
}

// Returns a counter from the |hash_map_counter_|.  Creates
// a new one if not found and inserts into |hash_map_counter_|.
// Returns NULL upon memory allocation failure.
static counter_t *name_to_counter_(const char *name) {
  assert(hash_map_counter_ != NULL);
  if (hash_map_has_key(hash_map_counter_, name))
    return (counter_t *)hash_map_get(hash_map_counter_, name);

  pthread_mutex_lock(&hash_map_lock_);
  // On the uncommon path double check to make sure that another thread has
  // not already created this counter
  counter_t *counter = (counter_t *)hash_map_get(hash_map_counter_, name);
  if (counter)
    goto exit;

  counter = counter_new_(0);
  if (!counter) {
    LOG_ERROR(LOG_TAG, "%s unable to create new counter name:%s", __func__, name);
    goto exit;
  }

  hash_element_t *element = hash_element_new_();
  if (!element) {
    LOG_ERROR(LOG_TAG, "%s unable to create counter element name:%s", __func__, name);
    counter_free_(counter);
    counter = NULL;
    goto exit;
  }

  element->key = name;
  element->val = counter;
  if (!hash_map_set(hash_map_counter_, name, counter)) {
    LOG_ERROR(LOG_TAG, "%s unable to set new counter into hash map name:%s", __func__, name);
    hash_element_free_(element);
    counter_free_(counter);
    counter = NULL;
  }

 exit:;
  pthread_mutex_unlock(&hash_map_lock_);
  return counter;
}

static bool counter_foreach_cb_(hash_map_entry_t *hash_map_entry, void *context) {
  assert(hash_map_entry != NULL);
  const char *key = (const char *)hash_map_entry->key;
  counter_data_t data = *(counter_data_t *)hash_map_entry->data;
  counter_data_cb_t *counter_cb_data = (counter_data_cb_t *)context;
  counter_cb_data->counter_iter_cb(key, data, counter_cb_data->user_context);
  return true;
}

static bool counter_socket_open(void) {
#if (!defined(BT_NET_DEBUG) || (BT_NET_DEBUG != TRUE))
  return true;          // Disable using network sockets for security reasons
#endif

  assert(listen_socket_ == NULL);
  assert(thread_ == NULL);
  assert(clients_ == NULL);

  clients_ = list_new(client_free);
  if (!clients_) {
    LOG_ERROR(LOG_TAG, "%s unable to create counter clients list", __func__);
    goto error;
  }

  thread_ = thread_new("counter_socket");
  if (!thread_) {
    LOG_ERROR(LOG_TAG, "%s unable to create counter thread", __func__);
    goto error;
  }

  listen_socket_ = socket_new();
  if (!listen_socket_) {
    LOG_ERROR(LOG_TAG, "%s unable to create listen socket", __func__);
    goto error;
  }

  if (!socket_listen(listen_socket_, LISTEN_PORT)) {
    LOG_ERROR(LOG_TAG, "%s unable to setup listen socket", __func__);
    goto error;
  }

  LOG_INFO(LOG_TAG, "%s opened counter server socket", __func__);
  socket_register(listen_socket_, thread_get_reactor(thread_), NULL, accept_ready, NULL);
  return true;

error:;
  counter_socket_close();
  return false;
}

static void counter_socket_close(void) {
#if (!defined(BT_NET_DEBUG) || (BT_NET_DEBUG != TRUE))
  return;               // Disable using network sockets for security reasons
#endif

  socket_free(listen_socket_);
  thread_free(thread_);
  list_free(clients_);

  listen_socket_ = NULL;
  thread_ = NULL;
  clients_ = NULL;

  LOG_INFO(LOG_TAG, "%s closed counter server socket", __func__);
}

static bool monitor_counter_iter_cb(const char *name, counter_data_t val, void *context) {
  socket_t *socket = (socket_t *)context;
  output(socket, "counter:%s val:%lld\n", name, val);
  return true;
}

static void client_free(void *ptr) {
  if (!ptr)
    return;

  client_t *client = (client_t *)ptr;
  socket_free(client->socket);
  osi_free(client);
}

static void accept_ready(socket_t *socket, UNUSED_ATTR void *context) {
  assert(socket != NULL);
  assert(socket == listen_socket_);

  LOG_INFO(LOG_TAG, "%s accepted OSI monitor socket", __func__);
  socket = socket_accept(socket);
  if (!socket)
    return;

  client_t *client = (client_t *)osi_calloc(sizeof(client_t));
  client->socket = socket;

  if (!list_append(clients_, client)) {
    LOG_ERROR(LOG_TAG, "%s unable to add client to list", __func__);
    client_free(client);
    return;
  }

  socket_register(socket, thread_get_reactor(thread_), client, read_ready, NULL);

  output(socket, WELCOME);
  output(socket, PROMPT);
}

static void read_ready(socket_t *socket, void *context) {
  assert(socket != NULL);

  client_t *client = (client_t *)context;

  ssize_t ret = socket_read(socket, client->buffer + client->buffer_size, sizeof(client->buffer) - client->buffer_size);
  if (ret == 0 || (ret == -1 && ret != EWOULDBLOCK && ret != EAGAIN)) {
    list_remove(clients_, client);
    return;
  }

  // Replace newline with end of string termination
  // TODO(cmanton) Need proper semantics
  for (size_t i = ret - 1; i > 0; --i) {
    if (client->buffer[i] < 16)
      *(client->buffer + i) = 0;
    else
      break;
  }

  const command_t *command = find_command((const char *)client->buffer);
  if (!command) {
    output(socket, "unable to find command %s\n", client->buffer);
  } else {
    int rc = command->handler(socket);
    if (rc == 1) {
      output(socket, GOODBYE);
      socket_free(socket);
      return;
    }
  }
  output(socket, PROMPT);
}

static void output(socket_t *socket, const char* format, ...) {
  char dest[4096];
  va_list argptr;
  va_start(argptr, format);
  vsprintf(dest, format, argptr);
  va_end(argptr);
  socket_write(socket, dest, strlen(dest));
}

static int help(UNUSED_ATTR socket_t *socket) {
  output(socket, "help command unimplemented\n");
  return 0;
}

static int quit(UNUSED_ATTR socket_t *socket) {
  return 1;
}

static int set(UNUSED_ATTR socket_t *socket) {
  output(socket, "set command unimplemented\n");
  return 0;
}

static int show(socket_t *socket) {
  output(socket, "counter count registered:%d\n", counter_cnt_);
  counter_foreach(monitor_counter_iter_cb, (void *)socket);
  return 0;
}

static const command_t *find_command(const char *name) {
  for  (size_t i = 0; i < ARRAY_SIZE(commands); ++i)
    if (!strcmp(commands[i].name, name))
      return &commands[i];
  return NULL;
}
+0 −102
Original line number Diff line number Diff line
/******************************************************************************
 *
 *  Copyright (C) 2014 Google, Inc.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at:
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 ******************************************************************************/

#include <gtest/gtest.h>
#include "osi/test/AllocationTestHarness.h"

extern "C" {
#include "btcore/include/counter.h"
#include "btcore/include/module.h"

extern module_t counter_module;
}  // "C"

static const uint64_t COUNTER_TEST_TEN = 10;

typedef struct mycounter_t {
  const char *name;
  uint64_t val;
  bool found;
} mycounter_t;

static bool counter_iter(const char *name, counter_data_t val, void *context) {
  mycounter_t *mycounter = (mycounter_t *)context;
  if (!strcmp(name, mycounter->name)) {
    mycounter->val = val;
    mycounter->found = true;
    return false;
  }
  return true;
}

static bool find_val(const char *name, uint64_t *val) {
  mycounter_t mycounter;

  mycounter.val = 0;
  mycounter.name = name;
  mycounter.found = false;
  counter_foreach(counter_iter, &mycounter);
  *val = mycounter.val;
  if (mycounter.found)
    return true;
  return false;
}

class CounterTest : public AllocationTestHarness {
  protected:
    virtual void SetUp() {
      counter_module.init();
    }

    virtual void TearDown() {
      counter_module.clean_up();
    }
};

TEST_F(CounterTest, counter_no_exist) {
  uint64_t val;

  EXPECT_FALSE(find_val("one.two.three", &val));
}

TEST_F(CounterTest, counter_inc_dec) {
  uint64_t val;

  counter_add("one.two.three", 1);

  EXPECT_TRUE(find_val("one.two.three", &val));
  EXPECT_EQ((uint64_t)1, val);

  counter_add("one.two.three", 1);
  EXPECT_TRUE(find_val("one.two.three", &val));
  EXPECT_EQ((uint64_t)2, val);

  counter_add("one.two.three", -1);
  EXPECT_TRUE(find_val("one.two.three", &val));
  EXPECT_EQ((uint64_t)1, val);
}

TEST_F(CounterTest, counter_get_set) {
  uint64_t val;

  counter_set("one.two.three", COUNTER_TEST_TEN);
  EXPECT_TRUE(find_val("one.two.three", &val));
  EXPECT_EQ(COUNTER_TEST_TEN, val);

  EXPECT_FALSE(find_val("foo.bar", &val));
}
Loading