Code is quite independent so move in separate file. Signed-off-by: Frediano Ziglio <fziglio@xxxxxxxxxx> --- server/Makefile.am | 2 + server/reds-private.h | 12 +--- server/reds.c | 122 +++------------------------------- server/stat-file.c | 177 ++++++++++++++++++++++++++++++++++++++++++++++++++ server/stat-file.h | 43 ++++++++++++ server/stat.h | 4 +- 6 files changed, 233 insertions(+), 127 deletions(-) create mode 100644 server/stat-file.c create mode 100644 server/stat-file.h diff --git a/server/Makefile.am b/server/Makefile.am index 972f3e2..8d4eae9 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -143,6 +143,8 @@ libserver_la_SOURCES = \ sound.c \ sound.h \ stat.h \ + stat-file.c \ + stat-file.h \ spicevmc.c \ video-encoder.h \ zlib-encoder.c \ diff --git a/server/reds-private.h b/server/reds-private.h index 8198a8d..d293ddc 100644 --- a/server/reds-private.h +++ b/server/reds-private.h @@ -24,6 +24,7 @@ #include "main-dispatcher.h" #include "main-channel.h" #include "inputs-channel.h" +#include "stat-file.h" #define MIGRATE_TIMEOUT (MSEC_PER_SEC * 10) #define MM_TIME_DELTA 400 /*ms*/ @@ -45,13 +46,6 @@ typedef struct MonitorMode { uint32_t y_res; } MonitorMode; -#ifdef RED_STATISTICS - -#define REDS_MAX_STAT_NODES 100 -#define REDS_STAT_SHM_SIZE (sizeof(SpiceStat) + REDS_MAX_STAT_NODES * sizeof(SpiceStatNode)) - -#endif - typedef struct RedsMigPendingLink { SpiceLinkMess *link_msg; RedsStream *stream; @@ -127,9 +121,7 @@ struct RedsState { SSL_CTX *ctx; #ifdef RED_STATISTICS - char *stat_shm_name; - SpiceStat *stat; - pthread_mutex_t stat_lock; + RedStatFile stat_file; #endif int allow_multiple_clients; diff --git a/server/reds.c b/server/reds.c index 12a274c..061a190 100644 --- a/server/reds.c +++ b/server/reds.c @@ -76,6 +76,8 @@ #include "main-channel-client.h" #include "red-client.h" +#define REDS_MAX_STAT_NODES 100 + static void reds_client_monitors_config(RedsState *reds, VDAgentMonitorsConfig *monitors_config); static gboolean reds_use_client_monitors_config(RedsState *reds); @@ -348,105 +350,24 @@ static void reds_link_free(RedLinkInfo *link) #ifdef RED_STATISTICS -static void reds_insert_stat_node(RedsState *reds, StatNodeRef parent, StatNodeRef ref) -{ - SpiceStatNode *node = &reds->stat->nodes[ref]; - uint32_t pos = INVALID_STAT_REF; - uint32_t node_index; - uint32_t *head; - SpiceStatNode *n; - - node->first_child_index = INVALID_STAT_REF; - head = (parent == INVALID_STAT_REF ? &reds->stat->root_index : - &reds->stat->nodes[parent].first_child_index); - node_index = *head; - while (node_index != INVALID_STAT_REF && (n = &reds->stat->nodes[node_index]) && - strcmp(node->name, n->name) > 0) { - pos = node_index; - node_index = n->next_sibling_index; - } - if (pos == INVALID_STAT_REF) { - node->next_sibling_index = *head; - *head = ref; - } else { - n = &reds->stat->nodes[pos]; - node->next_sibling_index = n->next_sibling_index; - n->next_sibling_index = ref; - } -} - StatNodeRef stat_add_node(RedsState *reds, StatNodeRef parent, const char *name, int visible) { - StatNodeRef ref; - SpiceStatNode *node; - - spice_assert(name && strlen(name) > 0); - if (strlen(name) >= sizeof(node->name)) { - return INVALID_STAT_REF; - } - pthread_mutex_lock(&reds->stat_lock); - ref = (parent == INVALID_STAT_REF ? reds->stat->root_index : - reds->stat->nodes[parent].first_child_index); - while (ref != INVALID_STAT_REF) { - node = &reds->stat->nodes[ref]; - if (strcmp(name, node->name)) { - ref = node->next_sibling_index; - } else { - pthread_mutex_unlock(&reds->stat_lock); - return ref; - } - } - if (reds->stat->num_of_nodes >= REDS_MAX_STAT_NODES || reds->stat == NULL) { - pthread_mutex_unlock(&reds->stat_lock); - return INVALID_STAT_REF; - } - reds->stat->generation++; - reds->stat->num_of_nodes++; - for (ref = 0; ref <= REDS_MAX_STAT_NODES; ref++) { - node = &reds->stat->nodes[ref]; - if (!(node->flags & SPICE_STAT_NODE_FLAG_ENABLED)) { - break; - } - } - spice_assert(!(node->flags & SPICE_STAT_NODE_FLAG_ENABLED)); - node->value = 0; - node->flags = SPICE_STAT_NODE_FLAG_ENABLED | (visible ? SPICE_STAT_NODE_FLAG_VISIBLE : 0); - g_strlcpy(node->name, name, sizeof(node->name)); - reds_insert_stat_node(reds, parent, ref); - pthread_mutex_unlock(&reds->stat_lock); - return ref; -} - -static void reds_stat_remove(RedsState *reds, SpiceStatNode *node) -{ - pthread_mutex_lock(&reds->stat_lock); - node->flags &= ~SPICE_STAT_NODE_FLAG_ENABLED; - reds->stat->generation++; - reds->stat->num_of_nodes--; - pthread_mutex_unlock(&reds->stat_lock); + return stat_file_add_node(&reds->stat_file, parent, name, visible); } void stat_remove_node(RedsState *reds, StatNodeRef ref) { - reds_stat_remove(reds, &reds->stat->nodes[ref]); + stat_file_remove_node(&reds->stat_file, ref); } uint64_t *stat_add_counter(RedsState *reds, StatNodeRef parent, const char *name, int visible) { - StatNodeRef ref = stat_add_node(reds, parent, name, visible); - SpiceStatNode *node; - - if (ref == INVALID_STAT_REF) { - return NULL; - } - node = &reds->stat->nodes[ref]; - node->flags |= SPICE_STAT_NODE_FLAG_VALUE; - return &node->value; + return stat_file_add_counter(&reds->stat_file, parent, name, visible); } void stat_remove_counter(RedsState *reds, uint64_t *counter) { - reds_stat_remove(reds, (SpiceStatNode *)(counter - SPICE_OFFSETOF(SpiceStatNode, value))); + stat_file_remove_counter(&reds->stat_file, counter); } #endif @@ -2906,11 +2827,7 @@ static int reds_init_ssl(RedsState *reds) static void reds_cleanup(RedsState *reds) { #ifdef RED_STATISTICS - if (reds->stat_shm_name) { - shm_unlink(reds->stat_shm_name); - free(reds->stat_shm_name); - reds->stat_shm_name = NULL; - } + stat_file_unlink(&reds->stat_file); #endif } @@ -3442,30 +3359,7 @@ static int do_spice_init(RedsState *reds, SpiceCoreInterface *core_interface) } #ifdef RED_STATISTICS - int shm_name_len; - int fd; - - shm_name_len = strlen(SPICE_STAT_SHM_NAME) + 20; - reds->stat_shm_name = (char *)spice_malloc(shm_name_len); - snprintf(reds->stat_shm_name, shm_name_len, SPICE_STAT_SHM_NAME, getpid()); - shm_unlink(reds->stat_shm_name); - if ((fd = shm_open(reds->stat_shm_name, O_CREAT | O_RDWR, 0444)) == -1) { - spice_error("statistics shm_open failed, %s", strerror(errno)); - } - if (ftruncate(fd, REDS_STAT_SHM_SIZE) == -1) { - spice_error("statistics ftruncate failed, %s", strerror(errno)); - } - reds->stat = (SpiceStat *)mmap(NULL, REDS_STAT_SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (reds->stat == (SpiceStat *)MAP_FAILED) { - spice_error("statistics mmap failed, %s", strerror(errno)); - } - memset(reds->stat, 0, REDS_STAT_SHM_SIZE); - reds->stat->magic = SPICE_STAT_MAGIC; - reds->stat->version = SPICE_STAT_VERSION; - reds->stat->root_index = INVALID_STAT_REF; - if (pthread_mutex_init(&reds->stat_lock, NULL)) { - spice_error("mutex init failed"); - } + stat_file_init(&reds->stat_file, REDS_MAX_STAT_NODES); #endif if (reds_init_net(reds) < 0) { diff --git a/server/stat-file.c b/server/stat-file.c new file mode 100644 index 0000000..d688f80 --- /dev/null +++ b/server/stat-file.c @@ -0,0 +1,177 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009-2016 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <common/log.h> +#include <common/mem.h> + +#include "stat-file.h" + +#define STAT_SHM_SIZE(max_nodes) \ + (sizeof(SpiceStat) + (max_nodes) * sizeof(SpiceStatNode)) + +void stat_file_init(RedStatFile *stat_file, unsigned int max_nodes) +{ + int shm_name_len; + int fd; + size_t shm_size = STAT_SHM_SIZE(max_nodes); + + stat_file->max_nodes = max_nodes; + shm_name_len = strlen(SPICE_STAT_SHM_NAME) + 20; + stat_file->shm_name = (char *)spice_malloc(shm_name_len); + snprintf(stat_file->shm_name, shm_name_len, SPICE_STAT_SHM_NAME, getpid()); + shm_unlink(stat_file->shm_name); + if ((fd = shm_open(stat_file->shm_name, O_CREAT | O_RDWR, 0444)) == -1) { + spice_error("statistics shm_open failed, %s", strerror(errno)); + } + if (ftruncate(fd, shm_size) == -1) { + spice_error("statistics ftruncate failed, %s", strerror(errno)); + } + stat_file->stat = (SpiceStat *)mmap(NULL, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (stat_file->stat == (SpiceStat *)MAP_FAILED) { + spice_error("statistics mmap failed, %s", strerror(errno)); + } + memset(stat_file->stat, 0, shm_size); + stat_file->stat->magic = SPICE_STAT_MAGIC; + stat_file->stat->version = SPICE_STAT_VERSION; + stat_file->stat->root_index = INVALID_STAT_REF; + if (pthread_mutex_init(&stat_file->lock, NULL)) { + spice_error("mutex init failed"); + } +} + +void stat_file_unlink(RedStatFile *stat_file) +{ + if (stat_file->shm_name) { + shm_unlink(stat_file->shm_name); + free(stat_file->shm_name); + stat_file->shm_name = NULL; + } +} + +static void reds_insert_stat_node(RedStatFile *stat_file, StatNodeRef parent, StatNodeRef ref) +{ + SpiceStatNode *node = &stat_file->stat->nodes[ref]; + uint32_t pos = INVALID_STAT_REF; + uint32_t node_index; + uint32_t *head; + SpiceStatNode *n; + + node->first_child_index = INVALID_STAT_REF; + head = (parent == INVALID_STAT_REF ? &stat_file->stat->root_index : + &stat_file->stat->nodes[parent].first_child_index); + node_index = *head; + while (node_index != INVALID_STAT_REF && (n = &stat_file->stat->nodes[node_index]) && + strcmp(node->name, n->name) > 0) { + pos = node_index; + node_index = n->next_sibling_index; + } + if (pos == INVALID_STAT_REF) { + node->next_sibling_index = *head; + *head = ref; + } else { + n = &stat_file->stat->nodes[pos]; + node->next_sibling_index = n->next_sibling_index; + n->next_sibling_index = ref; + } +} + +StatNodeRef +stat_file_add_node(RedStatFile *stat_file, StatNodeRef parent, const char *name, int visible) +{ + StatNodeRef ref; + SpiceStatNode *node; + + spice_assert(name && strlen(name) > 0); + if (strlen(name) >= sizeof(node->name)) { + return INVALID_STAT_REF; + } + pthread_mutex_lock(&stat_file->lock); + ref = (parent == INVALID_STAT_REF ? stat_file->stat->root_index : + stat_file->stat->nodes[parent].first_child_index); + while (ref != INVALID_STAT_REF) { + node = &stat_file->stat->nodes[ref]; + if (strcmp(name, node->name)) { + ref = node->next_sibling_index; + } else { + pthread_mutex_unlock(&stat_file->lock); + return ref; + } + } + if (stat_file->stat->num_of_nodes >= stat_file->max_nodes || stat_file->stat == NULL) { + pthread_mutex_unlock(&stat_file->lock); + return INVALID_STAT_REF; + } + stat_file->stat->generation++; + stat_file->stat->num_of_nodes++; + for (ref = 0; ref <= stat_file->max_nodes; ref++) { + node = &stat_file->stat->nodes[ref]; + if (!(node->flags & SPICE_STAT_NODE_FLAG_ENABLED)) { + break; + } + } + spice_assert(!(node->flags & SPICE_STAT_NODE_FLAG_ENABLED)); + node->value = 0; + node->flags = SPICE_STAT_NODE_FLAG_ENABLED | (visible ? SPICE_STAT_NODE_FLAG_VISIBLE : 0); + g_strlcpy(node->name, name, sizeof(node->name)); + reds_insert_stat_node(stat_file, parent, ref); + pthread_mutex_unlock(&stat_file->lock); + return ref; +} + +uint64_t * +stat_file_add_counter(RedStatFile *stat_file, StatNodeRef parent, const char *name, int visible) +{ + StatNodeRef ref = stat_file_add_node(stat_file, parent, name, visible); + SpiceStatNode *node; + + if (ref == INVALID_STAT_REF) { + return NULL; + } + node = &stat_file->stat->nodes[ref]; + node->flags |= SPICE_STAT_NODE_FLAG_VALUE; + return &node->value; +} + +static void stat_file_remove(RedStatFile *stat_file, SpiceStatNode *node) +{ + pthread_mutex_lock(&stat_file->lock); + node->flags &= ~SPICE_STAT_NODE_FLAG_ENABLED; + stat_file->stat->generation++; + stat_file->stat->num_of_nodes--; + pthread_mutex_unlock(&stat_file->lock); +} + +void stat_file_remove_node(RedStatFile *stat_file, StatNodeRef ref) +{ + stat_file_remove(stat_file, &stat_file->stat->nodes[ref]); +} + +void stat_file_remove_counter(RedStatFile *stat_file, uint64_t *counter) +{ + stat_file_remove(stat_file, (SpiceStatNode *)(counter - SPICE_OFFSETOF(SpiceStatNode, value))); +} diff --git a/server/stat-file.h b/server/stat-file.h new file mode 100644 index 0000000..8ac8efc --- /dev/null +++ b/server/stat-file.h @@ -0,0 +1,43 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2016 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ +#ifndef STAT_FILE_H_ +#define STAT_FILE_H_ + +#include <pthread.h> +#include <spice/stats.h> + +typedef uint32_t StatNodeRef; +#define INVALID_STAT_REF (~(StatNodeRef)0) + +typedef struct { + char *shm_name; + SpiceStat *stat; + pthread_mutex_t lock; + unsigned int max_nodes; +} RedStatFile; + +void stat_file_init(RedStatFile *stat_file, unsigned int max_nodes); +void stat_file_unlink(RedStatFile *file_stat); +StatNodeRef stat_file_add_node(RedStatFile *stat_file, StatNodeRef parent, + const char *name, int visible); +uint64_t *stat_file_add_counter(RedStatFile *stat_file, StatNodeRef parent, + const char *name, int visible); +void stat_file_remove_node(RedStatFile *stat_file, StatNodeRef ref); +void stat_file_remove_counter(RedStatFile *stat_file, uint64_t *counter); + +#endif /* STAT_FILE_H_ */ diff --git a/server/stat.h b/server/stat.h index 7bf90da..a5df7ea 100644 --- a/server/stat.h +++ b/server/stat.h @@ -22,9 +22,7 @@ #include <glib.h> #include "spice.h" - -typedef uint32_t StatNodeRef; -#define INVALID_STAT_REF (~(StatNodeRef)0) +#include "stat-file.h" #ifdef RED_STATISTICS StatNodeRef stat_add_node(SpiceServer *reds, StatNodeRef parent, const char *name, int visible); -- 2.7.4 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel