Annotation of qemu/docs/writing-qmp-commands.txt, revision 1.1.1.1

1.1       root        1: = How to write QMP commands using the QAPI framework =
                      2: 
                      3: This document is a step-by-step guide on how to write new QMP commands using
                      4: the QAPI framework. It also shows how to implement new style HMP commands.
                      5: 
                      6: This document doesn't discuss QMP protocol level details, nor does it dive
                      7: into the QAPI framework implementation.
                      8: 
                      9: For an in-depth introduction to the QAPI framework, please refer to
                     10: docs/qapi-code-gen.txt. For documentation about the QMP protocol, please
                     11: check the files in QMP/.
                     12: 
                     13: == Overview ==
                     14: 
                     15: Generally speaking, the following steps should be taken in order to write a
                     16: new QMP command.
                     17: 
                     18: 1. Write the command's and type(s) specification in the QAPI schema file
                     19:    (qapi-schema.json in the root source directory)
                     20: 
                     21: 2. Write the QMP command itself, which is a regular C function. Preferably,
                     22:    the command should be exported by some QEMU subsystem. But it can also be
                     23:    added to the qmp.c file
                     24: 
                     25: 3. At this point the command can be tested under the QMP protocol
                     26: 
                     27: 4. Write the HMP command equivalent. This is not required and should only be
                     28:    done if it does make sense to have the functionality in HMP. The HMP command
                     29:    is implemented in terms of the QMP command
                     30: 
                     31: The following sections will demonstrate each of the steps above. We will start
                     32: very simple and get more complex as we progress.
                     33: 
                     34: === Testing ===
                     35: 
                     36: For all the examples in the next sections, the test setup is the same and is
                     37: shown here.
                     38: 
                     39: First, QEMU should be started as:
                     40: 
                     41: # /path/to/your/source/qemu [...] \
                     42:     -chardev socket,id=qmp,port=4444,host=localhost,server \
                     43:     -mon chardev=qmp,mode=control,pretty=on
                     44: 
                     45: Then, in a different terminal:
                     46: 
                     47: $ telnet localhost 4444
                     48: Trying 127.0.0.1...
                     49: Connected to localhost.
                     50: Escape character is '^]'.
                     51: {
                     52:     "QMP": {
                     53:         "version": {
                     54:             "qemu": {
                     55:                 "micro": 50, 
                     56:                 "minor": 15, 
                     57:                 "major": 0
                     58:             }, 
                     59:             "package": ""
                     60:         }, 
                     61:         "capabilities": [
                     62:         ]
                     63:     }
                     64: }
                     65: 
                     66: The above output is the QMP server saying you're connected. The server is
                     67: actually in capabilities negotiation mode. To enter in command mode type:
                     68: 
                     69: { "execute": "qmp_capabilities" }
                     70: 
                     71: Then the server should respond:
                     72: 
                     73: {
                     74:     "return": {
                     75:     }
                     76: }
                     77: 
                     78: Which is QMP's way of saying "the latest command executed OK and didn't return
                     79: any data". Now you're ready to enter the QMP example commands as explained in
                     80: the following sections.
                     81: 
                     82: == Writing a command that doesn't return data ==
                     83: 
                     84: That's the most simple QMP command that can be written. Usually, this kind of
                     85: command carries some meaningful action in QEMU but here it will just print
                     86: "Hello, world" to the standard output.
                     87: 
                     88: Our command will be called "hello-world". It takes no arguments, nor does it
                     89: return any data.
                     90: 
                     91: The first step is to add the following line to the bottom of the
                     92: qapi-schema.json file:
                     93: 
                     94: { 'command': 'hello-world' }
                     95: 
                     96: The "command" keyword defines a new QMP command. It's an JSON object. All
                     97: schema entries are JSON objects. The line above will instruct the QAPI to
                     98: generate any prototypes and the necessary code to marshal and unmarshal
                     99: protocol data.
                    100: 
                    101: The next step is to write the "hello-world" implementation. As explained
                    102: earlier, it's preferable for commands to live in QEMU subsystems. But
                    103: "hello-world" doesn't pertain to any, so we put its implementation in qmp.c:
                    104: 
                    105: void qmp_hello_world(Error **errp)
                    106: {
                    107:     printf("Hello, world!\n");
                    108: }
                    109: 
                    110: There are a few things to be noticed:
                    111: 
                    112: 1. QMP command implementation functions must be prefixed with "qmp_"
                    113: 2. qmp_hello_world() returns void, this is in accordance with the fact that the
                    114:    command doesn't return any data
                    115: 3. It takes an "Error **" argument. This is required. Later we will see how to
                    116:    return errors and take additional arguments. The Error argument should not
                    117:    be touched if the command doesn't return errors
                    118: 4. We won't add the function's prototype. That's automatically done by the QAPI
                    119: 5. Printing to the terminal is discouraged for QMP commands, we do it here
                    120:    because it's the easiest way to demonstrate a QMP command
                    121: 
                    122: Now a little hack is needed. As we're still using the old QMP server we need
                    123: to add the new command to its internal dispatch table. This step won't be
                    124: required in the near future. Open the qmp-commands.hx file and add the
                    125: following in the botton:
                    126: 
                    127:     {
                    128:         .name       = "hello-world",
                    129:         .args_type  = "",
                    130:         .mhandler.cmd_new = qmp_marshal_input_hello_world,
                    131:     },
                    132: 
                    133: You're done. Now build qemu, run it as suggested in the "Testing" section,
                    134: and then type the following QMP command:
                    135: 
                    136: { "execute": "hello-world" }
                    137: 
                    138: Then check the terminal running qemu and look for the "Hello, world" string. If
                    139: you don't see it then something went wrong.
                    140: 
                    141: === Arguments ===
                    142: 
                    143: Let's add an argument called "message" to our "hello-world" command. The new
                    144: argument will contain the string to be printed to stdout. It's an optional
                    145: argument, if it's not present we print our default "Hello, World" string.
                    146: 
                    147: The first change we have to do is to modify the command specification in the
                    148: schema file to the following:
                    149: 
                    150: { 'command': 'hello-world', 'data': { '*message': 'str' } }
                    151: 
                    152: Notice the new 'data' member in the schema. It's an JSON object whose each
                    153: element is an argument to the command in question. Also notice the asterisk,
                    154: it's used to mark the argument optional (that means that you shouldn't use it
                    155: for mandatory arguments). Finally, 'str' is the argument's type, which
                    156: stands for "string". The QAPI also supports integers, booleans, enumerations
                    157: and user defined types.
                    158: 
                    159: Now, let's update our C implementation in qmp.c:
                    160: 
                    161: void qmp_hello_world(bool has_message, const char *message, Error **errp)
                    162: {
                    163:     if (has_message) {
                    164:         printf("%s\n", message);
                    165:     } else {
                    166:         printf("Hello, world\n");
                    167:     }
                    168: }
                    169: 
                    170: There are two important details to be noticed:
                    171: 
                    172: 1. All optional arguments are accompanied by a 'has_' boolean, which is set
                    173:    if the optional argument is present or false otherwise
                    174: 2. The C implementation signature must follow the schema's argument ordering,
                    175:    which is defined by the "data" member
                    176: 
                    177: The last step is to update the qmp-commands.hx file:
                    178: 
                    179:     {
                    180:         .name       = "hello-world",
                    181:         .args_type  = "message:s?",
                    182:         .mhandler.cmd_new = qmp_marshal_input_hello_world,
                    183:     },
                    184: 
                    185: Notice that the "args_type" member got our "message" argument. The character
                    186: "s" stands for "string" and "?" means it's optional. This too must be ordered
                    187: according to the C implementation and schema file. You can look for more
                    188: examples in the qmp-commands.hx file if you need to define more arguments.
                    189: 
                    190: Again, this step won't be required in the future.
                    191: 
                    192: Time to test our new version of the "hello-world" command. Build qemu, run it as
                    193: described in the "Testing" section and then send two commands:
                    194: 
                    195: { "execute": "hello-world" }
                    196: {
                    197:     "return": {
                    198:     }
                    199: }
                    200: 
                    201: { "execute": "hello-world", "arguments": { "message": "We love qemu" } }
                    202: {
                    203:     "return": {
                    204:     }
                    205: }
                    206: 
                    207: You should see "Hello, world" and "we love qemu" in the terminal running qemu,
                    208: if you don't see these strings, then something went wrong.
                    209: 
                    210: === Errors ===
                    211: 
                    212: QMP commands should use the error interface exported by the error.h header
                    213: file. The basic function used to set an error is the error_set() one.
                    214: 
                    215: Let's say we don't accept the string "message" to contain the word "love". If
                    216: it does contain it, we want the "hello-world" command to the return the
                    217: InvalidParameter error.
                    218: 
                    219: Only one change is required, and it's in the C implementation:
                    220: 
                    221: void qmp_hello_world(bool has_message, const char *message, Error **errp)
                    222: {
                    223:     if (has_message) {
                    224:         if (strstr(message, "love")) {
                    225:             error_set(errp, QERR_INVALID_PARAMETER, "message");
                    226:             return;
                    227:         }
                    228:         printf("%s\n", message);
                    229:     } else {
                    230:         printf("Hello, world\n");
                    231:     }
                    232: }
                    233: 
                    234: Let's test it. Build qemu, run it as defined in the "Testing" section, and
                    235: then issue the following command:
                    236: 
                    237: { "execute": "hello-world", "arguments": { "message": "we love qemu" } }
                    238: 
                    239: The QMP server's response should be:
                    240: 
                    241: {
                    242:     "error": {
                    243:         "class": "InvalidParameter",
                    244:         "desc": "Invalid parameter 'message'",
                    245:         "data": {
                    246:             "name": "message"
                    247:         }
                    248:     }
                    249: }
                    250: 
                    251: Which is the InvalidParameter error.
                    252: 
                    253: When you have to return an error but you're unsure what error to return or
                    254: which arguments an error takes, you should look at the qerror.h file. Note
                    255: that you might be required to add new errors if needed.
                    256: 
                    257: FIXME: describe better the error API and how to add new errors.
                    258: 
                    259: === Command Documentation ===
                    260: 
                    261: There's only one step missing to make "hello-world"'s implementation complete,
                    262: and that's its documentation in the schema file.
                    263: 
                    264: This is very important. No QMP command will be accepted in QEMU without proper
                    265: documentation.
                    266: 
                    267: There are many examples of such documentation in the schema file already, but
                    268: here goes "hello-world"'s new entry for the qapi-schema.json file:
                    269: 
                    270: ##
                    271: # @hello-world
                    272: #
                    273: # Print a client provided string to the standard output stream.
                    274: #
                    275: # @message: #optional string to be printed
                    276: #
                    277: # Returns: Nothing on success.
                    278: #          If @message contains "love", InvalidParameter
                    279: #
                    280: # Notes: if @message is not provided, the "Hello, world" string will
                    281: #        be printed instead
                    282: #
                    283: # Since: <next qemu stable release, eg. 1.0>
                    284: ##
                    285: { 'command': 'hello-world', 'data': { '*message': 'str' } }
                    286: 
                    287: Please, note that the "Returns" clause is optional if a command doesn't return
                    288: any data nor any errors.
                    289: 
                    290: === Implementing the HMP command ===
                    291: 
                    292: Now that the QMP command is in place, we can also make it available in the human
                    293: monitor (HMP).
                    294: 
                    295: With the introduction of the QAPI, HMP commands make QMP calls. Most of the
                    296: time HMP commands are simple wrappers. All HMP commands implementation exist in
                    297: the hmp.c file.
                    298: 
                    299: Here's the implementation of the "hello-world" HMP command:
                    300: 
                    301: void hmp_hello_world(Monitor *mon, const QDict *qdict)
                    302: {
                    303:     const char *message = qdict_get_try_str(qdict, "message");
                    304:     Error *errp = NULL;
                    305: 
                    306:     qmp_hello_world(!!message, message, &errp);
                    307:     if (error_is_set(&errp)) {
                    308:         monitor_printf(mon, "%s\n", error_get_pretty(errp));
                    309:         error_free(errp);
                    310:         return;
                    311:     }
                    312: }
                    313: 
                    314: Also, you have to add the function's prototype to the hmp.h file.
                    315: 
                    316: There are three important points to be noticed:
                    317: 
                    318: 1. The "mon" and "qdict" arguments are mandatory for all HMP functions. The
                    319:    former is the monitor object. The latter is how the monitor passes
                    320:    arguments entered by the user to the command implementation
                    321: 2. hmp_hello_world() performs error checking. In this example we just print
                    322:    the error description to the user, but we could do more, like taking
                    323:    different actions depending on the error qmp_hello_world() returns
                    324: 3. The "errp" variable must be initialized to NULL before performing the
                    325:    QMP call
                    326: 
                    327: There's one last step to actually make the command available to monitor users,
                    328: we should add it to the hmp-commands.hx file:
                    329: 
                    330:     {
                    331:         .name       = "hello-world",
                    332:         .args_type  = "message:s?",
                    333:         .params     = "hello-world [message]",
                    334:         .help       = "Print message to the standard output",
                    335:         .mhandler.cmd = hmp_hello_world,
                    336:     },
                    337: 
                    338: STEXI
                    339: @item hello_world @var{message}
                    340: @findex hello_world
                    341: Print message to the standard output
                    342: ETEXI
                    343: 
                    344: To test this you have to open a user monitor and issue the "hello-world"
                    345: command. It might be instructive to check the command's documentation with
                    346: HMP's "help" command.
                    347: 
                    348: Please, check the "-monitor" command-line option to know how to open a user
                    349: monitor.
                    350: 
                    351: == Writing a command that returns data ==
                    352: 
                    353: A QMP command is capable of returning any data the QAPI supports like integers,
                    354: strings, booleans, enumerations and user defined types.
                    355: 
                    356: In this section we will focus on user defined types. Please, check the QAPI
                    357: documentation for information about the other types.
                    358: 
                    359: === User Defined Types ===
                    360: 
                    361: For this example we will write the query-alarm-clock command, which returns
                    362: information about QEMU's timer alarm. For more information about it, please
                    363: check the "-clock" command-line option.
                    364: 
                    365: We want to return two pieces of information. The first one is the alarm clock's
                    366: name. The second one is when the next alarm will fire. The former information is
                    367: returned as a string, the latter is an integer in nanoseconds (which is not
                    368: very useful in practice, as the timer has probably already fired when the
                    369: information reaches the client).
                    370: 
                    371: The best way to return that data is to create a new QAPI type, as shown below:
                    372: 
                    373: ##
                    374: # @QemuAlarmClock
                    375: #
                    376: # QEMU alarm clock information.
                    377: #
                    378: # @clock-name: The alarm clock method's name.
                    379: #
                    380: # @next-deadline: #optional The time (in nanoseconds) the next alarm will fire.
                    381: #
                    382: # Since: 1.0
                    383: ##
                    384: { 'type': 'QemuAlarmClock',
                    385:   'data': { 'clock-name': 'str', '*next-deadline': 'int' } }
                    386: 
                    387: The "type" keyword defines a new QAPI type. Its "data" member contains the
                    388: type's members. In this example our members are the "clock-name" and the
                    389: "next-deadline" one, which is optional.
                    390: 
                    391: Now let's define the query-alarm-clock command:
                    392: 
                    393: ##
                    394: # @query-alarm-clock
                    395: #
                    396: # Return information about QEMU's alarm clock.
                    397: #
                    398: # Returns a @QemuAlarmClock instance describing the alarm clock method
                    399: # being currently used by QEMU (this is usually set by the '-clock'
                    400: # command-line option).
                    401: #
                    402: # Since: 1.0
                    403: ##
                    404: { 'command': 'query-alarm-clock', 'returns': 'QemuAlarmClock' }
                    405: 
                    406: Notice the "returns" keyword. As its name suggests, it's used to define the
                    407: data returned by a command.
                    408: 
                    409: It's time to implement the qmp_query_alarm_clock() function, you can put it
                    410: in the qemu-timer.c file:
                    411: 
                    412: QemuAlarmClock *qmp_query_alarm_clock(Error **errp)
                    413: {
                    414:     QemuAlarmClock *clock;
                    415:     int64_t deadline;
                    416: 
                    417:     clock = g_malloc0(sizeof(*clock));
                    418: 
                    419:     deadline = qemu_next_alarm_deadline();
                    420:     if (deadline > 0) {
                    421:         clock->has_next_deadline = true;
                    422:         clock->next_deadline = deadline;
                    423:     }
                    424:     clock->clock_name = g_strdup(alarm_timer->name);
                    425: 
                    426:     return clock;
                    427: }
                    428: 
                    429: There are a number of things to be noticed:
                    430: 
                    431: 1. The QemuAlarmClock type is automatically generated by the QAPI framework,
                    432:    its members correspond to the type's specification in the schema file
                    433: 2. As specified in the schema file, the function returns a QemuAlarmClock
                    434:    instance and takes no arguments (besides the "errp" one, which is mandatory
                    435:    for all QMP functions)
                    436: 3. The "clock" variable (which will point to our QAPI type instance) is
                    437:    allocated by the regular g_malloc0() function. Note that we chose to
                    438:    initialize the memory to zero. This is recommended for all QAPI types, as
                    439:    it helps avoiding bad surprises (specially with booleans)
                    440: 4. Remember that "next_deadline" is optional? All optional members have a
                    441:    'has_TYPE_NAME' member that should be properly set by the implementation,
                    442:    as shown above
                    443: 5. Even static strings, such as "alarm_timer->name", should be dynamically
                    444:    allocated by the implementation. This is so because the QAPI also generates
                    445:    a function to free its types and it cannot distinguish between dynamically
                    446:    or statically allocated strings
                    447: 6. You have to include the "qmp-commands.h" header file in qemu-timer.c,
                    448:    otherwise qemu won't build
                    449: 
                    450: The last step is to add the correspoding entry in the qmp-commands.hx file:
                    451: 
                    452:     {
                    453:         .name       = "query-alarm-clock",
                    454:         .args_type  = "",
                    455:         .mhandler.cmd_new = qmp_marshal_input_query_alarm_clock,
                    456:     },
                    457: 
                    458: Time to test the new command. Build qemu, run it as described in the "Testing"
                    459: section and try this:
                    460: 
                    461: { "execute": "query-alarm-clock" }
                    462: {
                    463:     "return": {
                    464:         "next-deadline": 2368219,
                    465:         "clock-name": "dynticks"
                    466:     }
                    467: }
                    468: 
                    469: ==== The HMP command ====
                    470: 
                    471: Here's the HMP counterpart of the query-alarm-clock command:
                    472: 
                    473: void hmp_info_alarm_clock(Monitor *mon)
                    474: {
                    475:     QemuAlarmClock *clock;
                    476:     Error *errp = NULL;
                    477: 
                    478:     clock = qmp_query_alarm_clock(&errp);
                    479:     if (error_is_set(&errp)) {
                    480:         monitor_printf(mon, "Could not query alarm clock information\n");
                    481:         error_free(errp);
                    482:         return;
                    483:     }
                    484: 
                    485:     monitor_printf(mon, "Alarm clock method in use: '%s'\n", clock->clock_name);
                    486:     if (clock->has_next_deadline) {
                    487:         monitor_printf(mon, "Next alarm will fire in %" PRId64 " nanoseconds\n",
                    488:                        clock->next_deadline);
                    489:     }
                    490: 
                    491:    qapi_free_QemuAlarmClock(clock); 
                    492: }
                    493: 
                    494: It's important to notice that hmp_info_alarm_clock() calls
                    495: qapi_free_QemuAlarmClock() to free the data returned by qmp_query_alarm_clock().
                    496: For user defined types, the QAPI will generate a qapi_free_QAPI_TYPE_NAME()
                    497: function and that's what you have to use to free the types you define and
                    498: qapi_free_QAPI_TYPE_NAMEList() for list types (explained in the next section).
                    499: If the QMP call returns a string, then you should g_free() to free it.
                    500: 
                    501: Also note that hmp_info_alarm_clock() performs error handling. That's not
                    502: strictly required if you're sure the QMP function doesn't return errors, but
                    503: it's good practice to always check for errors.
                    504: 
                    505: Another important detail is that HMP's "info" commands don't go into the
                    506: hmp-commands.hx. Instead, they go into the info_cmds[] table, which is defined
                    507: in the monitor.c file. The entry for the "info alarmclock" follows:
                    508: 
                    509:     {
                    510:         .name       = "alarmclock",
                    511:         .args_type  = "",
                    512:         .params     = "",
                    513:         .help       = "show information about the alarm clock",
                    514:         .mhandler.info = hmp_info_alarm_clock,
                    515:     },
                    516: 
                    517: To test this, run qemu and type "info alarmclock" in the user monitor.
                    518: 
                    519: === Returning Lists ===
                    520: 
                    521: For this example, we're going to return all available methods for the timer
                    522: alarm, which is pretty much what the command-line option "-clock ?" does,
                    523: except that we're also going to inform which method is in use.
                    524: 
                    525: This first step is to define a new type:
                    526: 
                    527: ##
                    528: # @TimerAlarmMethod
                    529: #
                    530: # Timer alarm method information.
                    531: #
                    532: # @method-name: The method's name.
                    533: #
                    534: # @current: true if this alarm method is currently in use, false otherwise
                    535: #
                    536: # Since: 1.0
                    537: ##
                    538: { 'type': 'TimerAlarmMethod',
                    539:   'data': { 'method-name': 'str', 'current': 'bool' } }
                    540: 
                    541: The command will be called "query-alarm-methods", here is its schema
                    542: specification:
                    543: 
                    544: ##
                    545: # @query-alarm-methods
                    546: #
                    547: # Returns information about available alarm methods.
                    548: #
                    549: # Returns: a list of @TimerAlarmMethod for each method
                    550: #
                    551: # Since: 1.0
                    552: ##
                    553: { 'command': 'query-alarm-methods', 'returns': ['TimerAlarmMethod'] }
                    554: 
                    555: Notice the syntax for returning lists "'returns': ['TimerAlarmMethod']", this
                    556: should be read as "returns a list of TimerAlarmMethod instances".
                    557: 
                    558: The C implementation follows:
                    559: 
                    560: TimerAlarmMethodList *qmp_query_alarm_methods(Error **errp)
                    561: {
                    562:     TimerAlarmMethodList *method_list = NULL;
                    563:     const struct qemu_alarm_timer *p;
                    564:     bool current = true;
                    565: 
                    566:     for (p = alarm_timers; p->name; p++) {
                    567:         TimerAlarmMethodList *info = g_malloc0(sizeof(*info));
                    568:         info->value = g_malloc0(sizeof(*info->value));
                    569:         info->value->method_name = g_strdup(p->name);
                    570:         info->value->current = current;
                    571: 
                    572:         current = false;
                    573: 
                    574:         info->next = method_list;
                    575:         method_list = info;
                    576:     }
                    577: 
                    578:     return method_list;
                    579: }
                    580: 
                    581: The most important difference from the previous examples is the
                    582: TimerAlarmMethodList type, which is automatically generated by the QAPI from
                    583: the TimerAlarmMethod type.
                    584: 
                    585: Each list node is represented by a TimerAlarmMethodList instance. We have to
                    586: allocate it, and that's done inside the for loop: the "info" pointer points to
                    587: an allocated node. We also have to allocate the node's contents, which is
                    588: stored in its "value" member. In our example, the "value" member is a pointer
                    589: to an TimerAlarmMethod instance.
                    590: 
                    591: Notice that the "current" variable is used as "true" only in the first
                    592: interation of the loop. That's because the alarm timer method in use is the
                    593: first element of the alarm_timers array. Also notice that QAPI lists are handled
                    594: by hand and we return the head of the list.
                    595: 
                    596: To test this you have to add the corresponding qmp-commands.hx entry:
                    597: 
                    598:     {
                    599:         .name       = "query-alarm-methods",
                    600:         .args_type  = "",
                    601:         .mhandler.cmd_new = qmp_marshal_input_query_alarm_methods,
                    602:     },
                    603: 
                    604: Now Build qemu, run it as explained in the "Testing" section and try our new
                    605: command:
                    606: 
                    607: { "execute": "query-alarm-methods" }
                    608: {
                    609:     "return": [
                    610:         {
                    611:             "current": false, 
                    612:             "method-name": "unix"
                    613:         }, 
                    614:         {
                    615:             "current": true, 
                    616:             "method-name": "dynticks"
                    617:         }
                    618:     ]
                    619: }
                    620: 
                    621: The HMP counterpart is a bit more complex than previous examples because it
                    622: has to traverse the list, it's shown below for reference:
                    623: 
                    624: void hmp_info_alarm_methods(Monitor *mon)
                    625: {
                    626:     TimerAlarmMethodList *method_list, *method;
                    627:     Error *errp = NULL;
                    628: 
                    629:     method_list = qmp_query_alarm_methods(&errp);
                    630:     if (error_is_set(&errp)) {
                    631:         monitor_printf(mon, "Could not query alarm methods\n");
                    632:         error_free(errp);
                    633:         return;
                    634:     }
                    635: 
                    636:     for (method = method_list; method; method = method->next) {
                    637:         monitor_printf(mon, "%c %s\n", method->value->current ? '*' : ' ',
                    638:                                        method->value->method_name);
                    639:     }
                    640: 
                    641:     qapi_free_TimerAlarmMethodList(method_list);
                    642: }

unix.superglobalmegacorp.com