daemon: Create priority workers pool

This patch annotates APIs with low or high priority.
In low set MUST be all APIs which might eventually access monitor
(and thus block indefinitely). Other APIs may be marked as high
priority. However, some must be (e.g. domainDestroy).

For high priority calls (HPC), there are some high priority workers
(HPW) created in the pool. HPW can execute only HPC, although normal
worker can process any call regardless priority. Therefore, only those
APIs which are guaranteed to end in reasonable small amount of time
can be marked as HPC.

The size of this HPC pool is static, because HPC are expected to end
quickly, therefore jobs assigned to this pool will be served quickly.
It can be configured in libvirtd.conf via prio_workers variable.
Default is set to 5.

To mark API with low or high priority, append priority:{low|high} to
it's comment in src/remote/remote_protocol.x. This is similar to
autogen|skipgen. If not marked, the generator assumes low as default.
This commit is contained in:
Michal Privoznik 2011-08-12 14:04:31 +02:00
parent 6337989089
commit 597fe3cee6
14 changed files with 376 additions and 199 deletions

View File

@ -57,6 +57,7 @@ module Libvirtd =
| int_entry "max_clients"
| int_entry "max_requests"
| int_entry "max_client_requests"
| int_entry "prio_workers"
let logging_entry = int_entry "log_level"
| str_entry "log_filters"

View File

@ -134,6 +134,8 @@ struct daemonConfig {
int max_workers;
int max_clients;
int prio_workers;
int max_requests;
int max_client_requests;
@ -886,6 +888,8 @@ daemonConfigNew(bool privileged ATTRIBUTE_UNUSED)
data->max_workers = 20;
data->max_clients = 20;
data->prio_workers = 5;
data->max_requests = 20;
data->max_client_requests = 5;
@ -1042,6 +1046,8 @@ daemonConfigLoad(struct daemonConfig *data,
GET_CONF_INT (conf, filename, max_workers);
GET_CONF_INT (conf, filename, max_clients);
GET_CONF_INT (conf, filename, prio_workers);
GET_CONF_INT (conf, filename, max_requests);
GET_CONF_INT (conf, filename, max_client_requests);
@ -1441,6 +1447,7 @@ int main(int argc, char **argv) {
config->auth_unix_ro == REMOTE_AUTH_POLKIT;
if (!(srv = virNetServerNew(config->min_workers,
config->max_workers,
config->prio_workers,
config->max_clients,
config->mdns_adv ? config->mdns_name : NULL,
use_polkit_dbus,

View File

@ -257,6 +257,12 @@
#min_workers = 5
#max_workers = 20
# The number of priority workers. If all workers from above
# pool will stuck, some calls marked as high priority
# (notably domainDestroy) can be executed in this pool.
#prio_workers = 5
# Total global limit on concurrent RPC calls. Should be
# at least as large as max_workers. Beyond this, RPC requests
# will be read into memory and queued. This directly impact

View File

@ -663,7 +663,7 @@ qemudStartup(int privileged) {
virHashForEach(qemu_driver->domains.objs, qemuDomainSnapshotLoad,
qemu_driver->snapshotDir);
qemu_driver->workerPool = virThreadPoolNew(0, 1, processWatchdogEvent, qemu_driver);
qemu_driver->workerPool = virThreadPoolNew(0, 1, 0, processWatchdogEvent, qemu_driver);
if (!qemu_driver->workerPool)
goto error;

View File

@ -571,7 +571,7 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
* deleted before handling watchdog event is finished.
*/
virDomainObjRef(vm);
if (virThreadPoolSendJob(driver->workerPool, wdEvent) < 0) {
if (virThreadPoolSendJob(driver->workerPool, 0, wdEvent) < 0) {
if (virDomainObjUnref(vm) == 0)
vm = NULL;
VIR_FREE(wdEvent);

View File

@ -52,9 +52,14 @@ const QEMU_PROGRAM = 0x20008087;
const QEMU_PROTOCOL_VERSION = 1;
enum qemu_procedure {
/* Each function must have a two-word comment. The first word is
/* Each function must have a three-word comment. The first word is
* whether gendispatch.pl handles daemon, the second whether
* it handles src/remote. */
QEMU_PROC_MONITOR_COMMAND = 1, /* skipgen skipgen */
QEMU_PROC_DOMAIN_ATTACH = 2 /* autogen autogen */
* it handles src/remote.
* The last argument describes priority of API. There are two accepted
* values: low, high; Each API that might eventually access hypervisor's
* monitor (and thus block) MUST fall into low priority. However, there
* are some exceptions to this rule, e.g. domainDestroy. Other APIs MAY
* be marked as high priority. If in doubt, it's safe to choose low. */
QEMU_PROC_MONITOR_COMMAND = 1, /* skipgen skipgen priority:low */
QEMU_PROC_DOMAIN_ATTACH = 2 /* autogen autogen priority:low */
};

View File

@ -2211,189 +2211,195 @@ const REMOTE_PROGRAM = 0x20008086;
const REMOTE_PROTOCOL_VERSION = 1;
enum remote_procedure {
/* Each function must have a two-word comment. The first word is
/* Each function must have a three-word comment. The first word is
* whether gendispatch.pl handles daemon, the second whether
* it handles src/remote. Additional flags can be specified after a
* pipe.
* The last argument describes priority of API. There are two accepted
* values: low, high; Each API that might eventually access hypervisor's
* monitor (and thus block) MUST fall into low priority. However, there
* are some exceptions to this rule, e.g. domainDestroy. Other APIs MAY
* be marked as high priority. If in doubt, it's safe to choose low.
* Low is taken as default, and thus can be left out.
*
* The (readstream|writestream)@<offset> flag lets daemon and src/remote
* create a stream. The direction is defined from the src/remote point
* of view. A readstream transfers data from daemon to src/remote. The
* <offset> specifies at which offset the stream parameter is inserted
* in the function parameter list. */
REMOTE_PROC_OPEN = 1, /* skipgen skipgen */
REMOTE_PROC_CLOSE = 2, /* skipgen skipgen */
REMOTE_PROC_GET_TYPE = 3, /* autogen skipgen */
REMOTE_PROC_GET_VERSION = 4, /* autogen autogen */
REMOTE_PROC_GET_MAX_VCPUS = 5, /* autogen autogen */
REMOTE_PROC_NODE_GET_INFO = 6, /* autogen autogen */
REMOTE_PROC_OPEN = 1, /* skipgen skipgen priority:high */
REMOTE_PROC_CLOSE = 2, /* skipgen skipgen priority:high */
REMOTE_PROC_GET_TYPE = 3, /* autogen skipgen priority:high */
REMOTE_PROC_GET_VERSION = 4, /* autogen autogen priority:high */
REMOTE_PROC_GET_MAX_VCPUS = 5, /* autogen autogen priority:high */
REMOTE_PROC_NODE_GET_INFO = 6, /* autogen autogen priority:high */
REMOTE_PROC_GET_CAPABILITIES = 7, /* autogen autogen */
REMOTE_PROC_DOMAIN_ATTACH_DEVICE = 8, /* autogen autogen */
REMOTE_PROC_DOMAIN_CREATE = 9, /* autogen skipgen */
REMOTE_PROC_DOMAIN_CREATE_XML = 10, /* autogen autogen */
REMOTE_PROC_DOMAIN_DEFINE_XML = 11, /* autogen autogen */
REMOTE_PROC_DOMAIN_DESTROY = 12, /* autogen autogen */
REMOTE_PROC_DOMAIN_DEFINE_XML = 11, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_DESTROY = 12, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_DETACH_DEVICE = 13, /* autogen autogen */
REMOTE_PROC_DOMAIN_GET_XML_DESC = 14, /* autogen autogen */
REMOTE_PROC_DOMAIN_GET_AUTOSTART = 15, /* autogen autogen */
REMOTE_PROC_DOMAIN_GET_AUTOSTART = 15, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_GET_INFO = 16, /* autogen autogen */
REMOTE_PROC_DOMAIN_GET_MAX_MEMORY = 17, /* autogen autogen */
REMOTE_PROC_DOMAIN_GET_MAX_VCPUS = 18, /* autogen autogen */
REMOTE_PROC_DOMAIN_GET_OS_TYPE = 19, /* autogen autogen */
REMOTE_PROC_DOMAIN_GET_VCPUS = 20, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_GET_MAX_MEMORY = 17, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_GET_MAX_VCPUS = 18, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_GET_OS_TYPE = 19, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_GET_VCPUS = 20, /* skipgen skipgen priority:high */
REMOTE_PROC_LIST_DEFINED_DOMAINS = 21, /* autogen autogen */
REMOTE_PROC_DOMAIN_LOOKUP_BY_ID = 22, /* autogen autogen */
REMOTE_PROC_DOMAIN_LOOKUP_BY_NAME = 23, /* autogen autogen */
REMOTE_PROC_DOMAIN_LOOKUP_BY_UUID = 24, /* autogen autogen */
REMOTE_PROC_NUM_OF_DEFINED_DOMAINS = 25, /* autogen autogen */
REMOTE_PROC_LIST_DEFINED_DOMAINS = 21, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_LOOKUP_BY_ID = 22, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_LOOKUP_BY_NAME = 23, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_LOOKUP_BY_UUID = 24, /* autogen autogen priority:high */
REMOTE_PROC_NUM_OF_DEFINED_DOMAINS = 25, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_PIN_VCPU = 26, /* autogen autogen */
REMOTE_PROC_DOMAIN_REBOOT = 27, /* autogen autogen */
REMOTE_PROC_DOMAIN_RESUME = 28, /* autogen autogen */
REMOTE_PROC_DOMAIN_SET_AUTOSTART = 29, /* autogen autogen */
REMOTE_PROC_DOMAIN_SET_MAX_MEMORY = 30, /* autogen autogen */
REMOTE_PROC_DOMAIN_SET_AUTOSTART = 29, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_SET_MAX_MEMORY = 30, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_SET_MEMORY = 31, /* autogen autogen */
REMOTE_PROC_DOMAIN_SET_VCPUS = 32, /* autogen autogen */
REMOTE_PROC_DOMAIN_SHUTDOWN = 33, /* autogen autogen */
REMOTE_PROC_DOMAIN_SUSPEND = 34, /* autogen autogen */
REMOTE_PROC_DOMAIN_UNDEFINE = 35, /* autogen autogen */
REMOTE_PROC_LIST_DEFINED_NETWORKS = 36, /* autogen autogen */
REMOTE_PROC_LIST_DOMAINS = 37, /* autogen skipgen */
REMOTE_PROC_LIST_NETWORKS = 38, /* autogen autogen */
REMOTE_PROC_DOMAIN_UNDEFINE = 35, /* autogen autogen priority:high */
REMOTE_PROC_LIST_DEFINED_NETWORKS = 36, /* autogen autogen priority:high */
REMOTE_PROC_LIST_DOMAINS = 37, /* autogen skipgen priority:high */
REMOTE_PROC_LIST_NETWORKS = 38, /* autogen autogen priority:high */
REMOTE_PROC_NETWORK_CREATE = 39, /* autogen autogen */
REMOTE_PROC_NETWORK_CREATE_XML = 40, /* autogen autogen */
REMOTE_PROC_NETWORK_DEFINE_XML = 41, /* autogen autogen */
REMOTE_PROC_NETWORK_DESTROY = 42, /* autogen autogen */
REMOTE_PROC_NETWORK_GET_XML_DESC = 43, /* autogen autogen */
REMOTE_PROC_NETWORK_GET_AUTOSTART = 44, /* autogen autogen */
REMOTE_PROC_NETWORK_GET_BRIDGE_NAME = 45, /* autogen autogen */
REMOTE_PROC_NETWORK_LOOKUP_BY_NAME = 46, /* autogen autogen */
REMOTE_PROC_NETWORK_LOOKUP_BY_UUID = 47, /* autogen autogen */
REMOTE_PROC_NETWORK_SET_AUTOSTART = 48, /* autogen autogen */
REMOTE_PROC_NETWORK_UNDEFINE = 49, /* autogen autogen */
REMOTE_PROC_NUM_OF_DEFINED_NETWORKS = 50, /* autogen autogen */
REMOTE_PROC_NETWORK_DEFINE_XML = 41, /* autogen autogen priority:high */
REMOTE_PROC_NETWORK_DESTROY = 42, /* autogen autogen priority:high */
REMOTE_PROC_NETWORK_GET_XML_DESC = 43, /* autogen autogen priority:high */
REMOTE_PROC_NETWORK_GET_AUTOSTART = 44, /* autogen autogen priority:high */
REMOTE_PROC_NETWORK_GET_BRIDGE_NAME = 45, /* autogen autogen priority:high */
REMOTE_PROC_NETWORK_LOOKUP_BY_NAME = 46, /* autogen autogen priority:high */
REMOTE_PROC_NETWORK_LOOKUP_BY_UUID = 47, /* autogen autogen priority:high */
REMOTE_PROC_NETWORK_SET_AUTOSTART = 48, /* autogen autogen priority:high */
REMOTE_PROC_NETWORK_UNDEFINE = 49, /* autogen autogen priority:high */
REMOTE_PROC_NUM_OF_DEFINED_NETWORKS = 50, /* autogen autogen priority:high */
REMOTE_PROC_NUM_OF_DOMAINS = 51, /* autogen autogen */
REMOTE_PROC_NUM_OF_NETWORKS = 52, /* autogen autogen */
REMOTE_PROC_NUM_OF_DOMAINS = 51, /* autogen autogen priority:high */
REMOTE_PROC_NUM_OF_NETWORKS = 52, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_CORE_DUMP = 53, /* autogen autogen */
REMOTE_PROC_DOMAIN_RESTORE = 54, /* autogen autogen */
REMOTE_PROC_DOMAIN_SAVE = 55, /* autogen autogen */
REMOTE_PROC_DOMAIN_GET_SCHEDULER_TYPE = 56, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_GET_SCHEDULER_PARAMETERS = 57, /* skipgen autogen */
REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS = 58, /* autogen autogen */
REMOTE_PROC_GET_HOSTNAME = 59, /* autogen autogen */
REMOTE_PROC_SUPPORTS_FEATURE = 60, /* autogen autogen */
REMOTE_PROC_GET_HOSTNAME = 59, /* autogen autogen priority:high */
REMOTE_PROC_SUPPORTS_FEATURE = 60, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_MIGRATE_PREPARE = 61, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_MIGRATE_PERFORM = 62, /* autogen autogen */
REMOTE_PROC_DOMAIN_MIGRATE_FINISH = 63, /* autogen autogen */
REMOTE_PROC_DOMAIN_BLOCK_STATS = 64, /* autogen autogen */
REMOTE_PROC_DOMAIN_INTERFACE_STATS = 65, /* autogen autogen */
REMOTE_PROC_AUTH_LIST = 66, /* skipgen skipgen */
REMOTE_PROC_AUTH_SASL_INIT = 67, /* skipgen skipgen */
REMOTE_PROC_AUTH_SASL_START = 68, /* skipgen skipgen */
REMOTE_PROC_AUTH_SASL_STEP = 69, /* skipgen skipgen */
REMOTE_PROC_AUTH_POLKIT = 70, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_INTERFACE_STATS = 65, /* autogen autogen priority:high */
REMOTE_PROC_AUTH_LIST = 66, /* skipgen skipgen priority:high */
REMOTE_PROC_AUTH_SASL_INIT = 67, /* skipgen skipgen priority:high */
REMOTE_PROC_AUTH_SASL_START = 68, /* skipgen skipgen priority:high */
REMOTE_PROC_AUTH_SASL_STEP = 69, /* skipgen skipgen priority:high */
REMOTE_PROC_AUTH_POLKIT = 70, /* skipgen skipgen priority:high */
REMOTE_PROC_NUM_OF_STORAGE_POOLS = 71, /* autogen autogen */
REMOTE_PROC_LIST_STORAGE_POOLS = 72, /* autogen autogen */
REMOTE_PROC_NUM_OF_DEFINED_STORAGE_POOLS = 73, /* autogen autogen */
REMOTE_PROC_LIST_DEFINED_STORAGE_POOLS = 74, /* autogen autogen */
REMOTE_PROC_NUM_OF_STORAGE_POOLS = 71, /* autogen autogen priority:high */
REMOTE_PROC_LIST_STORAGE_POOLS = 72, /* autogen autogen priority:high */
REMOTE_PROC_NUM_OF_DEFINED_STORAGE_POOLS = 73, /* autogen autogen priority:high */
REMOTE_PROC_LIST_DEFINED_STORAGE_POOLS = 74, /* autogen autogen priority:high */
REMOTE_PROC_FIND_STORAGE_POOL_SOURCES = 75, /* autogen skipgen */
REMOTE_PROC_STORAGE_POOL_CREATE_XML = 76, /* autogen autogen */
REMOTE_PROC_STORAGE_POOL_DEFINE_XML = 77, /* autogen autogen */
REMOTE_PROC_STORAGE_POOL_DEFINE_XML = 77, /* autogen autogen priority:high */
REMOTE_PROC_STORAGE_POOL_CREATE = 78, /* autogen autogen */
REMOTE_PROC_STORAGE_POOL_BUILD = 79, /* autogen autogen */
REMOTE_PROC_STORAGE_POOL_DESTROY = 80, /* autogen autogen */
REMOTE_PROC_STORAGE_POOL_DESTROY = 80, /* autogen autogen priority:high */
REMOTE_PROC_STORAGE_POOL_DELETE = 81, /* autogen autogen */
REMOTE_PROC_STORAGE_POOL_UNDEFINE = 82, /* autogen autogen */
REMOTE_PROC_STORAGE_POOL_UNDEFINE = 82, /* autogen autogen priority:high */
REMOTE_PROC_STORAGE_POOL_REFRESH = 83, /* autogen autogen */
REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_NAME = 84, /* autogen autogen */
REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_UUID = 85, /* autogen autogen */
REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_VOLUME = 86, /* autogen autogen */
REMOTE_PROC_STORAGE_POOL_GET_INFO = 87, /* autogen autogen */
REMOTE_PROC_STORAGE_POOL_GET_XML_DESC = 88, /* autogen autogen */
REMOTE_PROC_STORAGE_POOL_GET_AUTOSTART = 89, /* autogen autogen */
REMOTE_PROC_STORAGE_POOL_SET_AUTOSTART = 90, /* autogen autogen */
REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_NAME = 84, /* autogen autogen priority:high */
REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_UUID = 85, /* autogen autogen priority:high */
REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_VOLUME = 86, /* autogen autogen priority:high */
REMOTE_PROC_STORAGE_POOL_GET_INFO = 87, /* autogen autogen priority:high */
REMOTE_PROC_STORAGE_POOL_GET_XML_DESC = 88, /* autogen autogen priority:high */
REMOTE_PROC_STORAGE_POOL_GET_AUTOSTART = 89, /* autogen autogen priority:high */
REMOTE_PROC_STORAGE_POOL_SET_AUTOSTART = 90, /* autogen autogen priority:high */
REMOTE_PROC_STORAGE_POOL_NUM_OF_VOLUMES = 91, /* autogen autogen */
REMOTE_PROC_STORAGE_POOL_LIST_VOLUMES = 92, /* autogen autogen */
REMOTE_PROC_STORAGE_POOL_NUM_OF_VOLUMES = 91, /* autogen autogen priority:high */
REMOTE_PROC_STORAGE_POOL_LIST_VOLUMES = 92, /* autogen autogen priority:high */
REMOTE_PROC_STORAGE_VOL_CREATE_XML = 93, /* autogen autogen */
REMOTE_PROC_STORAGE_VOL_DELETE = 94, /* autogen autogen */
REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_NAME = 95, /* autogen autogen */
REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_KEY = 96, /* autogen autogen */
REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_PATH = 97, /* autogen autogen */
REMOTE_PROC_STORAGE_VOL_GET_INFO = 98, /* autogen autogen */
REMOTE_PROC_STORAGE_VOL_GET_XML_DESC = 99, /* autogen autogen */
REMOTE_PROC_STORAGE_VOL_GET_PATH = 100, /* autogen autogen */
REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_NAME = 95, /* autogen autogen priority:high */
REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_KEY = 96, /* autogen autogen priority:high */
REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_PATH = 97, /* autogen autogen priority:high */
REMOTE_PROC_STORAGE_VOL_GET_INFO = 98, /* autogen autogen priority:high */
REMOTE_PROC_STORAGE_VOL_GET_XML_DESC = 99, /* autogen autogen priority:high */
REMOTE_PROC_STORAGE_VOL_GET_PATH = 100, /* autogen autogen priority:high */
REMOTE_PROC_NODE_GET_CELLS_FREE_MEMORY = 101, /* autogen skipgen */
REMOTE_PROC_NODE_GET_FREE_MEMORY = 102, /* autogen autogen */
REMOTE_PROC_NODE_GET_CELLS_FREE_MEMORY = 101, /* autogen skipgen priority:high */
REMOTE_PROC_NODE_GET_FREE_MEMORY = 102, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_BLOCK_PEEK = 103, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_MEMORY_PEEK = 104, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_EVENTS_REGISTER = 105, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER = 106, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_EVENTS_REGISTER = 105, /* skipgen skipgen priority:high */
REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER = 106, /* skipgen skipgen priority:high */
REMOTE_PROC_DOMAIN_EVENT_LIFECYCLE = 107, /* autogen autogen */
REMOTE_PROC_DOMAIN_MIGRATE_PREPARE2 = 108, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_MIGRATE_FINISH2 = 109, /* autogen autogen */
REMOTE_PROC_GET_URI = 110, /* autogen skipgen */
REMOTE_PROC_GET_URI = 110, /* autogen skipgen priority:high */
REMOTE_PROC_NODE_NUM_OF_DEVICES = 111, /* autogen autogen */
REMOTE_PROC_NODE_LIST_DEVICES = 112, /* autogen autogen */
REMOTE_PROC_NODE_DEVICE_LOOKUP_BY_NAME = 113, /* autogen autogen */
REMOTE_PROC_NODE_NUM_OF_DEVICES = 111, /* autogen autogen priority:high */
REMOTE_PROC_NODE_LIST_DEVICES = 112, /* autogen autogen priority:high */
REMOTE_PROC_NODE_DEVICE_LOOKUP_BY_NAME = 113, /* autogen autogen priority:high */
REMOTE_PROC_NODE_DEVICE_GET_XML_DESC = 114, /* autogen autogen */
REMOTE_PROC_NODE_DEVICE_GET_PARENT = 115, /* skipgen autogen */
REMOTE_PROC_NODE_DEVICE_NUM_OF_CAPS = 116, /* autogen autogen */
REMOTE_PROC_NODE_DEVICE_LIST_CAPS = 117, /* autogen autogen */
REMOTE_PROC_NODE_DEVICE_GET_PARENT = 115, /* skipgen autogen priority:high */
REMOTE_PROC_NODE_DEVICE_NUM_OF_CAPS = 116, /* autogen autogen priority:high */
REMOTE_PROC_NODE_DEVICE_LIST_CAPS = 117, /* autogen autogen priority:high */
REMOTE_PROC_NODE_DEVICE_DETTACH = 118, /* autogen skipgen */
REMOTE_PROC_NODE_DEVICE_RE_ATTACH = 119, /* autogen skipgen */
REMOTE_PROC_NODE_DEVICE_RESET = 120, /* autogen skipgen */
REMOTE_PROC_DOMAIN_GET_SECURITY_LABEL = 121, /* skipgen skipgen */
REMOTE_PROC_NODE_GET_SECURITY_MODEL = 122, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_GET_SECURITY_LABEL = 121, /* skipgen skipgen priority:high */
REMOTE_PROC_NODE_GET_SECURITY_MODEL = 122, /* skipgen skipgen priority:high */
REMOTE_PROC_NODE_DEVICE_CREATE_XML = 123, /* autogen autogen */
REMOTE_PROC_NODE_DEVICE_DESTROY = 124, /* autogen autogen */
REMOTE_PROC_NODE_DEVICE_DESTROY = 124, /* autogen autogen priority:high */
REMOTE_PROC_STORAGE_VOL_CREATE_XML_FROM = 125, /* autogen autogen */
REMOTE_PROC_NUM_OF_INTERFACES = 126, /* autogen autogen */
REMOTE_PROC_LIST_INTERFACES = 127, /* autogen autogen */
REMOTE_PROC_INTERFACE_LOOKUP_BY_NAME = 128, /* autogen autogen */
REMOTE_PROC_INTERFACE_LOOKUP_BY_MAC_STRING = 129, /* autogen autogen */
REMOTE_PROC_NUM_OF_INTERFACES = 126, /* autogen autogen priority:high */
REMOTE_PROC_LIST_INTERFACES = 127, /* autogen autogen priority:high */
REMOTE_PROC_INTERFACE_LOOKUP_BY_NAME = 128, /* autogen autogen priority:high */
REMOTE_PROC_INTERFACE_LOOKUP_BY_MAC_STRING = 129, /* autogen autogen priority:high */
REMOTE_PROC_INTERFACE_GET_XML_DESC = 130, /* autogen autogen */
REMOTE_PROC_INTERFACE_DEFINE_XML = 131, /* autogen autogen */
REMOTE_PROC_INTERFACE_UNDEFINE = 132, /* autogen autogen */
REMOTE_PROC_INTERFACE_DEFINE_XML = 131, /* autogen autogen priority:high */
REMOTE_PROC_INTERFACE_UNDEFINE = 132, /* autogen autogen priority:high */
REMOTE_PROC_INTERFACE_CREATE = 133, /* autogen autogen */
REMOTE_PROC_INTERFACE_DESTROY = 134, /* autogen autogen */
REMOTE_PROC_INTERFACE_DESTROY = 134, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_XML_FROM_NATIVE = 135, /* autogen autogen */
REMOTE_PROC_DOMAIN_XML_TO_NATIVE = 136, /* autogen autogen */
REMOTE_PROC_NUM_OF_DEFINED_INTERFACES = 137, /* autogen autogen */
REMOTE_PROC_LIST_DEFINED_INTERFACES = 138, /* autogen autogen */
REMOTE_PROC_NUM_OF_SECRETS = 139, /* autogen autogen */
REMOTE_PROC_LIST_SECRETS = 140, /* autogen autogen */
REMOTE_PROC_NUM_OF_DEFINED_INTERFACES = 137, /* autogen autogen priority:high */
REMOTE_PROC_LIST_DEFINED_INTERFACES = 138, /* autogen autogen priority:high */
REMOTE_PROC_NUM_OF_SECRETS = 139, /* autogen autogen priority:high */
REMOTE_PROC_LIST_SECRETS = 140, /* autogen autogen priority:high */
REMOTE_PROC_SECRET_LOOKUP_BY_UUID = 141, /* autogen autogen */
REMOTE_PROC_SECRET_DEFINE_XML = 142, /* autogen autogen */
REMOTE_PROC_SECRET_GET_XML_DESC = 143, /* autogen autogen */
REMOTE_PROC_SECRET_SET_VALUE = 144, /* autogen autogen */
REMOTE_PROC_SECRET_GET_VALUE = 145, /* skipgen skipgen */
REMOTE_PROC_SECRET_UNDEFINE = 146, /* autogen autogen */
REMOTE_PROC_SECRET_LOOKUP_BY_USAGE = 147, /* autogen autogen */
REMOTE_PROC_SECRET_LOOKUP_BY_UUID = 141, /* autogen autogen priority:high */
REMOTE_PROC_SECRET_DEFINE_XML = 142, /* autogen autogen priority:high */
REMOTE_PROC_SECRET_GET_XML_DESC = 143, /* autogen autogen priority:high */
REMOTE_PROC_SECRET_SET_VALUE = 144, /* autogen autogen priority:high */
REMOTE_PROC_SECRET_GET_VALUE = 145, /* skipgen skipgen priority:high */
REMOTE_PROC_SECRET_UNDEFINE = 146, /* autogen autogen priority:high */
REMOTE_PROC_SECRET_LOOKUP_BY_USAGE = 147, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL = 148, /* autogen autogen | writestream@1 */
REMOTE_PROC_IS_SECURE = 149, /* autogen skipgen */
REMOTE_PROC_DOMAIN_IS_ACTIVE = 150, /* autogen autogen */
REMOTE_PROC_IS_SECURE = 149, /* autogen skipgen priority:high */
REMOTE_PROC_DOMAIN_IS_ACTIVE = 150, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_IS_PERSISTENT = 151, /* autogen autogen */
REMOTE_PROC_NETWORK_IS_ACTIVE = 152, /* autogen autogen */
REMOTE_PROC_NETWORK_IS_PERSISTENT = 153, /* autogen autogen */
REMOTE_PROC_STORAGE_POOL_IS_ACTIVE = 154, /* autogen autogen */
REMOTE_PROC_STORAGE_POOL_IS_PERSISTENT = 155, /* autogen autogen */
REMOTE_PROC_INTERFACE_IS_ACTIVE = 156, /* autogen autogen */
REMOTE_PROC_GET_LIB_VERSION = 157, /* autogen autogen */
REMOTE_PROC_CPU_COMPARE = 158, /* autogen autogen */
REMOTE_PROC_DOMAIN_IS_PERSISTENT = 151, /* autogen autogen priority:high */
REMOTE_PROC_NETWORK_IS_ACTIVE = 152, /* autogen autogen priority:high */
REMOTE_PROC_NETWORK_IS_PERSISTENT = 153, /* autogen autogen priority:high */
REMOTE_PROC_STORAGE_POOL_IS_ACTIVE = 154, /* autogen autogen priority:high */
REMOTE_PROC_STORAGE_POOL_IS_PERSISTENT = 155, /* autogen autogen priority:high */
REMOTE_PROC_INTERFACE_IS_ACTIVE = 156, /* autogen autogen priority:high */
REMOTE_PROC_GET_LIB_VERSION = 157, /* autogen autogen priority:high */
REMOTE_PROC_CPU_COMPARE = 158, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_MEMORY_STATS = 159, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_ATTACH_DEVICE_FLAGS = 160, /* autogen autogen */
@ -2403,8 +2409,8 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_ABORT_JOB = 164, /* autogen autogen */
REMOTE_PROC_STORAGE_VOL_WIPE = 165, /* autogen autogen */
REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_DOWNTIME = 166, /* autogen autogen */
REMOTE_PROC_DOMAIN_EVENTS_REGISTER_ANY = 167, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER_ANY = 168, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_EVENTS_REGISTER_ANY = 167, /* skipgen skipgen priority:high */
REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER_ANY = 168, /* skipgen skipgen priority:high */
REMOTE_PROC_DOMAIN_EVENT_REBOOT = 169, /* autogen autogen */
REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE = 170, /* autogen autogen */
@ -2412,22 +2418,22 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_EVENT_IO_ERROR = 172, /* autogen autogen */
REMOTE_PROC_DOMAIN_EVENT_GRAPHICS = 173, /* autogen autogen */
REMOTE_PROC_DOMAIN_UPDATE_DEVICE_FLAGS = 174, /* autogen autogen */
REMOTE_PROC_NWFILTER_LOOKUP_BY_NAME = 175, /* autogen autogen */
REMOTE_PROC_NWFILTER_LOOKUP_BY_UUID = 176, /* autogen autogen */
REMOTE_PROC_NWFILTER_GET_XML_DESC = 177, /* autogen autogen */
REMOTE_PROC_NUM_OF_NWFILTERS = 178, /* autogen autogen */
REMOTE_PROC_LIST_NWFILTERS = 179, /* autogen autogen */
REMOTE_PROC_NWFILTER_DEFINE_XML = 180, /* autogen autogen */
REMOTE_PROC_NWFILTER_LOOKUP_BY_NAME = 175, /* autogen autogen priority:high */
REMOTE_PROC_NWFILTER_LOOKUP_BY_UUID = 176, /* autogen autogen priority:high */
REMOTE_PROC_NWFILTER_GET_XML_DESC = 177, /* autogen autogen priority:high */
REMOTE_PROC_NUM_OF_NWFILTERS = 178, /* autogen autogen priority:high */
REMOTE_PROC_LIST_NWFILTERS = 179, /* autogen autogen priority:high */
REMOTE_PROC_NWFILTER_DEFINE_XML = 180, /* autogen autogen priority:high */
REMOTE_PROC_NWFILTER_UNDEFINE = 181, /* autogen autogen */
REMOTE_PROC_NWFILTER_UNDEFINE = 181, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_MANAGED_SAVE = 182, /* autogen autogen */
REMOTE_PROC_DOMAIN_HAS_MANAGED_SAVE_IMAGE = 183, /* autogen autogen */
REMOTE_PROC_DOMAIN_MANAGED_SAVE_REMOVE = 184, /* autogen autogen */
REMOTE_PROC_DOMAIN_SNAPSHOT_CREATE_XML = 185, /* autogen autogen */
REMOTE_PROC_DOMAIN_SNAPSHOT_GET_XML_DESC = 186, /* autogen autogen */
REMOTE_PROC_DOMAIN_SNAPSHOT_NUM = 187, /* autogen autogen */
REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_NAMES = 188, /* autogen autogen */
REMOTE_PROC_DOMAIN_SNAPSHOT_LOOKUP_BY_NAME = 189, /* autogen autogen */
REMOTE_PROC_DOMAIN_SNAPSHOT_GET_XML_DESC = 186, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_SNAPSHOT_NUM = 187, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_NAMES = 188, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_SNAPSHOT_LOOKUP_BY_NAME = 189, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_HAS_CURRENT_SNAPSHOT = 190, /* autogen autogen */
REMOTE_PROC_DOMAIN_SNAPSHOT_CURRENT = 191, /* autogen autogen */
@ -2442,8 +2448,8 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_GET_VCPUS_FLAGS = 200, /* autogen autogen */
REMOTE_PROC_DOMAIN_OPEN_CONSOLE = 201, /* autogen autogen | readstream@2 */
REMOTE_PROC_DOMAIN_IS_UPDATED = 202, /* autogen autogen */
REMOTE_PROC_GET_SYSINFO = 203, /* autogen autogen */
REMOTE_PROC_DOMAIN_IS_UPDATED = 202, /* autogen autogen priority:high */
REMOTE_PROC_GET_SYSINFO = 203, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_SET_MEMORY_FLAGS = 204, /* autogen autogen */
REMOTE_PROC_DOMAIN_SET_BLKIO_PARAMETERS = 205, /* autogen autogen */
REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206, /* skipgen skipgen */
@ -2453,7 +2459,7 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_INJECT_NMI = 210, /* autogen autogen */
REMOTE_PROC_DOMAIN_SCREENSHOT = 211, /* autogen autogen | readstream@1 */
REMOTE_PROC_DOMAIN_GET_STATE = 212, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_GET_STATE = 212, /* skipgen skipgen priority:high */
REMOTE_PROC_DOMAIN_MIGRATE_BEGIN3 = 213, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_MIGRATE_PREPARE3 = 214, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL3 = 215, /* autogen skipgen | writestream@1 */
@ -2469,17 +2475,17 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_EVENT_CONTROL_ERROR = 224, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_PIN_VCPU_FLAGS = 225, /* autogen autogen */
REMOTE_PROC_DOMAIN_SEND_KEY = 226, /* autogen autogen */
REMOTE_PROC_NODE_GET_CPU_STATS = 227, /* skipgen skipgen */
REMOTE_PROC_NODE_GET_MEMORY_STATS = 228, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_GET_CONTROL_INFO = 229, /* autogen autogen */
REMOTE_PROC_NODE_GET_CPU_STATS = 227, /* skipgen skipgen priority:high */
REMOTE_PROC_NODE_GET_MEMORY_STATS = 228, /* skipgen skipgen priority:high */
REMOTE_PROC_DOMAIN_GET_CONTROL_INFO = 229, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_GET_VCPU_PIN_INFO = 230, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_UNDEFINE_FLAGS = 231, /* autogen autogen */
REMOTE_PROC_DOMAIN_UNDEFINE_FLAGS = 231, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_SAVE_FLAGS = 232, /* autogen autogen */
REMOTE_PROC_DOMAIN_RESTORE_FLAGS = 233, /* autogen autogen */
REMOTE_PROC_DOMAIN_DESTROY_FLAGS = 234, /* autogen autogen */
REMOTE_PROC_DOMAIN_SAVE_IMAGE_GET_XML_DESC = 235, /* autogen autogen */
REMOTE_PROC_DOMAIN_SAVE_IMAGE_DEFINE_XML = 236, /* autogen autogen */
REMOTE_PROC_DOMAIN_DESTROY_FLAGS = 234, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_SAVE_IMAGE_GET_XML_DESC = 235, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_SAVE_IMAGE_DEFINE_XML = 236, /* autogen autogen priority:high */
REMOTE_PROC_DOMAIN_BLOCK_JOB_ABORT = 237, /* autogen autogen */
REMOTE_PROC_DOMAIN_GET_BLOCK_JOB_INFO = 238, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_BLOCK_JOB_SET_SPEED = 239, /* autogen autogen */
@ -2492,10 +2498,16 @@ enum remote_procedure {
* Notice how the entries are grouped in sets of 10 ?
* Nice isn't it. Please keep it this way when adding more.
*
* Each function must have a two-word comment. The first word is
* Each function must have a three-word comment. The first word is
* whether gendispatch.pl handles daemon, the second whether
* it handles src/remote. Additional flags can be specified after a
* pipe.
* The last argument describes priority of API. There are two accepted
* values: low, high; Each API that might eventually access hypervisor's
* monitor (and thus block) MUST fall into low priority. However, there
* are some exceptions to this rule, e.g. domainDestroy. Other APIs MAY
* be marked as high priority. If in doubt, it's safe to choose low.
* Low is taken as default, and thus can be left out.
*
* The (readstream|writestream)@<offset> flag lets daemon and src/remote
* create a stream. The direction is defined from the src/remote point

View File

@ -146,12 +146,13 @@ while (<PROTOCOL>) {
}
if ($opt_b or $opt_k) {
if (!($flags =~ m/^\s*\/\*\s*(\S+)\s+(\S+)\s*(.*)\*\/\s*$/)) {
if (!($flags =~ m/^\s*\/\*\s*(\S+)\s+(\S+)\s*(\|.*)?\s+(priority:(\S+))?\s*\*\/\s*$/)) {
die "invalid generator flags for ${procprefix}_PROC_${name}"
}
my $genmode = $opt_b ? $1 : $2;
my $genflags = $3;
my $priority = defined $5 ? $5 : "low";
if ($genmode eq "autogen") {
push(@autogen, $ProcName);
@ -171,6 +172,16 @@ while (<PROTOCOL>) {
} else {
$calls{$name}->{streamflag} = "none";
}
# for now, we distinguish only two levels of prioroty:
# low (0) and high (1)
if ($priority eq "high") {
$calls{$name}->{priority} = 1;
} elsif ($priority eq "low") {
$calls{$name}->{priority} = 0;
} else {
die "invalid priority ${priority} for ${procprefix}_PROC_${name}"
}
}
$calls[$id] = $calls{$name};
@ -260,6 +271,7 @@ if ($opt_d) {
print "$_:\n";
print " name $calls{$_}->{name} ($calls{$_}->{ProcName})\n";
print " $calls{$_}->{args} -> $calls{$_}->{ret}\n";
print " priority -> $calls{$_}->{priority}\n";
}
}
@ -935,7 +947,7 @@ elsif ($opt_b) {
print "virNetServerProgramProc ${structprefix}Procs[] = {\n";
for ($id = 0 ; $id <= $#calls ; $id++) {
my ($comment, $name, $argtype, $arglen, $argfilter, $retlen, $retfilter);
my ($comment, $name, $argtype, $arglen, $argfilter, $retlen, $retfilter, $priority);
if (defined $calls[$id] && !$calls[$id]->{msg}) {
$comment = "/* Method $calls[$id]->{ProcName} => $id */";
@ -958,7 +970,9 @@ elsif ($opt_b) {
$retfilter = "xdr_void";
}
print "{ $comment\n ${name},\n $arglen,\n (xdrproc_t)$argfilter,\n $retlen,\n (xdrproc_t)$retfilter,\n true \n},\n";
$priority = defined $calls[$id]->{priority} ? $calls[$id]->{priority} : 0;
print "{ $comment\n ${name},\n $arglen,\n (xdrproc_t)$argfilter,\n $retlen,\n (xdrproc_t)$retfilter,\n true,\n $priority\n},\n";
}
print "};\n";
print "size_t ${structprefix}NProcs = ARRAY_CARDINALITY(${structprefix}Procs);\n";

View File

@ -64,6 +64,7 @@ typedef virNetServerJob *virNetServerJobPtr;
struct _virNetServerJob {
virNetServerClientPtr client;
virNetMessagePtr msg;
virNetServerProgramPtr prog;
};
struct _virNetServer {
@ -128,61 +129,41 @@ static void virNetServerHandleJob(void *jobOpaque, void *opaque)
{
virNetServerPtr srv = opaque;
virNetServerJobPtr job = jobOpaque;
virNetServerProgramPtr prog = NULL;
size_t i;
virNetServerLock(srv);
VIR_DEBUG("server=%p client=%p message=%p",
srv, job->client, job->msg);
VIR_DEBUG("server=%p client=%p message=%p prog=%p",
srv, job->client, job->msg, job->prog);
for (i = 0 ; i < srv->nprograms ; i++) {
if (virNetServerProgramMatches(srv->programs[i], job->msg)) {
prog = srv->programs[i];
break;
}
}
if (!prog) {
if (virNetServerProgramUnknownError(job->client,
job->msg,
&job->msg->header) < 0)
goto error;
else
goto cleanup;
}
virNetServerProgramRef(prog);
virNetServerUnlock(srv);
if (virNetServerProgramDispatch(prog,
if (virNetServerProgramDispatch(job->prog,
srv,
job->client,
job->msg) < 0)
goto error;
virNetServerLock(srv);
cleanup:
virNetServerProgramFree(prog);
virNetServerProgramFree(job->prog);
virNetServerUnlock(srv);
virNetServerClientFree(job->client);
VIR_FREE(job);
return;
error:
virNetServerProgramFree(job->prog);
virNetMessageFree(job->msg);
virNetServerClientClose(job->client);
goto cleanup;
virNetServerClientFree(job->client);
VIR_FREE(job);
}
static int virNetServerDispatchNewMessage(virNetServerClientPtr client,
virNetMessagePtr msg,
void *opaque)
{
virNetServerPtr srv = opaque;
virNetServerJobPtr job;
int ret;
virNetServerProgramPtr prog = NULL;
unsigned int priority = 0;
size_t i;
int ret = -1;
VIR_DEBUG("server=%p client=%p message=%p",
srv, client, msg);
@ -196,8 +177,29 @@ static int virNetServerDispatchNewMessage(virNetServerClientPtr client,
job->msg = msg;
virNetServerLock(srv);
if ((ret = virThreadPoolSendJob(srv->workers, job)) < 0)
for (i = 0 ; i < srv->nprograms ; i++) {
if (virNetServerProgramMatches(srv->programs[i], job->msg)) {
prog = srv->programs[i];
break;
}
}
if (!prog) {
virNetServerProgramUnknownError(client, msg, &msg->header);
goto cleanup;
}
virNetServerProgramRef(prog);
job->prog = prog;
priority = virNetServerProgramGetPriority(prog, msg->header.proc);
ret = virThreadPoolSendJob(srv->workers, priority, job);
cleanup:
if (ret < 0) {
VIR_FREE(job);
virNetServerProgramFree(prog);
}
virNetServerUnlock(srv);
return ret;
@ -274,6 +276,7 @@ static void virNetServerFatalSignal(int sig, siginfo_t *siginfo ATTRIBUTE_UNUSED
virNetServerPtr virNetServerNew(size_t min_workers,
size_t max_workers,
size_t priority_workers,
size_t max_clients,
const char *mdnsGroupName,
bool connectDBus ATTRIBUTE_UNUSED,
@ -290,6 +293,7 @@ virNetServerPtr virNetServerNew(size_t min_workers,
srv->refs = 1;
if (!(srv->workers = virThreadPoolNew(min_workers, max_workers,
priority_workers,
virNetServerHandleJob,
srv)))
goto error;

View File

@ -39,6 +39,7 @@ typedef int (*virNetServerClientInitHook)(virNetServerPtr srv,
virNetServerPtr virNetServerNew(size_t min_workers,
size_t max_workers,
size_t priority_workers,
size_t max_clients,
const char *mdnsGroupName,
bool connectDBus,

View File

@ -108,6 +108,17 @@ static virNetServerProgramProcPtr virNetServerProgramGetProc(virNetServerProgram
return &prog->procs[procedure];
}
unsigned int
virNetServerProgramGetPriority(virNetServerProgramPtr prog,
int procedure)
{
virNetServerProgramProcPtr proc = virNetServerProgramGetProc(prog, procedure);
if (!proc)
return 0;
return proc->priority;
}
static int
virNetServerProgramSendError(unsigned program,

View File

@ -53,6 +53,7 @@ struct _virNetServerProgramProc {
size_t ret_len;
xdrproc_t ret_filter;
bool needAuth;
unsigned int priority;
};
virNetServerProgramPtr virNetServerProgramNew(unsigned program,
@ -63,6 +64,9 @@ virNetServerProgramPtr virNetServerProgramNew(unsigned program,
int virNetServerProgramGetID(virNetServerProgramPtr prog);
int virNetServerProgramGetVersion(virNetServerProgramPtr prog);
unsigned int virNetServerProgramGetPriority(virNetServerProgramPtr prog,
int procedure);
void virNetServerProgramRef(virNetServerProgramPtr prog);
int virNetServerProgramMatches(virNetServerProgramPtr prog,

View File

@ -37,7 +37,9 @@ typedef struct _virThreadPoolJob virThreadPoolJob;
typedef virThreadPoolJob *virThreadPoolJobPtr;
struct _virThreadPoolJob {
virThreadPoolJobPtr prev;
virThreadPoolJobPtr next;
unsigned int priority;
void *data;
};
@ -47,7 +49,8 @@ typedef virThreadPoolJobList *virThreadPoolJobListPtr;
struct _virThreadPoolJobList {
virThreadPoolJobPtr head;
virThreadPoolJobPtr *tail;
virThreadPoolJobPtr tail;
virThreadPoolJobPtr firstPrio;
};
@ -57,6 +60,7 @@ struct _virThreadPool {
virThreadPoolJobFunc jobFunc;
void *jobOpaque;
virThreadPoolJobList jobList;
size_t jobQueueDepth;
virMutex mutex;
virCond cond;
@ -66,33 +70,75 @@ struct _virThreadPool {
size_t freeWorkers;
size_t nWorkers;
virThreadPtr workers;
size_t nPrioWorkers;
virThreadPtr prioWorkers;
virCond prioCond;
};
struct virThreadPoolWorkerData {
virThreadPoolPtr pool;
virCondPtr cond;
bool priority;
};
static void virThreadPoolWorker(void *opaque)
{
virThreadPoolPtr pool = opaque;
struct virThreadPoolWorkerData *data = opaque;
virThreadPoolPtr pool = data->pool;
virCondPtr cond = data->cond;
bool priority = data->priority;
virThreadPoolJobPtr job = NULL;
VIR_FREE(data);
virMutexLock(&pool->mutex);
while (1) {
while (!pool->quit &&
!pool->jobList.head) {
pool->freeWorkers++;
if (virCondWait(&pool->cond, &pool->mutex) < 0) {
pool->freeWorkers--;
((!priority && !pool->jobList.head) ||
(priority && !pool->jobList.firstPrio))) {
if (!priority)
pool->freeWorkers++;
if (virCondWait(cond, &pool->mutex) < 0) {
if (!priority)
pool->freeWorkers--;
goto out;
}
pool->freeWorkers--;
if (!priority)
pool->freeWorkers--;
}
if (pool->quit)
break;
virThreadPoolJobPtr job = pool->jobList.head;
pool->jobList.head = pool->jobList.head->next;
job->next = NULL;
if (pool->jobList.tail == &job->next)
pool->jobList.tail = &pool->jobList.head;
if (priority) {
job = pool->jobList.firstPrio;
} else {
job = pool->jobList.head;
}
if (job == pool->jobList.firstPrio) {
virThreadPoolJobPtr tmp = job->next;
while (tmp) {
if (tmp->priority) {
break;
}
tmp = tmp->next;
}
pool->jobList.firstPrio = tmp;
}
if (job->prev)
job->prev->next = job->next;
else
pool->jobList.head = job->next;
if (job->next)
job->next->prev = job->prev;
else
pool->jobList.tail = job->prev;
pool->jobQueueDepth--;
virMutexUnlock(&pool->mutex);
(pool->jobFunc)(job->data, pool->jobOpaque);
@ -101,19 +147,24 @@ static void virThreadPoolWorker(void *opaque)
}
out:
pool->nWorkers--;
if (pool->nWorkers == 0)
if (priority)
pool->nPrioWorkers--;
else
pool->nWorkers--;
if (pool->nWorkers == 0 && pool->nPrioWorkers==0)
virCondSignal(&pool->quit_cond);
virMutexUnlock(&pool->mutex);
}
virThreadPoolPtr virThreadPoolNew(size_t minWorkers,
size_t maxWorkers,
size_t prioWorkers,
virThreadPoolJobFunc func,
void *opaque)
{
virThreadPoolPtr pool;
size_t i;
struct virThreadPoolWorkerData *data = NULL;
if (minWorkers > maxWorkers)
minWorkers = maxWorkers;
@ -123,8 +174,7 @@ virThreadPoolPtr virThreadPoolNew(size_t minWorkers,
return NULL;
}
pool->jobList.head = NULL;
pool->jobList.tail = &pool->jobList.head;
pool->jobList.tail = pool->jobList.head = NULL;
pool->jobFunc = func;
pool->jobOpaque = opaque;
@ -141,18 +191,51 @@ virThreadPoolPtr virThreadPoolNew(size_t minWorkers,
pool->maxWorkers = maxWorkers;
for (i = 0; i < minWorkers; i++) {
if (VIR_ALLOC(data) < 0) {
virReportOOMError();
goto error;
}
data->pool = pool;
data->cond = &pool->cond;
if (virThreadCreate(&pool->workers[i],
true,
virThreadPoolWorker,
pool) < 0) {
data) < 0) {
goto error;
}
pool->nWorkers++;
}
if (prioWorkers) {
if (virCondInit(&pool->prioCond) < 0)
goto error;
if (VIR_ALLOC_N(pool->prioWorkers, prioWorkers) < 0)
goto error;
for (i = 0; i < prioWorkers; i++) {
if (VIR_ALLOC(data) < 0) {
virReportOOMError();
goto error;
}
data->pool = pool;
data->cond = &pool->prioCond;
data->priority = true;
if (virThreadCreate(&pool->prioWorkers[i],
true,
virThreadPoolWorker,
data) < 0) {
goto error;
}
pool->nPrioWorkers++;
}
}
return pool;
error:
VIR_FREE(data);
virThreadPoolFree(pool);
return NULL;
@ -161,17 +244,22 @@ error:
void virThreadPoolFree(virThreadPoolPtr pool)
{
virThreadPoolJobPtr job;
bool priority = false;
if (!pool)
return;
virMutexLock(&pool->mutex);
pool->quit = true;
if (pool->nWorkers > 0) {
if (pool->nWorkers > 0)
virCondBroadcast(&pool->cond);
ignore_value(virCondWait(&pool->quit_cond, &pool->mutex));
if (pool->nPrioWorkers > 0) {
priority = true;
virCondBroadcast(&pool->prioCond);
}
ignore_value(virCondWait(&pool->quit_cond, &pool->mutex));
while ((job = pool->jobList.head)) {
pool->jobList.head = pool->jobList.head->next;
VIR_FREE(job);
@ -182,10 +270,19 @@ void virThreadPoolFree(virThreadPoolPtr pool)
virMutexDestroy(&pool->mutex);
ignore_value(virCondDestroy(&pool->quit_cond));
ignore_value(virCondDestroy(&pool->cond));
if (priority) {
VIR_FREE(pool->prioWorkers);
ignore_value(virCondDestroy(&pool->prioCond));
}
VIR_FREE(pool);
}
/*
* @priority - job priority
* Return: 0 on success, -1 otherwise
*/
int virThreadPoolSendJob(virThreadPoolPtr pool,
unsigned int priority,
void *jobData)
{
virThreadPoolJobPtr job;
@ -194,7 +291,7 @@ int virThreadPoolSendJob(virThreadPoolPtr pool,
if (pool->quit)
goto error;
if (pool->freeWorkers == 0 &&
if (pool->freeWorkers - pool->jobQueueDepth <= 0 &&
pool->nWorkers < pool->maxWorkers) {
if (VIR_EXPAND_N(pool->workers, pool->nWorkers, 1) < 0) {
virReportOOMError();
@ -216,13 +313,26 @@ int virThreadPoolSendJob(virThreadPoolPtr pool,
}
job->data = jobData;
job->next = NULL;
*pool->jobList.tail = job;
pool->jobList.tail = &(*pool->jobList.tail)->next;
job->priority = priority;
job->prev = pool->jobList.tail;
if (pool->jobList.tail)
pool->jobList.tail->next = job;
pool->jobList.tail = job;
if (!pool->jobList.head)
pool->jobList.head = job;
if (priority && !pool->jobList.firstPrio)
pool->jobList.firstPrio = job;
pool->jobQueueDepth++;
virCondSignal(&pool->cond);
virMutexUnlock(&pool->mutex);
if (priority)
virCondSignal(&pool->prioCond);
virMutexUnlock(&pool->mutex);
return 0;
error:

View File

@ -35,12 +35,14 @@ typedef void (*virThreadPoolJobFunc)(void *jobdata, void *opaque);
virThreadPoolPtr virThreadPoolNew(size_t minWorkers,
size_t maxWorkers,
size_t prioWorkers,
virThreadPoolJobFunc func,
void *opaque) ATTRIBUTE_NONNULL(3);
void *opaque) ATTRIBUTE_NONNULL(4);
void virThreadPoolFree(virThreadPoolPtr pool);
int virThreadPoolSendJob(virThreadPoolPtr pool,
unsigned int priority,
void *jobdata) ATTRIBUTE_NONNULL(1)
ATTRIBUTE_RETURN_CHECK;