mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
* TODO src/hash.[ch] src/internal.h src/libvirt.c src/xend_internal.c
src/xs_internal.c: implementing domain pointers unification, thread safety and reference counting for domain and connections, this was the last critical change needed before making further progresses at the API level. Still a couple fo things TODO for this, unification at the Python level and adding UUID to hash. All domain/connect alloc and free routines are now centralized in hash.c * docs/APIchunk1.html docs/libvirt-api.xml docs/libvirt-refs.xml docs/html/libvirt-libvirt.html: regenerated the docs, that doesn't change the API. Daniel
This commit is contained in:
parent
1ea832d65b
commit
572806a99b
13
ChangeLog
13
ChangeLog
@ -1,3 +1,16 @@
|
|||||||
|
Sun Apr 9 13:10:34 EDT 2006 Daniel Veillard <veillard@redhat.com>
|
||||||
|
|
||||||
|
* TODO src/hash.[ch] src/internal.h src/libvirt.c src/xend_internal.c
|
||||||
|
src/xs_internal.c: implementing domain pointers unification, thread
|
||||||
|
safety and reference counting for domain and connections, this was
|
||||||
|
the last critical change needed before making further progresses at
|
||||||
|
the API level. Still a couple fo things TODO for this, unification
|
||||||
|
at the Python level and adding UUID to hash. All domain/connect alloc
|
||||||
|
and free routines are now centralized in hash.c
|
||||||
|
* docs/APIchunk1.html docs/libvirt-api.xml docs/libvirt-refs.xml
|
||||||
|
docs/html/libvirt-libvirt.html: regenerated the docs, that doesn't
|
||||||
|
change the API.
|
||||||
|
|
||||||
Thu Apr 6 11:32:46 CEST 2006 Karel Zak <kzak@redhat.com>
|
Thu Apr 6 11:32:46 CEST 2006 Karel Zak <kzak@redhat.com>
|
||||||
|
|
||||||
* src/virsh.c: use stdout for standard outputs, improve
|
* src/virsh.c: use stdout for standard outputs, improve
|
||||||
|
6
TODO
6
TODO
@ -1,6 +1,3 @@
|
|||||||
Absolute TODOs:
|
|
||||||
- thread protection, reentrancy, refcounting, etc ...
|
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
- Create() API, how do we best keep flexibility and allow various
|
- Create() API, how do we best keep flexibility and allow various
|
||||||
specific environment and space for evolution (VMX)
|
specific environment and space for evolution (VMX)
|
||||||
@ -12,6 +9,8 @@ TODO:
|
|||||||
to return a non-None object
|
to return a non-None object
|
||||||
- Add uuid to XML format
|
- Add uuid to XML format
|
||||||
- add error handling hooks at the python level
|
- add error handling hooks at the python level
|
||||||
|
- object unicity for domains at the Python level
|
||||||
|
- UUID lookup in hash.c
|
||||||
|
|
||||||
virsh TODO:
|
virsh TODO:
|
||||||
- decide where will be default directory for domains configurations (/etc/xen/domains/* ?)
|
- decide where will be default directory for domains configurations (/etc/xen/domains/* ?)
|
||||||
@ -48,3 +47,4 @@ Done:
|
|||||||
- UUID based lookup and naming
|
- UUID based lookup and naming
|
||||||
- Error API similar to libxml2 structured API
|
- Error API similar to libxml2 structured API
|
||||||
- extract error messages from the Xend rpc
|
- extract error messages from the Xend rpc
|
||||||
|
- thread protection, reentrancy, refcounting, etc ...
|
||||||
|
@ -145,7 +145,8 @@
|
|||||||
<a href="html/libvirt-libvirt.html#virDomainSave">virDomainSave</a><br />
|
<a href="html/libvirt-libvirt.html#virDomainSave">virDomainSave</a><br />
|
||||||
</dd></dl><h2>Letter k:</h2><dl><dt>kept</dt><dd><a href="html/libvirt-libvirt.html#virDomainFree">virDomainFree</a><br />
|
</dd></dl><h2>Letter k:</h2><dl><dt>kept</dt><dd><a href="html/libvirt-libvirt.html#virDomainFree">virDomainFree</a><br />
|
||||||
</dd><dt>kernel</dt><dd><a href="html/libvirt-libvirt.html#_virDomainKernel">_virDomainKernel</a><br />
|
</dd><dt>kernel</dt><dd><a href="html/libvirt-libvirt.html#_virDomainKernel">_virDomainKernel</a><br />
|
||||||
</dd><dt>kilobytes</dt><dd><a href="html/libvirt-libvirt.html#virDomainGetMaxMemory">virDomainGetMaxMemory</a><br />
|
</dd><dt>kilobytes</dt><dd><a href="html/libvirt-libvirt.html#_virNodeInfo">_virNodeInfo</a><br />
|
||||||
|
<a href="html/libvirt-libvirt.html#virDomainGetMaxMemory">virDomainGetMaxMemory</a><br />
|
||||||
<a href="html/libvirt-libvirt.html#virDomainSetMaxMemory">virDomainSetMaxMemory</a><br />
|
<a href="html/libvirt-libvirt.html#virDomainSetMaxMemory">virDomainSetMaxMemory</a><br />
|
||||||
</dd><dt>knowing</dt><dd><a href="html/libvirt-libvirt.html#virDomainShutdown">virDomainShutdown</a><br />
|
</dd><dt>knowing</dt><dd><a href="html/libvirt-libvirt.html#virDomainShutdown">virDomainShutdown</a><br />
|
||||||
</dd></dl><h2>Letter l:</h2><dl><dt>lack</dt><dd><a href="html/libvirt-libvirt.html#virConnectGetVersion">virConnectGetVersion</a><br />
|
</dd></dl><h2>Letter l:</h2><dl><dt>lack</dt><dd><a href="html/libvirt-libvirt.html#virConnectGetVersion">virConnectGetVersion</a><br />
|
||||||
@ -196,7 +197,6 @@
|
|||||||
<a href="html/libvirt-libvirt.html#virDomainShutdown">virDomainShutdown</a><br />
|
<a href="html/libvirt-libvirt.html#virDomainShutdown">virDomainShutdown</a><br />
|
||||||
<a href="html/libvirt-libvirt.html#virDomainSuspend">virDomainSuspend</a><br />
|
<a href="html/libvirt-libvirt.html#virDomainSuspend">virDomainSuspend</a><br />
|
||||||
<a href="html/libvirt-virterror.html#virGetLastError">virGetLastError</a><br />
|
<a href="html/libvirt-virterror.html#virGetLastError">virGetLastError</a><br />
|
||||||
</dd><dt>megabytes</dt><dd><a href="html/libvirt-libvirt.html#_virNodeInfo">_virNodeInfo</a><br />
|
|
||||||
</dd><dt>mem</dt><dd><a href="html/libvirt-libvirt.html#_virNodeInfo">_virNodeInfo</a><br />
|
</dd><dt>mem</dt><dd><a href="html/libvirt-libvirt.html#_virNodeInfo">_virNodeInfo</a><br />
|
||||||
</dd><dt>memory</dt><dd><a href="html/libvirt-libvirt.html#_virDomainInfo">_virDomainInfo</a><br />
|
</dd><dt>memory</dt><dd><a href="html/libvirt-libvirt.html#_virDomainInfo">_virDomainInfo</a><br />
|
||||||
<a href="html/libvirt-libvirt.html#_virNodeInfo">_virNodeInfo</a><br />
|
<a href="html/libvirt-libvirt.html#_virNodeInfo">_virNodeInfo</a><br />
|
||||||
|
@ -97,7 +97,7 @@ The content of this structure is not made public by the API.
|
|||||||
}
|
}
|
||||||
</pre><h3><a name="virNodeInfo" id="virNodeInfo">Structure virNodeInfo</a></h3><pre class="programlisting">Structure virNodeInfo<br />struct _virNodeInfo {
|
</pre><h3><a name="virNodeInfo" id="virNodeInfo">Structure virNodeInfo</a></h3><pre class="programlisting">Structure virNodeInfo<br />struct _virNodeInfo {
|
||||||
charmodel[32] model : string indicating the CPU model
|
charmodel[32] model : string indicating the CPU model
|
||||||
unsigned long memory : memory size in megabytes
|
unsigned long memory : memory size in kilobytes
|
||||||
unsigned int cpus : the number of active CPUs
|
unsigned int cpus : the number of active CPUs
|
||||||
unsigned int mhz : expected CPU frequency
|
unsigned int mhz : expected CPU frequency
|
||||||
unsigned int nodes : the number of NUMA cell, 1 for uniform
|
unsigned int nodes : the number of NUMA cell, 1 for uniform
|
||||||
|
@ -237,7 +237,7 @@
|
|||||||
<typedef name='virErrorPtr' file='virterror' type='virError *'/>
|
<typedef name='virErrorPtr' file='virterror' type='virError *'/>
|
||||||
<struct name='virNodeInfo' file='libvirt' type='struct _virNodeInfo'>
|
<struct name='virNodeInfo' file='libvirt' type='struct _virNodeInfo'>
|
||||||
<field name='model' type='charmodel[32]' info=' string indicating the CPU model'/>
|
<field name='model' type='charmodel[32]' info=' string indicating the CPU model'/>
|
||||||
<field name='memory' type='unsigned long' info=' memory size in megabytes'/>
|
<field name='memory' type='unsigned long' info=' memory size in kilobytes'/>
|
||||||
<field name='cpus' type='unsigned int' info=' the number of active CPUs'/>
|
<field name='cpus' type='unsigned int' info=' the number of active CPUs'/>
|
||||||
<field name='mhz' type='unsigned int' info=' expected CPU frequency'/>
|
<field name='mhz' type='unsigned int' info=' expected CPU frequency'/>
|
||||||
<field name='nodes' type='unsigned int' info=' the number of NUMA cell, 1 for uniform mem access'/>
|
<field name='nodes' type='unsigned int' info=' the number of NUMA cell, 1 for uniform mem access'/>
|
||||||
|
@ -1232,6 +1232,7 @@
|
|||||||
<ref name='_virDomainKernel'/>
|
<ref name='_virDomainKernel'/>
|
||||||
</word>
|
</word>
|
||||||
<word name='kilobytes'>
|
<word name='kilobytes'>
|
||||||
|
<ref name='_virNodeInfo'/>
|
||||||
<ref name='virDomainGetMaxMemory'/>
|
<ref name='virDomainGetMaxMemory'/>
|
||||||
<ref name='virDomainSetMaxMemory'/>
|
<ref name='virDomainSetMaxMemory'/>
|
||||||
</word>
|
</word>
|
||||||
@ -1320,9 +1321,6 @@
|
|||||||
<ref name='virDomainSuspend'/>
|
<ref name='virDomainSuspend'/>
|
||||||
<ref name='virGetLastError'/>
|
<ref name='virGetLastError'/>
|
||||||
</word>
|
</word>
|
||||||
<word name='megabytes'>
|
|
||||||
<ref name='_virNodeInfo'/>
|
|
||||||
</word>
|
|
||||||
<word name='mem'>
|
<word name='mem'>
|
||||||
<ref name='_virNodeInfo'/>
|
<ref name='_virNodeInfo'/>
|
||||||
</word>
|
</word>
|
||||||
|
256
src/hash.c
256
src/hash.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* hash.c: chained hash tables
|
* hash.c: chained hash tables for domain and domain/connection deallocations
|
||||||
*
|
*
|
||||||
* Reference: Your favorite introductory book on algorithms
|
* Reference: Your favorite introductory book on algorithms
|
||||||
*
|
*
|
||||||
@ -15,10 +15,13 @@
|
|||||||
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
|
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
|
||||||
*
|
*
|
||||||
* Author: breese@users.sourceforge.net
|
* Author: breese@users.sourceforge.net
|
||||||
|
* Daniel Veillard <veillard@redhat.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <libxml/threads.h>
|
||||||
|
#include "internal.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
|
|
||||||
#define MAX_HASH_LEN 8
|
#define MAX_HASH_LEN 8
|
||||||
@ -469,3 +472,254 @@ virHashRemoveEntry(virHashTablePtr table, const char *name,
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* Domain and Connections allocations *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virHashError:
|
||||||
|
* @conn: the connection if available
|
||||||
|
* @error: the error noumber
|
||||||
|
* @info: extra information string
|
||||||
|
*
|
||||||
|
* Handle an error at the connection level
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
virHashError(virConnectPtr conn, virErrorNumber error, const char *info)
|
||||||
|
{
|
||||||
|
const char *errmsg;
|
||||||
|
|
||||||
|
if (error == VIR_ERR_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
errmsg = __virErrorMsg(error, info);
|
||||||
|
__virRaiseError(conn, NULL, VIR_FROM_NONE, error, VIR_ERR_ERROR,
|
||||||
|
errmsg, info, NULL, 0, 0, errmsg, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virDomainFreeName:
|
||||||
|
* @domain: a domain object
|
||||||
|
*
|
||||||
|
* Destroy the domain object, this is just used by the domain hash callback.
|
||||||
|
*
|
||||||
|
* Returns 0 in case of success and -1 in case of failure.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
virDomainFreeName(virDomainPtr domain, const char *name ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
return (virDomainFree(domain));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virGetConnect:
|
||||||
|
*
|
||||||
|
* Allocates a new hypervisor connection structure
|
||||||
|
*
|
||||||
|
* Returns a new pointer or NULL in case of error.
|
||||||
|
*/
|
||||||
|
virConnectPtr
|
||||||
|
virGetConnect(void) {
|
||||||
|
virConnectPtr ret;
|
||||||
|
|
||||||
|
ret = (virConnectPtr) malloc(sizeof(virConnect));
|
||||||
|
if (ret == NULL) {
|
||||||
|
virHashError(NULL, VIR_ERR_NO_MEMORY, "Allocating connection");
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
memset(ret, 0, sizeof(virConnect));
|
||||||
|
ret->magic = VIR_CONNECT_MAGIC;
|
||||||
|
ret->nb_drivers = 0;
|
||||||
|
ret->domains = virHashCreate(20);
|
||||||
|
if (ret->domains == NULL)
|
||||||
|
goto failed;
|
||||||
|
ret->domains_mux = xmlNewMutex();
|
||||||
|
if (ret->domains_mux == NULL)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
ret->uses = 1;
|
||||||
|
return(ret);
|
||||||
|
|
||||||
|
failed:
|
||||||
|
if (ret != NULL) {
|
||||||
|
if (ret->domains != NULL)
|
||||||
|
virHashFree(ret->domains, (virHashDeallocator) virDomainFreeName);
|
||||||
|
if (ret->domains_mux != NULL)
|
||||||
|
xmlFreeMutex(ret->domains_mux);
|
||||||
|
free(ret);
|
||||||
|
}
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virFreeConnect:
|
||||||
|
* @conn: the hypervisor connection
|
||||||
|
*
|
||||||
|
* Release the connection. if the use count drops to zero, the structure is
|
||||||
|
* actually freed.
|
||||||
|
*
|
||||||
|
* Returns the reference count or -1 in case of failure.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
virFreeConnect(virConnectPtr conn) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((!VIR_IS_CONNECT(conn)) || (conn->domains_mux == NULL)) {
|
||||||
|
virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
xmlMutexLock(conn->domains_mux);
|
||||||
|
conn->uses--;
|
||||||
|
ret = conn->uses;
|
||||||
|
if (ret > 0) {
|
||||||
|
xmlMutexUnlock(conn->domains_mux);
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conn->domains != NULL)
|
||||||
|
virHashFree(conn->domains, (virHashDeallocator) virDomainFreeName);
|
||||||
|
if (conn->domains_mux != NULL)
|
||||||
|
xmlFreeMutex(conn->domains_mux);
|
||||||
|
free(conn);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virGetDomain:
|
||||||
|
* @conn: the hypervisor connection
|
||||||
|
* @name: pointer to the domain name or NULL
|
||||||
|
* @uuid: pointer to the uuid or NULL
|
||||||
|
*
|
||||||
|
* Lookup if the domain is already registered for that connection,
|
||||||
|
* if yes return a new pointer to it, if no allocate a new structure,
|
||||||
|
* and register it in the table. In any case a corresponding call to
|
||||||
|
* virFreeDomain() is needed to not leak data.
|
||||||
|
*
|
||||||
|
* Returns a pointer to the domain, or NULL in case of failure
|
||||||
|
*/
|
||||||
|
virDomainPtr
|
||||||
|
virGetDomain(virConnectPtr conn, const char *name, const char *uuid) {
|
||||||
|
virDomainPtr ret = NULL;
|
||||||
|
|
||||||
|
if ((!VIR_IS_CONNECT(conn)) || ((name == NULL) && (uuid == NULL)) ||
|
||||||
|
(conn->domains_mux == NULL)) {
|
||||||
|
virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
xmlMutexLock(conn->domains_mux);
|
||||||
|
|
||||||
|
/* TODO search by UUID first as they are better differenciators */
|
||||||
|
|
||||||
|
ret = (virDomainPtr) virHashLookup(conn->domains, name);
|
||||||
|
if (ret != NULL) {
|
||||||
|
/* TODO check the UUID */
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* not found, allocate a new one
|
||||||
|
*/
|
||||||
|
ret = (virDomainPtr) malloc(sizeof(virDomain));
|
||||||
|
if (ret == NULL) {
|
||||||
|
virHashError(conn, VIR_ERR_NO_MEMORY, "Allocating domain");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
memset(ret, 0, sizeof(virDomain));
|
||||||
|
ret->name = strdup(name);
|
||||||
|
if (ret->name == NULL) {
|
||||||
|
virHashError(conn, VIR_ERR_NO_MEMORY, "Allocating domain");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
ret->magic = VIR_DOMAIN_MAGIC;
|
||||||
|
ret->conn = conn;
|
||||||
|
if (uuid != NULL)
|
||||||
|
memcpy(&(ret->uuid[0]), uuid, 16);
|
||||||
|
|
||||||
|
if (virHashAddEntry(conn->domains, name, ret) < 0) {
|
||||||
|
virHashError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"Failed to add domain to connectio hash table");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
conn->uses++;
|
||||||
|
done:
|
||||||
|
ret->uses++;
|
||||||
|
xmlMutexUnlock(conn->domains_mux);
|
||||||
|
return(ret);
|
||||||
|
|
||||||
|
error:
|
||||||
|
xmlMutexUnlock(conn->domains_mux);
|
||||||
|
if (ret != NULL) {
|
||||||
|
if (ret->name != NULL)
|
||||||
|
free(ret->name );
|
||||||
|
free(ret);
|
||||||
|
}
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virFreeDomain:
|
||||||
|
* @conn: the hypervisor connection
|
||||||
|
* @domain: the domain to release
|
||||||
|
*
|
||||||
|
* Release the given domain, if the reference count drops to zero, then
|
||||||
|
* the domain is really freed.
|
||||||
|
*
|
||||||
|
* Returns the reference count or -1 in case of failure.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
virFreeDomain(virConnectPtr conn, virDomainPtr domain) {
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if ((!VIR_IS_CONNECT(conn)) || (!VIR_IS_CONNECTED_DOMAIN(domain)) ||
|
||||||
|
(domain->conn != conn) || (conn->domains_mux == NULL)) {
|
||||||
|
virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
xmlMutexLock(conn->domains_mux);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* decrement the count for the domain
|
||||||
|
*/
|
||||||
|
domain->uses--;
|
||||||
|
ret = domain->uses;
|
||||||
|
if (ret > 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* TODO search by UUID first as they are better differenciators */
|
||||||
|
|
||||||
|
if (virHashRemoveEntry(conn->domains, domain->name, NULL) < 0) {
|
||||||
|
virHashError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"domain missing from connection hash table");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
domain->magic = -1;
|
||||||
|
domain->handle = -1;
|
||||||
|
if (domain->path != NULL)
|
||||||
|
free(domain->path);
|
||||||
|
if (domain->name)
|
||||||
|
free(domain->name);
|
||||||
|
free(domain);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* decrement the count for the connection
|
||||||
|
*/
|
||||||
|
conn->uses--;
|
||||||
|
if (conn->uses > 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if (conn->domains != NULL)
|
||||||
|
virHashFree(conn->domains, (virHashDeallocator) virDomainFreeName);
|
||||||
|
if (conn->domains_mux != NULL)
|
||||||
|
xmlFreeMutex(conn->domains_mux);
|
||||||
|
free(conn);
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
done:
|
||||||
|
xmlMutexUnlock(conn->domains_mux);
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
36
src/hash.h
36
src/hash.h
@ -1,11 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* Summary: Chained hash tables
|
* Summary: Chained hash tables and domain/connections handling
|
||||||
* Description: This module implements the hash table support used in
|
* Description: This module implements the hash table and allocation and
|
||||||
* various places in the library.
|
* deallocation of domains and connections
|
||||||
*
|
*
|
||||||
* Copy: Copyright (C) 2005 Red Hat, Inc.
|
* Copy: Copyright (C) 2005 Red Hat, Inc.
|
||||||
*
|
*
|
||||||
* Author: Bjorn Reese <bjorn.reese@systematic.dk>
|
* Author: Bjorn Reese <bjorn.reese@systematic.dk>
|
||||||
|
* Daniel Veillard <veillard@redhat.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __VIR_HASH_H__
|
#ifndef __VIR_HASH_H__
|
||||||
@ -18,8 +19,8 @@ extern "C" {
|
|||||||
/*
|
/*
|
||||||
* The hash table.
|
* The hash table.
|
||||||
*/
|
*/
|
||||||
typedef struct _virHashTable virHashTable;
|
typedef struct _virHashTable virHashTable;
|
||||||
typedef virHashTable *virHashTablePtr;
|
typedef virHashTable *virHashTablePtr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* function types:
|
* function types:
|
||||||
@ -32,35 +33,34 @@ extern "C" {
|
|||||||
*
|
*
|
||||||
* Callback to free data from a hash.
|
* Callback to free data from a hash.
|
||||||
*/
|
*/
|
||||||
typedef void (*virHashDeallocator) (void *payload, char *name);
|
typedef void (*virHashDeallocator) (void *payload, char *name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constructor and destructor.
|
* Constructor and destructor.
|
||||||
*/
|
*/
|
||||||
virHashTablePtr virHashCreate(int size);
|
virHashTablePtr virHashCreate(int size);
|
||||||
void
|
void virHashFree(virHashTablePtr table, virHashDeallocator f);
|
||||||
virHashFree(virHashTablePtr table, virHashDeallocator f);
|
int virHashSize(virHashTablePtr table);
|
||||||
int virHashSize(virHashTablePtr table);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a new entry to the hash table.
|
* Add a new entry to the hash table.
|
||||||
*/
|
*/
|
||||||
int virHashAddEntry(virHashTablePtr table,
|
int virHashAddEntry(virHashTablePtr table,
|
||||||
const char *name, void *userdata);
|
const char *name, void *userdata);
|
||||||
int virHashUpdateEntry(virHashTablePtr table,
|
int virHashUpdateEntry(virHashTablePtr table,
|
||||||
const char *name,
|
const char *name,
|
||||||
void *userdata, virHashDeallocator f);
|
void *userdata, virHashDeallocator f);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove an entry from the hash table.
|
* Remove an entry from the hash table.
|
||||||
*/
|
*/
|
||||||
int virHashRemoveEntry(virHashTablePtr table,
|
int virHashRemoveEntry(virHashTablePtr table,
|
||||||
const char *name, virHashDeallocator f);
|
const char *name, virHashDeallocator f);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Retrieve the userdata.
|
* Retrieve the userdata.
|
||||||
*/
|
*/
|
||||||
void *virHashLookup(virHashTablePtr table, const char *name);
|
void *virHashLookup(virHashTablePtr table, const char *name);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -94,6 +94,7 @@ extern "C" {
|
|||||||
struct _virConnect {
|
struct _virConnect {
|
||||||
unsigned int magic; /* specific value to check */
|
unsigned int magic; /* specific value to check */
|
||||||
|
|
||||||
|
int uses; /* reference count */
|
||||||
/* the list of available drivers for that connection */
|
/* the list of available drivers for that connection */
|
||||||
virDriverPtr drivers[MAX_DRIVERS];
|
virDriverPtr drivers[MAX_DRIVERS];
|
||||||
int nb_drivers;
|
int nb_drivers;
|
||||||
@ -137,6 +138,7 @@ enum {
|
|||||||
*/
|
*/
|
||||||
struct _virDomain {
|
struct _virDomain {
|
||||||
unsigned int magic; /* specific value to check */
|
unsigned int magic; /* specific value to check */
|
||||||
|
int uses; /* reference count */
|
||||||
virConnectPtr conn; /* pointer back to the connection */
|
virConnectPtr conn; /* pointer back to the connection */
|
||||||
char *name; /* the domain external name */
|
char *name; /* the domain external name */
|
||||||
char *path; /* the domain internal path */
|
char *path; /* the domain internal path */
|
||||||
@ -152,6 +154,11 @@ char *virDomainGetVM(virDomainPtr domain);
|
|||||||
char *virDomainGetVMInfo(virDomainPtr domain,
|
char *virDomainGetVMInfo(virDomainPtr domain,
|
||||||
const char *vm, const char *name);
|
const char *vm, const char *name);
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* API for error handling *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
void __virRaiseError(virConnectPtr conn,
|
void __virRaiseError(virConnectPtr conn,
|
||||||
virDomainPtr dom,
|
virDomainPtr dom,
|
||||||
int domain,
|
int domain,
|
||||||
@ -163,6 +170,20 @@ void __virRaiseError(virConnectPtr conn,
|
|||||||
int int1, int int2, const char *msg, ...);
|
int int1, int int2, const char *msg, ...);
|
||||||
const char *__virErrorMsg(virErrorNumber error, const char *info);
|
const char *__virErrorMsg(virErrorNumber error, const char *info);
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* API for domain/connections (de)allocations *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
virConnectPtr virGetConnect (void);
|
||||||
|
int virFreeConnect (virConnectPtr conn);
|
||||||
|
virDomainPtr virGetDomain (virConnectPtr conn,
|
||||||
|
const char *name,
|
||||||
|
const char *uuid);
|
||||||
|
int virFreeDomain (virConnectPtr conn,
|
||||||
|
virDomainPtr domain);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
108
src/libvirt.c
108
src/libvirt.c
@ -25,7 +25,6 @@
|
|||||||
#include "xen_internal.h"
|
#include "xen_internal.h"
|
||||||
#include "xend_internal.h"
|
#include "xend_internal.h"
|
||||||
#include "xs_internal.h"
|
#include "xs_internal.h"
|
||||||
#include "hash.h"
|
|
||||||
#include "xml.h"
|
#include "xml.h"
|
||||||
|
|
||||||
|
|
||||||
@ -36,8 +35,6 @@
|
|||||||
* - memory wrappers for malloc/free ?
|
* - memory wrappers for malloc/free ?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int virDomainFreeName(virDomainPtr domain, const char *name);
|
|
||||||
|
|
||||||
static virDriverPtr virDriverTab[MAX_DRIVERS];
|
static virDriverPtr virDriverTab[MAX_DRIVERS];
|
||||||
static int initialized = 0;
|
static int initialized = 0;
|
||||||
|
|
||||||
@ -222,14 +219,11 @@ virConnectOpen(const char *name)
|
|||||||
if (!initialized)
|
if (!initialized)
|
||||||
virInitialize();
|
virInitialize();
|
||||||
|
|
||||||
ret = (virConnectPtr) malloc(sizeof(virConnect));
|
ret = virGetConnect();
|
||||||
if (ret == NULL) {
|
if (ret == NULL) {
|
||||||
virLibConnError(NULL, VIR_ERR_NO_MEMORY, "Allocating connection");
|
virLibConnError(NULL, VIR_ERR_NO_MEMORY, "Allocating connection");
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
memset(ret, 0, sizeof(virConnect));
|
|
||||||
ret->magic = VIR_CONNECT_MAGIC;
|
|
||||||
ret->nb_drivers = 0;
|
|
||||||
|
|
||||||
for (i = 0;i < MAX_DRIVERS;i++) {
|
for (i = 0;i < MAX_DRIVERS;i++) {
|
||||||
if ((virDriverTab[i] != NULL) && (virDriverTab[i]->open != NULL)) {
|
if ((virDriverTab[i] != NULL) && (virDriverTab[i]->open != NULL)) {
|
||||||
@ -252,14 +246,6 @@ virConnectOpen(const char *name)
|
|||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret->domains = virHashCreate(20);
|
|
||||||
if (ret->domains == NULL)
|
|
||||||
goto failed;
|
|
||||||
ret->domains_mux = xmlNewMutex();
|
|
||||||
if (ret->domains_mux == NULL)
|
|
||||||
goto failed;
|
|
||||||
ret->flags = 0;
|
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
|
|
||||||
failed:
|
failed:
|
||||||
@ -268,11 +254,7 @@ failed:
|
|||||||
if ((ret->drivers[i] != NULL) && (ret->drivers[i]->close != NULL))
|
if ((ret->drivers[i] != NULL) && (ret->drivers[i]->close != NULL))
|
||||||
ret->drivers[i]->close(ret);
|
ret->drivers[i]->close(ret);
|
||||||
}
|
}
|
||||||
if (ret->domains != NULL)
|
virFreeConnect(ret);
|
||||||
virHashFree(ret->domains, (virHashDeallocator) virDomainFreeName);
|
|
||||||
if (ret->domains_mux != NULL)
|
|
||||||
xmlFreeMutex(ret->domains_mux);
|
|
||||||
free(ret);
|
|
||||||
}
|
}
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
@ -296,14 +278,11 @@ virConnectOpenReadOnly(const char *name)
|
|||||||
if (!initialized)
|
if (!initialized)
|
||||||
virInitialize();
|
virInitialize();
|
||||||
|
|
||||||
ret = (virConnectPtr) malloc(sizeof(virConnect));
|
ret = virGetConnect();
|
||||||
if (ret == NULL) {
|
if (ret == NULL) {
|
||||||
virLibConnError(NULL, VIR_ERR_NO_MEMORY, "Allocating connection");
|
virLibConnError(NULL, VIR_ERR_NO_MEMORY, "Allocating connection");
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
memset(ret, 0, sizeof(virConnect));
|
|
||||||
ret->magic = VIR_CONNECT_MAGIC;
|
|
||||||
ret->nb_drivers = 0;
|
|
||||||
|
|
||||||
for (i = 0;i < MAX_DRIVERS;i++) {
|
for (i = 0;i < MAX_DRIVERS;i++) {
|
||||||
if ((virDriverTab[i] != NULL) && (virDriverTab[i]->open != NULL)) {
|
if ((virDriverTab[i] != NULL) && (virDriverTab[i]->open != NULL)) {
|
||||||
@ -322,13 +301,6 @@ virConnectOpenReadOnly(const char *name)
|
|||||||
virLibConnError(NULL, VIR_ERR_NO_SUPPORT, name);
|
virLibConnError(NULL, VIR_ERR_NO_SUPPORT, name);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret->domains = virHashCreate(20);
|
|
||||||
if (ret->domains == NULL)
|
|
||||||
goto failed;
|
|
||||||
ret->domains_mux = xmlNewMutex();
|
|
||||||
if (ret->domains_mux == NULL)
|
|
||||||
goto failed;
|
|
||||||
ret->flags = VIR_CONNECT_RO;
|
ret->flags = VIR_CONNECT_RO;
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
@ -339,29 +311,11 @@ failed:
|
|||||||
if ((ret->drivers[i] != NULL) && (ret->drivers[i]->close != NULL))
|
if ((ret->drivers[i] != NULL) && (ret->drivers[i]->close != NULL))
|
||||||
ret->drivers[i]->close(ret);
|
ret->drivers[i]->close(ret);
|
||||||
}
|
}
|
||||||
if (ret->domains != NULL)
|
virFreeConnect(ret);
|
||||||
virHashFree(ret->domains, (virHashDeallocator) virDomainFreeName);
|
|
||||||
if (ret->domains_mux != NULL)
|
|
||||||
xmlFreeMutex(ret->domains_mux);
|
|
||||||
free(ret);
|
|
||||||
}
|
}
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* virDomainFreeName:
|
|
||||||
* @domain: a domain object
|
|
||||||
*
|
|
||||||
* Destroy the domain object, this is just used by the domain hash callback.
|
|
||||||
*
|
|
||||||
* Returns 0 in case of success and -1 in case of failure.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
virDomainFreeName(virDomainPtr domain, const char *name ATTRIBUTE_UNUSED)
|
|
||||||
{
|
|
||||||
return (virDomainFree(domain));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virConnectClose:
|
* virConnectClose:
|
||||||
* @conn: pointer to the hypervisor connection
|
* @conn: pointer to the hypervisor connection
|
||||||
@ -376,20 +330,10 @@ virDomainFreeName(virDomainPtr domain, const char *name ATTRIBUTE_UNUSED)
|
|||||||
int
|
int
|
||||||
virConnectClose(virConnectPtr conn)
|
virConnectClose(virConnectPtr conn)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!VIR_IS_CONNECT(conn))
|
if (!VIR_IS_CONNECT(conn))
|
||||||
return (-1);
|
return (-1);
|
||||||
virHashFree(conn->domains, (virHashDeallocator) virDomainFreeName);
|
if (virFreeConnect(conn) < 0)
|
||||||
conn->domains = NULL;
|
return (-1);
|
||||||
xmlFreeMutex(conn->domains_mux);
|
|
||||||
conn->domains_mux = NULL;
|
|
||||||
for (i = 0;i < conn->nb_drivers;i++) {
|
|
||||||
if ((conn->drivers[i] != NULL) && (conn->drivers[i]->close != NULL))
|
|
||||||
conn->drivers[i]->close(conn);
|
|
||||||
}
|
|
||||||
conn->magic = -1;
|
|
||||||
free(conn);
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -663,26 +607,23 @@ virDomainLookupByID(virConnectPtr conn, int id)
|
|||||||
}
|
}
|
||||||
free(names);
|
free(names);
|
||||||
}
|
}
|
||||||
|
if (name == NULL)
|
||||||
|
goto error;
|
||||||
|
|
||||||
ret = (virDomainPtr) malloc(sizeof(virDomain));
|
ret = virGetDomain(conn, name, &uuid[0]);
|
||||||
if (ret == NULL) {
|
if (ret == NULL) {
|
||||||
|
virLibConnError(conn, VIR_ERR_NO_MEMORY, "Allocating domain");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
memset(ret, 0, sizeof(virDomain));
|
|
||||||
ret->magic = VIR_DOMAIN_MAGIC;
|
|
||||||
ret->conn = conn;
|
|
||||||
ret->handle = id;
|
ret->handle = id;
|
||||||
ret->path = path;
|
ret->path = path;
|
||||||
ret->name = name;
|
if (name != NULL)
|
||||||
memcpy(&ret->uuid[0], uuid, 16);
|
free(name);
|
||||||
if (ret->name == NULL) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
error:
|
error:
|
||||||
if (ret != NULL)
|
if (name != NULL)
|
||||||
free(ret);
|
free(name);
|
||||||
if (path != NULL)
|
if (path != NULL)
|
||||||
free(path);
|
free(path);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@ -737,19 +678,13 @@ virDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
|
|||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
ret = (virDomainPtr) malloc(sizeof(virDomain));
|
ret = virGetDomain(conn, name, &uuid[0]);
|
||||||
if (ret == NULL) {
|
if (ret == NULL) {
|
||||||
if (name != NULL)
|
if (name != NULL)
|
||||||
free(name);
|
free(name);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
memset(ret, 0, sizeof(virDomain));
|
|
||||||
ret->magic = VIR_DOMAIN_MAGIC;
|
|
||||||
ret->conn = conn;
|
|
||||||
ret->handle = id;
|
ret->handle = id;
|
||||||
ret->name = name;
|
|
||||||
ret->path = 0;
|
|
||||||
memcpy(ret->uuid, uuid, 16);
|
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
@ -847,14 +782,9 @@ virDomainFree(virDomainPtr domain)
|
|||||||
virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
|
virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
domain->magic = -1;
|
if (virFreeDomain(domain->conn, domain) < 0)
|
||||||
domain->handle = -1;
|
return (-1);
|
||||||
if (domain->path != NULL)
|
return(0);
|
||||||
free(domain->path);
|
|
||||||
if (domain->name)
|
|
||||||
free(domain->name);
|
|
||||||
free(domain);
|
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1586,41 +1586,37 @@ sexpr_to_xend_node_info(struct sexpr *root, virNodeInfoPtr info)
|
|||||||
static virDomainPtr
|
static virDomainPtr
|
||||||
sexpr_to_domain(virConnectPtr conn, struct sexpr *root)
|
sexpr_to_domain(virConnectPtr conn, struct sexpr *root)
|
||||||
{
|
{
|
||||||
virDomainPtr ret;
|
virDomainPtr ret = NULL;
|
||||||
char *dst_uuid = NULL;
|
char *dst_uuid = NULL;
|
||||||
|
char uuid[16];
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
if ((conn == NULL) || (root == NULL))
|
if ((conn == NULL) || (root == NULL))
|
||||||
return(NULL);
|
return(NULL);
|
||||||
|
|
||||||
ret = (virDomainPtr) malloc(sizeof(virDomain));
|
dst_uuid = (char *) &uuid[0];
|
||||||
if (ret == NULL) {
|
|
||||||
virXendError(conn, VIR_ERR_NO_MEMORY, "Allocating domain");
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
memset(ret, 0, sizeof(virDomain));
|
|
||||||
ret->magic = VIR_DOMAIN_MAGIC;
|
|
||||||
ret->conn = conn;
|
|
||||||
ret->handle = sexpr_int(root, "domain/domid");
|
|
||||||
if (ret->handle < 0)
|
|
||||||
goto error;
|
|
||||||
dst_uuid = (char *) &(ret->uuid[0]);
|
|
||||||
if (sexpr_uuid(&dst_uuid, root, "domain/uuid") == NULL)
|
if (sexpr_uuid(&dst_uuid, root, "domain/uuid") == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
name = sexpr_node(root, "domain/name");
|
name = sexpr_node(root, "domain/name");
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
ret->name = strdup(name);
|
|
||||||
if (ret->name == NULL)
|
ret = virGetDomain(conn, name, &uuid[0]);
|
||||||
|
if (ret == NULL) {
|
||||||
|
virXendError(conn, VIR_ERR_NO_MEMORY, "Allocating domain");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
ret->handle = sexpr_int(root, "domain/domid");
|
||||||
|
if (ret->handle < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
virXendError(conn, VIR_ERR_INTERNAL_ERROR,
|
virXendError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
"failed to parse Xend domain informations");
|
"failed to parse Xend domain informations");
|
||||||
if (ret->name != NULL)
|
if (ret != NULL)
|
||||||
free(ret->name );
|
virFreeDomain(conn, ret);
|
||||||
free(ret);
|
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -556,15 +556,15 @@ xenStoreDomainLookupByName(virConnectPtr conn, const char *name)
|
|||||||
if (!found)
|
if (!found)
|
||||||
return(NULL);
|
return(NULL);
|
||||||
|
|
||||||
ret = (virDomainPtr) malloc(sizeof(virDomain));
|
ret = virGetDomain(conn, name, NULL);
|
||||||
if (ret == NULL)
|
if (ret == NULL) {
|
||||||
|
virXenStoreError(conn, VIR_ERR_NO_MEMORY, "Allocating domain");
|
||||||
|
if (path != NULL)
|
||||||
|
free(path);
|
||||||
goto done;
|
goto done;
|
||||||
memset(ret, 0, sizeof(virDomain));
|
}
|
||||||
ret->magic = VIR_DOMAIN_MAGIC;
|
|
||||||
ret->conn = conn;
|
|
||||||
ret->handle = id;
|
ret->handle = id;
|
||||||
ret->path = path;
|
ret->path = path;
|
||||||
ret->name = strdup(name);
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (xenddomain != NULL)
|
if (xenddomain != NULL)
|
||||||
|
Loading…
Reference in New Issue
Block a user