]> xenbits.xensource.com Git - libvirt.git/commitdiff
daemon: Create priority workers pool
authorMichal Privoznik <mprivozn@redhat.com>
Fri, 12 Aug 2011 12:04:31 +0000 (14:04 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Mon, 5 Sep 2011 16:14:08 +0000 (18:14 +0200)
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.

14 files changed:
daemon/libvirtd.aug
daemon/libvirtd.c
daemon/libvirtd.conf
src/qemu/qemu_driver.c
src/qemu/qemu_process.c
src/remote/qemu_protocol.x
src/remote/remote_protocol.x
src/rpc/gendispatch.pl
src/rpc/virnetserver.c
src/rpc/virnetserver.h
src/rpc/virnetserverprogram.c
src/rpc/virnetserverprogram.h
src/util/threadpool.c
src/util/threadpool.h

index 3f47ebb66b10138a24259df816309a4af95310c5..ce00db5394a9243ef915dd26f53f79c236b73565 100644 (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"
index 7734ffff07f008eb424e0a37f90b8f51236db177..1a9fd82d96ff29d3596828f42d23dba635e4ead8 100644 (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,
index 95e43dd23d7fcededad5b96f8d868fc19790dac4..da3983ecef1835af159ac9537ceeec0a041a5e0f 100644 (file)
 #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
index 0dc886a01faea647978914aa0b3a2c56591eaf93..b1992a62db061c5fe204cb924dc8a2bc2c94d6a5 100644 (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;
 
index f36efeaf9548fc73407ecc24c1ec6b6113d9497e..e5f25f56ceacdf4b10196adf6cbcc7d126d17943 100644 (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);
index 3279405b76dbb0cddea7d86aada8f6f2e44b6007..39f9adfe1b1671b0f97e3ef790ab8f0110b2f6af 100644 (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 */
 };
index 676570ea4332fec461d5fa4a68a631d93b7fbe39..4bb64532010988795b63e678cbe518c0d79c0a00 100644 (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_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_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 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_NUM_OF_DOMAINS = 51, /* autogen autogen */
-    REMOTE_PROC_NUM_OF_NETWORKS = 52, /* 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 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_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_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 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_NUM_OF_VOLUMES = 91, /* autogen autogen */
-    REMOTE_PROC_STORAGE_POOL_LIST_VOLUMES = 92, /* 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 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_NODE_GET_CELLS_FREE_MEMORY = 101, /* autogen skipgen */
-    REMOTE_PROC_NODE_GET_FREE_MEMORY = 102, /* 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 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_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_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 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_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_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 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_UNDEFINE = 181, /* 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 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
index 2be903352ce924456ce8aa48e1f0badde196ae9d..fcd1a263fc7ddcf4055f683d3bf573dbda058101 100755 (executable)
@@ -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";
index fd8781d6759928efa9037b563ffaa13f5bee6205..d71ed18d729771306c97eb45f5eab71ac613014f 100644 (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);
 
-    for (i = 0 ; i < srv->nprograms ; i++) {
-        if (virNetServerProgramMatches(srv->programs[i], job->msg)) {
-            prog = srv->programs[i];
-            break;
-        }
-    }
+    VIR_DEBUG("server=%p client=%p message=%p prog=%p",
+              srv, job->client, job->msg, job->prog);
 
-    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;
index 324cfb7186725db16b90e5b8af54eb9e24a42ba9..cc9d039adcf17bd4ff49e87b99b77a339462212a 100644 (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,
index 643a97dba026b31c6578b38aa88f87cc87b0cbad..334a0bf7a5da0ea24d0f8373ce0e2502b3522ee0 100644 (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,
index 06b16d72bb1f44a4a2c14ca86d2411713b742bf2..9dabf92167ed3c6ad8e30871a78f87cfb0a27d20 100644 (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,
index 821759133d873d7dc40823082d9a911218266701..70a75c05125ed10a51df48f0050610ccbccd19de 100644 (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:
index 8b8c6768a8d761ed45ee64ca9d6161d06fe16e7b..c4612ad1a9e244d3859da31cddd3f9ffedcf7f78 100644 (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;