Skip to content

Commit

Permalink
libxc: ocaml: add simple binding for xentoollog (output only).
Browse files Browse the repository at this point in the history
These bindings allow ocaml code to receive log message via xentoollog
but do not support injecting messages into xentoollog from ocaml.
Receiving log messages from libx{c,l} and forwarding them to ocaml is
the use case which is needed by the following patches.

Add a simple noddy test case (tools/ocaml/test).

Signed-off-by: Ian Campbell <[email protected]>
Signed-off-by: Rob Hoes <[email protected]>
Acked-by: David Scott <[email protected]>
[ ijc -- dropped the xtl test harness, it failed to link ]
  • Loading branch information
robhoes authored and Ian Campbell committed Nov 11, 2013
1 parent 3832037 commit 65e35eb
Show file tree
Hide file tree
Showing 9 changed files with 505 additions and 1 deletion.
2 changes: 1 addition & 1 deletion tools/ocaml/Makefile.rules
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ ALL_OCAML_OBJS ?= $(OBJS)
%.cmi: %.mli
$(call quiet-command, $(OCAMLC) $(OCAMLCFLAGS) -c -o $@ $<,MLI,$@)

%.cmx: %.ml
%.cmx %.o: %.ml
$(call quiet-command, $(OCAMLOPT) $(OCAMLOPTFLAGS) -c -o $@ $<,MLOPT,$@)

%.ml: %.mll
Expand Down
1 change: 1 addition & 0 deletions tools/ocaml/libs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ include $(XEN_ROOT)/tools/Rules.mk

SUBDIRS= \
mmap \
xentoollog \
xc eventchn \
xb xs xl

Expand Down
4 changes: 4 additions & 0 deletions tools/ocaml/libs/xentoollog/META.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
version = "@VERSION@"
description = "Xen Tools Logger Interface"
archive(byte) = "xentoollog.cma"
archive(native) = "xentoollog.cmxa"
61 changes: 61 additions & 0 deletions tools/ocaml/libs/xentoollog/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
TOPLEVEL=$(CURDIR)/../..
XEN_ROOT=$(TOPLEVEL)/../..
include $(TOPLEVEL)/common.make

CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest)
OCAMLINCLUDE +=

OBJS = xentoollog
INTF = xentoollog.cmi
LIBS = xentoollog.cma xentoollog.cmxa

LIBS_xentoollog = $(LDLIBS_libxenctrl)

xentoollog_OBJS = $(OBJS)
xentoollog_C_OBJS = xentoollog_stubs

OCAML_LIBRARY = xentoollog

GENERATED_FILES += xentoollog.ml xentoollog.ml.tmp xentoollog.mli xentoollog.mli.tmp
GENERATED_FILES += _xtl_levels.mli.in _xtl_levels.ml.in _xtl_levels.inc META

all: $(INTF) $(LIBS)

xentoollog.ml: xentoollog.ml.in _xtl_levels.ml.in
$(Q)sed -e '1i\
(*\
* AUTO-GENERATED FILE DO NOT EDIT\
* Generated from xentoollog.ml.in and _xtl_levels.ml.in\
*)\
' \
-e '/^(\* @@XTL_LEVELS@@ \*)$$/r_xtl_levels.ml.in' \
< xentoollog.ml.in > xentoollog.ml.tmp
$(Q)mv xentoollog.ml.tmp xentoollog.ml

xentoollog.mli: xentoollog.mli.in _xtl_levels.mli.in
$(Q)sed -e '1i\
(*\
* AUTO-GENERATED FILE DO NOT EDIT\
* Generated from xentoollog.mli.in and _xtl_levels.mli.in\
*)\
' \
-e '/^(\* @@XTL_LEVELS@@ \*)$$/r_xtl_levels.mli.in' \
< xentoollog.mli.in > xentoollog.mli.tmp
$(Q)mv xentoollog.mli.tmp xentoollog.mli

libs: $(LIBS)

_xtl_levels.ml.in _xtl_levels.mli.in _xtl_levels.inc: genlevels.py $(XEN_ROOT)/tools/libxc/xentoollog.h
$(PYTHON) genlevels.py _xtl_levels.mli.in _xtl_levels.ml.in _xtl_levels.inc

.PHONY: install
install: $(LIBS) META
mkdir -p $(OCAMLDESTDIR)
ocamlfind remove -destdir $(OCAMLDESTDIR) xentoollog
ocamlfind install -destdir $(OCAMLDESTDIR) -ldconf ignore xentoollog META $(INTF) $(LIBS) *.a *.so *.cmx

.PHONY: uninstall
uninstall:
ocamlfind remove -destdir $(OCAMLDESTDIR) xentoollog

include $(TOPLEVEL)/Makefile.rules
24 changes: 24 additions & 0 deletions tools/ocaml/libs/xentoollog/caml_xentoollog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright (C) 2013 Citrix Ltd.
* Author Ian Campbell <[email protected]>
* Author Rob Hoes <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; version 2.1 only. with the special
* exception on linking described in file LICENSE.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*/

struct caml_xtl {
xentoollog_logger vtable;
char *vmessage_cb;
char *progress_cb;
};

#define Xtl_val(x)(*((struct caml_xtl **) Data_custom_val(x)))

127 changes: 127 additions & 0 deletions tools/ocaml/libs/xentoollog/genlevels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#!/usr/bin/python

import sys

def read_levels():
f = open('../../../libxc/xentoollog.h', 'r')

levels = []
record = False
for l in f.readlines():
if 'XTL_NUM_LEVELS' in l:
break
if record == True:
levels.append(l.split(',')[0].strip())
if 'XTL_NONE' in l:
record = True

f.close()

olevels = [level[4:].capitalize() for level in levels]

return levels, olevels

# .ml

def gen_ml(olevels):
s = ""

s += "type level = \n"
for level in olevels:
s += '\t| %s\n' % level

s += "\nlet level_to_string level =\n"
s += "\tmatch level with\n"
for level in olevels:
s += '\t| %s -> "%s"\n' % (level, level)

s += "\nlet level_to_prio level =\n"
s += "\tmatch level with\n"
for index,level in enumerate(olevels):
s += '\t| %s -> %d\n' % (level, index)

return s

# .mli

def gen_mli(olevels):
s = ""

s += "type level = \n"
for level in olevels:
s += '\t| %s\n' % level

return s

# .c

def gen_c(level):
s = ""

s += "static value Val_level(xentoollog_level c_level)\n"
s += "{\n"
s += "\tswitch (c_level) {\n"
s += "\tcase XTL_NONE: /* Not a real value */\n"
s += '\t\tcaml_raise_sys_error(caml_copy_string("Val_level XTL_NONE"));\n'
s += "\t\tbreak;\n"

for index,level in enumerate(levels):
s += "\tcase %s:\n\t\treturn Val_int(%d);\n" % (level, index)

s += """\tcase XTL_NUM_LEVELS: /* Not a real value! */
\t\tcaml_raise_sys_error(
\t\t\tcaml_copy_string("Val_level XTL_NUM_LEVELS"));
#if 0 /* Let the compiler catch this */
\tdefault:
\t\tcaml_raise_sys_error(caml_copy_string("Val_level Unknown"));
\t\tbreak;
#endif
\t}
\tabort();
}
"""

return s

def autogen_header(open_comment, close_comment):
s = open_comment + " AUTO-GENERATED FILE DO NOT EDIT " + close_comment + "\n"
s += open_comment + " autogenerated by \n"
s += reduce(lambda x,y: x + " ", range(len(open_comment + " ")), "")
s += "%s" % " ".join(sys.argv)
s += "\n " + close_comment + "\n\n"
return s

if __name__ == '__main__':
if len(sys.argv) < 3:
print >>sys.stderr, "Usage: genlevels.py <mli> <ml> <c-inc>"
sys.exit(1)

levels, olevels = read_levels()

_mli = sys.argv[1]
mli = open(_mli, 'w')
mli.write(autogen_header("(*", "*)"))

_ml = sys.argv[2]
ml = open(_ml, 'w')
ml.write(autogen_header("(*", "*)"))

_cinc = sys.argv[3]
cinc = open(_cinc, 'w')
cinc.write(autogen_header("/*", "*/"))

mli.write(gen_mli(olevels))
mli.write("\n")

ml.write(gen_ml(olevels))
ml.write("\n")

cinc.write(gen_c(levels))
cinc.write("\n")

ml.write("(* END OF AUTO-GENERATED CODE *)\n")
ml.close()
mli.write("(* END OF AUTO-GENERATED CODE *)\n")
mli.close()
cinc.close()

48 changes: 48 additions & 0 deletions tools/ocaml/libs/xentoollog/xentoollog.ml.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
(*
* Copyright (C) 2012 Citrix Ltd.
* Author Ian Campbell <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; version 2.1 only. with the special
* exception on linking described in file LICENSE.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*)

open Printf
open Random
open Callback

(* @@XTL_LEVELS@@ *)

let compare_level x y =
compare (level_to_prio x) (level_to_prio y)

type handle

type logger_cbs = {
vmessage : level -> int option -> string option -> string -> unit;
progress : string option -> string -> int -> int64 -> int64 -> unit;
(*destroy : unit -> unit*)
}

external _create_logger: (string * string) -> handle = "stub_xtl_create_logger"
external test: handle -> unit = "stub_xtl_test"

let counter = ref 0L

let create name cbs : handle =
(* Callback names are supposed to be unique *)
let suffix = Int64.to_string !counter in
counter := Int64.succ !counter;
let vmessage_name = sprintf "%s_vmessage_%s" name suffix in
let progress_name = sprintf "%s_progress_%s" name suffix in
(*let destroy_name = sprintf "%s_destroy" name in*)
Callback.register vmessage_name cbs.vmessage;
Callback.register progress_name cbs.progress;
_create_logger (vmessage_name, progress_name)

43 changes: 43 additions & 0 deletions tools/ocaml/libs/xentoollog/xentoollog.mli.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
(*
* Copyright (C) 2012 Citrix Ltd.
* Author Ian Campbell <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; version 2.1 only. with the special
* exception on linking described in file LICENSE.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*)

(* @@XTL_LEVELS@@ *)

val level_to_string : level -> string
val compare_level : level -> level -> int

type handle

(** call back arguments. See xentoollog.h for more info.
vmessage:
level: level as above
errno: Some <errno> or None
context: Some <string> or None
message: The log message (already formatted)
progress:
context: Some <string> or None
doing_what: string
percent, done, total.
*)
type logger_cbs = {
vmessage : level -> int option -> string option -> string -> unit;
progress : string option -> string -> int -> int64 -> int64 -> unit;
(*destroy : handle -> unit*)
}

external test: handle -> unit = "stub_xtl_test"

val create : string -> logger_cbs -> handle

Loading

0 comments on commit 65e35eb

Please sign in to comment.