mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-08-08 22:10:46 +00:00
Separate code to manage statistic file
Code is quite independent so move in separate file. Signed-off-by: Frediano Ziglio <fziglio@redhat.com> Acked-by: Christophe Fergeau <cfergeau@redhat.com>
This commit is contained in:
parent
99eff8500b
commit
f9ccabfaea
@ -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 \
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
122
server/reds.c
122
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) {
|
||||
|
||||
177
server/stat-file.c
Normal file
177
server/stat-file.c
Normal file
@ -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)));
|
||||
}
|
||||
43
server/stat-file.h
Normal file
43
server/stat-file.h
Normal file
@ -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_ */
|
||||
@ -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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user