diff options
Diffstat (limited to 'lib/runtime_tools')
85 files changed, 17966 insertions, 9972 deletions
diff --git a/lib/runtime_tools/Makefile b/lib/runtime_tools/Makefile index 0094bb036d..eec1ff379b 100644 --- a/lib/runtime_tools/Makefile +++ b/lib/runtime_tools/Makefile @@ -1,18 +1,19 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1999-2009. All Rights Reserved. +# Copyright Ericsson AB 1999-2016. All Rights Reserved. # -# The contents of this file are subject to the Erlang Public License, -# Version 1.1, (the "License"); you may not use this file except in -# compliance with the License. You should have received a copy of the -# Erlang Public License along with this software. If not, it can be -# retrieved online at http://www.erlang.org/. -# -# Software distributed under the License is distributed on an "AS IS" -# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -# the License for the specific language governing rights and limitations -# under the License. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # %CopyrightEnd% # diff --git a/lib/runtime_tools/c_src/Makefile.in b/lib/runtime_tools/c_src/Makefile.in index 754e6ccd78..4530a83aee 100644 --- a/lib/runtime_tools/c_src/Makefile.in +++ b/lib/runtime_tools/c_src/Makefile.in @@ -1,18 +1,19 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1999-2012. All Rights Reserved. +# Copyright Ericsson AB 1999-2016. All Rights Reserved. # -# The contents of this file are subject to the Erlang Public License, -# Version 1.1, (the "License"); you may not use this file except in -# compliance with the License. You should have received a copy of the -# Erlang Public License along with this software. If not, it can be -# retrieved online at http://www.erlang.org/. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# Software distributed under the License is distributed on an "AS IS" -# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -# the License for the specific language governing rights and limitations -# under the License. +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # %CopyrightEnd% # @@ -21,11 +22,6 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk include $(ERL_TOP)/make/$(TARGET)/otp_ded.mk # ---------------------------------------------------- -# Items from top-level configure -# ---------------------------------------------------- -DTRACE_ENABLED=@DTRACE_ENABLED@ -DTRACE_ENABLED_2STEP=@DTRACE_ENABLED_2STEP@ -# ---------------------------------------------------- # Application version # ---------------------------------------------------- include ../vsn.mk @@ -37,24 +33,18 @@ VSN=$(RUNTIME_TOOLS_VSN) # be set for that system only. # ---------------------------------------------------- CC = $(DED_CC) -CFLAGS = $(DED_CFLAGS) +CFLAGS = $(DED_CFLAGS) -I./ LD = $(DED_LD) SHELL = /bin/sh LIBS = $(DED_LIBS) LDFLAGS += $(DED_LDFLAGS) -DTRACE_LIBNAME = dyntrace +TRACE_LIBNAME = dyntrace trace_file_drv trace_ip_drv SYSINCLUDE = $(DED_SYS_INCLUDE) -ifeq ($(findstring vxworks,$(TARGET)),vxworks) - SYSINCLUDE += -I$(ERL_TOP)/erts/etc/vxworks -endif TRACE_DRV_INCLUDES = $(SYSINCLUDE) -ALL_CFLAGS = $(CFLAGS) @DEFS@ $(TYPE_FLAGS) $(TRACE_DRV_INCLUDES) \ - -I$(OBJDIR) -I$(ERL_TOP)/erts/emulator/$(TARGET) - ifeq ($(TYPE),debug) TYPEMARKER = .debug TYPE_FLAGS = $(subst -O3,,$(subst -O2,,$(CFLAGS))) -DDEBUG @DEBUG_FLAGS@ @@ -68,6 +58,9 @@ TYPE_FLAGS = $(CFLAGS) endif endif +ALL_CFLAGS = @DEFS@ $(TYPE_FLAGS) $(TRACE_DRV_INCLUDES) \ + -I$(OBJDIR) -I$(ERL_TOP)/erts/emulator/$(TARGET) + ROOTDIR = $(ERL_TOP)/lib PRIVDIR = ../priv LIBDIR = $(PRIVDIR)/lib/$(TARGET) @@ -81,62 +74,16 @@ RELSYSDIR = $(RELEASE_PATH)/lib/runtime_tools-$(VSN) # ---------------------------------------------------- # Misc Macros # ---------------------------------------------------- -before_DTrace_OBJS = $(OBJDIR)/dyntrace$(TYPEMARKER).o -## NIF_MAKEFILE = $(PRIVDIR)/Makefile -# Higher-level makefiles says that we can only compile on UNIX flavors -NIF_LIB = $(LIBDIR)/dyntrace$(TYPEMARKER).@DED_EXT@ +TRACE_LIBS = $(foreach LIB, $(TRACE_LIBNAME), $(LIBDIR)/$(LIB)$(TYPEMARKER).@DED_EXT@) -ifeq ($(HOST_OS),) -HOST_OS := $(shell $(ERL_TOP)/erts/autoconf/config.guess) -endif - -TRACE_IP_DRV_OBJS = \ - $(OBJDIR)/trace_ip_drv.o - -TRACE_FILE_DRV_OBJS = \ - $(OBJDIR)/trace_file_drv.o - -ifeq ($(findstring win32,$(TARGET)), win32) -SOLIBS = $(LIBDIR)/trace_ip_drv.dll $(LIBDIR)/trace_file_drv.dll -LN=cp -else -ifeq ($(findstring vxworks,$(TARGET)),vxworks) -SOLIBS = $(LIBDIR)/trace_ip_drv.eld $(LIBDIR)/trace_file_drv.eld -else -SOLIBS = $(LIBDIR)/trace_ip_drv.so $(LIBDIR)/trace_file_drv.so -endif -endif # ---------------------------------------------------- # Targets # ---------------------------------------------------- _create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR)) -debug opt valgrind: $(SOLIBS) $(OBJDIR) $(LIBDIR) $(NIF_LIB) - -ifdef DTRACE_ENABLED -DTRACE_USER_HEADER=$(OBJDIR)/dtrace_user.h -$(OBJDIR)/dtrace_user.h: ./dtrace_user.d - dtrace -h -C $(INCLUDES) \ - -s ./dtrace_user.d \ - -o ./dtrace_user.tmp - sed -e '/^#define[ ]*ERLANG_[A-Z0-9_]*(.*)/y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/' ./dtrace_user.tmp > $@ - rm ./dtrace_user.tmp -else -DTRACE_USER_HEADER= -endif - -DTRACE_OBJS = -ifdef DTRACE_ENABLED_2STEP -DTRACE_OBJS += $(OBJDIR)/dtrace_user.o -$(OBJDIR)/dtrace_user.o: $(before_DTrace_OBJS) $(OBJDIR)/dtrace_user.h - dtrace -G -C \ - -s ./dtrace_user.d \ - -o $@ $(before_DTrace_OBJS) -endif - -DYNTRACE_OBJS = $(before_DTrace_OBJS) $(DTRACE_OBJS) +debug opt valgrind: $(SOLIBS) $(OBJDIR) $(LIBDIR) $(TRACE_LIBS) $(OBJDIR): -@mkdir -p $(OBJDIR) @@ -144,59 +91,26 @@ $(OBJDIR): $(LIBDIR): -@mkdir -p $(LIBDIR) -$(OBJDIR)/dyntrace$(TYPEMARKER).o: dyntrace.c $(DTRACE_USER_HEADER) - $(INSTALL_DIR) $(OBJDIR) - $(CC) -c -o $@ $(ALL_CFLAGS) $< - -$(NIF_LIB): $(DYNTRACE_OBJS) - $(INSTALL_DIR) $(LIBDIR) - $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS) +$(OBJDIR)/%$(TYPEMARKER).o: %.c dyntrace_lttng.h + $(V_CC) -c -o $@ $(ALL_CFLAGS) $< -$(OBJDIR)/%.o: %.c - $(CC) -c -o $@ $(ALL_CFLAGS) $< - -$(LIBDIR)/trace_ip_drv.so: $(TRACE_IP_DRV_OBJS) - $(LD) $(LDFLAGS) -o $@ $^ -lc $(LIBS) - -$(LIBDIR)/trace_file_drv.so: $(TRACE_FILE_DRV_OBJS) - $(LD) $(LDFLAGS) -o $@ $^ -lc $(LIBS) - -$(LIBDIR)/trace_ip_drv.dll: $(TRACE_IP_DRV_OBJS) - $(LD) $(LDFLAGS) -o $@ $^ $(LIBS) -$(LIBDIR)/trace_file_drv.dll: $(TRACE_FILE_DRV_OBJS) - $(LD) $(LDFLAGS) -o $@ $^ $(LIBS) -# -# VxWorks is simply to different from Unix in this sense. -# Here are the inference rules for VxWorks -# -$(LIBDIR)/trace_ip_drv.eld: $(TRACE_IP_DRV_OBJS) - $(LD) $(LDFLAGS) -o $@ $^ - -$(LIBDIR)/trace_file_drv.eld: $(TRACE_FILE_DRV_OBJS) - $(LD) $(LDFLAGS) -o $@ $^ +$(LIBDIR)/%$(TYPEMARKER).@DED_EXT@: $(OBJDIR)/%$(TYPEMARKER).o + $(V_LD) $(LDFLAGS) -o $@ $^ $(LIBS) clean: - rm -f $(SOLIBS) $(TRACE_IP_DRV_OBJS) $(TRACE_FILE_DRV_OBJS) - rm -f $(LIBDIR)/dyntrace.@DED_EXT@ - rm -f $(LIBDIR)/dyntrace.debug.@DED_EXT@ - rm -f $(LIBDIR)/dyntrace.valgrind.@DED_EXT@ - rm -f $(OBJDIR)/dyntrace.o - rm -f $(OBJDIR)/dyntrace.debug.o - rm -f $(OBJDIR)/dyntrace.valgrind.o + rm -f $(TRACE_LIBS) rm -f core *~ docs: # ---------------------------------------------------- # Release Target -# ---------------------------------------------------- +# ---------------------------------------------------- include $(ERL_TOP)/make/otp_release_targets.mk release_spec: opt - $(INSTALL_DIR) "$(RELSYSDIR)/priv/obj" $(INSTALL_DIR) "$(RELSYSDIR)/priv/lib" - $(INSTALL_PROGRAM) $(DYNTRACE_OBJS) "$(RELSYSDIR)/priv/obj" - $(INSTALL_PROGRAM) $(NIF_LIB) $(SOLIBS) "$(RELSYSDIR)/priv/lib" + $(INSTALL_PROGRAM) $(TRACE_LIBS) "$(RELSYSDIR)/priv/lib" release_docs_spec: diff --git a/lib/runtime_tools/c_src/dtrace_user.d b/lib/runtime_tools/c_src/dtrace_user.d index 9e180a3cb2..2b74e9ef6f 100644 --- a/lib/runtime_tools/c_src/dtrace_user.d +++ b/lib/runtime_tools/c_src/dtrace_user.d @@ -1,19 +1,20 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie 2011-2012. + * Copyright Scott Lystig Fritchie 2011-2016. * All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/c_src/dyntrace.c b/lib/runtime_tools/c_src/dyntrace.c index eef03afd1c..3d2de9c21c 100644 --- a/lib/runtime_tools/c_src/dyntrace.c +++ b/lib/runtime_tools/c_src/dyntrace.c @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ @@ -28,10 +29,13 @@ #include "sys.h" #include "dtrace-wrapper.h" #if defined(USE_DYNAMIC_TRACE) && (defined(USE_DTRACE) || defined(USE_SYSTEMTAP)) -#define HAVE_USE_DTRACE 1 +# define HAVE_USE_DTRACE 1 #endif -#ifdef HAVE_USE_DTRACE -#include "dtrace_user.h" +#if defined(USE_LTTNG) +# define HAVE_USE_LTTNG 1 +# define TRACEPOINT_DEFINE +# define TRACEPOINT_CREATE_PROBES +# include "dyntrace_lttng.h" #endif void dtrace_nifenv_str(ErlNifEnv *env, char *process_buf); @@ -62,11 +66,55 @@ static ERL_NIF_TERM user_trace_s1(ErlNifEnv* env, int argc, const ERL_NIF_TERM a static ERL_NIF_TERM user_trace_i4s4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM user_trace_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); + +#ifdef HAVE_USE_LTTNG +static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM trace_ports(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM trace_running_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM trace_running_ports(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM trace_call(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM trace_send(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM trace_receive(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM trace_garbage_collection(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); + +static ERL_NIF_TERM enabled_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM enabled_ports(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM enabled_running_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM enabled_running_ports(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM enabled_call(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM enabled_send(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM enabled_receive(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM enabled_garbage_collection(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +#endif + + static ErlNifFunc nif_funcs[] = { {"available", 0, available}, {"user_trace_s1", 1, user_trace_s1}, {"user_trace_i4s4", 9, user_trace_i4s4}, - {"user_trace_n", 10, user_trace_n} + {"user_trace_n", 10, user_trace_n}, +#ifdef HAVE_USE_LTTNG + {"trace_procs", 5, trace_procs}, + {"trace_ports", 5, trace_ports}, + {"trace_running_procs", 5, trace_running_procs}, + {"trace_running_ports", 5, trace_running_ports}, + {"trace_call", 5, trace_call}, + {"trace_send", 5, trace_send}, + {"trace_receive", 5, trace_receive}, + {"trace_garbage_collection", 5, trace_garbage_collection}, + {"enabled_procs", 3, enabled_procs}, + {"enabled_ports", 3, enabled_ports}, + {"enabled_running_procs", 3, enabled_running_procs}, + {"enabled_running_ports", 3, enabled_running_ports}, + {"enabled_call", 3, enabled_call}, + {"enabled_send", 3, enabled_send}, + {"enabled_receive", 3, enabled_receive}, + {"enabled_garbage_collection", 3, enabled_garbage_collection}, +#endif + {"enabled", 3, enabled}, + {"trace", 5, trace} }; ERL_NIF_INIT(dyntrace, nif_funcs, load, NULL, NULL, NULL) @@ -74,19 +122,131 @@ ERL_NIF_INIT(dyntrace, nif_funcs, load, NULL, NULL, NULL) static ERL_NIF_TERM atom_true; static ERL_NIF_TERM atom_false; static ERL_NIF_TERM atom_error; +static ERL_NIF_TERM atom_extra; static ERL_NIF_TERM atom_not_available; static ERL_NIF_TERM atom_badarg; static ERL_NIF_TERM atom_ok; +static ERL_NIF_TERM atom_trace; +static ERL_NIF_TERM atom_seq_trace; +static ERL_NIF_TERM atom_remove; +static ERL_NIF_TERM atom_discard; + +#ifdef HAVE_USE_LTTNG + +/* gc atoms */ + +static ERL_NIF_TERM atom_gc_minor_start; +static ERL_NIF_TERM atom_gc_minor_end; +static ERL_NIF_TERM atom_gc_major_start; +static ERL_NIF_TERM atom_gc_major_end; + +static ERL_NIF_TERM atom_old_heap_block_size; /* for debug */ +static ERL_NIF_TERM atom_heap_block_size; /* for debug */ + +/* process 'procs' */ + +static ERL_NIF_TERM atom_spawn; +static ERL_NIF_TERM atom_exit; +static ERL_NIF_TERM atom_register; +static ERL_NIF_TERM atom_unregister; +static ERL_NIF_TERM atom_link; +static ERL_NIF_TERM atom_unlink; +static ERL_NIF_TERM atom_getting_linked; +static ERL_NIF_TERM atom_getting_unlinked; + +/* process 'running' and 'exiting' */ + +static ERL_NIF_TERM atom_in; +static ERL_NIF_TERM atom_out; +static ERL_NIF_TERM atom_in_exiting; +static ERL_NIF_TERM atom_out_exiting; +static ERL_NIF_TERM atom_out_exited; + +/* process messages 'send' and 'receive' */ + +static ERL_NIF_TERM atom_send; +static ERL_NIF_TERM atom_receive; +static ERL_NIF_TERM atom_send_to_non_existing_process; + +/* ports 'ports' */ + +static ERL_NIF_TERM atom_open; +static ERL_NIF_TERM atom_closed; + +/* 'call' */ + +static ERL_NIF_TERM atom_call; +static ERL_NIF_TERM atom_return_from; +static ERL_NIF_TERM atom_return_to; +static ERL_NIF_TERM atom_exception_from; +#endif + static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) { atom_true = enif_make_atom(env,"true"); atom_false = enif_make_atom(env,"false"); atom_error = enif_make_atom(env,"error"); + atom_extra = enif_make_atom(env,"extra"); atom_not_available = enif_make_atom(env,"not_available"); atom_badarg = enif_make_atom(env,"badarg"); atom_ok = enif_make_atom(env,"ok"); + atom_trace = enif_make_atom(env,"trace"); + atom_seq_trace = enif_make_atom(env,"seq_trace"); + atom_remove = enif_make_atom(env,"remove"); + atom_discard = enif_make_atom(env,"discard"); + +#ifdef HAVE_USE_LTTNG + + /* gc */ + + atom_gc_minor_start = enif_make_atom(env,"gc_minor_start"); + atom_gc_minor_end = enif_make_atom(env,"gc_minor_end"); + atom_gc_major_start = enif_make_atom(env,"gc_major_start"); + atom_gc_major_end = enif_make_atom(env,"gc_major_end"); + + atom_old_heap_block_size = enif_make_atom(env,"old_heap_block_size"); + atom_heap_block_size = enif_make_atom(env,"heap_block_size"); + + /* process 'proc' */ + + atom_spawn = enif_make_atom(env,"spawn"); + atom_exit = enif_make_atom(env,"exit"); + atom_register = enif_make_atom(env,"register"); + atom_unregister = enif_make_atom(env,"unregister"); + atom_link = enif_make_atom(env,"link"); + atom_unlink = enif_make_atom(env,"unlink"); + atom_getting_unlinked = enif_make_atom(env,"getting_unlinked"); + atom_getting_linked = enif_make_atom(env,"getting_linked"); + + /* process 'running' and 'exiting' */ + + atom_in = enif_make_atom(env,"in"); + atom_out = enif_make_atom(env,"out"); + atom_in_exiting = enif_make_atom(env,"in_exiting"); + atom_out_exiting = enif_make_atom(env,"out_exiting"); + atom_out_exited = enif_make_atom(env,"out_exited"); + + /* process messages 'send' and 'receive' */ + + atom_send = enif_make_atom(env,"send"); + atom_receive = enif_make_atom(env,"receive"); + atom_send_to_non_existing_process = enif_make_atom(env,"send_to_non_existing_process"); + + /* ports 'ports' */ + + atom_open = enif_make_atom(env,"open"); + atom_closed = enif_make_atom(env,"closed"); + + /* 'call' */ + + atom_call = enif_make_atom(env,"call"); + atom_return_from = enif_make_atom(env,"return_from"); + atom_return_to = enif_make_atom(env,"return_to"); + atom_exception_from = enif_make_atom(env,"exception_from"); +#endif + return 0; } @@ -125,3 +285,452 @@ static ERL_NIF_TERM user_trace_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar return atom_error; #endif } + +static ERL_NIF_TERM enabled(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ +#ifdef HAVE_USE_LTTNG + ASSERT(argc == 3); + return atom_trace; +#endif + return atom_remove; +} + +static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + return atom_ok; +} + +#ifdef HAVE_USE_LTTNG +static ERL_NIF_TERM enabled_garbage_collection(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + ASSERT(argc == 3); + + if (argv[0] == atom_gc_minor_start && LTTNG_ENABLED(gc_minor_start)) { + return atom_trace; + } else if (argv[0] == atom_gc_minor_end && LTTNG_ENABLED(gc_minor_end)) { + return atom_trace; + } else if (argv[0] == atom_gc_major_start && LTTNG_ENABLED(gc_major_start)) { + return atom_trace; + } else if (argv[0] == atom_gc_major_end && LTTNG_ENABLED(gc_major_end)) { + return atom_trace; + } + + return atom_discard; +} + +static ERL_NIF_TERM trace_garbage_collection(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + lttng_decl_procbuf(pid); + ERL_NIF_TERM gci, tup; + const ERL_NIF_TERM *vals; + int arity; + unsigned long ohbsz, nhbsz, size; + + ASSERT(argc == 5); + + /* Assume gc info order does not change */ + gci = argv[3]; + + /* get reclaimed or need */ + enif_get_list_cell(env, gci, &tup, &gci); + enif_get_tuple(env, tup, &arity, &vals); + ASSERT(arity == 2); + enif_get_ulong(env, vals[1], &size); + + /* get old heap block size */ + enif_get_list_cell(env, gci, &tup, &gci); + enif_get_tuple(env, tup, &arity, &vals); + ASSERT(arity == 2); + ASSERT(vals[0] == atom_old_heap_block_size); + enif_get_ulong(env, vals[1], &ohbsz); + + /* get new heap block size */ + enif_get_list_cell(env, gci, &tup, &gci); + enif_get_tuple(env, tup, &arity, &vals); + ASSERT(arity == 2); + ASSERT(vals[0] == atom_heap_block_size); + enif_get_ulong(env, vals[1], &nhbsz); + + lttng_pid_to_str(argv[2], pid); + + if (argv[0] == atom_gc_minor_start) { + LTTNG4(gc_minor_start, pid, size, nhbsz, ohbsz); + } else if (argv[0] == atom_gc_minor_end) { + LTTNG4(gc_minor_end, pid, size, nhbsz, ohbsz); + } else if (argv[0] == atom_gc_major_start) { + LTTNG4(gc_major_start, pid, size, nhbsz, ohbsz); + } else if (argv[0] == atom_gc_major_end) { + LTTNG4(gc_major_end, pid, size, nhbsz, ohbsz); + } + return atom_ok; +} + +static ERL_NIF_TERM enabled_call(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + ASSERT(argc == 3); + + if (argv[0] == atom_call && LTTNG_ENABLED(function_call)) + return atom_trace; + else if (argv[0] == atom_return_from && LTTNG_ENABLED(function_return)) + return atom_trace; + else if (argv[0] == atom_exception_from && LTTNG_ENABLED(function_exception)) + return atom_trace; + + return atom_discard; +} + +static ERL_NIF_TERM trace_call(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + lttng_decl_procbuf(pid); + unsigned int len; + char undef[] = "undefined"; + + lttng_pid_to_str(argv[2], pid); + + if (argv[0] == atom_call) { + const ERL_NIF_TERM* tuple; + int arity; + lttng_decl_mfabuf(mfa); + + if (enif_get_tuple(env, argv[3], &arity, &tuple)) { + if (enif_is_list(env, tuple[2])) { + enif_get_list_length(env, tuple[2], &len); + } else { + enif_get_uint(env, tuple[2], &len); + } + lttng_mfa_to_str(tuple[0], tuple[1], len, mfa); + LTTNG3(function_call, pid, mfa, 0); + } else { + LTTNG3(function_call, pid, undef, 0); + } + } else if (argv[0] == atom_return_from) { + const ERL_NIF_TERM* tuple; + int arity; + lttng_decl_mfabuf(mfa); + + if (enif_get_tuple(env, argv[3], &arity, &tuple)) { + enif_get_uint(env, tuple[2], &len); + lttng_mfa_to_str(tuple[0], tuple[1], len, mfa); + LTTNG3(function_return, pid, mfa, 0); + } else { + LTTNG3(function_return, pid, undef, 0); + } + } else if (argv[0] == atom_return_to) { + const ERL_NIF_TERM* tuple; + int arity; + lttng_decl_mfabuf(mfa); + + if (enif_get_tuple(env, argv[3], &arity, &tuple)) { + enif_get_uint(env, tuple[2], &len); + lttng_mfa_to_str(tuple[0], tuple[1], len, mfa); + LTTNG3(function_return, pid, mfa, 0); + } else { + LTTNG3(function_return, pid, undef, 0); + } + } else if (argv[0] == atom_exception_from) { + const ERL_NIF_TERM* tuple; + ERL_NIF_TERM extra; + int arity; + lttng_decl_mfabuf(mfa); + char class[LTTNG_BUFFER_SZ]; + + enif_get_map_value(env, argv[4], atom_extra, &extra); + enif_get_tuple(env, extra, &arity, &tuple); + enif_snprintf(class, LTTNG_BUFFER_SZ, "%T", tuple[0]); + + if (enif_get_tuple(env, argv[3], &arity, &tuple)) { + enif_get_uint(env, tuple[2], &len); + lttng_mfa_to_str(tuple[0], tuple[1], len, mfa); + LTTNG3(function_exception, pid, mfa, class); + } else { + LTTNG3(function_exception, pid, undef, class); + } + } + return atom_ok; +} + +static ERL_NIF_TERM enabled_send(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + ASSERT(argc == 3); + if (LTTNG_ENABLED(message_send)) + return atom_trace; + + return atom_discard; +} + +static ERL_NIF_TERM trace_send(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + ERL_NIF_TERM extra; + lttng_decl_procbuf(pid); + lttng_pid_to_str(argv[2], pid); + + enif_get_map_value(env, argv[4], atom_extra, &extra); + + if (argv[0] == atom_send) { + lttng_decl_procbuf(to); + char msg[LTTNG_BUFFER_SZ]; + + lttng_pid_to_str(extra, to); + enif_snprintf(msg, LTTNG_BUFFER_SZ, "%T", argv[3]); + + LTTNG3(message_send, pid, to, msg); + } else if (argv[0] == atom_send_to_non_existing_process) { + lttng_decl_procbuf(to); + char msg[LTTNG_BUFFER_SZ]; + + lttng_pid_to_str(extra, to); + enif_snprintf(msg, LTTNG_BUFFER_SZ, "%T", argv[3]); + /* mark it as non existing ? */ + + LTTNG3(message_send, pid, to, msg); + } + return atom_ok; +} + +static ERL_NIF_TERM enabled_receive(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + if (LTTNG_ENABLED(message_receive)) + return atom_trace; + + return atom_discard; +} + +static ERL_NIF_TERM trace_receive(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + if (argv[0] == atom_receive) { + lttng_decl_procbuf(pid); + char msg[LTTNG_BUFFER_SZ]; + + lttng_pid_to_str(argv[2], pid); + enif_snprintf(msg, LTTNG_BUFFER_SZ, "%T", argv[3]); + + LTTNG2(message_receive, pid, msg); + } + return atom_ok; +} + +static ERL_NIF_TERM enabled_procs(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + ASSERT(argc == 3); + + if (argv[0] == atom_spawn && LTTNG_ENABLED(process_spawn)) { + return atom_trace; + } else if (argv[0] == atom_register && LTTNG_ENABLED(process_register)) { + return atom_trace; + } else if (argv[0] == atom_unregister && LTTNG_ENABLED(process_register)) { + return atom_trace; + } else if (argv[0] == atom_link && LTTNG_ENABLED(process_link)) { + return atom_trace; + } else if (argv[0] == atom_unlink && LTTNG_ENABLED(process_link)) { + return atom_trace; + } else if (argv[0] == atom_getting_linked && LTTNG_ENABLED(process_link)) { + return atom_trace; + } else if (argv[0] == atom_getting_unlinked && LTTNG_ENABLED(process_link)) { + return atom_trace; + } else if (argv[0] == atom_exit && LTTNG_ENABLED(process_exit)) { + return atom_trace; + } + + return atom_discard; +} + +static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + lttng_decl_procbuf(pid); + lttng_decl_procbuf(to); + + lttng_pid_to_str(argv[2], pid); + + /* spawn */ + if (argv[0] == atom_spawn) { + ERL_NIF_TERM extra; + char undef[] = "undefined"; + const ERL_NIF_TERM* tuple; + int arity; + unsigned int len; + lttng_decl_mfabuf(mfa); + + lttng_pid_to_str(argv[3], to); + + enif_get_map_value(env, argv[4], atom_extra, &extra); + + if (enif_get_tuple(env, extra, &arity, &tuple)) { + if (enif_is_list(env, tuple[2])) { + enif_get_list_length(env, tuple[2], &len); + } else { + enif_get_uint(env, tuple[2], &len); + } + lttng_mfa_to_str(tuple[0], tuple[1], len, mfa); + LTTNG3(process_spawn, to, pid, mfa); + } else { + LTTNG3(process_spawn, to, pid, undef); + } + + /* register */ + } else if (argv[0] == atom_register) { + char name[LTTNG_BUFFER_SZ]; + enif_snprintf(name, LTTNG_BUFFER_SZ, "%T", argv[3]); + LTTNG3(process_register, pid, name, "register"); + } else if (argv[0] == atom_unregister) { + char name[LTTNG_BUFFER_SZ]; + enif_snprintf(name, LTTNG_BUFFER_SZ, "%T", argv[3]); + LTTNG3(process_register, pid, name, "unregister"); + /* link */ + } else if (argv[0] == atom_link) { + lttng_pid_to_str(argv[3], to); + LTTNG3(process_link, pid, to, "link"); + } else if (argv[0] == atom_unlink) { + lttng_pid_to_str(argv[3], to); + LTTNG3(process_link, pid, to, "unlink"); + } else if (argv[0] == atom_getting_linked) { + lttng_pid_to_str(argv[3], to); + LTTNG3(process_link, to, pid, "link"); + } else if (argv[0] == atom_getting_unlinked) { + lttng_pid_to_str(argv[3], to); + LTTNG3(process_link, to, pid, "unlink"); + /* exit */ + } else if (argv[0] == atom_exit) { + char reason[LTTNG_BUFFER_SZ]; + enif_snprintf(reason, LTTNG_BUFFER_SZ, "%T", argv[3]); + LTTNG2(process_exit, pid, reason); + } + return atom_ok; +} + +static ERL_NIF_TERM enabled_ports(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + ASSERT(argc == 3); + + if (argv[0] == atom_open && LTTNG_ENABLED(port_open)) { + return atom_trace; + } else if (argv[0] == atom_link && LTTNG_ENABLED(port_link)) { + return atom_trace; + } else if (argv[0] == atom_unlink && LTTNG_ENABLED(port_link)) { + return atom_trace; + } else if (argv[0] == atom_getting_linked && LTTNG_ENABLED(port_link)) { + return atom_trace; + } else if (argv[0] == atom_getting_unlinked && LTTNG_ENABLED(port_link)) { + return atom_trace; + } else if (argv[0] == atom_closed && LTTNG_ENABLED(port_exit)) { + return atom_trace; + } + + return atom_discard; +} + +static ERL_NIF_TERM trace_ports(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + lttng_decl_portbuf(port); + lttng_decl_procbuf(to); + + lttng_portid_to_str(argv[2], port); + + /* open and closed */ + if (argv[0] == atom_open) { + ERL_NIF_TERM extra; + char driver[LTTNG_BUFFER_SZ]; + lttng_decl_procbuf(pid); + lttng_pid_to_str(argv[3], pid); + enif_get_map_value(env, argv[4], atom_extra, &extra); + + enif_snprintf(driver, LTTNG_BUFFER_SZ, "%T", extra); + LTTNG3(port_open, pid, driver, port); + } else if (argv[0] == atom_closed) { + char reason[LTTNG_BUFFER_SZ]; + enif_snprintf(reason, LTTNG_BUFFER_SZ, "%T", argv[3]); + + LTTNG2(port_exit, port, reason); + /* link */ + } else if (argv[0] == atom_link) { + lttng_pid_to_str(argv[3], to); + LTTNG3(port_link, port, to, "link"); + } else if (argv[0] == atom_unlink) { + lttng_pid_to_str(argv[3], to); + LTTNG3(port_link, port, to, "unlink"); + } else if (argv[0] == atom_getting_linked) { + lttng_pid_to_str(argv[3], to); + LTTNG3(port_link, to, port, "link"); + } else if (argv[0] == atom_getting_unlinked) { + lttng_pid_to_str(argv[3], to); + LTTNG3(port_link, to, port, "unlink"); + } + return atom_ok; +} + +static ERL_NIF_TERM enabled_running_procs(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + ASSERT(argc == 3); + + if (LTTNG_ENABLED(process_scheduled)) + return atom_trace; + + return atom_discard; +} + +static ERL_NIF_TERM trace_running_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + lttng_decl_procbuf(pid); + const ERL_NIF_TERM* tuple; + char *mfastr = "undefined"; + int arity; + lttng_decl_mfabuf(mfa); + + lttng_pid_to_str(argv[2], pid); + + if (enif_get_tuple(env, argv[3], &arity, &tuple)) { + int val; + enif_get_int(env, tuple[2], &val); + lttng_mfa_to_str(tuple[0], tuple[1], val, mfa); + mfastr = mfa; + } + /* running processes */ + if (argv[0] == atom_in) { + LTTNG3(process_scheduled, pid, mfastr, "in"); + } else if (argv[0] == atom_out) { + LTTNG3(process_scheduled, pid, mfastr, "out"); + /* exiting */ + } else if (argv[0] == atom_in_exiting) { + LTTNG3(process_scheduled, pid, mfastr, "in_exiting"); + } else if (argv[0] == atom_out_exiting) { + LTTNG3(process_scheduled, pid, mfastr, "out_exiting"); + } else if (argv[0] == atom_out_exited) { + LTTNG3(process_scheduled, pid, mfastr, "out_exited"); + } + + return atom_ok; +} + +static ERL_NIF_TERM enabled_running_ports(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + ASSERT(argc == 3); + + if (LTTNG_ENABLED(port_scheduled)) + return atom_trace; + + return atom_discard; +} + +static ERL_NIF_TERM trace_running_ports(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + lttng_decl_procbuf(pid); + lttng_decl_mfabuf(where); + + lttng_portid_to_str(argv[2], pid); + enif_snprintf(where, LTTNG_BUFFER_SZ, "%T", argv[3]); + + /* running ports */ + if (argv[0] == atom_in) { + LTTNG3(port_scheduled, pid, where, "in"); + } else if (argv[0] == atom_out) { + LTTNG3(port_scheduled, pid, where, "out"); + /* exiting */ + } else if (argv[0] == atom_in_exiting) { + LTTNG3(port_scheduled, pid, where, "in_exiting"); + } else if (argv[0] == atom_out_exiting) { + LTTNG3(port_scheduled, pid, where, "out_exiting"); + } else if (argv[0] == atom_out_exited) { + LTTNG3(port_scheduled, pid, where, "out_exited"); + } + return atom_ok; +} +#endif diff --git a/lib/runtime_tools/c_src/dyntrace_lttng.h b/lib/runtime_tools/c_src/dyntrace_lttng.h new file mode 100644 index 0000000000..5e838892d6 --- /dev/null +++ b/lib/runtime_tools/c_src/dyntrace_lttng.h @@ -0,0 +1,367 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2016. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * %CopyrightEnd% + */ + +#undef TRACEPOINT_PROVIDER +#define TRACEPOINT_PROVIDER org_erlang_dyntrace + +#if !defined(DYNTRACE_LTTNG_H) || defined(TRACEPOINT_HEADER_MULTI_READ) +#define DYNTRACE_LTTNG_H + +#include <lttng/tracepoint.h> + +#define LTTNG1(Name, Arg1) \ + tracepoint(org_erlang_dyntrace, Name, (Arg1)) + +#define LTTNG2(Name, Arg1, Arg2) \ + tracepoint(org_erlang_dyntrace, Name, (Arg1), (Arg2)) + +#define LTTNG3(Name, Arg1, Arg2, Arg3) \ + tracepoint(org_erlang_dyntrace, Name, (Arg1), (Arg2), (Arg3)) + +#define LTTNG4(Name, Arg1, Arg2, Arg3, Arg4) \ + tracepoint(org_erlang_dyntrace, Name, (Arg1), (Arg2), (Arg3), (Arg4)) + +#define LTTNG5(Name, Arg1, Arg2, Arg3, Arg4, Arg5) \ + tracepoint(org_erlang_dyntrace, Name, (Arg1), (Arg2), (Arg3), (Arg4), (Arg5)) + +#define LTTNG_ENABLED(Name) \ + tracepoint_enabled(org_erlang_dyntrace, Name) + +#define LTTNG_BUFFER_SZ (256) +#define LTTNG_PROC_BUFFER_SZ (16) +#define LTTNG_PORT_BUFFER_SZ (20) +#define LTTNG_MFA_BUFFER_SZ (256) + +#define lttng_decl_procbuf(Name) \ + char Name[LTTNG_PROC_BUFFER_SZ] + +#define lttng_decl_portbuf(Name) \ + char Name[LTTNG_PORT_BUFFER_SZ] + +#define lttng_decl_mfabuf(Name) \ + char Name[LTTNG_MFA_BUFFER_SZ] + +#define lttng_pid_to_str(pid, name) \ + enif_snprintf(name, LTTNG_PROC_BUFFER_SZ, "%T", (pid)) + +#define lttng_portid_to_str(pid, name) \ + enif_snprintf(name, LTTNG_PORT_BUFFER_SZ, "%T", (pid)) + +#define lttng_proc_to_str(p, name) \ + lttng_pid_to_str(((p) ? (p)->common.id : ERTS_INVALID_PID), name) + +#define lttng_port_to_str(p, name) \ + lttng_portid_to_str(((p) ? (p)->common.id : ERTS_INVALID_PORT), name) + +#define lttng_mfa_to_str(m,f,a, Name) \ + enif_snprintf(Name, LTTNG_MFA_BUFFER_SZ, "%T:%T/%lu", (Eterm)(m), (Eterm)(f), (Uint)(a)) + +/* Process scheduling */ + +TRACEPOINT_EVENT( + org_erlang_dyntrace, + process_spawn, + TP_ARGS( + char*, p, + char*, parent, + char*, mfa + ), + TP_FIELDS( + ctf_string(pid, p) + ctf_string(parent, parent) + ctf_string(entry, mfa) + ) +) + +TRACEPOINT_EVENT( + org_erlang_dyntrace, + process_link, + TP_ARGS( + char*, from, + char*, to, + char*, type + ), + TP_FIELDS( + ctf_string(from, from) + ctf_string(to, to) + ctf_string(type, type) + ) +) + +TRACEPOINT_EVENT( + org_erlang_dyntrace, + process_exit, + TP_ARGS( + char*, p, + char*, reason + ), + TP_FIELDS( + ctf_string(pid, p) + ctf_string(reason, reason) + ) +) + +TRACEPOINT_EVENT( + org_erlang_dyntrace, + process_register, + TP_ARGS( + char*, pid, + char*, name, + char*, type + ), + TP_FIELDS( + ctf_string(pid, pid) + ctf_string(name, name) + ctf_string(type, type) + ) +) + +/* Scheduled */ + +TRACEPOINT_EVENT( + org_erlang_dyntrace, + process_scheduled, + TP_ARGS( + char*, p, + char*, mfa, + char*, type + ), + TP_FIELDS( + ctf_string(pid, p) + ctf_string(entry, mfa) + ctf_string(type, type) + ) +) + +/* Ports */ + + +TRACEPOINT_EVENT( + org_erlang_dyntrace, + port_open, + TP_ARGS( + char*, pid, + char*, driver, + char*, port + ), + TP_FIELDS( + ctf_string(pid, pid) + ctf_string(driver, driver) + ctf_string(port, port) + ) +) + +TRACEPOINT_EVENT( + org_erlang_dyntrace, + port_exit, + TP_ARGS( + char*, port, + char*, reason + ), + TP_FIELDS( + ctf_string(port, port) + ctf_string(reason, reason) + ) +) + +TRACEPOINT_EVENT( + org_erlang_dyntrace, + port_link, + TP_ARGS( + char*, from, + char*, to, + char*, type + ), + TP_FIELDS( + ctf_string(from, from) + ctf_string(to, to) + ctf_string(type, type) + ) +) + +TRACEPOINT_EVENT( + org_erlang_dyntrace, + port_scheduled, + TP_ARGS( + char*, p, + char*, op, + char*, type + ), + TP_FIELDS( + ctf_string(pid, p) + ctf_string(entry, op) + ctf_string(type, type) + ) +) + +/* Call tracing */ + +TRACEPOINT_EVENT( + org_erlang_dyntrace, + function_call, + TP_ARGS( + char*, pid, + char*, mfa, + unsigned int, depth + ), + TP_FIELDS( + ctf_string(pid, pid) + ctf_string(entry, mfa) + ctf_integer(unsigned int, depth, depth) + ) +) + +TRACEPOINT_EVENT( + org_erlang_dyntrace, + function_return, + TP_ARGS( + char*, pid, + char*, mfa, + unsigned int, depth + ), + TP_FIELDS( + ctf_string(pid, pid) + ctf_string(entry, mfa) + ctf_integer(unsigned int, depth, depth) + ) +) + +TRACEPOINT_EVENT( + org_erlang_dyntrace, + function_exception, + TP_ARGS( + char*, pid, + char*, mfa, + char*, type + ), + TP_FIELDS( + ctf_string(pid, pid) + ctf_string(entry, mfa) + ctf_string(class, type) + ) +) + +/* Process messages */ + +TRACEPOINT_EVENT( + org_erlang_dyntrace, + message_send, + TP_ARGS( + char*, sender, + char*, receiver, + char*, msg + ), + TP_FIELDS( + ctf_string(from, sender) + ctf_string(to, receiver) + ctf_string(message, msg) + ) +) + +TRACEPOINT_EVENT( + org_erlang_dyntrace, + message_receive, + TP_ARGS( + char*, receiver, + char*, msg + ), + TP_FIELDS( + ctf_string(to, receiver) + ctf_string(message, msg) + ) +) + +/* Process Memory */ + +TRACEPOINT_EVENT( + org_erlang_dyntrace, + gc_minor_start, + TP_ARGS( + char*, p, + unsigned long, need, + unsigned long, nh, + unsigned long, oh + ), + TP_FIELDS( + ctf_string(pid, p) + ctf_integer(unsigned long, need, need) + ctf_integer(unsigned long, heap, nh) + ctf_integer(unsigned long, old_heap, oh) + ) +) + +TRACEPOINT_EVENT( + org_erlang_dyntrace, + gc_minor_end, + TP_ARGS( + char*, p, + unsigned long, reclaimed, + unsigned long, nh, + unsigned long, oh + ), + TP_FIELDS( + ctf_string(pid, p) + ctf_integer(unsigned long, reclaimed, reclaimed) + ctf_integer(unsigned long, heap, nh) + ctf_integer(unsigned long, old_heap, oh) + ) +) + +TRACEPOINT_EVENT( + org_erlang_dyntrace, + gc_major_start, + TP_ARGS( + char*, p, + unsigned long, need, + unsigned long, nh, + unsigned long, oh + ), + TP_FIELDS( + ctf_string(pid, p) + ctf_integer(unsigned long, need, need) + ctf_integer(unsigned long, heap, nh) + ctf_integer(unsigned long, old_heap, oh) + ) +) + +TRACEPOINT_EVENT( + org_erlang_dyntrace, + gc_major_end, + TP_ARGS( + char*, p, + unsigned long, reclaimed, + unsigned long, nh, + unsigned long, oh + ), + TP_FIELDS( + ctf_string(pid, p) + ctf_integer(unsigned long, reclaimed, reclaimed) + ctf_integer(unsigned long, heap, nh) + ctf_integer(unsigned long, old_heap, oh) + ) +) + +#endif /* DYNTRACE_LTTNG_H */ + +#undef TRACEPOINT_INCLUDE +#define TRACEPOINT_INCLUDE "./dyntrace_lttng.h" + +/* This part must be outside protection */ +#include <lttng/tracepoint-event.h> diff --git a/lib/runtime_tools/c_src/trace_file_drv.c b/lib/runtime_tools/c_src/trace_file_drv.c index 08bace80ef..e7fd5968c1 100644 --- a/lib/runtime_tools/c_src/trace_file_drv.c +++ b/lib/runtime_tools/c_src/trace_file_drv.c @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1999-2011. All Rights Reserved. + * Copyright Ericsson AB 1999-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ @@ -74,12 +75,8 @@ #ifdef DEBUG -#ifndef __WIN32__ -#define ASSERT(X) do {if (!(X)) {erl_exit(1,"%s",#X);} } while(0) -#else #include <assert.h> #define ASSERT(X) assert(X) -#endif #else #define ASSERT(X) #endif @@ -175,6 +172,7 @@ static ErlDrvData trace_file_start(ErlDrvPort port, char *buff); static void trace_file_stop(ErlDrvData handle); static void trace_file_output(ErlDrvData handle, char *buff, ErlDrvSizeT bufflen); +static void trace_file_outputv(ErlDrvData handle, ErlIOVec *ev); static void trace_file_finish(void); static ErlDrvSSizeT trace_file_control(ErlDrvData handle, unsigned int command, @@ -217,7 +215,7 @@ ErlDrvEntry trace_file_driver_entry = { NULL, /* void * that is not used (BC) */ trace_file_control, /* F_PTR control, port_control callback */ trace_file_timeout, /* F_PTR timeout, driver_set_timer callback */ - NULL, /* F_PTR outputv, reserved */ + trace_file_outputv, /* F_PTR outputv, reserved */ NULL, /* ready_async */ NULL, /* flush */ NULL, /* call */ @@ -326,9 +324,11 @@ static ErlDrvData trace_file_start(ErlDrvPort port, char *buff) | O_BINARY #endif , 0777)) < 0) { + int saved_errno = errno; if (wrap) driver_free(wrap); driver_free(data); + errno = saved_errno; return ERL_DRV_ERROR_ERRNO; } @@ -364,6 +364,16 @@ static void trace_file_stop(ErlDrvData handle) /* ** Data sent from erlang to port. */ +static void trace_file_outputv(ErlDrvData handle, ErlIOVec *ev) +{ + int i; + for (i = 0; i < ev->vsize; i++) { + if (ev->iov[i].iov_len) + trace_file_output(handle, ev->iov[i].iov_base, + ev->iov[i].iov_len); + } +} + static void trace_file_output(ErlDrvData handle, char *buff, ErlDrvSizeT bufflen) { @@ -524,14 +534,19 @@ static void *my_alloc(size_t size) ** A write wrapper that regards it as an error if not all data was written. */ static int do_write(FILETYPE fd, unsigned char *buff, int siz) { - int w = write(fd, buff, siz); - if (w != siz) { - if (w >= 0) { - errno = ENOSPC; + int w; + while (1) { + w = write(fd, buff, siz); + if (w < 0 && errno == EINTR) + continue; + else if (w != siz) { + if (w >= 0) { + errno = ENOSPC; + } + return -1; } - return -1; + return siz; } - return siz; } /* @@ -626,8 +641,10 @@ static void close_unlink_port(TraceFileData *data) */ static int wrap_file(TraceFileData *data) { if (my_flush(data) < 0) { + int saved_errno = errno; close(data->fd); data->fd = -1; + errno = saved_errno; return -1; } close(data->fd); @@ -643,12 +660,15 @@ static int wrap_file(TraceFileData *data) { next_name(&data->wrap->del); } next_name(&data->wrap->cur); +try_open: data->fd = open(data->wrap->cur.name, O_WRONLY | O_TRUNC | O_CREAT #ifdef O_BINARY | O_BINARY #endif , 0777); if (data->fd < 0) { + if (errno == EINTR) + goto try_open; data->fd = -1; return -1; } diff --git a/lib/runtime_tools/c_src/trace_ip_drv.c b/lib/runtime_tools/c_src/trace_ip_drv.c index 6b77128761..195558f958 100644 --- a/lib/runtime_tools/c_src/trace_ip_drv.c +++ b/lib/runtime_tools/c_src/trace_ip_drv.c @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1999-2012. All Rights Reserved. + * Copyright Ericsson AB 1999-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ @@ -34,37 +35,17 @@ #include <stdlib.h> #include <string.h> #ifndef __WIN32__ -# ifdef VXWORKS -# include <sockLib.h> -# include <sys/times.h> -# include <iosLib.h> -# include <taskLib.h> -# include <selectLib.h> -# include <ioLib.h> -# include "reclaim.h" -# endif -# include <unistd.h> -# include <errno.h> -# include <sys/types.h> -# include <sys/socket.h> -# include <netinet/in.h> -# include <fcntl.h> +# include <unistd.h> +# include <errno.h> +# include <sys/types.h> +# include <sys/socket.h> +# include <netinet/in.h> +# include <fcntl.h> #endif #ifdef DEBUG -# ifndef __WIN32__ - /* erl_exit is not available to dll_drivers on windows. */ - void erl_exit(int, char *, ...); -# define ASSERT(X) \ - do { \ - if (!(X)) { \ - erl_exit(1,"%s",#X); \ - } \ - } while(0) -# else -# include <assert.h> -# define ASSERT(X) assert(X) -# endif +# include <assert.h> +# define ASSERT(X) assert(X) #else # define ASSERT(X) #endif @@ -393,6 +374,7 @@ static void trace_ip_output(ErlDrvData handle, char *buff, ErlDrvSizeT bufflen) } return; } + ASSERT(!IS_INVALID_SOCKET(data->fd)); if (data->que[data->questart] != NULL) { trace_ip_ready_output(handle, sock2event(data->fd)); } @@ -431,6 +413,7 @@ static void trace_ip_ready_input(ErlDrvData handle, ErlDrvEvent fd) /* ** Maybe accept, we are a listen port... */ + ASSERT(IS_INVALID_SOCKET(data->fd)); if (!IS_INVALID_SOCKET((client = my_accept(data->listenfd)))) { data->fd = client; set_nonblocking(client); @@ -754,6 +737,7 @@ static void close_client(TraceIpData *data) { my_driver_select(data, data->fd, FLAG_WRITE | FLAG_READ, SELECT_CLOSE); data->flags |= FLAG_LISTEN_PORT; + data->fd = INVALID_SOCKET; if (!(data->flags & FLAG_FILL_ALWAYS)) { clean_que(data); } @@ -910,7 +894,7 @@ static void stop_select(ErlDrvEvent event, void* _) WSACloseEvent((HANDLE)event); } -#else /* UNIX/VXWORKS */ +#else /* UNIX */ static int my_driver_select(TraceIpData *desc, SOCKET fd, int flags, enum MySelectOp op) { diff --git a/lib/runtime_tools/doc/specs/.gitignore b/lib/runtime_tools/doc/specs/.gitignore new file mode 100644 index 0000000000..322eebcb06 --- /dev/null +++ b/lib/runtime_tools/doc/specs/.gitignore @@ -0,0 +1 @@ +specs_*.xml diff --git a/lib/runtime_tools/doc/src/LTTng.xml b/lib/runtime_tools/doc/src/LTTng.xml new file mode 100644 index 0000000000..7aae5e5c41 --- /dev/null +++ b/lib/runtime_tools/doc/src/LTTng.xml @@ -0,0 +1,595 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> +<chapter> + <header> + <copyright> + <year>2016</year><year>2016</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + </legalnotice> + + <title>LTTng and Erlang/OTP</title> + <prepared></prepared> + <responsible></responsible> + <docno></docno> + <approved></approved> + <checked></checked> + <date>2016-04-27</date> + <rev></rev> + <file>LTTng.xml</file> + </header> + + <section> + <title>Introduction</title> + <p>The Linux Trace Toolkit: next generation is an open source system software package + for correlated tracing of the Linux kernel, user applications and libraries. </p> + <p>For more information, please visit <url href="http://lttng.org">http://lttng.org</url></p> + </section> + + <section> + <title>Building Erlang/OTP with LTTng support</title> + <p> + Configure and build Erlang with LTTng support: + </p> + <p>For LTTng to work properly with Erlang/OTP you need + the following packages installed:</p> + + <list type="bulleted"> + <item><p>LTTng-tools: a command line interface to control tracing sessions.</p></item> + <item><p>LTTng-UST: user space tracing library.</p></item> + </list> + + <p>On Ubuntu this can be installed via <c>aptitude</c>:</p> + + <code type="none">$ sudo aptitude install lttng-tools liblttng-ust-dev</code> + <p>See <url href="http://lttng.org/docs/#doc-installing-lttng">Installing LTTng</url> + for more information on how to install LTTng on your system.</p> + + <p>After LTTng is properly installed on the system Erlang/OTP can be built with LTTng support.</p> + + +<code type="none">$ ./configure --with-dynamic-trace=lttng +$ make </code> + </section> + + <section> + <title>Dyntrace Tracepoints</title> + <p>All tracepoints are in the domain of <c>org_erlang_dyntrace</c></p> + <p>All Erlang types are the string equivalent in LTTng.</p> + + <p><em>process_spawn</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>parent : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>entry : string</c> :: Code Location. Ex. <c>"lists:sort/1"</c></item> + </list> + <p> + Available through + <seealso marker="erts:erlang#trace-3"><c>erlang:trace/3</c></seealso> with trace flag <c>procs</c> and <c>{tracer,dyntrace,[]}</c> as tracer module. + </p> + <p>Example:</p> + <code type="none">process_spawn: { cpu_id = 3 }, { pid = "<0.131.0>", parent = "<0.130.0>", entry = "erlang:apply/2" }</code> + + <p><em>process_link</em></p> + <list type="bulleted"> + <item><c>to : string</c> :: Process ID or Port ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>from : string</c> :: Process ID or Port ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>type : string</c> :: <c>"link" | "unlink"</c></item> + </list> + <p> + Available through + <seealso marker="erts:erlang#trace-3"><c>erlang:trace/3</c></seealso> with trace flag <c>procs</c> and <c>{tracer,dyntrace,[]}</c> as tracer module. + </p> + <p>Example:</p> + <code type="none">process_link: { cpu_id = 3 }, { from = "<0.130.0>", to = "<0.131.0>", type = "link" }</code> + + + <p><em>process_exit</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>reason : string</c> :: Exit reason. Ex. <c>"normal"</c></item> + </list> + <p> + Available through + <seealso marker="erts:erlang#trace-3"><c>erlang:trace/3</c></seealso> with trace flag <c>procs</c> and <c>{tracer,dyntrace,[]}</c> as tracer module. + </p> + <p>Example:</p> + <code type="none">process_exit: { cpu_id = 3 }, { pid = "<0.130.0>", reason = "normal" }</code> + + <p><em>process_register</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>name : string</c> :: Registered name. Ex. <c>"error_logger"</c></item> + <item><c>type : string</c> :: <c>"register" | "unregister"</c></item> + </list> + <p>Example:</p> + <code type="none">process_register: { cpu_id = 0 }, { pid = "<0.128.0>", name = "dyntrace_lttng_SUITE" type = "register" }</code> + + <p><em>process_scheduled</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>entry : string</c> :: Code Location. Ex. <c>"lists:sort/1"</c></item> + <item><c>type : string</c> :: <c>"in" | "out" | "in_exiting" | "out_exiting" | "out_exited"</c></item> + </list> + <p> + Available through + <seealso marker="erts:erlang#trace-3"><c>erlang:trace/3</c></seealso> with trace flag <c>running</c> and <c>{tracer,dyntrace,[]}</c> as tracer module. + </p> + <p>Example:</p> + <code type="none">process_scheduled: { cpu_id = 0 }, { pid = "<0.136.0>", entry = "erlang:apply/2", type = "in" }</code> + + + <p><em>port_open</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + </list> + <p> + Available through + <seealso marker="erts:erlang#trace-3"><c>erlang:trace/3</c></seealso> with trace flag <c>ports</c> and <c>{tracer,dyntrace,[]}</c> as tracer module. + </p> + <p>Example:</p> + <code type="none">port_open: { cpu_id = 5 }, { pid = "<0.131.0>", driver = "'/bin/sh -s unix:cmd'", port = "#Port<0.1887>" }</code> + + <p><em>port_exit</em></p> + <list type="bulleted"> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>reason : string</c> :: Exit reason. Ex. <c>"normal"</c></item> + </list> + <p> + Available through + <seealso marker="erts:erlang#trace-3"><c>erlang:trace/3</c></seealso> with trace flag <c>ports</c> and <c>{tracer,dyntrace,[]}</c> as tracer module. + </p> + <p>Example:</p> + <code type="none">port_exit: { cpu_id = 5 }, { port = "#Port<0.1887>", reason = "normal" }</code> + + <p><em>port_link</em></p> + <list type="bulleted"> + <item><c>to : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>from : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>type : string</c> :: <c>"link" | "unlink"</c></item> + </list> + <p> + Available through + <seealso marker="erts:erlang#trace-3"><c>erlang:trace/3</c></seealso> with trace flag <c>ports</c> and <c>{tracer,dyntrace,[]}</c> as tracer module. + </p> + <p>Example:</p> + <code type="none">port_link: { cpu_id = 5 }, { from = "#Port<0.1887>", to = "<0.131.0>", type = "unlink" }</code> + + <p><em>port_scheduled</em></p> + <p> + Available through + <seealso marker="erts:erlang#trace-3"><c>erlang:trace/3</c></seealso> with trace flag <c>running</c> and <c>{tracer,dyntrace,[]}</c> as tracer module. + </p> + <list type="bulleted"> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>entry : string</c> :: Callback. Ex. <c>"open"</c></item> + <item><c>type : string</c> :: <c>"in" | "out" | "in_exiting" | "out_exiting" | "out_exited"</c></item> + </list> + + <p>Example:</p> + <code type="none">port_scheduled: { cpu_id = 5 }, { pid = "#Port<0.1905>", entry = "close", type = "out" }</code> + <p> + Available through + <seealso marker="erts:erlang#trace-3"><c>erlang:trace/3</c></seealso> with trace flag <c>running</c> and <c>{tracer,dyntrace,[]}</c> as tracer module. + </p> + <p><em>function_call</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>entry : string</c> :: Code Location. Ex. <c>"lists:sort/1"</c></item> + <item><c>depth : integer</c> :: Stack depth. Ex. <c>0</c></item> + </list> + <p> + Available through + <seealso marker="erts:erlang#trace-3"><c>erlang:trace/3</c></seealso> with trace flag <c>call</c> and <c>{tracer,dyntrace,[]}</c> as tracer module. + </p> + <p>Example:</p> + <code type="none">function_call: { cpu_id = 5 }, { pid = "<0.145.0>", entry = "dyntrace_lttng_SUITE:'-t_call/1-fun-1-'/0", depth = 0 }</code> + + <p><em>function_return</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>entry : string</c> :: Code Location. Ex. <c>"lists:sort/1"</c></item> + <item><c>depth : integer</c> :: Stack depth. Ex. <c>0</c></item> + </list> + <p> + Available through + <seealso marker="erts:erlang#trace-3"><c>erlang:trace/3</c></seealso> with trace flag <c>call</c> or <c>return_to</c> and <c>{tracer,dyntrace,[]}</c> as tracer module. + </p> + <p>Example:</p> + <code type="none">function_return: { cpu_id = 5 }, { pid = "<0.145.0>", entry = "dyntrace_lttng_SUITE:waiter/0", depth = 0 }</code> + + <p><em>function_exception</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>entry : string</c> :: Code Location. Ex. <c>"lists:sort/1"</c></item> + <item><c>class : string</c> :: Error reason. Ex. <c>"error"</c></item> + </list> + <p> + Available through + <seealso marker="erts:erlang#trace-3"><c>erlang:trace/3</c></seealso> with trace flag <c>call</c> and <c>{tracer,dyntrace,[]}</c> as tracer module. + </p> + <p>Example:</p> + <code type="none">function_exception: { cpu_id = 5 }, { pid = "<0.144.0>", entry = "t:call_exc/1", class = "error" }</code> + + <p><em>message_send</em></p> + <list type="bulleted"> + <item><c>from : string</c> :: Process ID or Port ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>to : string</c> :: Process ID or Port ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>message : string</c> :: Message sent. Ex. <c>"{<0.162.0>,ok}"</c></item> + </list> + <p> + Available through + <seealso marker="erts:erlang#trace-3"><c>erlang:trace/3</c></seealso> with trace flag <c>send</c> and <c>{tracer,dyntrace,[]}</c> as tracer module. + </p> + <p>Example:</p> + <code type="none">message_send: { cpu_id = 3 }, { from = "#Port<0.1938>", to = "<0.160.0>", message = "{#Port<0.1938>,eof}" }</code> + + <p><em>message_receive</em></p> + <list type="bulleted"> + <item><c>to : string</c> :: Process ID or Port ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>message : string</c> :: Message received. Ex. <c>"{<0.162.0>,ok}"</c></item> + </list> + <p> + Available through + <seealso marker="erts:erlang#trace-3"><c>erlang:trace/3</c></seealso> with trace flag <c>'receive'</c> and <c>{tracer,dyntrace,[]}</c> as tracer module. + </p> + <p>Example:</p> + <code type="none">message_receive: { cpu_id = 7 }, { to = "<0.167.0>", message = "{<0.165.0>,ok}" }</code> + + <p><em>gc_minor_start</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>need : integer</c> :: Heap need. Ex. <c>2</c></item> + <item><c>heap : integer</c> :: Young heap word size. Ex. <c>233</c></item> + <item><c>old_heap : integer</c> :: Old heap word size. Ex. <c>233</c></item> + </list> + <p> + Available through + <seealso marker="erts:erlang#trace-3"><c>erlang:trace/3</c></seealso> with trace flag <c>garbage_collection</c> and <c>{tracer,dyntrace,[]}</c> as tracer module. + </p> + <p>Example:</p> + <code type="none">gc_minor_start: { cpu_id = 0 }, { pid = "<0.172.0>", need = 0, heap = 610, old_heap = 0 }</code> + + <p><em>gc_minor_end</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>reclaimed : integer</c> :: Heap reclaimed. Ex. <c>2</c></item> + <item><c>heap : integer</c> :: Young heap word size. Ex. <c>233</c></item> + <item><c>old_heap : integer</c> :: Old heap word size. Ex. <c>233</c></item> + </list> + <p> + Available through + <seealso marker="erts:erlang#trace-3"><c>erlang:trace/3</c></seealso> with trace flag <c>garbage_collection</c> and <c>{tracer,dyntrace,[]}</c> as tracer module. + </p> + <p>Example:</p> + <code type="none">gc_minor_end: { cpu_id = 0 }, { pid = "<0.172.0>", reclaimed = 120, heap = 1598, old_heap = 1598 }</code> + + <p><em>gc_major_start</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>need : integer</c> :: Heap need. Ex. <c>2</c></item> + <item><c>heap : integer</c> :: Young heap word size. Ex. <c>233</c></item> + <item><c>old_heap : integer</c> :: Old heap word size. Ex. <c>233</c></item> + </list> + <p> + Available through + <seealso marker="erts:erlang#trace-3"><c>erlang:trace/3</c></seealso> with trace flag <c>garbage_collection</c> and <c>{tracer,dyntrace,[]}</c> as tracer module. + </p> + <p>Example:</p> + <code type="none">gc_major_start: { cpu_id = 0 }, { pid = "<0.172.0>", need = 8, heap = 2586, old_heap = 1598 }</code> + + <p><em>gc_major_end</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>reclaimed : integer</c> :: Heap reclaimed. Ex. <c>2</c></item> + <item><c>heap : integer</c> :: Young heap word size. Ex. <c>233</c></item> + <item><c>old_heap : integer</c> :: Old heap word size. Ex. <c>233</c></item> + </list> + <p> + Available through + <seealso marker="erts:erlang#trace-3"><c>erlang:trace/3</c></seealso> with trace flag <c>garbage_collection</c> and <c>{tracer,dyntrace,[]}</c> as tracer module. + </p> + <p>Example:</p> + <code type="none">gc_major_end: { cpu_id = 0 }, { pid = "<0.172.0>", reclaimed = 240, heap = 4185, old_heap = 0 }</code> + + </section> + + <section> + <title>BEAM Tracepoints</title> + <p>All tracepoints are in the domain of <c>org_erlang_otp</c></p> + <p>All Erlang types are the string equivalent in LTTng.</p> + + <p><em>scheduler_poll</em></p> + <list type="bulleted"> + <item><c>scheduler : integer</c> :: Scheduler ID. Ex. <c>1</c></item> + <item><c>runnable : integer</c> :: Runnable. Ex. <c>1</c></item> + </list> + <p>Example:</p> + <code type="none">scheduler_poll: { cpu_id = 4 }, { scheduler = 1, runnable = 1 }</code> + + <p><em>driver_init</em></p> + <list type="bulleted"> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + <item><c>major : integer</c> :: Major version. Ex. <c>3</c></item> + <item><c>minor : integer</c> :: Minor version. Ex. <c>1</c></item> + <item><c>flags : integer</c> :: Flags. Ex. <c>1</c></item> + </list> + <p>Example:</p> + <code type="none">driver_init: { cpu_id = 2 }, { driver = "caller_drv", major = 3, minor = 3, flags = 1 }</code> + + <p><em>driver_start</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + </list> + <p>Example:</p> + <code type="none">driver_start: { cpu_id = 2 }, { pid = "<0.198.0>", driver = "caller_drv", port = "#Port<0.3676>" }</code> + + <p><em>driver_output</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + <item><c>bytes : integer</c> :: Size of data returned. Ex. <c>82</c></item> + </list> + <p>Example:</p> + <code type="none">driver_output: { cpu_id = 2 }, { pid = "<0.198.0>", port = "#Port<0.3677>", driver = "/bin/sh -s unix:cmd", bytes = 36 }</code> + + <p><em>driver_outputv</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + <item><c>bytes : integer</c> :: Size of data returned. Ex. <c>82</c></item> + </list> + <p>Example:</p> + <code type="none">driver_outputv: { cpu_id = 5 }, { pid = "<0.194.0>", port = "#Port<0.3663>", driver = "tcp_inet", bytes = 3 }</code> + + <p><em>driver_ready_input</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + </list> + <p>Example:</p> + <code type="none">driver_ready_input: { cpu_id = 5 }, { pid = "<0.189.0>", port = "#Port<0.3637>", driver = "inet_gethost 4 " }</code> + + <p><em>driver_ready_output</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + </list> + <p>Example:</p> + <code type="none">driver_ready_output: { cpu_id = 5 }, { pid = "<0.194.0>", port = "#Port<0.3663>", driver = "tcp_inet" }</code> + + <p><em>driver_timeout</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + </list> + <p>Example:</p> + <code type="none">driver_timeout: { cpu_id = 5 }, { pid = "<0.196.0>", port = "#Port<0.3664>", driver = "tcp_inet" }</code> + + <p><em>driver_stop_select</em></p> + <list type="bulleted"> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + </list> + <p>Example:</p> + <code type="none">driver_stop_select: { cpu_id = 5 }, { driver = "unknown" }</code> + + <p><em>driver_flush</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + </list> + <p>Example:</p> + <code type="none">driver_flush: { cpu_id = 7 }, { pid = "<0.204.0>", port = "#Port<0.3686>", driver = "tcp_inet" }</code> + + <p><em>driver_stop</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + </list> + <p>Example:</p> + <code type="none">driver_stop: { cpu_id = 5 }, { pid = "[]", port = "#Port<0.3673>", driver = "efile" }</code> + + <p><em>driver_process_exit</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + </list> + + <p><em>driver_ready_async</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + </list> + <p>Example:</p> + <code type="none">driver_ready_async: { cpu_id = 3 }, { pid = "<0.181.0>", port = "#Port<0.3622>", driver = "efile" }</code> + + <p><em>driver_call</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + <item><c>command : integer</c> :: Command integer. Ex. <c>1</c></item> + <item><c>bytes : integer</c> :: Size of data returned. Ex. <c>82</c></item> + </list> + <p>Example:</p> + <code type="none">driver_call: { cpu_id = 2 }, { pid = "<0.202.0>", port = "#Port<0.3676>", driver = "caller_drv", command = 0, bytes = 2 }</code> + + <p><em>driver_control</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + <item><c>command : integer</c> :: Command integer. Ex. <c>1</c></item> + <item><c>bytes : integer</c> :: Size of data returned. Ex. <c>82</c></item> + </list> + <p>Example:</p> + <code type="none">driver_control: { cpu_id = 3 }, { pid = "<0.32767.8191>", port = "#Port<0.0>", driver = "forker", command = 83, bytes = 32 }</code> + + <p><em>aio_pool_get</em></p> + <list type="bulleted"> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>length : integer</c> :: Async queue length. Ex. <c>0</c></item> + </list> + <p>Example:</p> + <code type="none">aio_pool_get: { cpu_id = 4 }, { port = "#Port<0.3614>", length = 0 }</code> + + <p><em>aio_pool_put</em></p> + <list type="bulleted"> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>length : integer</c> :: Async queue length. Ex. <c>-1</c></item> + </list> + <p>Async queue length is not defined for <c>put</c> operations.</p> + <p>Example:</p> + <code type="none">aio_pool_put: { cpu_id = 3 }, { port = "#Port<0.3614>", length = -1 }</code> + + <p><em>carrier_create</em></p> + <list type="bulleted"> + <item><c>type : string</c> :: Carrier type. Ex. <c>"ets_alloc"</c></item> + <item><c>instance : integer</c> :: Allocator instance. Ex. <c>1</c></item> + <item><c>size : integer</c> :: Carrier size. Ex. <c>262144</c></item> + <item><c>mbc_carriers : integer</c> :: Number of multiblock carriers in instance. Ex. <c>3</c></item> + <item><c>mbc_carriers_size : integer</c> :: Total size of multiblock blocks carriers in instance. Ex. <c>1343488</c></item> + <item><c>mbc_blocks : integer</c> :: Number of multiblock blocks in instance. Ex. <c>122</c></item> + <item><c>mbc_blocks_size : integer</c> :: Total size of all multiblock blocks in instance. Ex. <c>285296</c></item> + <item><c>sbc_carriers : integer</c> :: Number of singleblock carriers in instance. Ex. <c>1</c></item> + <item><c>sbc_carriers_size : integer</c> :: Total size of singleblock blocks carriers in instance. Ex. <c>1343488</c></item> + <item><c>sbc_blocks : integer</c> :: Number of singleblocks in instance. Ex. <c>1</c></item> + <item><c>sbc_blocks_size : integer</c> :: Total size of all singleblock blocks in instance. Ex. <c>285296</c></item> + + </list> + <p>Example:</p> + <code type="none">carrier_create: { cpu_id = 2 }, { type = "ets_alloc", instance = 7, size = 2097152, mbc_carriers = 4, mbc_carriers_size = 3440640, mbc_blocks = 526, mbc_blocks_size = 1278576, sbc_carriers = 0, sbc_carriers_size = 0, sbc_blocks = 0, sbc_blocks_size = 0 }</code> + + <p><em>carrier_destroy</em></p> + <list type="bulleted"> + <item><c>type : string</c> :: Carrier type. Ex. <c>"ets_alloc"</c></item> + <item><c>instance : integer</c> :: Allocator instance. Ex. <c>1</c></item> + <item><c>size : integer</c> :: Carrier size. Ex. <c>262144</c></item> + <item><c>mbc_carriers : integer</c> :: Number of multiblock carriers in instance. Ex. <c>3</c></item> + <item><c>mbc_carriers_size : integer</c> :: Total size of multiblock blocks carriers in instance. Ex. <c>1343488</c></item> + <item><c>mbc_blocks : integer</c> :: Number of multiblock blocks in instance. Ex. <c>122</c></item> + <item><c>mbc_blocks_size : integer</c> :: Total size of all multiblock blocks in instance. Ex. <c>285296</c></item> + <item><c>sbc_carriers : integer</c> :: Number of singleblock carriers in instance. Ex. <c>1</c></item> + <item><c>sbc_carriers_size : integer</c> :: Total size of singleblock blocks carriers in instance. Ex. <c>1343488</c></item> + <item><c>sbc_blocks : integer</c> :: Number of singleblocks in instance. Ex. <c>1</c></item> + <item><c>sbc_blocks_size : integer</c> :: Total size of all singleblock blocks in instance. Ex. <c>285296</c></item> + + </list> + <p>Example:</p> + <code type="none">carrier_destroy: { cpu_id = 6 }, { type = "ets_alloc", instance = 7, size = 262144, mbc_carriers = 3, mbc_carriers_size = 3178496, mbc_blocks = 925, mbc_blocks_size = 2305336, sbc_carriers = 0, sbc_carriers_size = 0, sbc_blocks = 0, sbc_blocks_size = 0 }</code> + + <p><em>carrier_pool_put</em></p> + <list type="bulleted"> + <item><c>type : string</c> :: Carrier type. Ex. <c>"ets_alloc"</c></item> + <item><c>instance : integer</c> :: Allocator instance. Ex. <c>1</c></item> + <item><c>size : integer</c> :: Carrier size. Ex. <c>262144</c></item> + </list> + <p>Example:</p> + <code type="none">carrier_pool_put: { cpu_id = 3 }, { type = "ets_alloc", instance = 5, size = 1048576 }</code> + + <p><em>carrier_pool_get</em></p> + <list type="bulleted"> + <item><c>type : string</c> :: Carrier type. Ex. <c>"ets_alloc"</c></item> + <item><c>instance : integer</c> :: Allocator instance. Ex. <c>1</c></item> + <item><c>size : integer</c> :: Carrier size. Ex. <c>262144</c></item> + </list> + <p>Example:</p> + <code type="none">carrier_pool_get: { cpu_id = 7 }, { type = "ets_alloc", instance = 4, size = 3208 }</code> + </section> + + <section> + <title>Example of process tracing</title> + <p>An example of process tracing of <c>os_mon</c> and friends.</p> + + <p>Clean start of lttng in a bash shell.</p> + + <pre>$ lttng create erlang-demo +Spawning a session daemon +Session erlang-demo created. +Traces will be written in /home/egil/lttng-traces/erlang-demo-20160526-165920</pre> + + <p>Start an Erlang node with lttng enabled.</p> + + <pre>$ erl +Erlang/OTP 19 [erts-8.0] [source-4d7b24d] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [lttng] + +Eshell V8.0 (abort with ^G) +1></pre> + + <p>Load the <c>dyntrace</c> module.</p> + + <pre>1> <input>l(dyntrace).</input> +{module,dyntrace}</pre> + + <p>All tracepoints via dyntrace are now visibile and can be listed through <c>lttng list -u</c>.</p> + + <p>Enable the process_register LTTng tracepoint for Erlang.</p> + + <pre>$ lttng enable-event -u org_erlang_dyntrace:process_register +UST event org_erlang_dyntrace:process_register created in channel channel0</pre> + + <p>Enable process tracing for new processes and use <c>dyntrace</c> as tracer backend.</p> + + <pre>2> <input>erlang:trace(new,true,[procs,{tracer,dyntrace,[]}]).</input> +0</pre> + + <p>Start LTTng tracing.</p> + + <pre>$ lttng start +Tracing started for session erlang-demo</pre> + + <p>Start the <c>os_mon</c> application in Erlang.</p> + + <pre>3> <input>application:ensure_all_started(os_mon).</input> +{ok,[sasl,os_mon]}</pre> + + <p>Stop LTTng tracing and view the result.</p> + + <pre>$ lttng stop +Tracing stopped for session erlang-demo +$ lttng view +[17:20:42.561168759] (+?.?????????) elxd1168lx9 org_erlang_dyntrace:process_register: \ + { cpu_id = 5 }, { pid = "<0.66.0>", name = "sasl_sup", type = "register" } +[17:20:42.561215519] (+0.000046760) elxd1168lx9 org_erlang_dyntrace:process_register: \ + { cpu_id = 5 }, { pid = "<0.67.0>", name = "sasl_safe_sup", type = "register" } +[17:20:42.562149024] (+0.000933505) elxd1168lx9 org_erlang_dyntrace:process_register: \ + { cpu_id = 5 }, { pid = "<0.68.0>", name = "alarm_handler", type = "register" } +[17:20:42.571035803] (+0.008886779) elxd1168lx9 org_erlang_dyntrace:process_register: \ + { cpu_id = 5 }, { pid = "<0.69.0>", name = "release_handler", type = "register" } +[17:20:42.574939868] (+0.003904065) elxd1168lx9 org_erlang_dyntrace:process_register: \ + { cpu_id = 5 }, { pid = "<0.74.0>", name = "os_mon_sup", type = "register" } +[17:20:42.576818712] (+0.001878844) elxd1168lx9 org_erlang_dyntrace:process_register: \ + { cpu_id = 5 }, { pid = "<0.75.0>", name = "disksup", type = "register" } +[17:20:42.580032013] (+0.003213301) elxd1168lx9 org_erlang_dyntrace:process_register: \ + { cpu_id = 5 }, { pid = "<0.76.0>", name = "memsup", type = "register" } +[17:20:42.583046339] (+0.003014326) elxd1168lx9 org_erlang_dyntrace:process_register: \ + { cpu_id = 5 }, { pid = "<0.78.0>", name = "cpu_sup", type = "register" } +[17:20:42.586206242] (+0.003159903) elxd1168lx9 org_erlang_dyntrace:process_register: \ + { cpu_id = 5 }, { pid = "<0.82.0>", name = "timer_server", type = "register" }</pre> + </section> +</chapter> diff --git a/lib/runtime_tools/doc/src/Makefile b/lib/runtime_tools/doc/src/Makefile index d240b287c3..5ce40bb995 100644 --- a/lib/runtime_tools/doc/src/Makefile +++ b/lib/runtime_tools/doc/src/Makefile @@ -1,18 +1,19 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1999-2012. All Rights Reserved. +# Copyright Ericsson AB 1999-2016. All Rights Reserved. # -# The contents of this file are subject to the Erlang Public License, -# Version 1.1, (the "License"); you may not use this file except in -# compliance with the License. You should have received a copy of the -# Erlang Public License along with this software. If not, it can be -# retrieved online at http://www.erlang.org/. -# -# Software distributed under the License is distributed on an "AS IS" -# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -# the License for the specific language governing rights and limitations -# under the License. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # %CopyrightEnd% # @@ -40,11 +41,13 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN) # Target Specs # ---------------------------------------------------- XML_APPLICATION_FILES = ref_man.xml -XML_REF3_FILES = dbg.xml dyntrace.xml erts_alloc_config.xml +XML_REF3_FILES = dbg.xml dyntrace.xml erts_alloc_config.xml system_information.xml msacc.xml XML_REF6_FILES = runtime_tools_app.xml -XML_PART_FILES = part_notes.xml part_notes_history.xml -XML_CHAPTER_FILES = notes.xml notes_history.xml +XML_PART_FILES = part_notes.xml part_notes_history.xml part.xml +XML_CHAPTER_FILES = notes.xml notes_history.xml LTTng.xml + +GENERATED_XML_FILES = DTRACE.xml SYSTEMTAP.xml BOOK_FILES = book.xml @@ -69,15 +72,28 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf +SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml) + +TOP_SPECS_FILE = specs.xml + # ---------------------------------------------------- # FLAGS # ---------------------------------------------------- XML_FLAGS += DVIPS_FLAGS += +SPECS_ESRC = ../../src + +SPECS_FLAGS = -I../../include -I../../../kernel/src + # ---------------------------------------------------- # Targets # ---------------------------------------------------- +$(XML_FILES): $(GENERATED_XML_FILES) + +%.xml: $(ERL_TOP)/HOWTO/%.md $(ERL_TOP)/make/emd2exml + $(ERL_TOP)/make/emd2exml $< $@ + $(HTMLDIR)/%.gif: %.gif $(INSTALL_DATA) $< $@ diff --git a/lib/runtime_tools/doc/src/book.xml b/lib/runtime_tools/doc/src/book.xml index 3f0dd7d55e..e2ab4c6f62 100644 --- a/lib/runtime_tools/doc/src/book.xml +++ b/lib/runtime_tools/doc/src/book.xml @@ -1,23 +1,24 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE book SYSTEM "book.dtd"> <book xmlns:xi="http://www.w3.org/2001/XInclude"> <header titlestyle="normal"> <copyright> - <year>1999</year><year>2009</year> + <year>1999</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -34,6 +35,9 @@ <preamble> <contents level="2"></contents> </preamble> + <parts lift="no"> + <xi:include href="part.xml"/> + </parts> <applications> <xi:include href="ref_man.xml"/> </applications> diff --git a/lib/runtime_tools/doc/src/dbg.xml b/lib/runtime_tools/doc/src/dbg.xml index c7c5cd4ff0..95f74d4607 100644 --- a/lib/runtime_tools/doc/src/dbg.xml +++ b/lib/runtime_tools/doc/src/dbg.xml @@ -1,23 +1,24 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> <header> <copyright> - <year>1996</year><year>2011</year> + <year>1996</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -35,14 +36,30 @@ <modulesummary>The Text Based Trace Facility</modulesummary> <description> <p>This module implements a text based interface to the - <c>trace/3</c> and the <c>trace_pattern/2</c> BIFs. It makes it - possible to trace functions, processes and messages on text based - terminals. It can be used instead of, or as complement to, the - <c>pman</c> module. - </p> - <p>For some examples of how to use <c>dbg</c> from the Erlang + <seealso marker="erts:erlang#trace-3"><c>trace/3</c></seealso> and the + <seealso marker="erts:erlang#trace_pattern-2"><c>trace_pattern/2</c></seealso> BIFs. It makes it + possible to trace functions, processes, ports and messages. + </p> + <p> + To quickly get started on tracing function calls you can use the following + code in the Erlang shell: + </p> + <pre> +1> dbg:tracer(). %% Start the default trace message receiver +{ok,<0.36.0>} +2> dbg:p(all, c). %% Setup call (c) tracing on all processes +{ok,[{matched,nonode@nohost,26}]} +3> dbg:tp(lists, seq, x). %% Setup an exception return trace (x) on lists:seq +{ok,[{matched,nonode@nohost,2},{saved,x}]} +4> lists:seq(1,10). +(<0.34.0>) call lists:seq(1,10) +(<0.34.0>) returned from lists:seq/2 -> [1,2,3,4,5,6,7,8,9,10] +[1,2,3,4,5,6,7,8,9,10] + </pre> + <p> + For more examples of how to use <c>dbg</c> from the Erlang shell, see the <seealso marker="#simple_example">simple example</seealso> section. - </p> + </p> <p>The utilities are also suitable to use in system testing on large systems, where other tools have too much impact on the system performance. Some primitive support for sequential tracing @@ -61,7 +78,7 @@ <p>Pseudo function that by means of a <c>parse_transform</c> translates the <em>literal</em><c>fun()</c> typed as parameter in the function call to a match specification as described in - the <c>match_spec</c> manual of <c>ERTS</c> users guide. + the <c>match_spec</c> manual of ERTS users guide. (with literal I mean that the <c>fun()</c> needs to textually be written as the parameter of the function, it cannot be held in a variable which in turn is passed to the @@ -101,7 +118,8 @@ allowed:</p> <pre> 4> <input>dbg:fun2ms(fun([M,N]) when N > X, is_atomm(M) -> return_trace() end).</input> -Error: fun containing local erlang function calls ('is_atomm' called in guard) cannot be translated into match_spec +Error: fun containing local erlang function calls ('is_atomm' called in guard)\ + cannot be translated into match_spec {error,transform_error} 5> <input>dbg:fun2ms(fun([M,N]) when N > X, is_atom(M) -> return_trace() end).</input> [{['$1','$2'],[{'>','$2',{const,3}},{is_atom,'$1'}],[{return_trace}]}]</pre> @@ -162,52 +180,67 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c <desc> <p>Traces <c>Item</c> in accordance to the value specified by <c>Flags</c>. The variation of <c>Item</c> is listed below:</p> - <list type="bulleted"> - <item>If the <c>Item</c> is a <c>pid()</c>, the corresponding - process is traced. The process may be a remote process - (on another Erlang node). The node must be in the list of - traced nodes (<seealso marker="#n">see</seealso><c>n/1</c> and <c>tracer/0/2/3</c>).</item> - <item>If the <c>Item</c> is the atom <c>all</c>, all processes in the - system as well as all processes created hereafter are - to be traced. This also affects all nodes added with the - <c>n/1</c> or <c>tracer/0/2/3</c> function.</item> - <item>If the <c>Item</c> is the atom <c>new</c>, no currently existing - processes are affected, but every process created after the - call is.This also affects all nodes added with the - <c>n/1</c> or <c>tracer/0/2/3</c> function.</item> - <item>If the <c>Item</c> is the atom <c>existing</c>, all - existing processes are traced, but new processes will not - be affected.This also affects all nodes added with the - <c>n/1</c> or <c>tracer/0/2/3</c> function.</item> - <item>If the <c>Item</c> is an atom other than <c>all</c>, - <c>new</c> or <c>existing</c>, the process with the - corresponding registered name is traced.The process may be a - remote process (on another Erlang node). The node must be added - with the <c>n/1</c> or <c>tracer/0/2/3</c> function.</item> - <item>If the <c>Item</c> is an integer, the process <c><![CDATA[<0.Item.0>]]></c> is - traced.</item> - <item>If the <c>Item</c> is a tuple <c>{X, Y, Z}</c>, the - process <c><![CDATA[<X.Y.Z>]]></c> is - traced. </item> - <item>If the <c>Item</c> is a string <![CDATA["<X.Y.Z>"]]> - as returned from <c>pid_to_list/1</c>, the process - <c><![CDATA[<X.Y.Z>]]></c> is traced. </item> - </list> + <taglist> + <tag><c>pid()</c> or <c>port()</c></tag> + <item>The corresponding process or port is traced. The process or port may + be a remote process or port (on another Erlang node). The node must + be in the list of traced nodes (see <seealso marker="#n-1"><c>n/1</c></seealso> + and <seealso marker="#tracer-3"><c>tracer/3</c></seealso>).</item> + <tag><c>all</c></tag> + <item>All processes and ports in the system as well as all processes and ports + created hereafter are to be traced.</item> + <tag><c>processes</c></tag> + <item>All processes in the system as well as all processes created hereafter are to be traced.</item> + <tag><c>ports</c></tag> + <item>All ports in the system as well as all ports created hereafter are to be traced.</item> + <tag><c>new</c></tag> + <item>All processes and ports created after the call is are to be traced.</item> + <tag><c>new_processes</c></tag> + <item>All processes created after the call is are to be traced.</item> + <tag><c>new_ports</c></tag> + <item>All ports created after the call is are to be traced.</item> + <tag><c>existing</c></tag> + <item>All existing processes and ports are traced.</item> + <tag><c>existing_processes</c></tag> + <item>All existing processes are traced.</item> + <tag><c>existing_ports</c></tag> + <item>All existing ports are traced.</item> + <tag><c>atom()</c></tag> + <item>The process or port with the corresponding registered name is traced. The process or + port may be a remote process (on another Erlang node). The node must be + added with the <seealso marker="#n-1"><c>n/1</c></seealso> or + <seealso marker="#tracer-3"><c>tracer/3</c></seealso> function.</item> + <tag><c>integer()</c></tag> + <item>The process <c><![CDATA[<0.Item.0>]]></c> is traced.</item> + <tag><c>{X, Y, Z}</c></tag> + <item>The process <c><![CDATA[<X.Y.Z>]]></c> is traced. </item> + <tag><c>string()</c></tag> + <item>If the <c>Item</c> is a string <![CDATA["<X.Y.Z>"]]> + as returned from <seealso marker="erts:erlang#pid_to_list-1"><c>pid_to_list/1</c></seealso>, + the process <c><![CDATA[<X.Y.Z>]]></c> is traced. + </item> + </taglist> + + <p>When enabling an <c>Item</c> that represents a group of processes, + the <c>Item</c> is enabled on all nodes added with the + <seealso marker="#n-1"><c>n/1</c></seealso> or + <seealso marker="#tracer-3"><c>tracer/3</c></seealso> function.</p> + <p><c>Flags</c> can be a single atom, or a list of flags. The available flags are: </p> <taglist> <tag><c>s (send)</c></tag> <item> - <p>Traces the messages the process sends.</p> + <p>Traces the messages the process or port sends.</p> </item> <tag><c>r (receive)</c></tag> <item> - <p>Traces the messages the process receives.</p> + <p>Traces the messages the process or port receives.</p> </item> <tag><c>m (messages)</c></tag> <item> - <p>Traces the messages the process receives and sends.</p> + <p>Traces the messages the process or port receives and sends.</p> </item> <tag><c>c (call)</c></tag> <item> @@ -218,6 +251,10 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c <item> <p>Traces process related events to the process.</p> </item> + <tag><c>ports</c></tag> + <item> + <p>Traces port related events to the port.</p> + </item> <tag><c>sos (set on spawn)</c></tag> <item> <p>Lets all processes created by the traced @@ -238,12 +275,12 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c <tag><c>sofl (set on first link)</c></tag> <item> <p>This is the same as <c>sol</c>, but only for - the first call to - <c>link/1</c> by the traced process.</p> + the first call to + <seealso marker="erts:erlang#link-1"><c>link/1</c></seealso> by the traced process.</p> </item> <tag><c>all</c></tag> <item> - <p>Sets all flags.</p> + <p>Sets all flags except <c>silent</c>.</p> </item> <tag><c>clear</c></tag> <item> @@ -252,10 +289,10 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c </item> </taglist> <p>The list can also include any of the flags allowed in - <c>erlang:trace/3</c></p> + <seealso marker="erts:erlang#trace-3"><c>erlang:trace/3</c></seealso></p> <p>The function returns either an error tuple or a tuple <c>{ok, List}</c>. The <c>List</c> consists of - specifications of how many processes that matched (in the + specifications of how many processes and ports that matched (in the case of a pure pid() exactly 1). The specification of matched processes is <c>{matched, Node, N}</c>. If the remote processor call,<c>rpc</c>, to a remote node fails, @@ -283,9 +320,9 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c </func> <func> <name>i() -> ok</name> - <fsummary>Display information about all traced processes.</fsummary> + <fsummary>Display information about all traced processes and ports.</fsummary> <desc> - <p>Displays information about all traced processes.</p> + <p>Displays information about all traced processes and ports.</p> </desc> </func> <func> @@ -324,35 +361,41 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c </type> <desc> <p>This function enables call trace for one or more - functions. All exported functions matching the <c>{Module, Function, Arity}</c> argument will be concerned, but the + functions. All exported functions matching the <c>{Module, Function, Arity}</c> + argument will be concerned, but the <c>match_spec()</c> may further narrow down the set of function calls generating trace messages.</p> <p>For a description of the <c>match_spec()</c> syntax, please turn to the <em>User's guide</em> part of the online documentation for the runtime system (<em>erts</em>). The - chapter <em>Match Specification in Erlang</em> explains the - general match specification "language".</p> + chapter <seealso marker="erts:match_spec"><em>Match Specifications in Erlang</em></seealso> + explains the general match specification "language". + The most common generic match specifications used can be + found as <c>Built-inAlias</c>', see + <seealso marker="#ltp-0"><c>ltp/0</c></seealso> below for details. + </p> <p>The Module, Function and/or Arity parts of the tuple may be specified as the atom <c>'_'</c> which is a "wild-card" matching all modules/functions/arities. Note, if the Module is specified as <c>'_'</c>, the Function and Arity parts have to be specified as '_' too. The same holds for the Functions relation to the Arity.</p> - <p>All nodes added with <c>n/1</c> or <c>tracer/0/2/3</c> will + <p>All nodes added with <seealso marker="#n-1"><c>n/1</c></seealso> or + <seealso marker="#tracer-3"><c>tracer/3</c></seealso> will be affected by this call, and if Module is not <c>'_'</c> the module will be loaded on all nodes.</p> <p>The function returns either an error tuple or a tuple <c>{ok, List}</c>. The <c>List</c> consists of specifications of how - many functions that matched, in the same way as the processes - are presented in the return value of <c>p/2</c>. </p> + many functions that matched, in the same way as the processes and ports + are presented in the return value of <seealso marker="#p-2"><c>p/2</c></seealso>. </p> <p>There may be a tuple <c>{saved, N}</c> in the return value, if the MatchSpec is other than []. The integer <c>N</c> may then be used in subsequent calls to this function and will stand as an "alias" for the given expression. There are also a couple of - built-in aliases for common expressions, see <c>ltp/0</c> below - for details.</p> + built-in aliases for common expressions, see + <seealso marker="#ltp-0"><c>ltp/0</c></seealso> below for details.</p> <p>If an error is returned, it can be due to errors in compilation of the match specification. Such errors are presented as a list of tuples <c>{error, string()}</c> where @@ -391,11 +434,55 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c <name>tpl({Module, Function, Arity}, MatchSpec) -> {ok, MatchDesc} | {error, term()}</name> <fsummary>Set pattern for traced local (as well as global) function calls</fsummary> <desc> - <p>This function works as <c>tp/2</c>, but enables + <p>This function works as <seealso marker="#tp-2"><c>tp/2</c></seealso>, but enables tracing for local calls (and local functions) as well as for global calls (and functions).</p> </desc> </func> + + + <func> + <name>tpe(Event, MatchSpec) -> {ok, MatchDesc} | {error, term()}</name> + <fsummary>Set pattern for traced event</fsummary> + <type> + <v>Event = send | 'receive'</v> + <v>MatchSpec = integer() | Built-inAlias | [] | match_spec()</v> + <v>Built-inAlias = x | c | cx</v> + <v>MatchDesc = [MatchInfo]</v> + <v>MatchInfo = {saved, integer()} | MatchNum</v> + <v>MatchNum = {matched, node(), 1} | {matched, node(), 0, RPCError}</v> + </type> + <desc> + <p>This function associates a match specification with trace event + <c>send</c> or <c>'receive'</c>. By default all executed <c>send</c> + and <c>'receive'</c> events are traced if enabled for a process. + A match specification can be used to filter traced events + based on sender, receiver and/or message content.</p> + <p>For a description of the <c>match_spec()</c> syntax, + please turn to the <em>User's guide</em> part of the online + documentation for the runtime system (<em>erts</em>). The + chapter <seealso marker="erts:match_spec"><em>Match Specifications in Erlang</em></seealso> + explains the general match specification "language".</p> + <p>For <c>send</c>, the matching is done on the list <c>[Receiver, Msg]</c>. + <c>Receiver</c> is the process or port identity of the receiver and + <c>Msg</c> is the message term. The pid of the sending process can be + accessed with the guard function <c>self/0</c>.</p> + <p>For <c>'receive'</c>, the matching is done on the list <c>[Node, Sender, Msg]</c>. + <c>Node</c> is the node name of the sender. <c>Sender</c> is the + process or port identity of the sender, or the atom + <c>undefined</c> if the sender is not known (which may + be the case for remote senders). <c>Msg</c> is the + message term. The pid of the receiving process can be + accessed with the guard function <c>self/0</c>.</p> + <p>All nodes added with <seealso marker="#n-1"><c>n/1</c></seealso> or + <seealso marker="#tracer-3"><c>tracer/3</c></seealso> will + be affected by this call.</p> + <p>The return value is the same as for + <seealso marker="#tp-2"><c>tp/2</c></seealso>. The number of matched + events are never larger than 1 as <c>tpe/2</c> does not + accept any form of wildcards for argument <c>Event</c>.</p> + </desc> + </func> <func> <name>ctp()</name> <fsummary>Clear call trace pattern for the specified functions</fsummary> @@ -438,10 +525,10 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c <p>This function disables call tracing on the specified functions. The semantics of the parameter is the same as for the corresponding function specification in - <c>tp/2</c> or <c>tpl/2</c>. Both local and global call trace + <seealso marker="#tp-2"><c>tp/2</c></seealso> or <seealso marker="#tpl-2"><c>tpl/2</c></seealso>. Both local and global call trace is disabled. </p> <p>The return value reflects how many functions that matched, - and is constructed as described in <c>tp/2</c>. No tuple + and is constructed as described in <seealso marker="#tp-2"><c>tp/2</c></seealso>. No tuple <c>{saved, N}</c> is however ever returned (for obvious reasons).</p> </desc> </func> @@ -477,8 +564,9 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c <name>ctpl({Module, Function, Arity}) -> {ok, MatchDesc} | {error, term()}</name> <fsummary>Clear call trace pattern for the specified functions</fsummary> <desc> - <p>This function works as <c>ctp/1</c>, but only disables - tracing set up with <c>tpl/2</c> (not with <c>tp/2</c>).</p> + <p>This function works as <seealso marker="#ctp-1"><c>ctp/1</c></seealso>, but only disables + tracing set up with <seealso marker="#tpl-2"><c>tpl/2</c></seealso> + (not with <seealso marker="#tp-2"><c>tp/2</c></seealso>).</p> </desc> </func> <func> @@ -513,8 +601,25 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c <name>ctpg({Module, Function, Arity}) -> {ok, MatchDesc} | {error, term()}</name> <fsummary>Clear call trace pattern for the specified functions</fsummary> <desc> - <p>This function works as <c>ctp/1</c>, but only disables - tracing set up with <c>tp/2</c> (not with <c>tpl/2</c>).</p> + <p>This function works as <seealso marker="#ctp-1"><c>ctp/1</c></seealso>, but only disables + tracing set up with <seealso marker="#tp-2"><c>tp/2</c></seealso> + (not with <seealso marker="#tpl-2"><c>tpl/2</c></seealso>).</p> + </desc> + </func> + <func> + <name>ctpe(Event) -> {ok, MatchDesc} | {error, term()}</name> + <fsummary>Clear trace pattern for the specified event</fsummary> + <type> + <v>Event = send | 'receive'</v> + <v>MatchDesc = [MatchNum]</v> + <v>MatchNum = {matched, node(), 1} | {matched, node(), 0, RPCError}</v> + </type> + <desc> + <p>This function clears match specifications for the specified + trace event (<c>send</c> or <c>'receive'</c>). It will revert back + to the default behavior of tracing all triggered events.</p> + <p>The return value follow the same style as for + <seealso marker="#ctp-1"><c>ctp/1</c></seealso>.</p> </desc> </func> <func> @@ -523,13 +628,14 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c <desc> <p>Use this function to recall all match specifications previously used in the session (i. e. previously saved during calls - to <c>tp/2</c>, and built-in match specifications. + to <seealso marker="#tp-2"><c>tp/2</c></seealso>, and built-in match specifications. This is very useful, as a complicated match_spec can be quite awkward to write. Note that the - match specifications are lost if <c>stop/0</c> is called.</p> + match specifications are lost if <seealso marker="#stop-0"><c>stop/0</c></seealso> is called.</p> <p>Match specifications used can be saved in a file (if a read-write file system is present) for use in later - debugging sessions, see <c>wtp/1</c> and <c>rtp/1</c></p> + debugging sessions, see <seealso marker="#wtp-1"><c>wtp/1</c></seealso> + and <seealso marker="#rtp-1"><c>rtp/1</c></seealso></p> <p>There are three built-in trace patterns: <c>exception_trace</c>, <c>caller_trace</c> and <c>caller_exception_trace</c> (or <c>x</c>, <c>c</c> and @@ -552,10 +658,10 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c <fsummary>Delete all saved match specifications.</fsummary> <desc> <p>Use this function to "forget" all match specifications - saved during calls to <c>tp/2</c>. - This is useful when one wants to restore other match - specifications from a file with <c>rtp/1</c>. Use - <c>dtp/1</c> to delete specific saved match specifications. </p> + saved during calls to <seealso marker="#tp-2"><c>tp/2</c></seealso>. + This is useful when one wants to restore other match + specifications from a file with <seealso marker="#rtp-1"><c>rtp/1</c></seealso>. Use + <seealso marker="#dtp-1"><c>dtp/1</c></seealso> to delete specific saved match specifications.</p> </desc> </func> <func> @@ -566,7 +672,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c </type> <desc> <p>Use this function to "forget" a specific match specification - saved during calls to <c>tp/2</c>.</p> + saved during calls to <seealso marker="#tp-2"><c>tp/2</c></seealso>.</p> </desc> </func> <func> @@ -578,12 +684,12 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c </type> <desc> <p>This function will save all match specifications saved - during the session (during calls to <c>tp/2</c>) + during the session (during calls to <seealso marker="#tp-2"><c>tp/2</c></seealso>) and built-in match specifications in a text file with the name designated by <c>Name</c>. The format of the file is textual, why it can be edited with an ordinary text editor, and then restored with - <c>rtp/1</c>. </p> + <seealso marker="#rtp-1"><c>rtp/1</c></seealso>. </p> <p>Each match spec in the file ends with a full stop (<c>.</c>) and new (syntactically correct) match specifications can be added to the file manually.</p> @@ -601,7 +707,8 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c </type> <desc> <p>This function reads match specifications from a file - (possibly) generated by the <c>wtp/1</c> function. It checks + (possibly) generated by the <seealso marker="#wtp-1"><c>wtp/1</c></seealso> + function. It checks the syntax of all match specifications and verifies that they are correct. The error handling principle is "all or nothing", i. e. if some of the match specifications are @@ -609,14 +716,15 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c saved match specifications for the running system. </p> <p>The match specifications in the file are <em>merged</em> with the current match specifications, so that no duplicates - are generated. Use <c>ltp/0</c> to see what numbers were + are generated. Use <seealso marker="#ltp-0"><c>ltp/0</c></seealso> + to see what numbers were assigned to the specifications from the file.</p> <p>The function will return an error, either due to I/O problems (like a non existing or non readable file) or due to file format problems. The errors from a bad format file are in a more or less textual format, which will give a hint - to what's causing the problem. <marker id="n"></marker> -</p> + to what's causing the problem. + </p> </desc> </func> <func> @@ -628,12 +736,12 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c </type> <desc> <p>The <c>dbg</c> server keeps a list of nodes where tracing - should be performed. Whenever a <c>tp/2</c> call or a - <c>p/2</c> call is made, it is executed for all nodes in this - list including the local node (except for <c>p/2</c> with a - specific <c>pid()</c> as first argument, in which case the + should be performed. Whenever a <seealso marker="#tp-2"><c>tp/2</c></seealso> call or a + <seealso marker="#p-2"><c>p/2</c></seealso> call is made, it is executed for all nodes in this + list including the local node (except for <seealso marker="#p-2"><c>p/2</c></seealso> with a + specific <c>pid()</c> or <c>port()</c> as first argument, in which case the command is executed only on the node where the designated - process resides). + process or port resides). </p> <p>This function adds a remote node (<c>Nodename</c>) to the list of nodes where tracing is performed. It starts a tracer @@ -642,17 +750,17 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c distribution). If no tracer process is running on the local node, the error reason <c>no_local_tracer</c> is returned. The tracer process on the local node must be started with the - <c>tracer/0/2</c> function. + <seealso marker="#tracer-2"><c>tracer/0/2</c></seealso> function. </p> <p>If <c>Nodename</c> is the local node, the error reason <c>cant_add_local_node</c> is returned. </p> - <p>If a trace port (<seealso marker="#trace_port">see</seealso><c>trace_port/2</c>) is + <p>If a trace port (see <seealso marker="#trace_port-2"><c>trace_port/2</c></seealso>) is running on the local node, remote nodes can not be traced with a tracer process. The error reason <c>cant_trace_remote_pid_to_local_port</c> is returned. A trace port can however be started on the remote node with the - <c>tracer/3</c> function. + <seealso marker="#tracer-3"><c>tracer/3</c></seealso> function. </p> <p>The function will also return an error if the node <c>Nodename</c> is not reachable.</p> @@ -666,9 +774,10 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c </type> <desc> <p>Clears a node from the list of traced nodes. Subsequent - calls to <c>tp/2</c> and <c>p/2</c> will not consider that - node, but tracing already activated on the node will continue - to be in effect.</p> + calls to <seealso marker="#tp-2"><c>tp/2</c></seealso> and + <seealso marker="#p-2"><c>p/2</c></seealso> will not consider that + node, but tracing already activated on the node will continue + to be in effect.</p> <p>Returns <c>ok</c>, cannot fail.</p> </desc> </func> @@ -685,37 +794,42 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c <desc> <p>This function starts a server on the local node that will be the recipient of all trace messages. All subsequent calls - to <c>p/2</c> will result in messages sent to the newly + to <seealso marker="#p-2"><c>p/2</c></seealso> will result in messages sent to the newly started trace server.</p> <p>A trace server started in this way will simply display the trace messages in a formatted way in the Erlang shell - (i. e. use io:format). See <c>tracer/2</c> for a description - of how the trace message handler can be customized. <marker id="tracer2"></marker> -</p> - <p>To start a similar tracer on a remote node, use <c>n/1</c>.</p> + (i. e. use io:format). See <seealso marker="#tracer-2"><c>tracer/2</c></seealso> + for a description of how the trace message handler can be customized. + </p> + <p>To start a similar tracer on a remote node, use <seealso marker="#n-1"><c>n/1</c></seealso>.</p> </desc> </func> <func> <name>tracer(Type, Data) -> {ok, pid()} | {error, Error}</name> <fsummary>Start a tracer server with additional parameters</fsummary> <type> - <v>Type = port | process</v> - <v>Data = PortGenerator | HandlerSpec</v> - <v>HandlerSpec = {HandlerFun, InitialData}</v> - <v>HandlerFun = fun() (two arguments)</v> - <v>InitialData = term()</v> + <v>Type = port | process | module</v> + <v>Data = PortGenerator | HandlerSpec | ModuleSpec</v> <v>PortGenerator = fun() (no arguments)</v> <v>Error = term()</v> + <v>HandlerSpec = {HandlerFun, InitialData}</v> + <v>HandlerFun = fun() (two arguments)</v> + <v>ModuleSpec = fun() (no arguments) | {TracerModule, TracerState}</v> + <v>ModuleModule = atom()</v> + <v>InitialData = TracerState = term()</v> </type> <desc> <p>This function starts a tracer server with additional parameters on the local node. The first parameter, the <c>Type</c>, indicates if trace messages should be handled - by a receiving process (<c>process</c>) or by a tracer port - (<c>port</c>). For a description about tracer ports see - <c>trace_port/2</c>. + by a receiving process (<c>process</c>), by a tracer port + (<c>port</c>) or by a tracer module + (<c>module</c>). For a description about tracer ports see + <seealso marker="#trace_port-2"><c>trace_port/2</c></seealso> + and for a tracer modules see + <seealso marker="erts:erl_tracer"><c>erl_tracer</c></seealso>. </p> - <p>If <c>Type</c> is a process, a message handler function can + <p>If <c>Type</c> is <c>process</c>, a message handler function can be specified (<c>HandlerSpec</c>). The handler function, which should be a <c>fun</c> taking two arguments, will be called for each trace message, with the first argument containing the @@ -726,18 +840,22 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c choose any appropriate action to take when invoked, and can save a state for the next invocation by returning it. </p> - <p>If <c>Type</c> is a port, then the second parameter should + <p>If <c>Type</c> is <c>port</c>, then the second parameter should be a <em>fun</em> which takes no arguments and returns a newly opened trace port when called. Such a <em>fun</em> is - preferably generated by calling <c>trace_port/2</c>. + preferably generated by calling <seealso marker="#trace_port-2"><c>trace_port/2</c></seealso>. </p> + <p>if <c>Type</c> is <c>module</c>, then the second parameter should + be either a tuple describing the <seealso marker="erts:erl_tracer"><c>erl_tracer</c></seealso> + module to be used for tracing and the state to be used for + that tracer module or a fun returning the same tuple.</p> <p>If an error is returned, it can either be due to a tracer server already running (<c>{error,already_started}</c>) or due to the <c>HandlerFun</c> throwing an exception. </p> <p>To start a similar tracer on a remote node, use - <c>tracer/3</c>. <marker id="trace_port"></marker> -</p> + <seealso marker="#tracer-3"><c>tracer/3</c></seealso>. + </p> </desc> </func> <func> @@ -747,20 +865,19 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c <v>Nodename = atom()</v> </type> <desc> - <p>This function is equivalent to <c>tracer/2</c>, but acts on + <p>This function is equivalent to <seealso marker="#tracer-2"><c>tracer/2</c></seealso>, but acts on the given node. A tracer is started on the node - (<c>Nodename</c>) and the node is added to the list of traced - nodes. + (<c>Nodename</c>) and the node is added to the list of traced nodes. </p> <note> - <p>This function is not equivalent to <c>n/1</c>. While - <c>n/1</c> starts a process tracer which redirects all trace + <p>This function is not equivalent to <seealso marker="#n-1"><c>n/1</c></seealso>. While + <seealso marker="#n-1"><c>n/1</c></seealso> starts a process tracer which redirects all trace information to a process tracer on the local node (i.e. the - trace control node), <c>tracer/3</c> starts a tracer of any + trace control node), <seealso marker="#tracer-3"><c>tracer/3</c></seealso> starts a tracer of any type which is independent of the tracer on the trace control node.</p> </note> - <p>For details, <seealso marker="#tracer2">see</seealso><c>tracer/2</c>.</p> + <p>For details, see <seealso marker="#tracer-2"><c>tracer/2</c></seealso>.</p> </desc> </func> <func> @@ -792,9 +909,9 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c <c>file</c> and the <c>ip</c> trace drivers. The file driver sends all trace messages into one or several binary files, from where they later can be fetched and processed with the - <c>trace_client/2</c> function. The ip driver opens a TCP/IP + <seealso marker="#trace_client-2"><c>trace_client/2</c></seealso> function. The ip driver opens a TCP/IP port where it listens for connections. When a client - (preferably started by calling <c>trace_client/2</c> on + (preferably started by calling <seealso marker="#trace_client-2"><c>trace_client/2</c></seealso> on another Erlang node) connects, all trace messages are sent over the IP network for further processing by the remote client. </p> @@ -833,10 +950,11 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c as fast as they are produced by the runtime system, a special message is sent, which indicates how many messages that are dropped. That message will arrive at the handler function - specified in <c>trace_client/3</c> as the tuple <c>{drop, N}</c> where <c>N</c> is the number of consecutive messages + specified in <seealso marker="#trace_client-3"><c>trace_client/3</c></seealso> + as the tuple <c>{drop, N}</c> where <c>N</c> is the number of consecutive messages dropped. In case of heavy tracing, drop's are likely to occur, and they surely occur if no client is reading the trace - messages.</p> + messages. The default value of <c>QueSize</c> is 200.</p> </desc> </func> <func> @@ -887,7 +1005,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c </item> <tag><c>get_listen_port</c></tag> <item> - <p>Returns <c>{ok, IpPort}</c> where <c>IpPort</c>is + <p>Returns <c>{ok, IpPort}</c> where <c>IpPort</c> is the IP port number used by the driver listen socket. Only the ip trace driver supports this operation.</p> </item> @@ -910,8 +1028,8 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c <desc> <p>This function starts a trace client that reads the output created by a trace port driver and handles it in mostly the - same way as a tracer process created by the <c>tracer/0</c> - function.</p> + same way as a tracer process created by the + <seealso marker="#tracer-0"><c>tracer/0</c></seealso> function.</p> <p>If <c>Type</c> is <c>file</c>, the client reads all trace messages stored in the file named <c>Filename</c> or specified by <c>WrapFilesSpec</c> (must be the same as used @@ -922,7 +1040,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c <p>If <c>Type</c> is <c>follow_file</c>, the client behaves as in the <c>file</c> case, but keeps trying to read (and process) more data - from the file until stopped by <c>stop_trace_client/1</c>. + from the file until stopped by <seealso marker="#stop_trace_client-1"><c>stop_trace_client/1</c></seealso>. <c>WrapFilesSpec</c> is not allowed as second argument for this <c>Type</c>.</p> <p>If <c>Type</c> is <c>ip</c>, the client connects to the @@ -978,10 +1096,10 @@ hello</pre> <v>InitialData = term()</v> </type> <desc> - <p>This function works exactly as <c>trace_client/2</c>, but - allows you to write your own handler function. The handler + <p>This function works exactly as <seealso marker="#trace_client-2"><c>trace_client/2</c></seealso>, + but allows you to write your own handler function. The handler function works mostly as the one described in - <c>tracer/2</c>, but will also have to be prepared to handle + <seealso marker="#tracer-2"><c>tracer/2</c></seealso>, but will also have to be prepared to handle trace messages of the form <c>{drop, N}</c>, where <c>N</c> is the number of dropped messages. This pseudo trace message will only occur if the ip trace driver is used.</p> @@ -1000,7 +1118,8 @@ hello</pre> <desc> <p>This function shuts down a previously started trace client. The <c>Pid</c> argument is the process id returned - from the <c>trace_client/2</c> or <c>trace_client/3</c> call.</p> + from the <seealso marker="#trace_client-2"><c>trace_client/2</c></seealso> + or <seealso marker="#trace_client-3"><c>trace_client/3</c></seealso> call.</p> </desc> </func> <func> @@ -1015,30 +1134,29 @@ hello</pre> <fsummary>Return the process or port to which all trace messages are sent.</fsummary> <type> <v>Nodename = atom()</v> - <v>Tracer = port() | pid()</v> + <v>Tracer = port() | pid() | {module(), term()}</v> </type> <desc> - <p>Returns the process or port to which all trace - messages are sent. </p> + <p>Returns the process, port or tracer module to which all trace + messages are sent.</p> </desc> </func> <func> - <name>stop() -> stopped</name> + <name>stop() -> ok</name> <fsummary>Stop the <c>dbg</c>server and the tracing of all processes.</fsummary> <desc> <p>Stops the <c>dbg</c> server and clears all trace flags for - all processes and all trace patterns for all functions. Also + all processes and all local trace patterns for all functions. Also shuts down all trace clients and closes all trace ports.</p> - <p>Note that no trace patterns are affected by this + <p>Note that no global trace patterns are affected by this function.</p> </desc> </func> <func> - <name>stop_clear() -> stopped</name> + <name>stop_clear() -> ok</name> <fsummary>Stop the <c>dbg</c>server and the tracing of all processes, and clears trace patterns.</fsummary> <desc> - <p>Same as stop/0, but also clears all trace patterns on local - and global functions calls.</p> + <p>Same as stop/0, but also clears all trace patterns on global functions calls.</p> </desc> </func> </funcs> @@ -1154,8 +1272,9 @@ SeqTrace [0]: (<0.30.0>) <0.25.0> ! {dbg,{ok,<0.31.0>}} [Serial: {4,5}] of causing a deadlock. This will happen if a group leader process generates a trace message and the tracer process, by calling the trace handler function, sends an IO request to the same group leader. The problem can only occur if the trace handler - prints to tty using an <c>io</c> function such as <c>format/2</c>. Note that when - <c>dbg:p(all,call)</c> is called, IO processes are also traced. + prints to tty using an <c>io</c> function such as <seealso marker="stdlib:io#format-2"><c>format/2</c></seealso>. + Note that when + <c>dbg:p(all,call)</c> is called, IO processes are also traced. Here's an example:</p> <pre> %% Using a default line editing shell diff --git a/lib/runtime_tools/doc/src/dyntrace.xml b/lib/runtime_tools/doc/src/dyntrace.xml index 5fc5530f25..0cdcecab68 100644 --- a/lib/runtime_tools/doc/src/dyntrace.xml +++ b/lib/runtime_tools/doc/src/dyntrace.xml @@ -1,23 +1,24 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> <header> <copyright> - <year>1996</year><year>2012</year> + <year>1996</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -42,7 +43,7 @@ </list> <p>Both building with dynamic trace probes and using them is experimental and unsupported by Erlang/OTP. It is included as an option for the developer to trace and debug performance issues in their systems.</p> <p>The original implementation is mostly done by Scott Lystiger Fritchie as an Open Source Contribution and it should be viewed as such even though the source for dynamic tracing as well as this module is included in the main distribution. However, the ability to use dynamic tracing of the virtual machine is a very valuable contribution which OTP has every intention to maintain as a tool for the developer.</p> - <p>How to write <c>d</c> programs or <c>systemtap</c> scripts can be learned from books and from a lot of pages on the Internet. This manual page does not include any documentation about using the dynamic trace tools of respective platform. The <c>examples</c> directory of the <c>runtime_tools</c> application however contains comprehensive examples of both <c>d</c> and <c>systemtap</c> programs that will help you get started. Another source of information is the <c>README.dtrace(.md)</c> and <c>README.systemtap(.md)</c> files in the Erlang source top directory.</p> + <p>How to write <c>d</c> programs or <c>systemtap</c> scripts can be learned from books and from a lot of pages on the Internet. This manual page does not include any documentation about using the dynamic trace tools of respective platform. The <c>examples</c> directory of the <c>runtime_tools</c> application however contains comprehensive examples of both <c>d</c> and <c>systemtap</c> programs that will help you get started. Another source of information is the <seealso marker="DTRACE">dtrace</seealso> and <seealso marker="SYSTEMTAP">systemtap</seealso> chapters in the Runtime Tools Users' Guide.</p> </description> <funcs> <func> diff --git a/lib/runtime_tools/doc/src/erts_alloc_config.xml b/lib/runtime_tools/doc/src/erts_alloc_config.xml index 6acf498411..ffc4ec5285 100644 --- a/lib/runtime_tools/doc/src/erts_alloc_config.xml +++ b/lib/runtime_tools/doc/src/erts_alloc_config.xml @@ -1,23 +1,24 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> <header> <copyright> - <year>2007</year><year>2010</year> + <year>2007</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> diff --git a/lib/runtime_tools/doc/src/fascicules.xml b/lib/runtime_tools/doc/src/fascicules.xml index 5230dc7e90..1a0bd6ec97 100644 --- a/lib/runtime_tools/doc/src/fascicules.xml +++ b/lib/runtime_tools/doc/src/fascicules.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE fascicules SYSTEM "fascicules.dtd"> <fascicules> diff --git a/lib/runtime_tools/doc/src/msacc.xml b/lib/runtime_tools/doc/src/msacc.xml new file mode 100644 index 0000000000..129da3d230 --- /dev/null +++ b/lib/runtime_tools/doc/src/msacc.xml @@ -0,0 +1,305 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE erlref SYSTEM "erlref.dtd"> + +<erlref> + <header> + <copyright> + <year>2014</year><year>2014</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + </legalnotice> + + <title>Microstate Accounting</title> + <prepared>Lukas Larsson</prepared> + <responsible></responsible> + <docno>1</docno> + <approved></approved> + <checked></checked> + <date>14-09-30</date> + <rev>A</rev> + <file>msacc.xml</file> + </header> + <module>msacc</module> + <modulesummary>Convenience functions for microstate accounting</modulesummary> + <description> + <p>This module implements some convenience functions for analyzing + microstate accounting data. For details about how to use the basic api and + what the different states represent see + <seealso marker="erts:erlang#statistics_microstate_accounting"><c> + erlang:statistics(microstate_accounting)</c></seealso>.</p> + <marker id="msacc_print_example"></marker> + <p><em>Basic Scenario</em></p> + <pre>1> <input>msacc:start(1000).</input> +ok +2> <input>msacc:print().</input> +Average thread real-time : 1000513 us +Accumulated system run-time : 2213 us +Average scheduler run-time : 1076 us + + Thread aux check_io emulator gc other port sleep + +Stats per thread: + async( 0) 0.00% 0.00% 0.00% 0.00% 0.00% 0.00% 100.00% + async( 1) 0.00% 0.00% 0.00% 0.00% 0.00% 0.00% 100.00% + aux( 1) 0.00% 0.00% 0.00% 0.00% 0.00% 0.00% 99.99% + scheduler( 1) 0.00% 0.03% 0.13% 0.00% 0.01% 0.00% 99.82% + scheduler( 2) 0.00% 0.00% 0.00% 0.00% 0.03% 0.00% 99.97% + +Stats per type: + async 0.00% 0.00% 0.00% 0.00% 0.00% 0.00% 100.00% + aux 0.00% 0.00% 0.00% 0.00% 0.00% 0.00% 99.99% + scheduler 0.00% 0.02% 0.06% 0.00% 0.02% 0.00% 99.89% +ok +</pre> + <p>This first command enables microstate accounting for 1000 milliseconds. + See <seealso marker="#start-0"><c>start/0</c></seealso>, + <seealso marker="#stop-0"><c>stop/0</c></seealso>, + <seealso marker="#reset-0"><c>reset/0</c></seealso> and + <seealso marker="#start-1"><c>start/1</c></seealso> for more details. + The second command prints the statistics gathered during that time. + First three general statistics are printed.</p> + <taglist> + <tag>Average real-time</tag> + <item>The average time spent collecting data in the threads. + This should be close to the time which data was collected. + </item> + <tag>System run-time</tag> + <item>The total run-time of all threads in the system. + This is what you get if you call <c>msacc:stats(total_runtime,Stats).</c> + </item> + <tag>Average scheduler run-time</tag> + <item>The average run-time for the schedulers. + This is the average amount of time the schedulers did not sleep.</item> + </taglist> + <p>Then one column per state is printed with a the percentage of time this + thread spent in the state out of it's own real-time. After the thread + specific time, the accumulated time for each type of thread is printed in + a similar format.</p> + <p>Since we have the average real-time and the percentage spent in each + state we can easily calculate the time spent in each state by multiplying + <c>Average thread real-time</c> with <c>Thread state %</c>, i.e. to + get the time Scheduler 1 spent in the emulator state we do + <c>1000513us * 0.13% = 1300us</c>.</p> + </description> + <datatypes> + <datatype> + <name name="msacc_data"/> + </datatype> + <datatype> + <name name="msacc_data_thread"/> + </datatype> + <datatype> + <name name="msacc_data_counters"/> + <desc><p>A map containing the different microstate accounting states and + the number of microseconds spent in it.</p></desc> + </datatype> + <datatype> + <name name="msacc_stats"/> + </datatype> + <datatype> + <name name="msacc_stats_thread"/> + <desc><p>A map containing information about a specific thread. The + percentages in the map can be either run-time or real-time depending + on if <c>runtime</c> or <c>realtime</c> was requested from + <seealso marker="#stats-2">stats/2</seealso>. <c>system</c> is the + percentage of total system time for this specific thread.</p></desc> + </datatype> + <datatype> + <name name="msacc_stats_counters"/> + <desc><p>A map containing the different microstate accounting states. Each + value in the map contains another map with the percentage of time that + this thread has spent in the specific state. Both the percentage of + <c>system</c> time and the time for that specific <c>thread</c> is part of + the map.</p></desc> + </datatype> + <datatype> + <name name="msacc_type"/> + </datatype> + <datatype> + <name name="msacc_id"/> + </datatype> + <datatype> + <name name="msacc_state"/> + <desc><p>The different states that a thread can be in. See + <seealso marker="erts:erlang#statistics_microstate_accounting"> + erlang:statistics(microstate_accounting)</seealso> for details. + </p></desc> + </datatype> + <datatype> + <name name="msacc_print_options"/> + <desc><p>The different options that can be given to + <seealso marker="#print-2"><c>print/2</c></seealso>. + </p></desc> + </datatype> + </datatypes> + <funcs> + <func> + <name name="available" arity="0"/> + <fsummary>Check if microstate accounting is available</fsummary> + <desc> + <p>This function checks whether microstate accounting + is available or not.</p> + </desc> + </func> + <func> + <name name="start" arity="0"/> + <fsummary>Start microstate accounting.</fsummary> + <desc> + <p>Start microstate accounting. Returns whether it was + previously enabled or disabled.</p> + </desc> + </func> + <func> + <name name="start" arity="1"/> + <fsummary>Start microstate accounting for a time.</fsummary> + <desc> + <p>Resets all counters and then starts microstate accounting + for the given milliseconds.</p> + </desc> + </func> + <func> + <name name="stop" arity="0"/> + <fsummary>Stop microstate accounting.</fsummary> + <desc> + <p>Stop microstate accounting. + Returns whether is was previously enabled or disabled.</p> + </desc> + </func> + <func> + <name name="reset" arity="0"/> + <fsummary>Reset microstate accounting counters</fsummary> + <desc> + <p>Reset microstate accounting counters. + Returns whether is was enabled or disabled.</p> + </desc> + </func> + <func> + <name name="print" arity="0"/> + <fsummary>Print microstate statistics</fsummary> + <desc> + <p> + Prints the current microstate accounting to standard out. + Same as + <seealso marker="#print-1"> + <c>msacc:print(msacc:stats(),#{}).</c> + </seealso> + </p> + </desc> + </func> + <func> + <name name="print" arity="1"/> + <fsummary>Print microstate statistics</fsummary> + <desc> + <p>Print the given microstate statistics values to stdout. + Same as + <seealso marker="#print-1"> + <c>msacc:print(DataOrStats,#{}).</c> + </seealso> + </p> + </desc> + </func> + <func> + <name name="print" arity="2"/> + <fsummary>Print microstate statistics</fsummary> + <desc> + <p>Print the given microstate statistics values to standard out. + With many states this can be quite verbose. See the top of this + reference manual for a brief description of what the fields mean.</p> + <p>It is possible to print more specific types of statistics by + first manipulating the <c>DataOrStats</c> using + <seealso marker="#stats-2"><c>stats/2</c></seealso>. + For instance if you want to print the percentage of run-time for each + thread you can do:</p> + <pre><input>msacc:print(msacc:stats(runtime,msacc:stats())).</input></pre> + <p>If you want to only print run-time per thread type you can do:</p> + <pre><input>msacc:print(msacc:stats(type,msacc:stats(runtime,msacc:stats()))).</input></pre> + <p><em>Options</em></p> + <taglist> + <tag><c>system</c></tag><item>Print percentage of time spent in each + state out of system time as well as thread time. + Default: false.</item> + </taglist> + </desc> + </func> + <func> + <name name="print" arity="3"/> + <fsummary>Print microstate statistics</fsummary> + <desc> + <p>Print the given microstate statistics values to the given file + or device. The other arguments behave the same way as for + <seealso marker="#print-2"><c>print/2</c></seealso>.</p> + </desc> + </func> + <func> + <name name="stats" arity="0"/> + <fsummary></fsummary> + <desc> + <p>Returns a runtime system independent version of the microstate + statistics data presented by + <seealso marker="erts:erlang#statistics_microstate_accounting"> + <c>erlang:statistics(microstate_accounting)</c></seealso>. + All counters have been normalized to be in microsecond resolution.</p> + </desc> + </func> + <func> + <name name="stats" arity="2" clause_i="1"/> + <fsummary></fsummary> + <desc> + <p>Returns the system time for the given microstate statistics values. + System time is the accumulated time of all threads.</p> + <taglist> + <tag><c>realtime</c></tag> + <item>Returns all time recorded for all threads.</item> + <tag><c>runtime</c></tag> + <item>Returns all time spent doing work for all threads, i.e. + all time not spent in the <c>sleep</c> state.</item> + </taglist> + </desc> + </func> + <func> + <name name="stats" arity="2" clause_i="2"/> + <fsummary></fsummary> + <desc> + <p>Returns fractions of real-time or run-time spent in the various + threads from the given microstate statistics values.</p> + </desc> + </func> + <func> + <name name="stats" arity="2" clause_i="3"/> + <fsummary></fsummary> + <desc> + <p>Returns a list of microstate statistics values where the values + for all threads of the same type has been merged.</p> + </desc> + </func> + <func> + <name name="to_file" arity="1"/> + <fsummary></fsummary> + <desc> + <p>Dumps the current microstate statistics counters to a file that can + be parsed with <seealso marker="kernel:file#consult/1"> + file:consult/1</seealso>.</p> + </desc> + </func> + <func> + <name name="from_file" arity="1"/> + <fsummary></fsummary> + <desc> + <p>Read a file dump produced by <seealso marker="#to_file/1"> + to_file(Filename)</seealso>.</p> + </desc> + </func> + </funcs> +</erlref> diff --git a/lib/runtime_tools/doc/src/notes.xml b/lib/runtime_tools/doc/src/notes.xml index 90641719c5..4c79a560ec 100644 --- a/lib/runtime_tools/doc/src/notes.xml +++ b/lib/runtime_tools/doc/src/notes.xml @@ -1,23 +1,24 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd"> <chapter> <header> <copyright> - <year>2004</year><year>2012</year> + <year>2004</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -31,6 +32,455 @@ <p>This document describes the changes made to the Runtime_Tools application.</p> +<section><title>Runtime_Tools 1.11</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Add option <c>queue_size</c> to ttb:tracer/2. This sets + the maximum queue size for the IP trace driver which is + used when tracing to shell and/or <c>{local,File}</c>.</p> + <p> + The default value for <c>queue_size</c> is specified by + <c>dbg</c>, and it is now changed from 50 to 200.</p> + <p> + Own Id: OTP-13829 Aux Id: seq13171 </p> + </item> + <item> + <p> + The port information page is updated to show more + information per port.</p> + <p> + Own Id: OTP-13948 Aux Id: ERL-272 </p> + </item> + </list> + </section> + +</section> + +<section><title>Runtime_Tools 1.10.1</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> Correct some minor documentation issues. </p> + <p> + Own Id: OTP-13891</p> + </item> + </list> + </section> + +</section> + +<section><title>Runtime_Tools 1.10</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix bug in dbg:trace_port/2 that could cause the trace ip + driver to produce faulty error reports "...(re)selected + before stop_select was called for driver trace_ip_drv".</p> + <p> + Own Id: OTP-13576 Aux Id: ERL-119 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Add microstate accounting</p> + <p> + Microstate accounting is a way to track which state the + different threads within ERTS are in. The main usage area + is to pin point performance bottlenecks by checking which + states the threads are in and then from there figuring + out why and where to optimize.</p> + <p> + Since checking whether microstate accounting is on or off + is relatively expensive only a few of the states are + enabled by default and more states can be enabled through + configure.</p> + <p> + There is a convenience module called msacc that has been + added to runtime_tools that can assist in gathering and + interpreting the data from Microstate accounting.</p> + <p> + For more information see <seealso + marker="erts:erlang#statistics_microstate_accounting">erlang:statistics(microstate_accounting, + _)</seealso> and the <seealso + marker="runtime_tools:msacc">msacc</seealso> module in + runtime_tools.</p> + <p> + Own Id: OTP-12345</p> + </item> + <item> + <p> + Update observer GUI to support tracing on ports, and to + set matchspecs for send/receive. This required some minor + bugfixes in runtime_tools/dbg.</p> + <p> + Own Id: OTP-13481</p> + </item> + <item> + <p> + Update dbg and ttb to work with a tracer module as tracer + and tracing on ports.</p> + <p> + Own Id: OTP-13500</p> + </item> + <item> + <p> + Updated dbg to accept the new trace options + <c>monotonic_timestamp</c> and + <c>strict_monotonic_timestamp</c>.</p> + <p> + Own Id: OTP-13502</p> + </item> + <item> + <p> + Introduce LTTng tracing via Erlang tracing.</p> + <p> + For LTTng to be enabled OTP needs to be built with + configure option <c>--with-dynamic-trace=lttng</c>.</p> + <p>The dynamic trace module <c>dyntrace</c> is now + capable to be used as a LTTng sink for Erlang tracing. + For a list of all tracepoints, see <seealso + marker="runtime_tools:LTTng">Runtime Tools User's + Guide</seealso> .</p> + <p>This feature also introduces an incompatible change in + trace tags. The trace tags <c>gc_start</c> and + <c>gc_end</c> has been split into <c>gc_minor_start</c>, + <c>gc_minor_end</c> and <c>gc_major_start</c>, + <c>gc_major_end</c>.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-13532</p> + </item> + </list> + </section> + +</section> + +<section><title>Runtime_Tools 1.9.3</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p><c>dbg:trace_client()</c> now uses a read buffer to + speed up reading of trace files.</p> + <p> + Own Id: OTP-13279</p> + </item> + </list> + </section> + +</section> + +<section><title>Runtime_Tools 1.9.2</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Clarified dbg:stop documentation</p> + <p> + Own Id: OTP-13078</p> + </item> + </list> + </section> + +</section> + +<section><title>Runtime_Tools 1.9.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The <c>trace_file_drv</c> did not handle <c>EINTR</c> + correct which caused it to fail when the runtime system + received a signal.</p> + <p> + Own Id: OTP-12890 Aux Id: seq12885 </p> + </item> + </list> + </section> + +</section> + +<section><title>Runtime_Tools 1.9</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Change license text from Erlang Public License to Apache + Public License v2</p> + <p> + Own Id: OTP-12845</p> + </item> + </list> + </section> + +</section> + +<section><title>Runtime_Tools 1.8.16</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The trace process started by <c>dbg</c> would not always + terminate when <c>dbg:stop/0</c> was called.</p> + <p> + Own Id: OTP-12517</p> + </item> + </list> + </section> + +</section> + +<section><title>Runtime_Tools 1.8.15</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Add <c>nif_version</c> to <c>erlang:system_info/1</c> in + order to get the NIF API version of the runtime system in + a way similar to <c>driver_version</c>.</p> + <p> + Own Id: OTP-12298</p> + </item> + </list> + </section> + +</section> + +<section><title>Runtime_Tools 1.8.14</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The documentation for the return value of + dbg:{stop,stop_clear} functions are now correct (Thanks + to Luca Favatella)</p> + <p> + Own Id: OTP-11603</p> + </item> + <item> + <p> + Fix DTrace build on Illumos. (Thanks to Ryan Zezeski.)</p> + <p> + Own Id: OTP-11622</p> + </item> + <item> + <p> + Do not turn off scheduler_wall_time, as it can interfere + with other applications usage.</p> + <p> + Own Id: OTP-11693 Aux Id: seq12528 </p> + </item> + <item> + <p> + Application upgrade (appup) files are corrected for the + following applications: </p> + <p> + <c>asn1, common_test, compiler, crypto, debugger, + dialyzer, edoc, eldap, erl_docgen, et, eunit, gs, hipe, + inets, observer, odbc, os_mon, otp_mibs, parsetools, + percept, public_key, reltool, runtime_tools, ssh, + syntax_tools, test_server, tools, typer, webtool, wx, + xmerl</c></p> + <p> + A new test utility for testing appup files is added to + test_server. This is now used by most applications in + OTP.</p> + <p> + (Thanks to Tobias Schlager)</p> + <p> + Own Id: OTP-11744</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Allow install path to have unicode characters.</p> + <p> + Own Id: OTP-10877</p> + </item> + <item> + <p> + The <c>erts_alloc_config</c> tool has been updated to + produce configurations that better fit todays SMP support + in the VM.</p> + <p> + Own Id: OTP-11662</p> + </item> + <item> + <p> + The <seealso + marker="kernel:app"><c>app</c></seealso>-file key + <seealso + marker="kernel:app#runtime_dependencies"><c>runtime_dependencies</c></seealso> + has been introduced.</p> + <p> + Runtime dependencies have been added to all app-files in + OTP. Note that these may not be completely correct during + OTP 17, but this is actively being worked on.</p> + <p> + The function <seealso + marker="runtime_tools:system_information#sanity_check/0"><c>system_information:sanity_check/0</c></seealso> + will verify all declared runtime dependencies in the + system when called.</p> + <p> + Own Id: OTP-11773</p> + </item> + </list> + </section> + +</section> + +<section><title>Runtime_Tools 1.8.13</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Observer did not produce correct result when ERTS + internal memory allocators had been disabled.</p> + <p> + Own Id: OTP-11520</p> + </item> + </list> + </section> + +</section> + +<section><title>Runtime_Tools 1.8.12</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The process trace flag 'silent' is now allowed in call to + dbg:p/2.</p> + <p> + Own Id: OTP-11222</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Introduced functionality for inspection of system and + build configuration.</p> + <p> + Own Id: OTP-11196</p> + </item> + </list> + </section> + +</section> + +<section><title>Runtime_Tools 1.8.11</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Some bugs related to calculation of CPU/scheduler + utilization in observer are corrected.</p> + <p> + Current function for a process is accepted to be + 'undefined' when running hipe.</p> + <p> + Own Id: OTP-10894</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>Erlang source files with non-ASCII characters are now + encoded in UTF-8 (instead of latin1).</p> + <p> + Own Id: OTP-11041 Aux Id: OTP-10907 </p> + </item> + </list> + </section> + +</section> + +<section><title>Runtime_Tools 1.8.10</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix Table Viewer refresh crash on no more existing ets + tables (Thanks to Peti Gömori)</p> + <p> + Own Id: OTP-10635</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + User Guides for the dynamic tracing tools dtrace and + systemtap have been added to the documentation.</p> + <p> + Own Id: OTP-10155</p> + </item> + <item> + <p>Where necessary a comment stating encoding has been + added to Erlang files. The comment is meant to be removed + in Erlang/OTP R17B when UTF-8 becomes the default + encoding. </p> + <p> + Own Id: OTP-10630</p> + </item> + <item> + <p> Some examples overflowing the width of PDF pages have + been corrected. </p> + <p> + Own Id: OTP-10665</p> + </item> + <item> + <p> + The backend module appmon_info.erl is moved from appmon + application to runtime_tools. This allows appmon to be + run from a remote erlang node towards a target node which + does not have appmon (and its dependencies) installed, as + long as runtime_tools is installed there.</p> + <p> + Own Id: OTP-10786</p> + </item> + </list> + </section> + +</section> + <section><title>Runtime_Tools 1.8.9</title> <section><title>Fixed Bugs and Malfunctions</title> @@ -259,7 +709,7 @@ also been extended. </item><item> The <c>configure</c> scripts of <c>erl_interface</c> and <c>odbc</c> now search for thread libraries and thread library quirks the - same way as <c>erts</c> do. </item><item> The + same way as ERTS do. </item><item> The <c>configure</c> script of the <c>odbc</c> application now also looks for odbc libraries in <c>lib64</c> and <c>lib/64</c> directories when building on a 64-bit diff --git a/lib/runtime_tools/doc/src/notes_history.xml b/lib/runtime_tools/doc/src/notes_history.xml index 8fe27f619c..48b868ff5b 100644 --- a/lib/runtime_tools/doc/src/notes_history.xml +++ b/lib/runtime_tools/doc/src/notes_history.xml @@ -1,24 +1,25 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd"> <chapter> <header> <copyright> <year>2006</year> - <year>2011</year> + <year>2016</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. The Initial Developer of the Original Code is Ericsson AB. </legalnotice> diff --git a/lib/runtime_tools/doc/src/part.xml b/lib/runtime_tools/doc/src/part.xml new file mode 100644 index 0000000000..34acf69fc8 --- /dev/null +++ b/lib/runtime_tools/doc/src/part.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE part SYSTEM "part.dtd"> + +<part xmlns:xi="http://www.w3.org/2001/XInclude"> + <header> + <copyright> + <year>2012</year><year>2016</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + </legalnotice> + + <title>Runtime Tools User's Guide</title> + <prepared>Lukas Larsson</prepared> + <docno></docno> + <date>2012-07-18</date> + <rev></rev> + <file>part.xml</file> + </header> + + <description> + <p><em>Runtime Tools</em></p> + </description> + + <xi:include href="LTTng.xml"/> + <xi:include href="DTRACE.xml"/> + <xi:include href="SYSTEMTAP.xml"/> +</part> + + + + diff --git a/lib/runtime_tools/doc/src/part_notes.xml b/lib/runtime_tools/doc/src/part_notes.xml index 6f7f610da0..cabf3e39da 100644 --- a/lib/runtime_tools/doc/src/part_notes.xml +++ b/lib/runtime_tools/doc/src/part_notes.xml @@ -1,23 +1,24 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE part SYSTEM "part.dtd"> <part xmlns:xi="http://www.w3.org/2001/XInclude"> <header> <copyright> - <year>2004</year><year>2009</year> + <year>2004</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> diff --git a/lib/runtime_tools/doc/src/part_notes_history.xml b/lib/runtime_tools/doc/src/part_notes_history.xml index 2ce1a5de05..dd1991f23a 100644 --- a/lib/runtime_tools/doc/src/part_notes_history.xml +++ b/lib/runtime_tools/doc/src/part_notes_history.xml @@ -1,24 +1,25 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE part SYSTEM "part.dtd"> <part> <header> <copyright> <year>2006</year> - <year>2011</year> + <year>2016</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. The Initial Developer of the Original Code is Ericsson AB. </legalnotice> diff --git a/lib/runtime_tools/doc/src/ref_man.xml b/lib/runtime_tools/doc/src/ref_man.xml index df3446cd17..d2fb7a29af 100644 --- a/lib/runtime_tools/doc/src/ref_man.xml +++ b/lib/runtime_tools/doc/src/ref_man.xml @@ -1,23 +1,24 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE application SYSTEM "application.dtd"> <application xmlns:xi="http://www.w3.org/2001/XInclude"> <header> <copyright> - <year>1999</year><year>2012</year> + <year>1999</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -35,5 +36,7 @@ <xi:include href="dbg.xml"/> <xi:include href="dyntrace.xml"/> <xi:include href="erts_alloc_config.xml"/> + <xi:include href="msacc.xml"/> + <xi:include href="system_information.xml"/> </application> diff --git a/lib/runtime_tools/doc/src/runtime_tools_app.xml b/lib/runtime_tools/doc/src/runtime_tools_app.xml index 1fd61b84d8..a2cf623977 100644 --- a/lib/runtime_tools/doc/src/runtime_tools_app.xml +++ b/lib/runtime_tools/doc/src/runtime_tools_app.xml @@ -1,24 +1,25 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE appref SYSTEM "appref.dtd"> <appref> <header> <copyright> <year>1999</year> - <year>2011</year> + <year>2016</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. The Initial Developer of the Original Code is Ericsson AB. </legalnotice> diff --git a/lib/runtime_tools/doc/src/specs.xml b/lib/runtime_tools/doc/src/specs.xml new file mode 100644 index 0000000000..978bd39e55 --- /dev/null +++ b/lib/runtime_tools/doc/src/specs.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" ?> +<specs xmlns:xi="http://www.w3.org/2001/XInclude"> + <xi:include href="../specs/specs_system_information.xml"/> + <xi:include href="../specs/specs_msacc.xml"/> +</specs> diff --git a/lib/runtime_tools/doc/src/system_information.xml b/lib/runtime_tools/doc/src/system_information.xml new file mode 100644 index 0000000000..53dc595e64 --- /dev/null +++ b/lib/runtime_tools/doc/src/system_information.xml @@ -0,0 +1,99 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE erlref SYSTEM "erlref.dtd"> + +<erlref> + <header> + <copyright> + <year>2014</year><year>2016</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + </legalnotice> + + <title></title> + <prepared></prepared> + <responsible></responsible> + <docno>1</docno> + <approved></approved> + <checked></checked> + <date></date> + <rev></rev> + <file>system_information.xml</file> + </header> + <module>system_information</module> + <modulesummary>System Information</modulesummary> + <description> + <p></p> + </description> + <funcs> + <func> + <name name="sanity_check" arity="0"/> + <fsummary>Perform a sanity check</fsummary> + <desc> + <p>Performs a sanity check on the system. If no issues + were found, <c>ok</c> is returned. If issues were + found, <c>{failed, <anno>Failures</anno>}</c> is + returned. All failures found will be part of the + <c><anno>Failures</anno></c> list. Currently defined + <c><anno>Failure</anno></c> elements in the + <c><anno>Failures</anno></c> list:</p> + <taglist> + <tag><c><anno>InvalidAppFile</anno></c></tag> + <item><p>An application has an invalid <c>.app</c> file. The + second element identifies the application which has the + invalid <c>.app</c> file.</p></item> + <tag><c><anno>InvalidApplicationVersion</anno></c></tag> + <item><p>An application has an invalid application version. + The second element identifies the application version that + is invalid.</p></item> + <tag><c><anno>MissingRuntimeDependencies</anno></c></tag> + <item><p>An application is missing + <seealso marker="kernel:app#runtime_dependencies">runtime + dependencies</seealso>. The second element identifies the + application (with version) that has missing dependencies. + The third element contains the missing dependencies.</p> + <p>Note that this check use application versions that + are loaded, or will be loaded when used. You might have + application versions that satisfies all dependencies + installed in the system, but if those are not loaded this + check will fail. The system will of course also fail when + used like this. This may happen when you have multiple + <seealso marker="doc/system_principles:versions">branched + versions</seealso> of the same application installed in the + system, but you do not use a + <seealso marker="doc/system_principles:system_principles#BOOTSCRIPT">boot + script</seealso> identifing the correct application version.</p> + </item> + </taglist> + <p>Currently the sanity check is limited to verifying + runtime dependencies found in the <c>.app</c> files of + all applications. More checks will be introduced in the + future. This implies that the return type <em>will</em> + change in the future.</p> + <note><p>An <c>ok</c> return value only means that + <c>sanity_check/0</c> did not find any issues, <em>not</em> + that no issues exist.</p></note> + </desc> + </func> + <func> + <name name="to_file" arity="1"/> + <fsummary>Write miscellaneous system information to file</fsummary> + <desc><p>Writes miscellaneous system information to file. This + information will typically be requested by the Erlang/OTP team + at Ericsson AB when reporting an issue.</p></desc> + </func> + </funcs> + </erlref> + diff --git a/lib/runtime_tools/examples/dist.d b/lib/runtime_tools/examples/dist.d index 7e2d7f0e35..3da2171a85 100644 --- a/lib/runtime_tools/examples/dist.d +++ b/lib/runtime_tools/examples/dist.d @@ -2,18 +2,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/dist.systemtap b/lib/runtime_tools/examples/dist.systemtap index 8935e19e28..bb20d617e1 100644 --- a/lib/runtime_tools/examples/dist.systemtap +++ b/lib/runtime_tools/examples/dist.systemtap @@ -2,18 +2,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/driver1.d b/lib/runtime_tools/examples/driver1.d index 4871a8ee69..f63033ce6a 100644 --- a/lib/runtime_tools/examples/driver1.d +++ b/lib/runtime_tools/examples/driver1.d @@ -2,18 +2,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/driver1.systemtap b/lib/runtime_tools/examples/driver1.systemtap index deae82f8fb..e1ee8ecffc 100644 --- a/lib/runtime_tools/examples/driver1.systemtap +++ b/lib/runtime_tools/examples/driver1.systemtap @@ -2,18 +2,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/efile_drv.d b/lib/runtime_tools/examples/efile_drv.d index 2442222552..a470518dd9 100644 --- a/lib/runtime_tools/examples/efile_drv.d +++ b/lib/runtime_tools/examples/efile_drv.d @@ -2,18 +2,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/efile_drv.systemtap b/lib/runtime_tools/examples/efile_drv.systemtap index 4b92e67048..29c3637e10 100644 --- a/lib/runtime_tools/examples/efile_drv.systemtap +++ b/lib/runtime_tools/examples/efile_drv.systemtap @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/function-calls.d b/lib/runtime_tools/examples/function-calls.d index ec6090553e..f8ca388228 100644 --- a/lib/runtime_tools/examples/function-calls.d +++ b/lib/runtime_tools/examples/function-calls.d @@ -2,18 +2,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/function-calls.systemtap b/lib/runtime_tools/examples/function-calls.systemtap index 4de54cfb5a..9c44b2d014 100644 --- a/lib/runtime_tools/examples/function-calls.systemtap +++ b/lib/runtime_tools/examples/function-calls.systemtap @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/garbage-collection.d b/lib/runtime_tools/examples/garbage-collection.d index ebc40a19ec..7d5a07c6fb 100644 --- a/lib/runtime_tools/examples/garbage-collection.d +++ b/lib/runtime_tools/examples/garbage-collection.d @@ -2,18 +2,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/garbage-collection.systemtap b/lib/runtime_tools/examples/garbage-collection.systemtap index 81e9d38196..e414eea821 100644 --- a/lib/runtime_tools/examples/garbage-collection.systemtap +++ b/lib/runtime_tools/examples/garbage-collection.systemtap @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/memory1.d b/lib/runtime_tools/examples/memory1.d index b222aeae62..79f5fa70a5 100644 --- a/lib/runtime_tools/examples/memory1.d +++ b/lib/runtime_tools/examples/memory1.d @@ -2,18 +2,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/memory1.systemtap b/lib/runtime_tools/examples/memory1.systemtap index 9374b97d18..04df4d64c4 100644 --- a/lib/runtime_tools/examples/memory1.systemtap +++ b/lib/runtime_tools/examples/memory1.systemtap @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/messages.d b/lib/runtime_tools/examples/messages.d index 08cf52f3d2..d48c807afd 100644 --- a/lib/runtime_tools/examples/messages.d +++ b/lib/runtime_tools/examples/messages.d @@ -2,18 +2,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/messages.systemtap b/lib/runtime_tools/examples/messages.systemtap index c58e1168f9..f2ef56a22b 100644 --- a/lib/runtime_tools/examples/messages.systemtap +++ b/lib/runtime_tools/examples/messages.systemtap @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/port1.d b/lib/runtime_tools/examples/port1.d index 1e3bd3d8a9..79266f78ca 100644 --- a/lib/runtime_tools/examples/port1.d +++ b/lib/runtime_tools/examples/port1.d @@ -2,18 +2,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/port1.systemtap b/lib/runtime_tools/examples/port1.systemtap index c8af240d85..f7ce03a65e 100644 --- a/lib/runtime_tools/examples/port1.systemtap +++ b/lib/runtime_tools/examples/port1.systemtap @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/process-scheduling.d b/lib/runtime_tools/examples/process-scheduling.d index 6408d7d5f2..30bfcaa21d 100644 --- a/lib/runtime_tools/examples/process-scheduling.d +++ b/lib/runtime_tools/examples/process-scheduling.d @@ -2,18 +2,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/process-scheduling.systemtap b/lib/runtime_tools/examples/process-scheduling.systemtap index 4cc3ef555c..b0b74257b3 100644 --- a/lib/runtime_tools/examples/process-scheduling.systemtap +++ b/lib/runtime_tools/examples/process-scheduling.systemtap @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/spawn-exit.d b/lib/runtime_tools/examples/spawn-exit.d index ae690b819a..feeaa7960e 100644 --- a/lib/runtime_tools/examples/spawn-exit.d +++ b/lib/runtime_tools/examples/spawn-exit.d @@ -2,18 +2,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/spawn-exit.systemtap b/lib/runtime_tools/examples/spawn-exit.systemtap index 4b69e4aea6..89bca14496 100644 --- a/lib/runtime_tools/examples/spawn-exit.systemtap +++ b/lib/runtime_tools/examples/spawn-exit.systemtap @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/user-probe-n.d b/lib/runtime_tools/examples/user-probe-n.d index 06a3e5c9b9..4b4300fe83 100644 --- a/lib/runtime_tools/examples/user-probe-n.d +++ b/lib/runtime_tools/examples/user-probe-n.d @@ -2,18 +2,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/user-probe-n.systemtap b/lib/runtime_tools/examples/user-probe-n.systemtap index 6aa415bb67..25f7503283 100644 --- a/lib/runtime_tools/examples/user-probe-n.systemtap +++ b/lib/runtime_tools/examples/user-probe-n.systemtap @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/user-probe.d b/lib/runtime_tools/examples/user-probe.d index 5cb5d61a76..4806bae783 100644 --- a/lib/runtime_tools/examples/user-probe.d +++ b/lib/runtime_tools/examples/user-probe.d @@ -2,18 +2,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/examples/user-probe.systemtap b/lib/runtime_tools/examples/user-probe.systemtap index 0482235324..1777476e54 100644 --- a/lib/runtime_tools/examples/user-probe.systemtap +++ b/lib/runtime_tools/examples/user-probe.systemtap @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2012. All Rights Reserved. + * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2016. All Rights Reserved. * - * The contents of this file are subject to the Erlang Public License, - * Version 1.1, (the "License"); you may not use this file except in - * compliance with the License. You should have received a copy of the - * Erlang Public License along with this software. If not, it can be - * retrieved online at http://www.erlang.org/. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * * %CopyrightEnd% */ diff --git a/lib/runtime_tools/include/observer_backend.hrl b/lib/runtime_tools/include/observer_backend.hrl index 4be9baca5b..257e525a15 100644 --- a/lib/runtime_tools/include/observer_backend.hrl +++ b/lib/runtime_tools/include/observer_backend.hrl @@ -1,26 +1,28 @@ -%% ``The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved via the world wide web at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% The Initial Developer of the Original Code is Ericsson Utvecklings AB. -%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings -%% AB. All Rights Reserved.'' -%% -%% $Id$ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2002-2016. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% %% -record(etop_info, {now = {0, 0, 0}, n_procs = 0, - wall_clock = {0, 0}, - runtime = {0, 0}, + wall_clock, + runtime, run_queue = 0, alloc_areas = [], memi = [{total, 0}, diff --git a/lib/runtime_tools/src/Makefile b/lib/runtime_tools/src/Makefile index 810e3e8741..2c902952a1 100644 --- a/lib/runtime_tools/src/Makefile +++ b/lib/runtime_tools/src/Makefile @@ -1,18 +1,19 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1999-2012. All Rights Reserved. +# Copyright Ericsson AB 1999-2016. All Rights Reserved. # -# The contents of this file are subject to the Erlang Public License, -# Version 1.1, (the "License"); you may not use this file except in -# compliance with the License. You should have received a copy of the -# Erlang Public License along with this software. If not, it can be -# retrieved online at http://www.erlang.org/. -# -# Software distributed under the License is distributed on an "AS IS" -# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -# the License for the specific language governing rights and limitations -# under the License. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # %CopyrightEnd% # @@ -35,20 +36,18 @@ RELSYSDIR = $(RELEASE_PATH)/lib/runtime_tools-$(VSN) # ---------------------------------------------------- MODULES= \ + appmon_info \ erts_alloc_config \ - inviso_rt \ - inviso_rt_meta \ - inviso_rt_lib \ - inviso_as_lib \ - inviso_autostart \ - inviso_autostart_server \ runtime_tools \ runtime_tools_sup \ dbg \ dyntrace \ percept_profile \ + system_information \ observer_backend \ - ttb_autostart + ttb_autostart\ + msacc + HRL_FILES= ../include/observer_backend.hrl ERL_FILES= $(MODULES:%=%.erl) @@ -73,7 +72,8 @@ EXAMPLE_FILES= \ ERL_COMPILE_FLAGS += \ -I../include \ -I ../../et/include \ - -I ../../../libraries/et/include + -I ../../../libraries/et/include \ + -Werror # ---------------------------------------------------- # Targets @@ -86,10 +86,10 @@ clean: rm -f errs core *~ $(APP_TARGET): $(APP_SRC) ../vsn.mk - sed -e 's;%VSN%;$(VSN);' $< > $@ + $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk - sed -e 's;%VSN%;$(VSN);' $< > $@ + $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@ docs: diff --git a/lib/runtime_tools/src/appmon_info.erl b/lib/runtime_tools/src/appmon_info.erl new file mode 100644 index 0000000000..b5500085a3 --- /dev/null +++ b/lib/runtime_tools/src/appmon_info.erl @@ -0,0 +1,962 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +%%---------------------------------------------------------------------- +%% +%% Information centre for appmon. Must be present on each node +%% monitored. +%% +%% +%% A worklist is maintained that contain all current work that +%% should be performed at each timeout. Each entry in the +%% worklist describes where the result shall be sent and a list +%% of options relevant for that particular task +%% +%% +%% Maintenance Note: +%% +%% This module is supposed to be updated by any who would like to +%% subscribe for information. The idea is that several tools +%% could use this module for their core information gathering +%% services. +%% +%% The module is based on the notion of tasks. Each task should +%% have a nice public interface function which should handle task +%% administration. Tasks are identified by a "key" consisting of +%% three items, the requesting pid, the name of the task and the +%% task auxillary parameter. The requesting pid is the pid of the +%% callee (in the appmon case it can be the node window for +%% instance), the task name is whatever name the task is given +%% (in the appmon case it can be app, app_ctrl or load). The task +%% name can be seen as the type of the task. The task auxillary +%% parameter is an all purpose parameter that have a different +%% meaning for each type of task so in appmon the Aux for app +%% contains the root pid of the monitored application and in +%% app_ctrl it contains the node name (just to distinguish from +%% the other app_ctrl tasks, if any) while the Aux parameter is +%% not used for the load task at all. +%% +%% Each task also carries a list of options for +%% customisation. The options valid for a task is completely +%% internal to that task type except for the timeout option which +%% is used by do_work to determine the interval at which to +%% perform the task. The timeout option may also have the value +%% at_most_once that indicates that the task should not be done +%% more than once, in appmon the remote port (or process) info +%% (pinfo) task is such a task that is only done once for each +%% call. Note that the only way to change or update options is to +%% call the public interface function for the task, this will +%% merge the old options with the new ones and also force the +%% task to be executed. +%% +%% All tasks are managed by the do_work function. The basic +%% functionality being that the result of the task is compared to +%% the previous result and a delivery is sent to the callee if +%% they differ. Most tasks are then done on a regular basis using +%% the timer module for a delay. +%% +%% There are a limited number of places where the module need to +%% be updated when new services are added, they are all marked +%% with "Maintenance Note", and here is a quick guide: +%% +%% First implement the task. Put the functions in this module +%% among the other task implementations. Currently all task +%% implementations should be put in this file to make it simple +%% to monitor a node, this module should be the only one +%% needed. Then add your implementation to the do_work2 function +%% and finally add a public interface function among the other +%% public interface functions. Voila. +%% +%% +%% +%% Future ideas: +%% +%% Appmon should maybe be enhanced to show all processes on a +%% node. First put all processes in an ets P, then pick those +%% that belong to applications (the normal way), then try to find +%% those processes that are roots in process link trees and pick +%% them. The final step would be to do something with those +%% processes that are left. +%% +%%---------------------------------------------------------------------- +-module(appmon_info). +-behaviour(gen_server). + +%% Exported functions +-export([start_link/3, app/4, pinfo/4, load/4, app_ctrl/4]). + +%% For internal use (RPC call) +-export([start_link2/3]). + +%% For debugging +-export([status/0]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). + + +%%---------------------------------------------------------------------- +%% The records +%% +%% state is used for keeping track of all tasks. +%% +%% db is the database used in the app task. +%% + +-record(state, {starter, opts=[], work=[], clients=[]}). +-record(db, {q, p, links, links2}). + + +%%---------------------------------------------------------------------- +%% Macros +%% + +-define(MK_KEY(CMD, AUX, FROM, OPTS), {CMD, AUX, FROM}). +-define(MK_DOIT(KEY), {do_it, KEY}). +-define(ifthen(P,S), if P -> S; true -> ok end). + + +%%---------------------------------------------------------------------- +%% Public interface +%% +%% The Aux parameter is an auxillary parameter that can be used +%% freely by the requesting process, it is included in the work +%% task key. appmon uses it for storing the node name when +%% requesting load and app_ctrl tasks, and appmon_a uses it for +%% storing application name when requesting app task. +%% +%% Maintenance Note: Put new tasks at the end, please. +%% + + +%% Do not use gen_server:start_link because we do not want the +%% appmon_info to die when initiating process dies unless special +%% conditions apply. +%% Uhu, we don't??? Made a fix so that this proces DOES indeed die +%% if it's starter dies. /Gunilla +start_link(Node, Client, Opts) -> + rpc:call(Node, ?MODULE, start_link2, [self(), Client, Opts]). +start_link2(Starter, Client, Opts) -> + Name = {local, ?MODULE}, + Args = {Starter, Opts, Client}, + case gen_server:start(Name, ?MODULE, Args, []) of + {ok, Pid} -> + {ok, Pid}; + {error, {already_started, Pid}} -> + register_client(Pid, Client), + {ok, Pid} + end. + + +%% app_ctrl +%% +%% Monitors which applications exist on a node +%% +app_ctrl(Serv, Aux, OnOff, Opts) -> + gen_server:cast(Serv, {self(), app_ctrl, Aux, OnOff, Opts}). + + +%% load +%% +%% Monitors load on a node +%% +load(Serv, Aux, OnOff, Opts) -> + gen_server:cast(Serv, {self(), load, Aux, OnOff, Opts}). + + +%% app +%% +%% Monitors one application given by name (this ends up in a +%% process tree +%% +app(Serv, AppName, OnOff, Opts) -> + gen_server:cast(Serv, {self(), app, AppName, OnOff, Opts}). + +%% pinfo +%% +%% Process or Port info +%% +pinfo(Serv, Pid, OnOff, Opt) -> + gen_server:cast(Serv, {self(), pinfo, Pid, OnOff, Opt}). + +%% register_client +%% +%% Registers a client (someone subscribing for information) +%% + +register_client(Serv, P) -> + link(Serv), + gen_server:call(Serv, {register_client, P}). + +%% status +%% +%% Status of appmon_info +%% + +status() -> + gen_server:cast(?MODULE, status). + +%%---------------------------------------------------------------------- +%% +%% Gen server administration +%% +%%---------------------------------------------------------------------- + +init({Starter, Opts, Pid}) -> + link(Pid), + process_flag(trap_exit, true), + WorkStore = ets:new(workstore, [set, public]), + {ok, #state{starter=Starter, opts=Opts, work=WorkStore, + clients=[Pid]}}. + +terminate(_Reason, State) -> + ets:delete(State#state.work), + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + + +%%---------------------------------------------------------------------- +%% +%% Gen server calls +%% +%%---------------------------------------------------------------------- + +handle_call({register_client, Pid}, _From, State) -> + NewState = case lists:member(Pid, State#state.clients) of + true -> State; + _ -> State#state{clients=[Pid | State#state.clients]} + end, + {reply, ok, NewState}; +handle_call(_Other, _From, State) -> + {reply, ok, State}. + +%%---------------------------------------------------------------------- +%% +%% Gen server casts +%% +%%---------------------------------------------------------------------- + +%% Cmd = app_ctrl | load | app | pinfo +handle_cast({From, Cmd, Aux, OnOff, Opts}, State) -> + NewState = update_worklist(Cmd, Aux, From, OnOff, Opts, State), + {noreply, NewState}; +handle_cast(status, State) -> + print_state(State), + {noreply, State}; +handle_cast(_Other, State) -> + {noreply, State}. + + +%%---------------------------------------------------------------------- +%% +%% Gen server info's +%% +%%---------------------------------------------------------------------- + +handle_info({do_it, Key}, State) -> + ok = do_work(Key, State), + {noreply, State}; + +handle_info({'EXIT', Pid, Reason}, State) -> + case State#state.starter of + Pid -> + {stop, Reason, State}; + _Other -> + Work = State#state.work, + del_work(ets:match(Work, {{'$1','$2',Pid}, '_', '_', '_'}), + Pid, Work), + case lists:delete(Pid, State#state.clients) of + [] -> case get_opt(stay_resident, State#state.opts) of + true -> {noreply, State#state{clients=[]}}; + _ -> {stop, normal, State} + end; + NewClients -> {noreply, State#state{clients=NewClients}} + end + end; +handle_info(_Other, State) -> + {noreply, State}. + + +%%---------------------------------------------------------------------- +%% +%% Doing actual work +%% +%%---------------------------------------------------------------------- + +do_work(Key, State) -> + WorkStore = State#state.work, + {Cmd, Aux, From, _OldRef, Old, Opts} = retrieve(WorkStore, Key), + {ok, Result} = do_work2(Cmd, Aux, From, Old, Opts), + if + Result==Old -> ok; + true -> + From ! {delivery, self(), Cmd, Aux, Result}, + ok + end, + case get_opt(timeout, Opts) of + at_most_once -> + del_task(Key, WorkStore); + T when is_integer(T) -> + {ok, Ref} = timer:send_after(T, ?MK_DOIT(Key)), + store(WorkStore, Key, Ref, Result, Opts) + end, + ok. + + +%%---------------------------------------------------------------------- +%% +%% Name: do_work2 +%% +%% Maintenance Note: Add a clause here for each new task. +%% +do_work2(load, _Aux, _From, Old, Opts) -> + calc_load(Old, Opts); +do_work2(app_ctrl, _Aux, _From, _Old, _Opts) -> + calc_app_on_node(); +do_work2(app, Aux, _From, _Old, Opts) -> + calc_app_tree(Aux, Opts); +do_work2(pinfo, Aux, _From, _Old, _Opts) -> + calc_pinfo(pinfo, Aux); +do_work2(Cmd, Aux, _From, _Old, _Opts) -> + {Cmd, Aux}. + + +retrieve(Tab, Key) -> + case ets:lookup(Tab, Key) of + [{{Cmd, Aux, From}, Ref, Old, Opts}] -> + {Cmd, Aux, From, Ref, Old, Opts}; + _Other -> + false + end. + +store(Tab, Key, Ref, Old, Opts) -> + ets:insert(Tab, {Key, Ref, Old, Opts}), + Key. + + +%%---------------------------------------------------------------------- +%% +%% WorkStore handling +%% +%%---------------------------------------------------------------------- + +update_worklist(Cmd, Aux, From, true, Opts, State) -> + add_task(Cmd, Aux, From, Opts, State), + State; +update_worklist(Cmd, Aux, From, _Other, _Opts, State) -> + del_task(Cmd, Aux, From, State#state.work), + State. + +%% First check if a task like this already exists and if so cancel its +%% timer and make really sure that no stray do it command will come +%% later. Then start a new timer for the task and store it i +%% WorkStorage +add_task(Cmd, Aux, From, Opts, State) -> + WorkStore = State#state.work, + Key = ?MK_KEY(Cmd, Aux, From, Opts), + OldOpts = del_task(Key, WorkStore), + store(WorkStore, Key, nil, nil, ins_opts(Opts, OldOpts)), + catch do_work(Key, State), + ok. + +%% Delete a list of tasks belonging to a pid +del_work([[Cmd, Aux] | Ws], Pid, Work) -> + del_task(Cmd, Aux, Pid, Work), + del_work(Ws, Pid, Work); +del_work([], _Pid, _Work) -> ok. + +%% Must return old options or empty list +del_task(Cmd, Aux, From, WorkStore) -> + del_task(?MK_KEY(Cmd, Aux, From, []), WorkStore). +del_task(Key, WorkStore) -> + OldStuff = retrieve(WorkStore, Key), + ets:delete(WorkStore, Key), + case OldStuff of + {_Cmd, _Aux, _From, Ref, _Old, Opts} -> + if + Ref /= nil -> + {ok,_} = timer:cancel(Ref), + receive + {do_it, Key} -> + Opts + after 10 -> + Opts + end; + true -> Opts + end; + _ -> + [] + end. + + +%% +%% Maintenance Note: +%% +%% Add new task implementations somewhere here below. +%% + + +%%---------------------------------------------------------------------- +%%********************************************************************** +%% +%% +%% BEGIN OF calc_app_tree +%% +%% App tree is the process tree shown in the application window +%% +%% The top (root) pid is found by calling +%% application_controller:get_master(AppName) and this is done in +%% calc_app_on_node (before the call to calc_app_tree). +%% +%% We are going to add processes to the P ets and we are doing it +%% in a two step process. First all prospect processes are put on +%% the queue Q. Then we examine the front of Q and add this +%% process to P if it's not already in P. Then all children of +%% the process is put on the queue Q and the process is repeated. +%% +%% We also maintain two link ets'es, one for primary links and +%% one for secondary links. These databases are updated at the +%% same time as the queue is updated with children. +%% +%%********************************************************************** +%%---------------------------------------------------------------------- + + +calc_app_tree(Name, Opts) -> + Mode = get_opt(info_type, Opts), + case application_controller:get_master(Name) of + Pid when is_pid(Pid) -> + DB = new_db(Mode, Pid), + GL = groupl(Pid), + R = case catch do_find_proc(Mode, DB, GL, find_avoid()) of + {ok, DB2} -> + {ok, {format(Pid), + format(ets:tab2list(DB2#db.p)), + format(ets:tab2list(DB2#db.links)), + format(ets:tab2list(DB2#db.links2))}}; + {error, Reason} -> + {error, Reason}; + Other -> + {error, Other} + end, + ets:delete(DB#db.p), + ets:delete(DB#db.links), + ets:delete(DB#db.links2), + R; + _ -> + {ok, {[], [], [], []}} + end. + +get_pid(P) when is_pid(P) -> P; +get_pid(P) when is_port(P) -> P; +get_pid(X) when is_tuple(X) -> element(2, X). + + +%---------------------------------------------------------------------- +%%--------------------------------------------------------------------- +%% Handling process trees of processses that are linked to each other + +do_find_proc(Mode, DB, GL, Avoid) -> + case get_next(DB) of + {{value, V}, DB2} -> + do_find_proc2(V, Mode, DB2, GL, Avoid); + {empty, DB2} -> + {ok, DB2} + end. + +do_find_proc2(X, Mode, DB, GL, Avoid) when is_port(X) -> + %% There used to be a broken attempt here to handle ports, + %% but the rest of appmon can't handle ports, so now we + %% explicitly ignore ports. + do_find_proc(Mode, DB, GL, Avoid); +do_find_proc2(X, Mode, DB, GL, Avoid) -> + Xpid = get_pid(X), + DB2 = case is_proc(DB, Xpid) of + false -> + add_proc(DB, Xpid), + C1 = find_children(X, Mode), + add_children(C1, Xpid, DB, GL, Avoid, Mode); + _ -> + DB + end, + do_find_proc(Mode, DB2, GL, Avoid). + + +%% Find children finds the children of a process. The method varies +%% with the selected mode (sup or link) and there are also some +%% processes that must be treated differently, notably the application +%% master. +%% +find_children(X, sup) when is_pid(X) -> + %% This is the first (root) process of a supervision tree and it + %% better be a supervisor, we are smoked otherwise + supervisor:which_children(X); +find_children(X, link) when is_pid(X), node(X) /= node() -> + []; +find_children(X, link) when is_pid(X) -> + case process_info(X, links) of + {links, Links} -> + lists:reverse(Links); % OTP-4082 + _ -> [] + end; +find_children({master, X}, sup) -> + case application_master:get_child(X) of + {Pid, _Name} when is_pid(Pid) -> [Pid]; + Pid when is_pid(Pid) -> [Pid] + end; +find_children({_, _X, worker, _}, sup) -> []; +find_children({_, X, supervisor, _}, sup) -> + lists:filter(fun(Thing) -> + Pid = get_pid(Thing), + if + is_pid(Pid) -> true; + true -> false + end + end, + supervisor:which_children(X)). + + +%% Add links to primary (L1) or secondary (L2) sets and return an +%% updated queue. A link is considered secondary if its endpoint is in +%% the queue of un-visited but known processes. +add_children(CList, Paren, DB, _GL, _Avoid, sup) -> + lists:foldr(fun(C, DB2) -> + case get_pid(C) of + P when is_pid(P) -> + add_prim(C, Paren, DB2); + _ -> DB2 end end, + DB, CList); + +add_children(CList, Paren, DB, GL, Avoid, _Mode) -> + lists:foldr(fun(C, DB2) -> + maybe_add_child(C, Paren, DB2, GL, Avoid) + end, DB, CList). + +%% Check if the child is already in P +maybe_add_child(C, Paren, DB, GL, Avoid) -> + case is_proc(DB, C) of + false -> + maybe_add_child_node(C, Paren, DB, GL, Avoid); + _ -> DB % In P: no action + end. + +%% Check if process on this node +maybe_add_child_node(C, Paren, DB, GL, Avoid) -> + if + node(C) /= node() -> + add_foreign(C, Paren, DB); + true -> + maybe_add_child_avoid(C, Paren, DB, GL, Avoid) + end. + +%% Check if child is on the avoid list +maybe_add_child_avoid(C, Paren, DB, GL, Avoid) -> + case lists:member(C, Avoid) of + true -> DB; + false -> + maybe_add_child_port(C, Paren, DB, GL) + end. + +%% Check if it is a port, then it is added +maybe_add_child_port(C, Paren, DB, GL) -> + if + is_port(C) -> + add_prim(C, Paren, DB); + true -> + maybe_add_child_sasl(C, Paren, DB, GL) + end. + +%% Use SASL stuff if present +maybe_add_child_sasl(C, Paren, DB, GL) -> + case check_sasl_ancestor(Paren, C) of + yes -> % Primary + add_prim(C, Paren, DB); + no -> % Secondary + add_sec(C, Paren, DB); + dont_know -> + maybe_add_child_gl(C, Paren, DB, GL) + end. + +%% Check group leader +maybe_add_child_gl(C, Paren, DB, GL) -> + case cmp_groupl(GL, groupl(C)) of + true -> maybe_add_child_sec(C, Paren, DB); + _ -> DB + end. + +%% Check if the link should be a secondary one. Note that this part is +%% pretty much a guess. +maybe_add_child_sec(C, Paren, DB) -> + case is_in_queue(DB, C) of + true -> % Yes, secondary + add_sec(C, Paren, DB); + _ -> % Primary link + add_prim(C, Paren, DB) + end. + +check_sasl_ancestor(Paren, C) -> + case lists:keysearch('$ancestors', 1, + element(2,process_info(C, dictionary))) of + {value, {_, L}} when is_list(L) -> + H = if + is_atom(hd(L)) -> whereis(hd(L)); + true -> hd(L) + end, + if + H == Paren -> yes; + true -> no + end; + _ -> dont_know + end. + + +%---------------------------------------------------------------------- +%%--------------------------------------------------------------------- +%% Primitives for the database DB of all links, processes and the +%% queue of not visited yet processes. + +-define(add_link(C, Paren, L), ets:insert(L, {Paren, C})). + +new_db(Mode, Pid) -> + P = ets:new(processes, [set, public]), + L1 = ets:new(links, [bag, public]), + L2 = ets:new(extralinks, [bag, public]), + Q = if + Mode =:= sup -> queue:in({master, Pid}, queue:new()); + true -> queue:in(Pid, queue:new()) + end, + #db{q=Q, p=P, links=L1, links2=L2}. + +get_next(DB) -> + {X, Q} = queue:out(DB#db.q), + {X, DB#db{q=Q}}. +add_proc(DB, P) -> + ets:insert(DB#db.p, {P}). +add_prim(C, Paren, DB) -> + ?add_link(get_pid(C), Paren, DB#db.links), + DB#db{q=queue:in(C, DB#db.q)}. +add_foreign(C, Paren, DB) -> + ?add_link(C, Paren, DB#db.links2), + DB#db{q=queue:in(C, DB#db.q)}. +add_sec(C, Paren, DB) -> + ?add_link(C, Paren, DB#db.links2), + DB. + +is_proc(#db{p=Tab}, P) -> + ets:member(Tab, P). + +is_in_queue(#db{q=Q}, P) -> + queue:member(P, Q). + +%% Group leader handling. No processes or Links to processes must be +%% added when group leaders differ. Note that catch all is needed +%% because net_sup is undefined when not networked but still present +%% in the kernel_sup child list. Blahh, didn't like that. +groupl(P) -> + case process_info(P, group_leader) of + {group_leader, GL} -> GL; + _Other -> nil + end. + +cmp_groupl(_GL1, nil) -> true; +cmp_groupl(GL1, GL1) -> true; +cmp_groupl(_, _) -> false. + + +%% Do some intelligent guessing as to cut in the tree +find_avoid() -> + lists:foldr(fun(X, Accu) -> + case whereis(X) of + P when is_pid(P) -> + [P|Accu]; + _ -> Accu end end, + [undefined], + [application_controller, init, error_logger, gs, + node_serv, appmon, appmon_a, appmon_info]). + + + +%%---------------------------------------------------------------------- +%% +%% Formats the output strings +%% +%%---------------------------------------------------------------------- +format([{P} | Fs]) -> % Process or port + [{P, format(P)} | format(Fs)]; +format([{P1, P2} | Fs]) -> % Link + [{format(P1), format(P2)} | format(Fs)]; +format([]) -> []; +format(P) when is_pid(P), node(P) /= node() -> + pid_to_list(P) ++ " " ++ atom_to_list(node(P)); +format(P) when is_pid(P) -> + case process_info(P, registered_name) of + {registered_name, Name} -> atom_to_list(Name); + _ -> pid_to_list(P) + end; +format(P) when is_port(P) -> + "port " ++ integer_to_list(element(2, erlang:port_info(P, id))); +format(X) -> + io:format("What: ~p~n", [X]), + "???". + + +%%---------------------------------------------------------------------- +%%********************************************************************** +%% +%% +%% END OF calc_app_tree +%% +%% +%%********************************************************************** +%%---------------------------------------------------------------------- + + + + +%%---------------------------------------------------------------------- +%%********************************************************************** +%% +%% +%% BEGIN OF calc_app_on_node +%% +%% +%%********************************************************************** +%%---------------------------------------------------------------------- + +%% Finds all applications on a node +calc_app_on_node() -> + NewApps = reality_check(application:which_applications()), + {ok, NewApps}. + + +reality_check([E|Es]) -> + N = element(1, E), + case catch application_controller:get_master(N) of + P when is_pid(P) -> [{P, N, E} | reality_check(Es)]; + _ -> reality_check(Es) + end; +reality_check([]) -> []. + + + + +%%---------------------------------------------------------------------- +%%********************************************************************** +%% +%% +%% END OF calc_app_on_node +%% +%% +%%********************************************************************** +%%---------------------------------------------------------------------- + + + +%%---------------------------------------------------------------------- +%%********************************************************************** +%% +%% +%% BEGIN OF calc_load +%% +%% +%%********************************************************************** +%%---------------------------------------------------------------------- + +calc_load(Old, Opts) -> + L = load(Opts), + case get_opt(load_average, Opts) of + true -> + case Old of + {_, L} -> {ok, {L, L}}; + {_, O2} when abs(L-O2) < 3 -> {ok, {O2, L}}; + {_, O2} -> {ok, {O2, trunc((2*L+O2)/3)}}; + _ -> {ok, {0, L}} + end; + _ -> + case Old of + {_, O2} -> {ok, {O2, L}}; + _ -> {ok, {0, L}} + end + end. + + +load(Opts) -> + Q = get_sample(queue), + + case get_opt(load_method, Opts) of + time -> + Td = get_sample(runtime), + Tot = get_sample(tot_time), + + case get_opt(load_scale, Opts) of + linear -> + erlang:min(trunc(load_range()*(Td/Tot+Q/6)), + load_range()); + prog -> + erlang:min(trunc(load_range()*prog(Td/Tot+Q/6)), + load_range()) + end; + queue -> + case get_opt(load_scale, Opts) of + linear -> + erlang:min(trunc(load_range()*Q/6), load_range()); + prog -> + erlang:min(trunc(load_range()*prog(Q/6)), load_range()) + end + end. + + +%% +%% T shall be within 0 and 0.9 for this to work correctly +prog(T) -> + math:sqrt(abs(T)/0.9). + + +get_sample(queue) -> statistics(run_queue); +get_sample(runtime) -> {Rt,Rd} = statistics(runtime), + delta(runtime, Rt, Rd); +get_sample(tot_time) -> {Rt,Rd} = statistics(wall_clock), + delta(tot_time, Rt, Rd). + + +%% Keeps track of differences between calls +%% Needed because somebody else might have called +%% statistics/1. +%% +%% Note that due to wrap-arounds, we use a cheating +%% delta which is correct unless somebody else +%% uses statistics/1 +delta(KeyWord, Val, CheatDelta) -> + RetVal = case get(KeyWord) of + undefined -> + Val; + Other -> + if + Other > Val -> + CheatDelta; + true -> + Val-Other + end + end, + put(KeyWord, Val), + RetVal. + + +load_range() -> 16. + + + +%%---------------------------------------------------------------------- +%%********************************************************************** +%% +%% +%% END OF calc_load +%% +%% +%%********************************************************************** +%%---------------------------------------------------------------------- + + +%%---------------------------------------------------------------------- +%%********************************************************************** +%% +%% +%% BEGIN OF calc_pinfo +%% +%% +%%********************************************************************** +%%---------------------------------------------------------------------- + +calc_pinfo(pinfo, Pid) when is_pid(Pid) -> + Info = process_info(Pid), + {ok, io_lib:format("Node: ~p, Process: ~p~n~p~n~n", + [node(), Pid, Info])}; +calc_pinfo(pinfo, Pid) when is_port(Pid) -> + Info = lists:map(fun(Key) ->erlang:port_info(Pid, Key) end, + [id, name, connected, links, input, output]), + + {ok, io_lib:format("Node: ~p, Port: ~p~n~p~n~n", + [node(), element(2, erlang:port_info(Pid, id)), + Info])}; +calc_pinfo(pinfo, _Pid) -> + {ok, ""}. + + +%%---------------------------------------------------------------------- +%%********************************************************************** +%% +%% +%% END OF calc_pinfo +%% +%% +%%********************************************************************** +%%---------------------------------------------------------------------- + + + +%%---------------------------------------------------------------------- +%% +%% Print the State +%% +%% -record(state, {opts=[], work=[], clients=[]}). +%% +%%---------------------------------------------------------------------- +print_state(State) -> + io:format("Status:~n Opts: ~p~n" + "Clients: ~p~n WorkStore:~n", + [State#state.opts, State#state.clients]), + print_work(ets:tab2list(State#state.work)). + +print_work([W|Ws]) -> + io:format(" ~p~n", [W]), print_work(Ws); +print_work([]) -> ok. + + +%%---------------------------------------------------------------------- +%% +%% Option handling +%% +%%---------------------------------------------------------------------- + +%% The only options ever set by a user is info_type, timeout, +%% load_scale and load_method. +get_opt(Name, Opts) -> + case lists:keysearch(Name, 1, Opts) of + {value, Val} -> element(2, Val); + false -> default(Name) + end. + +%% not all options have default values +default(info_type) -> link; +default(load_average) -> true; +default(load_method) -> time; +default(load_scale) -> prog; +default(stay_resident) -> false; +default(timeout) -> 2000. + +ins_opts([Opt | Opts], Opts2) -> + ins_opts(Opts, ins_opt(Opt, Opts2)); +ins_opts([], Opts2) -> Opts2. + +ins_opt({Opt, Val}, [{Opt, _} | Os]) -> [{Opt, Val} | Os]; +ins_opt(Opt, [Opt2 | Os]) -> [Opt2 | ins_opt(Opt, Os)]; +ins_opt(Opt, []) -> [Opt]. diff --git a/lib/runtime_tools/src/dbg.erl b/lib/runtime_tools/src/dbg.erl index 385047ee73..f17aa528ed 100644 --- a/lib/runtime_tools/src/dbg.erl +++ b/lib/runtime_tools/src/dbg.erl @@ -1,24 +1,26 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. +%% Copyright Ericsson AB 1996-2016. All Rights Reserved. %% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at %% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. %% %% %CopyrightEnd% %% -module(dbg). -export([p/1,p/2,c/3,c/4,i/0,start/0,stop/0,stop_clear/0,tracer/0, tracer/2, tracer/3, get_tracer/0, get_tracer/1, tp/2, tp/3, tp/4, + tpe/2, ctpe/1, ctp/0, ctp/1, ctp/2, ctp/3, tpl/2, tpl/3, tpl/4, ctpl/0, ctpl/1, ctpl/2, ctpl/3, ctpg/0, ctpg/1, ctpg/2, ctpg/3, ltp/0, wtp/1, rtp/1, dtp/0, dtp/1, n/1, cn/1, ln/0, h/0, h/1]). @@ -127,7 +129,12 @@ tpl(Module, Pattern) when is_atom(Module) -> do_tp({Module, '_', '_'}, Pattern, [local]); tpl({_Module, _Function, _Arity} = X, Pattern) -> do_tp(X,Pattern,[local]). -do_tp({_Module, _Function, _Arity} = X, Pattern, Flags) + +tpe(Event, Pattern) when Event =:= send; + Event =:= 'receive' -> + do_tp(Event, Pattern, []). + +do_tp(X, Pattern, Flags) when is_integer(Pattern); is_atom(Pattern) -> case ets:lookup(get_pattern_table(), Pattern) of @@ -136,17 +143,16 @@ do_tp({_Module, _Function, _Arity} = X, Pattern, Flags) _ -> {error, unknown_pattern} end; -do_tp({Module, _Function, _Arity} = X, Pattern, Flags) when is_list(Pattern) -> +do_tp(X, Pattern, Flags) when is_list(Pattern) -> Nodes = req(get_nodes), - case Module of - '_' -> - ok; - M when is_atom(M) -> + case X of + {M,_,_} when is_atom(M) -> %% Try to load M on all nodes lists:foreach(fun(Node) -> rpc:call(Node, M, module_info, []) end, - Nodes) + Nodes); + _ -> ok end, case lint_tp(Pattern) of {ok,_} -> @@ -162,9 +168,9 @@ do_tp({Module, _Function, _Arity} = X, Pattern, Flags) when is_list(Pattern) -> end. %% All nodes are handled the same way - also the local node if it is traced -do_tp_on_nodes(Nodes, MFA, P, Flags) -> +do_tp_on_nodes(Nodes, X, P, Flags) -> lists:map(fun(Node) -> - case rpc:call(Node,erlang,trace_pattern,[MFA,P, Flags]) of + case rpc:call(Node,erlang,trace_pattern,[X,P, Flags]) of N when is_integer(N) -> {matched, Node, N}; Else -> @@ -209,13 +215,19 @@ ctpg(Module) when is_atom(Module) -> do_ctp({Module, '_', '_'}, [global]); ctpg({_Module, _Function, _Arity} = X) -> do_ctp(X,[global]). + do_ctp({Module, Function, Arity},[]) -> - do_ctp({Module, Function, Arity},[global]), + {ok,_} = do_ctp({Module, Function, Arity},[global]), do_ctp({Module, Function, Arity},[local]); do_ctp({_Module, _Function, _Arity}=MFA,Flags) -> Nodes = req(get_nodes), {ok,do_tp_on_nodes(Nodes,MFA,false,Flags)}. +ctpe(Event) when Event =:= send; + Event =:= 'receive' -> + Nodes = req(get_nodes), + {ok,do_tp_on_nodes(Nodes,Event,true,[])}. + %% %% ltp() -> ok %% List saved and built-in trace patterns. @@ -259,8 +271,7 @@ wtp(FileName) -> ok end, []), - file:close(File), - ok + ok = file:close(File) end. %% @@ -297,7 +308,12 @@ tracer(port, Port) when is_port(Port) -> start(fun() -> Port end); tracer(process, {Handler,HandlerData}) -> - start(fun() -> start_tracer_process(Handler, HandlerData) end). + start(fun() -> start_tracer_process(Handler, HandlerData) end); + +tracer(module, Fun) when is_function(Fun) -> + start(Fun); +tracer(module, {Module, State}) -> + start(fun() -> {Module, State} end). remote_tracer(port, Fun) when is_function(Fun) -> @@ -307,7 +323,13 @@ remote_tracer(port, Port) when is_port(Port) -> remote_start(fun() -> Port end); remote_tracer(process, {Handler,HandlerData}) -> - remote_start(fun() -> start_tracer_process(Handler, HandlerData) end). + remote_start(fun() -> start_tracer_process(Handler, HandlerData) end); + +remote_tracer(module, Fun) when is_function(Fun) -> + remote_start(Fun); +remote_tracer(module, {Module, State}) -> + remote_start(fun() -> {Module, State} end). + remote_start(StartTracer) -> case (catch StartTracer()) of @@ -405,7 +427,7 @@ trace_port(file, Filename) -> trace_port1(file, Filename, nowrap); trace_port(ip, Portno) when is_integer(Portno) -> - trace_port(ip,{Portno,50}); + trace_port(ip,{Portno,200}); trace_port(ip, {Portno, Qsiz}) when is_integer(Portno), is_integer(Qsiz) -> fun() -> @@ -431,10 +453,8 @@ trace_port1(file, Filename, Options) -> fun() -> Name = filename:absname(Filename), %% Absname is needed since the driver uses - %% the supplied name without further investigations, - %% and if the name is relative the resulting path - %% might be too long which can cause a bus error - %% on vxworks instead of a nice error code return. + %% the supplied name without further investigations. + %% Also, the absname must be found inside the fun, %% in case the actual node where the port shall be %% started is on another node (or even another host) @@ -544,17 +564,15 @@ c(M, F, A, Flags) -> {error,Reason} -> {error,Reason}; Flags1 -> tracer(), - {ok, Tracer} = get_tracer(), S = self(), - Pid = spawn(fun() -> c(S, M, F, A, [{tracer, Tracer} | Flags1]) end), + Pid = spawn(fun() -> c(S, M, F, A, [get_tracer_flag() | Flags1]) end), Mref = erlang:monitor(process, Pid), receive {'DOWN', Mref, _, _, Reason} -> stop_clear(), {error, Reason}; {Pid, Res} -> - erlang:demonitor(Mref), - receive {'DOWN', Mref, _, _, _} -> ok after 0 -> ok end, + erlang:demonitor(Mref, [flush]), %% 'sleep' prevents the tracer (recv_all_traces) from %% receiving garbage {'EXIT',...} when dbg i stopped. timer:sleep(1), @@ -581,7 +599,7 @@ stop() -> end. stop_clear() -> - ctp(), + {ok, _} = ctp(), stop(). %%% Calling the server. @@ -594,8 +612,7 @@ req(R) -> {'DOWN', Mref, _, _, _} -> % If server died exit(dbg_server_crash); {dbg, Reply} -> - erlang:demonitor(Mref), - receive {'DOWN', Mref, _, _, _} -> ok after 0 -> ok end, + erlang:demonitor(Mref, [flush]), Reply end. @@ -663,6 +680,9 @@ loop({C,T}=SurviveLinks, Table) -> reply(From, {error, Reason}); Tracer when is_pid(Tracer); is_port(Tracer) -> put(node(),{self(),Tracer}), + reply(From, {ok,self()}); + {Module, _State} = Tracer when is_atom(Module) -> + put(node(),{self(),Tracer}), reply(From, {ok,self()}) end; {_Relay,_Tracer} -> @@ -713,6 +733,9 @@ loop({C,T}=SurviveLinks, Table) -> {_LocalRelay,Tracer} when is_port(Tracer) -> reply(From, {error, cant_trace_remote_pid_to_local_port}), loop(SurviveLinks, Table); + {_LocalRelay,Tracer} when is_tuple(Tracer) -> + reply(From, {error, cant_trace_remote_pid_to_local_module}), + loop(SurviveLinks, Table); {_LocalRelay,Tracer} when is_pid(Tracer) -> case (catch relay(Node, Tracer)) of {ok,Relay} -> @@ -767,7 +790,8 @@ loop({C,T}=SurviveLinks, Table) -> end. reply(Pid, Reply) -> - Pid ! {dbg,Reply}. + Pid ! {dbg,Reply}, + ok. %%% A process-based tracer. @@ -782,50 +806,50 @@ tracer_init(Handler, HandlerData) -> tracer_loop(Handler, HandlerData). tracer_loop(Handler, Hdata) -> - receive - Msg -> - %% Don't match in receive to avoid giving EXIT message higher - %% priority than the trace messages. - case Msg of - {'EXIT',_Pid,_Reason} -> - ok; - Trace -> - NewData = recv_all_traces(Trace, Handler, Hdata), - tracer_loop(Handler, NewData) - end + {State, Suspended, Traces} = recv_all_traces(), + NewHdata = handle_traces(Suspended, Traces, Handler, Hdata), + case State of + done -> + exit(normal); + loop -> + tracer_loop(Handler, NewHdata) end. - -recv_all_traces(Trace, Handler, Hdata) -> - Suspended = suspend(Trace, []), - recv_all_traces(Suspended, Handler, Hdata, [Trace]). -recv_all_traces(Suspended0, Handler, Hdata, Traces) -> +recv_all_traces() -> + recv_all_traces([], [], infinity). + +recv_all_traces(Suspended0, Traces, Timeout) -> receive Trace when is_tuple(Trace), element(1, Trace) == trace -> Suspended = suspend(Trace, Suspended0), - recv_all_traces(Suspended, Handler, Hdata, [Trace|Traces]); + recv_all_traces(Suspended, [Trace|Traces], 0); Trace when is_tuple(Trace), element(1, Trace) == trace_ts -> Suspended = suspend(Trace, Suspended0), - recv_all_traces(Suspended, Handler, Hdata, [Trace|Traces]); + recv_all_traces(Suspended, [Trace|Traces], 0); Trace when is_tuple(Trace), element(1, Trace) == seq_trace -> Suspended = suspend(Trace, Suspended0), - recv_all_traces(Suspended, Handler, Hdata, [Trace|Traces]); + recv_all_traces(Suspended, [Trace|Traces], 0); Trace when is_tuple(Trace), element(1, Trace) == drop -> Suspended = suspend(Trace, Suspended0), - recv_all_traces(Suspended, Handler, Hdata, [Trace|Traces]); + recv_all_traces(Suspended, [Trace|Traces], 0); + {'EXIT', _Pid, _Reason} -> + {done, Suspended0, Traces}; Other -> %%% Is this really a good idea? io:format(user,"** tracer received garbage: ~p~n", [Other]), - recv_all_traces(Suspended0, Handler, Hdata, Traces) - after 0 -> - case catch invoke_handler(Traces, Handler, Hdata) of - {'EXIT',Reason} -> - resume(Suspended0), - exit({trace_handler_crashed,Reason}); - NewHdata -> - resume(Suspended0), - NewHdata - end + recv_all_traces(Suspended0, Traces, Timeout) + after Timeout -> + {loop, Suspended0, Traces} + end. + +handle_traces(Suspended, Traces, Handler, Hdata) -> + case catch invoke_handler(Traces, Handler, Hdata) of + {'EXIT',Reason} -> + resume(Suspended), + exit({trace_handler_crashed,Reason}); + NewHdata -> + resume(Suspended), + NewHdata end. invoke_handler([Tr|Traces], Handler, Hdata0) -> @@ -882,9 +906,9 @@ trac(Proc, How, Flags) -> end end. -trac(Node, {_Relay, Tracer}, AtomPid, How, Flags) -> +trac(Node, {_Replay, Tracer}, AtomPid, How, Flags) -> case rpc:call(Node, ?MODULE, erlang_trace, - [AtomPid, How, [{tracer, Tracer} | Flags]]) of + [AtomPid, How, [get_tracer_flag(Tracer) | Flags]]) of N when is_integer(N) -> {matched, Node, N}; {badrpc,Reason} -> @@ -920,9 +944,11 @@ do_relay(Parent,RelP) -> case RelP of {Type,Data} -> {ok,Tracer} = remote_tracer(Type,Data), - Parent ! {started,Tracer}; + Parent ! {started,Tracer}, + ok; Pid when is_pid(Pid) -> - Parent ! {started,self()} + Parent ! {started,self()}, + ok end, do_relay_1(RelP). @@ -1117,7 +1143,7 @@ transform_flags([sos|Tail],Acc) -> transform_flags(Tail,[set_on_spawn|Acc]); transform_flags([sol|Tail],Acc) -> transform_flags(Tail,[set_on_link|Acc]); transform_flags([sofs|Tail],Acc) -> transform_flags(Tail,[set_on_first_spawn|Acc]); transform_flags([sofl|Tail],Acc) -> transform_flags(Tail,[set_on_first_link|Acc]); -transform_flags([all|_],_Acc) -> all(); +transform_flags([all|_],_Acc) -> all()--[silent,running]; transform_flags([F|Tail]=List,Acc) when is_atom(F) -> case lists:member(F, all()) of true -> transform_flags(Tail,[F|Acc]); @@ -1126,9 +1152,10 @@ transform_flags([F|Tail]=List,Acc) when is_atom(F) -> transform_flags(Bad,_Acc) -> {error,{bad_flags,Bad}}. all() -> - [send,'receive',call,procs,garbage_collection,running, + [send,'receive',call,procs,ports,garbage_collection,running, set_on_spawn,set_on_first_spawn,set_on_link,set_on_first_link, - timestamp,arity,return_to]. + timestamp,monotonic_timestamp,strict_monotonic_timestamp, + arity,return_to,silent,running_procs,running_ports,exiting]. display_info([Node|Nodes]) -> io:format("~nNode ~w:~n",[Node]), @@ -1149,24 +1176,34 @@ display_info1([]) -> ok. get_info() -> - get_info(processes(),[]). + get_info(processes(),get_info(erlang:ports(),[])). +get_info([Port|T], Acc) when is_port(Port) -> + case pinfo(Port, name) of + undefined -> + get_info(T,Acc); + {name, Name} -> + get_info(T,get_tinfo(Port, Name, Acc)) + end; get_info([Pid|T],Acc) -> case pinfo(Pid, initial_call) of undefined -> get_info(T,Acc); {initial_call, Call} -> - case tinfo(Pid, flags) of - undefined -> - get_info(T,Acc); - {flags,[]} -> - get_info(T,Acc); - {flags,Flags} -> - get_info(T,[{Pid,Call,Flags}|Acc]) - end + get_info(T,get_tinfo(Pid, Call, Acc)) end; get_info([],Acc) -> Acc. +get_tinfo(P, Id, Acc) -> + case tinfo(P, flags) of + undefined -> + Acc; + {flags,[]} -> + Acc; + {flags,Flags} -> + [{P,Id,Flags}|Acc] + end. + format_trace([]) -> []; format_trace([Item]) -> [ts(Item)]; format_trace([Item|T]) -> [ts(Item) ," | ", format_trace(T)]. @@ -1191,9 +1228,22 @@ to_pidspec(X) when is_pid(X) -> true -> X; false -> {badpid,X} end; -to_pidspec(new) -> new; -to_pidspec(all) -> all; -to_pidspec(existing) -> existing; +to_pidspec(X) when is_port(X) -> + case erlang:port_info(X) of + undefined -> {badport, X}; + _ -> X + end; +to_pidspec(Tag) + when Tag =:= all; + Tag =:= ports; + Tag =:= processes; + Tag =:= new; + Tag =:= new_ports; + Tag =:= new_processes; + Tag =:= existing; + Tag =:= existing_ports; + Tag =:= existing_processes -> + Tag; to_pidspec(X) when is_atom(X) -> case whereis(X) of undefined -> {badpid,X}; @@ -1206,6 +1256,7 @@ to_pidspec(X) -> {badpid,X}. %% to_pid(X) when is_pid(X) -> X; +to_pid(X) when is_port(X) -> X; to_pid(X) when is_integer(X) -> to_pid({0,X,0}); to_pid({X,Y,Z}) -> to_pid(lists:concat(["<",integer_to_list(X),".", @@ -1220,9 +1271,12 @@ to_pid(X) when is_list(X) -> to_pid(X) -> {badpid,X}. +pinfo(P, X) when node(P) == node(), is_port(P) -> erlang:port_info(P, X); pinfo(P, X) when node(P) == node() -> erlang:process_info(P, X); +pinfo(P, X) when is_port(P) -> check(rpc:call(node(P), erlang, port_info, [P, X])); pinfo(P, X) -> check(rpc:call(node(P), erlang, process_info, [P, X])). + tinfo(P, X) when node(P) == node() -> erlang:trace_info(P, X); tinfo(P, X) -> check(rpc:call(node(P), erlang, trace_info, [P, X])). @@ -1259,6 +1313,9 @@ tc_loop(Other, _Handler, _HData) -> gen_reader(ip, {Host, Portno}) -> case gen_tcp:connect(Host, Portno, [{active, false}, binary]) of {ok, Sock} -> + %% Just in case this is on the traced node, + %% make sure the port is not traced. + p(Sock,clear), mk_reader(fun ip_read/2, Sock); Error -> exit(Error) @@ -1272,13 +1329,15 @@ gen_reader(follow_file, Filename) -> %% Opens a file and returns a reader (lazy list). gen_reader_file(ReadFun, Filename) -> - case file:open(Filename, [read, raw, binary]) of + case file:open(Filename, [read, raw, binary, read_ahead]) of {ok, File} -> mk_reader(ReadFun, File); Error -> exit({client_cannot_open, Error}) end. +-dialyzer({no_improper_lists, mk_reader/2}). + %% Creates and returns a reader (lazy list). mk_reader(ReadFun, Source) -> fun() -> @@ -1297,20 +1356,22 @@ mk_reader(ReadFun, Source) -> mk_reader_wrap([]) -> []; mk_reader_wrap([Hd | _] = WrapFiles) -> - case file:open(wrap_name(Hd), [read, raw, binary]) of + case file:open(wrap_name(Hd), [read, raw, binary, read_ahead]) of {ok, File} -> mk_reader_wrap(WrapFiles, File); Error -> exit({client_cannot_open, Error}) end. +-dialyzer({no_improper_lists, mk_reader_wrap/2}). + mk_reader_wrap([_Hd | Tail] = WrapFiles, File) -> fun() -> case read_term(fun file_read/2, File) of {ok, Term} -> [Term | mk_reader_wrap(WrapFiles, File)]; eof -> - file:close(File), + ok = file:close(File), case Tail of [_|_] -> mk_reader_wrap(Tail); @@ -1410,6 +1471,13 @@ get_tracer() -> req({get_tracer,node()}). get_tracer(Node) -> req({get_tracer,Node}). +get_tracer_flag() -> + {ok, Tracer} = get_tracer(), + get_tracer_flag(Tracer). +get_tracer_flag({Module,State}) -> + {tracer, Module, State}; +get_tracer_flag(Port = Pid) when is_port(Port); is_pid(Pid)-> + {tracer, Pid = Port}. save_pattern([]) -> 0; @@ -1790,12 +1858,12 @@ h(get_tracer) -> " - Returns the process or port to which all trace messages are sent."]); h(stop) -> help_display( - ["stop() -> stopped", + ["stop() -> ok", " - Stops the dbg server and the tracing of all processes.", " Does not clear any trace patterns."]); h(stop_clear) -> help_display( - ["stop_clear() -> stopped", + ["stop_clear() -> ok", " - Stops the dbg server and the tracing of all processes,", " and clears all trace patterns."]). diff --git a/lib/runtime_tools/src/dyntrace.erl b/lib/runtime_tools/src/dyntrace.erl index b4579fd5ce..58c5a773c3 100644 --- a/lib/runtime_tools/src/dyntrace.erl +++ b/lib/runtime_tools/src/dyntrace.erl @@ -41,6 +41,27 @@ pn/1, pn/2, pn/3, pn/4, pn/5, pn/6, pn/7, pn/8, pn/9]). -export([put_tag/1, get_tag/0, get_tag_data/0, spread_tag/1, restore_tag/1]). +-export([trace/5, + trace_procs/5, + trace_ports/5, + trace_running_procs/5, + trace_running_ports/5, + trace_call/5, + trace_send/5, + trace_receive/5, + trace_garbage_collection/5]). + +-export([enabled_procs/3, + enabled_ports/3, + enabled_running_procs/3, + enabled_running_ports/3, + enabled_call/3, + enabled_send/3, + enabled_receive/3, + enabled_garbage_collection/3, + enabled/3]). + + -export([user_trace_i4s4/9]). % Know what you're doing! -on_load(on_load/0). @@ -105,7 +126,7 @@ available() -> user_trace_s1(_Message) -> erlang:nif_error(nif_not_loaded). --spec user_trace_i4s4(iolist(), +-spec user_trace_i4s4(binary() | undefined, integer_maybe(), integer_maybe(), integer_maybe(), integer_maybe(), iolist_maybe(), iolist_maybe(), @@ -115,7 +136,7 @@ user_trace_s1(_Message) -> user_trace_i4s4(_, _, _, _, _, _, _, _, _) -> erlang:nif_error(nif_not_loaded). --spec user_trace_n(n_probe_label(), iolist(), +-spec user_trace_n(n_probe_label(), binary() | undefined, integer_maybe(), integer_maybe(), integer_maybe(), integer_maybe(), iolist_maybe(), iolist_maybe(), @@ -125,6 +146,60 @@ user_trace_i4s4(_, _, _, _, _, _, _, _, _) -> user_trace_n(_, _, _, _, _, _, _, _, _, _) -> erlang:nif_error(nif_not_loaded). +trace(_TraceTag, _TracerState, _Tracee, _TraceTerm, _Opts) -> + erlang:nif_error(nif_not_loaded). + +trace_procs(_TraceTag, _TracerState, _Tracee, _TraceTerm, _Opts) -> + erlang:nif_error(nif_not_loaded). + +trace_ports(_TraceTag, _TracerState, _Tracee, _TraceTerm, _Opts) -> + erlang:nif_error(nif_not_loaded). + +trace_running_procs(_TraceTag, _TracerState, _Tracee, _TraceTerm, _Opts) -> + erlang:nif_error(nif_not_loaded). + +trace_running_ports(_TraceTag, _TracerState, _Tracee, _TraceTerm, _Opts) -> + erlang:nif_error(nif_not_loaded). + +trace_call(_TraceTag, _TracerState, _Tracee, _TraceTerm, _Opts) -> + erlang:nif_error(nif_not_loaded). + +trace_send(_TraceTag, _TracerState, _Tracee, _TraceTerm, _Opts) -> + erlang:nif_error(nif_not_loaded). + +trace_receive(_TraceTag, _TracerState, _Tracee, _TraceTerm, _Opts) -> + erlang:nif_error(nif_not_loaded). + +trace_garbage_collection(_TraceTag, _TracerState, _Tracee, _TraceTerm, _Opts) -> + erlang:nif_error(nif_not_loaded). + +enabled(_TraceTag, _TracerState, _Tracee) -> + erlang:nif_error(nif_not_loaded). + +enabled_procs(_TraceTag, _TracerState, _Tracee) -> + erlang:nif_error(nif_not_loaded). + +enabled_ports(_TraceTag, _TracerState, _Tracee) -> + erlang:nif_error(nif_not_loaded). + +enabled_running_procs(_TraceTag, _TracerState, _Tracee) -> + erlang:nif_error(nif_not_loaded). + +enabled_running_ports(_TraceTag, _TracerState, _Tracee) -> + erlang:nif_error(nif_not_loaded). + +enabled_call(_TraceTag, _TracerState, _Tracee) -> + erlang:nif_error(nif_not_loaded). + +enabled_send(_TraceTag, _TracerState, _Tracee) -> + erlang:nif_error(nif_not_loaded). + +enabled_receive(_TraceTag, _TracerState, _Tracee) -> + erlang:nif_error(nif_not_loaded). + +enabled_garbage_collection(_TraceTag, _TracerState, _Tracee) -> + erlang:nif_error(nif_not_loaded). + %%% %%% Erlang support functions %%% diff --git a/lib/runtime_tools/src/erts_alloc_config.erl b/lib/runtime_tools/src/erts_alloc_config.erl index 284e88d4a7..514530332c 100644 --- a/lib/runtime_tools/src/erts_alloc_config.erl +++ b/lib/runtime_tools/src/erts_alloc_config.erl @@ -1,18 +1,19 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2011. All Rights Reserved. +%% Copyright Ericsson AB 2007-2016. All Rights Reserved. %% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. %% %% The Initial Developer of the Original Code is Ericsson AB. %% @@ -39,6 +40,8 @@ need_config_change, alloc_util, instances, + strategy, + acul, low_mbc_blocks_size, high_mbc_blocks_size, sbct, @@ -54,8 +57,6 @@ -define(SERVER, '__erts_alloc_config__'). --define(MAX_ALLOCATOR_INSTANCES, 16). - -define(KB, 1024). -define(MB, 1048576). @@ -99,23 +100,11 @@ {ets_alloc, 131072}, {fix_alloc, 131072}, {eheap_alloc, 524288}, - {ll_alloc, 2097152}, + {ll_alloc, 131072}, {sl_alloc, 131072}, {temp_alloc, 131072}, {driver_alloc, 131072}]). --define(MMMBC_DEFAULTS, - [{binary_alloc, 10}, - {std_alloc, 10}, - {ets_alloc, 10}, - {fix_alloc, 10}, - {eheap_alloc, 10}, - {ll_alloc, 0}, - {sl_alloc, 10}, - {temp_alloc, 10}, - {driver_alloc, 10}]). - - %%% %%% Exported interface %%% @@ -139,7 +128,7 @@ make_config(FileName) when is_list(FileName) -> case file:open(FileName, [write]) of {ok, IODev} -> Res = req({make_config, IODev}), - file:close(IODev), + ok = file:close(IODev), Res; Error -> Error @@ -211,9 +200,11 @@ server_loop(State) -> Conf = #conf{segments = ?MBC_MSEG_LIMIT, format_to = IODev}, Res = mk_config(Conf, State#state.alloc), - From ! {response, Ref, Res}; + From ! {response, Ref, Res}, + ok; _ -> - From ! {response, Ref, no_scenario_saved} + From ! {response, Ref, no_scenario_saved}, + ok end, State; {request, From, Ref, stop} -> @@ -230,20 +221,72 @@ server_loop(State) -> end, server_loop(NewState). -allocator_instances(temp_alloc) -> - erlang:system_info(schedulers) + 1; -allocator_instances(ll_alloc) -> +carrier_migration_support(aoff) -> + true; +carrier_migration_support(aoffcbf) -> + true; +carrier_migration_support(aoffcaobf) -> + true; +carrier_migration_support(_) -> + false. + +allocator_instances(ll_alloc, Strategy) -> + case carrier_migration_support(Strategy) of + true -> erlang:system_info(schedulers); + false -> 1 + end; +allocator_instances(_A, undefined) -> 1; -allocator_instances(_Allocator) -> - case erlang:system_info(schedulers) of - Schdlrs when Schdlrs =< ?MAX_ALLOCATOR_INSTANCES -> Schdlrs; - _Schdlrs -> ?MAX_ALLOCATOR_INSTANCES +allocator_instances(_A, _Strategy) -> + erlang:system_info(schedulers). + +strategy(temp_alloc, _AI) -> + af; +strategy(A, AI) -> + try + {A, OptList} = lists:keyfind(A, 1, AI), + {as, S} = lists:keyfind(as, 1, OptList), + S + catch + _ : _ -> + undefined end. - + +strategy_str(af) -> + "A fit"; +strategy_str(gf) -> + "Good fit"; +strategy_str(bf) -> + "Best fit"; +strategy_str(aobf) -> + "Address order best fit"; +strategy_str(aoff) -> + "Address order first fit"; +strategy_str(aoffcbf) -> + "Address order first fit carrier best fit"; +strategy_str(aoffcaobf) -> + "Address order first fit carrier adress order best fit". + +default_acul(A, S) -> + case carrier_migration_support(S) of + false -> + 0; + true -> + case A of + ll_alloc -> 85; + eheap_alloc -> 45; + _ -> 60 + end + end. + make_state() -> + {_, _, _, AI} = erlang:system_info(allocator), #state{alloc = lists:map(fun (A) -> + S = strategy(A, AI), #alloc{name = A, - instances = allocator_instances(A)} + strategy = S, + acul = default_acul(A, S), + instances = allocator_instances(A, S)} end, ?ALLOCATORS)}. @@ -345,7 +388,7 @@ do_save_scenario(AlcList) -> conf_size(Bytes) when is_integer(Bytes), Bytes < 0 -> exit({bad_value, Bytes}); conf_size(Bytes) when is_integer(Bytes), Bytes < 1*?MB -> - ?ROUNDUP(?B2KB(Bytes), 128); + ?ROUNDUP(?B2KB(Bytes), 256); conf_size(Bytes) when is_integer(Bytes), Bytes < 10*?MB -> ?ROUNDUP(?B2KB(Bytes), ?B2KB(1*?MB)); conf_size(Bytes) when is_integer(Bytes), Bytes < 100*?MB -> @@ -376,28 +419,25 @@ mmbcs(#conf{format_to = FTO}, temp_alloc -> BlocksSize; _ -> BlocksSize div Insts end, - case BS > default_mmbcs(A, Insts) of - true -> + DefMMBCS = default_mmbcs(A, Insts), + case {Insts, BS > DefMMBCS} of + {1, true} -> MMBCS = conf_size(BS), fc(FTO, "Main mbc size of ~p kilobytes.", [MMBCS]), format(FTO, " +M~cmmbcs ~p~n", [alloc_char(A), MMBCS]); - false -> + _ -> + MMBCS = ?B2KB(DefMMBCS), + fc(FTO, "Main mbc size of ~p kilobytes.", [MMBCS]), + format(FTO, " +M~cmmbcs ~p~n", [alloc_char(A), MMBCS]), ok end. -smbcs_lmbcs_mmmbc(#conf{format_to = FTO}, - #alloc{name = A, instances = Insts, segments = Segments}) -> - MMMBC = case {A, Insts} of - {_, 1} -> Segments#segment.number; - {temp_alloc, _} -> Segments#segment.number; - _ -> (Segments#segment.number div Insts) + 1 - end, +smbcs_lmbcs(#conf{format_to = FTO}, + #alloc{name = A, segments = Segments}) -> MBCS = Segments#segment.size, AC = alloc_char(A), fc(FTO, "Mseg mbc size of ~p kilobytes.", [MBCS]), format(FTO, " +M~csmbcs ~p +M~clmbcs ~p~n", [AC, MBCS, AC, MBCS]), - fc(FTO, "Max ~p mseg mbcs.", [MMMBC]), - format(FTO, " +M~cmmmbc ~p~n", [AC, MMMBC]), ok. alloc_char(binary_alloc) -> $B; @@ -462,6 +502,8 @@ au_conf_alloc(#conf{format_to = FTO} = Conf, #alloc{name = A, alloc_util = true, instances = Insts, + acul = Acul, + strategy = Strategy, low_mbc_blocks_size = Low, high_mbc_blocks_size = High} = Alc) -> fcp(FTO, "Usage of mbcs: ~p - ~p kilobytes", [?B2KB(Low), ?B2KB(High)]), @@ -470,31 +512,49 @@ au_conf_alloc(#conf{format_to = FTO} = Conf, fc(FTO, "One instance used."), format(FTO, " +M~ct false~n", [alloc_char(A)]); _ -> - fc(FTO, "~p instances used.", + fc(FTO, "~p + 1 instances used.", [Insts]), - format(FTO, " +M~ct true~n", [alloc_char(A)]) - end, + format(FTO, " +M~ct true~n", [alloc_char(A)]), + case Strategy of + undefined -> + ok; + _ -> + fc(FTO, "Allocation strategy: ~s.", + [strategy_str(Strategy)]), + format(FTO, " +M~cas ~s~n", [alloc_char(A), + atom_to_list(Strategy)]) + end, + case carrier_migration_support(Strategy) of + false -> + ok; + true -> + fc(FTO, "Abandon carrier utilization limit of ~p%.", [Acul]), + format(FTO, " +M~cacul ~p~n", [alloc_char(A), Acul]) + end + end, mmbcs(Conf, Alc), - smbcs_lmbcs_mmmbc(Conf, Alc), + smbcs_lmbcs(Conf, Alc), sbct(Conf, Alc). -large_growth(Low, High) -> - High - Low >= ?LARGE_GROWTH_ABS_LIMIT. - calc_seg_size(Growth, Segs) -> conf_size(round(Growth*?FRAG_FACT*?GROWTH_SEG_FACT) div Segs). calc_growth_segments(Conf, AlcList0) -> - CalcSmall = fun (#alloc{name = ll_alloc} = Alc, Acc) -> - {Alc#alloc{segments = #segment{size = 0, + CalcSmall = fun (#alloc{name = ll_alloc, instances = 1} = Alc, Acc) -> + {Alc#alloc{segments = #segment{size = conf_size(0), number = 0}}, Acc}; (#alloc{alloc_util = true, - low_mbc_blocks_size = Low, + instances = Insts, + low_mbc_blocks_size = LowMBC, high_mbc_blocks_size = High} = Alc, {SL, AL}) -> + Low = case Insts of + 1 -> LowMBC; + _ -> 0 + end, Growth = High - Low, - case large_growth(Low, High) of + case Growth >= ?LARGE_GROWTH_ABS_LIMIT of true -> {Alc, {SL, AL+1}}; false -> @@ -522,8 +582,13 @@ calc_growth_segments(Conf, AlcList0) -> end, CalcLarge = fun (#alloc{alloc_util = true, segments = undefined, - low_mbc_blocks_size = Low, + instances = Insts, + low_mbc_blocks_size = LowMBC, high_mbc_blocks_size = High} = Alc) -> + Low = case Insts of + 1 -> LowMBC; + _ -> 0 + end, Growth = High - Low, SegSize = calc_seg_size(Growth, SegsPerAlloc), @@ -560,15 +625,10 @@ format_header(FTO) -> case erlang:system_info(schedulers) of 1 -> ok; Schdlrs -> - MinSchdlrs = case Schdlrs > ?MAX_ALLOCATOR_INSTANCES of - true -> ?MAX_ALLOCATOR_INSTANCES; - false -> Schdlrs - end, fcp(FTO, "NOTE: This configuration was made for ~p schedulers. " - "It is very important that at least ~p schedulers " - "are used.", - [Schdlrs, MinSchdlrs]) + "It is very important that ~p schedulers are used.", + [Schdlrs, Schdlrs]) end, fcp(FTO, "This configuration is intended as a suggestion and " diff --git a/lib/runtime_tools/src/inviso_as_lib.erl b/lib/runtime_tools/src/inviso_as_lib.erl deleted file mode 100644 index 75f3d9d004..0000000000 --- a/lib/runtime_tools/src/inviso_as_lib.erl +++ /dev/null @@ -1,155 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2006-2009. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% - -%%% File : inviso_as_lib.erl -%%% Author : Lennart �hman <[email protected]> -%%% Description : -%% The purpose of the inviso autostart library is to provide useful functions -%% for anyone wanting to customize the autostart mechanism in the inviso -%% tracer. It is intended to work well with the example 'inviso_autostart_server'. -%%% -%%% Created : 15 Dec 2005 by Lennart �hman -%% ----------------------------------------------------------------------------- - --module(inviso_as_lib). - --export([setup_autostart/7,setup_autostart/8,setup_autostart/9, - inhibit_autostart/1, - set_repeat/2,set_repeat_2/2]). -%% ----------------------------------------------------------------------------- - -%% setup_autostart(Node,Repeat,Options,TracerData,CmdFiles,Bindings) = ok|{error,Reason}. -%% Repeat=integer(), where 0 means no (more) autostarts. -%% Options=List of options as taken by the runtime component at start-up. -%% TracerData= Tracerdata as given to inviso_rt:init_tracing. -%% CmdFiles=[FileName,...] list of string(), files that will be executed -%% by the subprocess started during autostart. -%% Bindings=[{VarName,Value},...] Variable bindings for CmdFiles. -%% VarName=atom(), -%% -%% This function creates the inviso_autostart.config file on Erlang node Node. -%% This is useful when you wish to prepare for an autostarted trace. -setup_autostart(Node,Repeat,Options,TracerData,CmdFiles,Bindings,Translations) -> - setup_autostart(Node,Repeat,Options,TracerData,CmdFiles, - Bindings,Translations,inviso_std_ref,off). -setup_autostart(Node,Repeat,Options,TracerData,CmdFiles,Bindings,Translations,RTtag) -> - setup_autostart(Node,Repeat,Options,TracerData,CmdFiles, - Bindings,Translations,RTtag,off). -setup_autostart(Node,Repeat,Options,TracerData,CmdFiles,Bindings,Translations,RTtag,Dbg) -> - case rpc:call(Node,inviso_autostart,which_config_file,[]) of - FileName when is_list(FileName) -> % Write to this file then. - {String,Args}=format_config_file(Repeat,TracerData,Options,CmdFiles, - Bindings,Translations,RTtag,Dbg), - Bytes=list_to_binary(io_lib:format(String,Args)), - case rpc:call(Node,file,write_file,[FileName,Bytes]) of - ok -> - ok; - {error,Reason} -> - {error,{write_file,Reason}}; - {badrpc,Reason} -> - {error,{badrpc,{write_file,Reason}}} - end; - {error,Reason} -> - {error,{which_config_file,Reason}}; - {badrpc,Reason} -> - {error,{badrpc,{which_config_file,Reason}}} - end. -%% ----------------------------------------------------------------------------- - -%% inhibit_autostart(Node) = ok|{error,Reason} -%% -%% Inhibits autostart by simply making the repeat parameter zero in the -%% configuration file at node Node. All other parameters are left untouched. -inhibit_autostart(Node) -> - set_repeat(Node,0). -%% ----------------------------------------------------------------------------- - -%% set_repeat(Node,N)=ok | {error,Reason} -%% N=integer(), the number of time autostart shall be allowed. -set_repeat(Node,N) -> - case examine_config_file(Node) of - {ok,FileName,Terms} -> - NewTerms=[{repeat,N}|lists:keydelete(repeat,1,Terms)], - case rpc:call(Node,?MODULE,set_repeat_2,[FileName,NewTerms]) of - {badrpc,Reason} -> - {error,{badrpc,{open,Reason}}}; - Result -> - Result - end; - {error,Reason} -> - {error,Reason} - end. - -%% Must be a sepparate function to do rpc on. The entire function must be done -%% in one rpc call. Otherwise the FD will die since it is linked to the opening -%% process. -set_repeat_2(FileName,NewTerms) -> - case file:open(FileName,[write]) of - {ok,FD} -> - String=lists:flatten(lists:map(fun(_)->"~w.~n" end,NewTerms)), - case catch io:format(FD,String,NewTerms) of - ok -> - file:close(FD), - ok; - {'EXIT',Reason} -> - file:close(FD), - {error,{format,Reason}} - end; - {error,Reason} -> - {error,Reason} - end. -%% ----------------------------------------------------------------------------- - -examine_config_file(Node) -> - case rpc:call(Node,inviso_autostart,which_config_file,[]) of - FileName when is_list(FileName) -> % Read this file, and then modify it. - case rpc:call(Node,file,consult,[FileName]) of - {ok,Terms} -> - {ok,FileName,Terms}; - {error,Reason} -> - {error,{consult,Reason}}; - {badrpc,Reason} -> - {error,{badrpc,{consult,Reason}}} - end; - {error,Reason} -> - {error,{which_config_file,Reason}}; - {badrpc,Reason} -> - {error,{badrpc,{which_config_file,Reason}}} - end. -%% ----------------------------------------------------------------------------- - -format_config_file(Repeat,TracerData,Options,CmdFiles,Bindings,Translations,RTtag,Dbg) -> - String="~w.~n~w.~n~w.~n~w.~n", - Args=[{repeat,Repeat}, - {mfa,{inviso_autostart_server,init,[[{tracerdata,TracerData}, - {cmdfiles,CmdFiles}, - {bindings,Bindings}, - {translations,Translations}, - {debug,Dbg}]]}}, - {options,Options}, - {tag,RTtag}], - {String,Args}. -%% ----------------------------------------------------------------------------- - - - - - - - diff --git a/lib/runtime_tools/src/inviso_autostart.erl b/lib/runtime_tools/src/inviso_autostart.erl deleted file mode 100644 index 787292e244..0000000000 --- a/lib/runtime_tools/src/inviso_autostart.erl +++ /dev/null @@ -1,201 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2006-2010. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% -%% Author: Lennart �hman, [email protected] --module(inviso_autostart). - --export([autostart/1,which_config_file/0]). - -%% This module implements the default autostart module for the inviso runtime -%% component. -%% It will: -%% (1) Open the autostart configuration file (either the default or the one -%% pointed out by the runtime_tools application parameter inviso_autostart_config). -%% (2) Check that the incarnation counter has not reached 0. If so, we do not -%% allow (yet) one autostart. -%% (3) Rewrite the configuration file if there was an incarnation counter. -%% (With the counter decreased). -%% (4) Inspect the content of the configuration file and pass paramters in the -%% return value (which is interpreted by the runtime component). -%% -%% CONTENT OF A CONFIGURATION FILE: -%% A plain text file containing erlang tuple terms, each ended with a period(.). -%% The following parameters are recognized: -%% {repeat,N} N=interger(), -%% The number of remaining allowed autostart incarnations of inviso. -%% {options,Options} Options=list() -%% The options which controls the runtime component, such as overload and -%% dependency. -%% {mfa,{Mod,Func,Args}} Args=list() -%% Controls how a spy process initiating tracing, patterns and flags shall -%% be started. -%% {tag,Tag} -%% The tag identifying the runtime component to control components. -%% ============================================================================= - -%% This function is run in the runtime component's context during autostart -%% to determine whether to continue and if, then how. -autostart(_AutoModArgs) -> - ConfigFile= - case application:get_env(inviso_autostart_conf) of - {ok,FileName} when is_list(FileName) -> % Use this filename then. - FileName; - {ok,{load,FileNames,{M,F}}} -> % First load the module, then... - case try_load_module(FileNames) of - ok -> - autostart_apply(M,F); - - false -> % No such module available - "inviso_autostart.config" - end; - {ok,{M,F}} -> % Use M:F(node()) - autostart_apply(M,F); - {ok,no_autostart} -> - false; - _ -> % Use a default name, in CWD! - "inviso_autostart.config" - end, - if - is_list(ConfigFile) -> - case file:consult(ConfigFile) of - {ok,Terms} -> % There is a configuration. - case handle_repeat(ConfigFile,Terms) of - ok -> % Handled or not, we shall continue. - {get_mfa(Terms),get_options(Terms),get_tag(Terms)}; - stop -> % We are out of allowed starts. - true % Then no autostart. - end; - {error,_} -> % There is no config file - true % Then no autostart! - end; - true -> % Skip it then. - true - end. - -autostart_apply(M,F) -> - case catch M:F(node()) of - FileName when is_list(FileName) -> - FileName; - no_autostart -> % No autostart after all. - false; - _ -> - "inviso_autostart.config" - end. - -%% This function is necessary since it is not always the case that all code-paths -%% are set at the time of an autostart. -try_load_module([AbsFileName|Rest]) when is_list(AbsFileName) -> - case catch code:load_abs(AbsFileName) of % May not be a proper filename. - {module,_Mod} -> - try_load_module(Rest); - _ -> - false - end; -try_load_module([]) -> % Load all beam files successfully. - ok; -try_load_module(AbsFileName) when is_list(AbsFileName) -> - try_load_module([AbsFileName]). -%% ----------------------------------------------------------------------------- - -%% Function returning the filename probably used as autostart config file. -%% Note that this function must be executed at the node in question. -which_config_file() -> - case application:get_env(runtime_tools,inviso_autostart_conf) of - {ok,FileName} when is_list(FileName) -> % Use this filename then. - FileName; - {ok,{M,F}} -> % Use M:F(node()) - case catch M:F(node()) of - FileName when is_list(FileName) -> - FileName; - _ -> - {ok,CWD}=file:get_cwd(), - filename:join(CWD,"inviso_autostart.config") - end; - _ -> % Use a default name, in CWD! - {ok,CWD}=file:get_cwd(), - filename:join(CWD,"inviso_autostart.config") - end. -%% ----------------------------------------------------------------------------- - - -%% Help function which finds out if there is a limit on the number of times -%% we shall autostart. If there is a repeat parameter and it is greater than -%% zero, the file must be rewritten with the parameter decreased with one. -%% Returns 'ok' or 'stop'. -handle_repeat(FileName,Terms) -> - case lists:keysearch(repeat,1,Terms) of - {value,{_,N}} when N>0 -> % Controlls how many time more. - handle_repeat_rewritefile(FileName,Terms,N-1), - ok; % Indicate that we shall continue. - {value,_} -> % No we have reached the limit. - stop; - false -> % There is no repeat parameter. - ok % No restrictions then! - end. - -%% Help function which writes the configuration file again, but with the -%% repeat parameter set to NewN. -%% Returns nothing significant. -handle_repeat_rewritefile(FileName,Term,NewN) -> - case file:open(FileName,[write]) of - {ok,FD} -> - NewTerm=lists:keyreplace(repeat,1,Term,{repeat,NewN}), - handle_repeat_rewritefile_2(FD,NewTerm), - file:close(FD); - {error,_Reason} -> % Not much we can do then?! - error - end. - -handle_repeat_rewritefile_2(FD,[Tuple|Rest]) -> - io:format(FD,"~w.~n",[Tuple]), - handle_repeat_rewritefile_2(FD,Rest); -handle_repeat_rewritefile_2(_,[]) -> - true. -%% ----------------------------------------------------------------------------- - -%% Three help functions finding the parameters possible to give to the runtime -%% component. Note that some of them have default values, should the parameter -%% not exist. -get_mfa(Terms) -> - case lists:keysearch(mfa,1,Terms) of - {value,{_,MFA}} -> - MFA; - false -> - false - end. - -get_options(Terms) -> - case lists:keysearch(options,1,Terms) of - {value,{_,Options}} -> - Options; - false -> - [] - end. - -get_tag(Terms) -> - case lists:keysearch(tag,1,Terms) of - {value,{_,Tag}} -> - Tag; - false -> - default_tag - end. -%% ----------------------------------------------------------------------------- - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - diff --git a/lib/runtime_tools/src/inviso_autostart_server.erl b/lib/runtime_tools/src/inviso_autostart_server.erl deleted file mode 100644 index 1e352822f4..0000000000 --- a/lib/runtime_tools/src/inviso_autostart_server.erl +++ /dev/null @@ -1,311 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2006-2010. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% -%% Author: Lennart �hman, [email protected] -%% --module(inviso_autostart_server). --export([init/1]). - -%% ----------------------------------------------------------------------------- -%% Internal exports -%% ----------------------------------------------------------------------------- --export([cmd_file_interpreter_init/4]). -%% ----------------------------------------------------------------------------- - - -%% This module provides a (well working) example of how to program an -%% autostart server responsible for initializing trace, setting patterns -%% and flags. -%% -%% The general idea is that this code spawns interpreter processes in order to -%% execute commands concurrently. Each of the interpreter processes opens one or -%% several files (in sequence) containing erlang function calls which are evaluated -%% in the interpreter process context. -%% The argument provided to init shall be a list of options controlling -%% how to initialize tracing, which file(s) to open and variable bindings. -%% -%% This autostart_server interpreters understands standard inviso trace case files. -%% -%% The runtime component provides an API very similar to the API provided -%% by the control component. It is therefore easy to translate inviso calls to -%% inviso_rt calls. -%% -%% This process may be killed by the inviso_rt process if stop_tracing is called. -%% The reason is that there is no time limit to the interpreter processes. Hence -%% they should be killed if tracing is not possible anylonger. -%% ============================================================================= - - -%% ----------------------------------------------------------------------------- - -%% The independent autostart process spawned by the runtime component to carry -%% out initializations is spawened on this function (if using the example -%% autostart which comes with inviso). -%% ArgsFromConfig is as can be heard from the name comming from a paramater in -%% the autostart configuration file. Here it is supposed to be: -%% ArgsFromConfig=[ServerParam,...] -%% ServerParam={tracerdata,TracerData}|{cmdfiles,Files}|{bindings,Bindings}| -%% {translations,Translations}|{debug,DbgLevel} -%% TracerData=tracerdata given to inviso_rt:init_tracing/1 function. -%% Files=[FileNameSpecs,...] where each FileNameSpecs will be executed in -%% a separate process. Making each FileNameSpec parallel. -%% FileNameSpecs=[FileNameSpec,...] -%% FileNameSpec=FileName | {FileName,Bindings} -%% Bindings=[{Var,Value},...] variable environment understood by -%% erl_eval:exprs/2. -%% Translations=[Translation,...] -%% A translation file is a text-file with following tuples -%% Translation={{Mod,Func,Arity,{Mod2,Func2,ParamMF}}}| -%% {{Func,Arity,{Mod2,Func2,ParamMF}}} -%% ParamMF={M,F} | any() -%% Translates Mod:Func/Arity to Mod2:Func2 with the arguments to -%% Mod:Func translated using M:F/1. Note that ParamMF is not -%% necessarily an MF. If no translation shall be done, ParamMF -%% shall be anything else but an MF. -%% Also note that Mod is optional in a Translation. That means that -%% function calls without a module in the trace case file will -%% be translated according to that translation. -init(ArgsFromConfig) -> - case get_tracerdata_opts(ArgsFromConfig) of - {ok,TracerData} -> % Otherwise we can not start a trace! - case inviso_rt:init_tracing(TracerData) of - {ok,_Response} -> % Ok, tracing has been initiated. - case get_cmdfiles_opts(ArgsFromConfig) of - {ok,CmdFiles} -> % List of cmd-files. - Bindings=get_initialbindings_opts(ArgsFromConfig), - Translations=get_translations_opts(ArgsFromConfig), - Dbg=get_dbg_opts(ArgsFromConfig), - Procs=start_cmd_file_interpreters(CmdFiles, - Bindings, - Translations, - Dbg), - loop(Procs,Dbg); % Wait for procs to be done. - false -> % Then we can terminate normally. - true - end; - {error,Reason} -> % This is fault, lets terminate abnormally. - exit({inviso,{error,Reason}}) - end; - false -> % Then there is not much use then. - true % Just terminate normally. - end. -%% ----------------------------------------------------------------------------- - -%% Help function which starts a process for each item found in the FileNames -%% list. The idea is that each item will be processed concurrently. The items -%% them selves may be a sequence of filenames. -%% Returns a list of spawned interpret processes. -start_cmd_file_interpreters([FileNames|Rest],Bindings,Translations,Dbg) -> - P=spawn_link(?MODULE,cmd_file_interpreter_init,[FileNames,Bindings,Translations,Dbg]), - MRef=erlang:monitor(process,P), % Can't trap exits in this process. - [{P,MRef}|start_cmd_file_interpreters(Rest,Bindings,Translations,Dbg)]; -start_cmd_file_interpreters([],_,_,_) -> - []. -%% ----------------------------------------------------------------------------- - - -%% The loop where this process simply waits for all of the interpreters to be -%% done. Note that that may take som time. An interpreter may take as long time -%% necessary to do its task. -loop(Procs,Dbg) -> - receive - {'DOWN',MRef,process,Pid,_Reason} -> - case lists:keysearch(MRef,1,Procs) of - {value,{Pid,_}} -> % It was an interpreter that terminated. - case lists:keydelete(MRef,1,Procs) of - [] -> % No more interpreters. - true; % Then terminate. - NewProcs -> - loop(NewProcs,Dbg) - end; - false -> - loop(Procs,Dbg) - end; - _ -> - loop(Procs,Dbg) - end. - - -%% ----------------------------------------------------------------------------- -%% The interpret process. -%% -%% An interpreter process executes trace case files. Several interpreter processes -%% may be running in parallel. It is not within the scoop of this implementation -%% of an autostart server to solve conflicts. (You may implement your own autostart -%% server!). -%% An interpret process may run for as long as necessary. Hence the function called -%% within the trace case file can contain wait functions, waiting for a certain -%% system state to occure before continuing. -%% Note that this process also mixes global and local bindings. GlobalBindings -%% is a binding() structure, where LocalBindings is a list of {Var,Value}. -%% Further it is possible to let FileName be a {inviso,Func,Args} tuple instead. -%% ----------------------------------------------------------------------------- - -%% Init function for an interpreter process instance. -cmd_file_interpreter_init(FileNames,GlobalBindings,Translations,Dbg) -> - interpret_cmd_files(FileNames,GlobalBindings,Translations,Dbg). - -interpret_cmd_files([{FileName,LocalBindings}|Rest],GlobalBindings,Translations,Dbg) -> - Bindings=join_local_and_global_vars(LocalBindings,GlobalBindings), - interpret_cmd_files_1(FileName,Bindings,Translations,Dbg), - interpret_cmd_files(Rest,GlobalBindings,Translations,Dbg); -interpret_cmd_files([],_,_,_) -> % Done, return nothing significant! - true; -interpret_cmd_files(FileName,GlobalBindings,Translations,Dbg) -> - interpret_cmd_files_1(FileName,GlobalBindings,Translations,Dbg). -% interpret_cmd_files(Rest,GlobalBindings,Translations,Dbg). - -%% This is "inline" inviso calls. -interpret_cmd_files_1({inviso,F,Args},Bindings,Translations,Dbg) -> - {ok,Tokens1,_}=erl_scan:string("inviso:"++atom_to_list(F)++"("), - Tokens2=tokenize_args(Args), - {ok,Tokens3,_}=erl_scan:string(")."), - case erl_parse:parse_exprs(Tokens1++Tokens2++Tokens3) of - {ok,Exprs} -> - interpret_cmd_files_3(Bindings,Exprs,Translations,Dbg); - {error,_Reason} -> - error - end; -interpret_cmd_files_1({Mod,Func,Args},_Bindings,_Translations,_Dbg) -> - catch apply(Mod,Func,Args); -%% This is the case when it actually is a trace case file. -interpret_cmd_files_1(FileName,Bindings,Translations,Dbg) -> - case file:open(FileName,[read]) of - {ok,FD} -> - interpret_cmd_files_2(FD,Bindings,io:parse_erl_exprs(FD,""),Translations,Dbg), - file:close(FD); - {error,Reason} -> % Something wrong with the file. - inviso_rt_lib:debug(Dbg,interpret_cmd_files,[FileName,{error,Reason}]) - end. - -%% Help function which handles Exprs returned from io:parse_erl_exprs and -%% tries to eval them. It is the side-effects we are interested in, like -%% setting flags and patterns. Note that we will get a failure should there -%% be a variable conflict. -%% Also note that there is logic to translate control component API calls to -%% corresponding runtime component calls. -%% Returns nothing significant. -interpret_cmd_files_2(FD,Bindings,{ok,Exprs,_},Translations,Dbg) -> - {next,NewBindings}=interpret_cmd_files_3(Bindings,Exprs,Translations,Dbg), - interpret_cmd_files_2(FD,NewBindings,io:parse_erl_exprs(FD,""),Translations,Dbg); -interpret_cmd_files_2(FD,Bindings,{error,ErrorInfo,Line},Translations,Dbg) -> - inviso_rt_lib:debug(Dbg,parse_erl_exprs,[ErrorInfo,Line]), - interpret_cmd_files_2(FD,Bindings,io:parse_erl_exprs(FD,""),Translations,Dbg); -interpret_cmd_files_2(_,_,{eof,_},_,_) -> % End of file. - true. - -interpret_cmd_files_3(Bindings,Exprs,Translations,Dbg) -> - case catch inviso_rt_lib:transform(Exprs,Translations) of - NewExprs when is_list(NewExprs) -> % We may have translated the API. - case catch erl_eval:exprs(NewExprs,Bindings) of - {'EXIT',Reason} -> - inviso_rt_lib:debug(Dbg,exprs,[Exprs,Bindings,{'EXIT',Reason}]), - {next,Bindings}; - {value,_Val,NewBindings} -> % Only interested in the side effects! - {next,NewBindings} - end; - {'EXIT',Reason} -> - inviso_rt_lib:debug(Dbg,translate2runtime_funcs,[Exprs,Reason]), - {next,Bindings} - end. - -%% Help function adding variables to a bindings structure. If the variable already -%% is assigned in the structure, it will be overridden. Returns a new -%% bindings structure. -join_local_and_global_vars([{Var,Val}|Rest],Bindings) when is_atom(Var) -> - join_local_and_global_vars(Rest,erl_eval:add_binding(Var,Val,Bindings)); -join_local_and_global_vars([_|Rest],Bindings) -> - join_local_and_global_vars(Rest,Bindings); -join_local_and_global_vars([],Bindings) -> - Bindings. - -%% Help function returning a string of tokens, including "," separation -%% between the arguments. -tokenize_args(Args=[Arg|Rest]) when length(Args)>1 -> - AbsTerm=erl_parse:abstract(Arg), - Tokens=erl_parse:tokens(AbsTerm), - {ok,Token,_}=erl_scan:string(","), - Tokens++Token++tokenize_args(Rest); -tokenize_args([Arg]) -> - AbsTerm=erl_parse:abstract(Arg), - erl_parse:tokens(AbsTerm); -tokenize_args([]) -> - "". -%% ----------------------------------------------------------------------------- - - -%% ----------------------------------------------------------------------------- -%% Help functions working on the options given as argument to init during spawn. -%% ----------------------------------------------------------------------------- - -get_tracerdata_opts(ArgsFromConfig) -> - case lists:keysearch(tracerdata,1,ArgsFromConfig) of - {value,{_,{mfa,{M,F,CompleteTDGargs}}}} -> % Dynamic tracerdata. - case catch apply(M,F,CompleteTDGargs) of - {'EXIT',_Reason} -> - false; - TracerData -> - {ok,TracerData} - end; - {value,{_,TracerData}} -> % Interpret this as static tracerdata. - {ok,TracerData}; - false -> - false - end. -%% ----------------------------------------------------------------------------- - -get_cmdfiles_opts(ArgsFromConfig) -> - case lists:keysearch(cmdfiles,1,ArgsFromConfig) of - {value,{_,CmdFiles}} -> - {ok,CmdFiles}; - false -> - false - end. -%% ----------------------------------------------------------------------------- - -get_initialbindings_opts(ArgsFromConfig) -> - case lists:keysearch(bindings,1,ArgsFromConfig) of - {value,{_,Bindings}} -> - Bindings; - false -> % Then we use empty bindings. - erl_eval:new_bindings() - end. -%% ----------------------------------------------------------------------------- - -get_translations_opts(ArgsFromConfig) -> - case lists:keysearch(translations,1,ArgsFromConfig) of - {value,{_,Translations}} -> - Translations; - false -> % This becomes nearly point less. - [] - end. -%% ----------------------------------------------------------------------------- - -get_dbg_opts(ArgsFromConfig) -> - case lists:keysearch(debug,1,ArgsFromConfig) of - {value,{_,DbgLevel}} -> - DbgLevel; - false -> - off - end. -%% ----------------------------------------------------------------------------- - -%% EOF - - - diff --git a/lib/runtime_tools/src/inviso_rt.erl b/lib/runtime_tools/src/inviso_rt.erl deleted file mode 100644 index b162f5b045..0000000000 --- a/lib/runtime_tools/src/inviso_rt.erl +++ /dev/null @@ -1,2885 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2005-2011. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% -%% Description: -%% The runtime component of the trace tool Inviso. -%% -%% Authors: -%% Ann-Marie L�f, [email protected] -%% Lennart �hman, [email protected] -%% ----------------------------------------------------------------------------- - --module(inviso_rt). - - -%% ----------------------------------------------------------------------------- -%% interface for supervisor -%% ----------------------------------------------------------------------------- --export([start_link_man/3,start_link_auto/1]). - -%% API for controll component. --export([start/4,stop/1, - init_tracing/2,stop_tracing_parallel/1, - try_to_adopt/3,confirm_connection/2,get_node_info/1, - suspend/2,call_suspend/2,cancel_suspension/1,change_options/2, - clear/2,clear_all_tp/1, - flush/1, - trace_patterns_parallel/3, - trace_flags_parallel/3,trace_flags_parallel/2,trace_flags_parallel/1, - meta_tracer_call_parallel/2, - get_status/1,get_tracerdata/1,list_logs/1,list_logs/2,fetch_log/2,fetch_log/3, - delete_log/1,delete_log/2, - state/1]). -%% ----------------------------------------------------------------------------- - -%% API mostly for autostart scripts, instead of corresponding control component -%% apis not available doing local function calls. --export([init_tracing/1,tp/4,tp/5,tp/1,tpg/4,tpg/5,tpg/1, - tpl/4,tpl/5,tpl/1, - ctp/1,ctp/3,ctpg/1,ctpg/3,ctpl/1,ctpl/3, - init_tpm/4,init_tpm/7, - tpm/4,tpm/5,tpm/8,tpm_tracer/4,tpm_tracer/5,tpm_tracer/8, - tpm_ms/5,tpm_ms_tracer/5, - ctpm_ms/4, - local_register/0,global_register/0, - ctpm/3,remove_local_register/0,remove_global_register/0, - tf/2,tf/1,ctf/2,ctf/1]). -%% ----------------------------------------------------------------------------- - -%% Internal exports. --export([init/4,auto_init/2,fetch_init/4]). -%% ----------------------------------------------------------------------------- - -%% ----------------------------------------------------------------------------- -%% Constants. -%% ----------------------------------------------------------------------------- - --define(DEFAULT_OVERLOAD_FUNC,default_overload_func). --define(NO_LOADCHECK,no_loadcheck). - --define(RT_SUP,runtime_tools_sup). % Refers to the registered name. --define(CTRL,inviso_c). % Refers to the registered name. -%% ----------------------------------------------------------------------------- - -%% ----------------------------------------------------------------------------- -%% Record definition. -%% ----------------------------------------------------------------------------- - -%% #rt -%% All record fields must be bound to listed values when leaving init or -%% auto_init. -%% dependency: Timeout accepting being without control component. -%% overload : Controlls which module to call, if any, when time for a check. -%% timer_ref: Used when timing delayed shutdown due to lost control component. --record(rt,{state = new, % new | idle | tracing - status = running, % running | {suspended, Reason} - next_loadcheck = now(), % now | "No Loadcheck" - parent, % pid() - tracerdata, % undefined|{fun(),term()}|{file,Param}|{ip,Param} - tracer_port, % port() | undefined - handler, % {fun(), term()} | undefined - auto_starter, % pid() | undefined; proc starting interpreters. - meta_tracer, % undefined | pid() - fetchers=[], % [pid(),...] processes transfering logfiles. -% spies = [], - dependency={infinity,node()}, % {TOut,Node} | TOut; TOut=int()|infinity - overload=no_loadcheck, % ?NO_LOADCHECK|{LoadMF,Interval,InitMFA,RemoveMFA} - overload_data=void, % Datastructure given to LoadMF and RemoveMFA. - timer_ref, % undefined | reference() - ctrl, % undefined | pid() - ctrl_ref, % undefined | reference() - vsn, % list() - tag % term() - }). -%% ----------------------------------------------------------------------------- - - -%% ============================================================================== -%% Start API -%% ============================================================================== - -%% Note that the runtime component may be started in many different ways. -%% It can be autostarted by the runtime_tools_sup during initial start-up of the -%% system. It is actually most likely that it will be started that way. However -%% if there are no autostart trace-cases to run, the inviso_rt runtime component -%% will terminate. It will then however remain as a child of the runtime_tools_sup -%% supervisor. This means that if the runtime component is started again, manually, -%% by the control component, some actions must be taken. -%% For instance is it very likely that the child already exists. But since it -%% must be started with different arguments when started manually, the child-spec -%% must be changed. -%% -%% The runtime component is not a proper gen_server, to allow full control of -%% what happens. It however mimcs gen_server behaviour to be managed by the -%% runtime_tools_sup supervisor. - - -%% start_link_auto(AutoModArgs)={ok,Pid} -%% -%% This function is entered into the child-spec when planning on doing autostart -%% of the runtime component. The autostart is controlled by the so called -%% inviso_autostart_mod. It is an application environment parameter of the -%% runtime_tools application. If it exists, it shall point out a module name. -%% If it does not exist, the default 'inviso_autostart' module will be tried. -%% Note that these start_link functions do not implement proper otp-behaviour. -%% For instance they return {ok,Pid} immediately making the init-phase of the -%% runtime component process empty. -%% -%% The inviso_autostart_mod shall export one function: -%% autostart(AutoModArgs) -> {MFA,Options,Tag}, where -%% AutoModArgs=term(), comes from the application start parameters in the -%% runtime_tools application resource file. -%% MFA={Mod,Func,Args} | term(). -%% If it is MFA it will cause a trace initiator process to start spawning -%% on spawn_link(Mod,Func,Args). The trace initiator may for instance -%% initiate the wanted tracing. -start_link_auto(AutoModArgs) -> - {ok,spawn_link(?MODULE,auto_init,[AutoModArgs,self()])}. -%% ------------------------------------------------------------------------------ - -%% This function is entered into the child-specification of the runtime_tools_sup -%% if the runtime component shall be started manually via the control component. -start_link_man(Ctrl,Options,Tag) -> - {ok,spawn_link(?MODULE,init,[Ctrl,Options,Tag,self()])}. -%% ------------------------------------------------------------------------------ - -%% start(Node,Options,Tag,Condition)=tbd -%% Node=The node where the runtime component shall be started. -%% Options=[Opt]; List of options to the runtime component. -%% Opt={dependency,Val}|{dependency,{Val,Node}} -%% Val=int()|infinity -%% If the runtime component may run on its own or not. Val=0 means a runtime -%% component which will terminate immediately without its control component. -%% Note that if the runtime component is started manually, the Node part -%% is never used. The runtime is supposed to be dependent of the Ctrl mentioned -%% in the start_link_man parameters. -%% Opt={overload,OverLoad} | overload -%% The latter means no loadcheck. Necessary if changing the options. -%% Overload=Iterval (int() in milliseconds) | -%% {LoadMF,Interval}|{LoadMF,Interval,InitMFA,RemoveMFA} -%% LoadMF={Mod,Func}|function() -%% InitMFA,RemoveMFA={Mod,Func,ArgList} where -%% apply(InitM,InitF,InitArgs) -> {ok,DataStruct}|'void'. -%% apply(RemoveM,RemoveF,[DataStruct|Args]) -> don't care -%% LoadMF is called each time loadcheck is performed. -%% Mod:Func(DataStruct)->ok|{suspend,Reason} -%% If just Interval is used, it means using a default overload check. -%% Tag=term(), used to identify an incarnation of a runtime component so that -%% a control component reconnecting will know if it was its own incarnation -%% still alive, or some elses. -%% Condition='if_ref'|term(). Controls if we want to adopt the runtime component. -%% If 'if_ref' is stated it means that we only want to adopt a runtime component -%% with the suggested Tag. -%% -%% This is the API used by the control component when tries to start a runtime -%% component. Note that it will try to adopt an already running, if possible. -%% Adoptions are only possible if the runtime component at hand is running -%% without control component. -start(Node, Options, Tag, Condition) when Node == node() -> - ChildSpec = {?MODULE, {?MODULE, start_link_man, [self(), Options, Tag]}, - temporary, 5000, worker, [?MODULE]}, - case catch supervisor:start_child(?RT_SUP, ChildSpec) of - {ok, Pid} when is_pid(Pid) -> - {node_info, _Node, Pid, VSN, State, Status, _Tag} = - get_node_info(Pid), - {node_info, Node, Pid, VSN, State, Status, new}; - {error, already_present} -> - supervisor:delete_child(?RT_SUP, ?MODULE), - start(Node, Options, Tag, Condition); - {error, {already_started, Pid}} -> - try_to_adopt(Pid, Tag, Condition); - {error,Reason} -> - {error,Reason}; - {'EXIT',Reason} -> - {error,Reason} - end; -start(Node, Options, Tag, Condition) -> - case rt_version(Node) of - {error,Error} -> - {error,Error}; - _VSN -> - ChildSpec = {?MODULE, {?MODULE, start_link_man, - [self(), Options, Tag]}, - temporary, 5000, worker, [?MODULE]}, - case catch rpc:call(Node, supervisor, start_child, - [?RT_SUP, ChildSpec]) of - {ok, Pid} when is_pid(Pid) -> - {node_info, _Node, Pid, - VSN, State, Status, _Tag} = get_node_info(Pid), - {node_info, Node, Pid, VSN, State, Status, new}; - {error, already_present} -> - rpc:call(Node, supervisor, delete_child, - [?RT_SUP, ?MODULE]), - start(Node, Options, Tag, Condition); - {error, {already_started, Pid}} -> - try_to_adopt(Pid, Tag, Condition); - {error,Reason} -> % Could not start child. - {error,Reason}; - {badrpc,nodedown} -> - {error,nodedown}; - {badrpc,Reason} -> - {error,{badrpc,Reason}}; - {'EXIT',Reason} -> - {error,Reason} - end - end. - -rt_version(Node) -> - case catch rpc:call(Node,application,loaded_applications,[]) of - List when is_list(List) -> - case lists:keysearch(runtime_tools,1,List) of - {value,{_,_,VSN}} -> - VSN; - false -> - {error,not_loaded} - end; - {badrpc,nodedown} -> - {error,nodedown}; - {'EXIT',Reason} -> - {error,Reason} - end. -%% ------------------------------------------------------------------------------ - -%% stop(Node)=ok|{error,Reason} -%% Stops the runtim component on node Node. Note that this is mearly calling the -%% supervisor API to shutdown the inviso_rt child belonging to the runtime_tools_sup. -stop(Node) when Node==node() -> - supervisor:terminate_child(?RT_SUP,?MODULE), - supervisor:delete_child(?RT_SUP,?MODULE), - ok; -stop(Node) -> - case catch rpc:call(Node,supervisor,terminate_child,[?RT_SUP,?MODULE]) of - ok -> - stop_delete_child(Node); - {error,_} -> % No child running. - stop_delete_child(Node); % Make sure we remove it also. - {badrpc,Reason} -> - {error,{badrpc,Reason}}; - {'EXIT',Reason} -> - {error,Reason} - end. - -stop_delete_child(Node) -> - case catch rpc:call(Node,supervisor,delete_child,[?RT_SUP,?MODULE]) of - ok -> - ok; - {error,_} -> % No child running. - ok; - {badrpc,Reason} -> - {error,{badrpc,Reason}}; - {'EXIT',Reason} -> - {error,Reason} - end. -%% ------------------------------------------------------------------------------ - - -%% ============================================================================== -%% API for the control component. -%% ============================================================================== - -%% init_tracing(TracerData) -> -%% TracerData = LogTD | [{trace,LogTD},{ti,TiTD}] -%% LogTD = {HandlerFun, Data} | collector | -%% {relayer, pid()} | {ip, IPPortParameters} | -%% {file, FilePortParameters} -%% TiTD = {file,FileName} | {file,FileName,{InitPublLD,RemovePublLD,CleanPublLD}} -%% | {relay,Node} | {relay,Node,{InitPublLD,RemovePublLD,CleanPublLD}} -%% HandlerFun=fun(TraceMsg,Data)->NewData -%% IPPortParameters = Portno | {Portno, Qsiz} -%% Qsiz = -%% FilePortParameters = {Filename, wrap, Tail, {time, WrapTime}, WrapCnt} | -%% {FileName, wrap, Tail, WrapSize, WrapCnt} | -%% {FileName, wrap, Tail, WrapSize} | -%% {FileName, wrap, Tail} | FileName -%% Defines a tracer: -%% {HandlerFun, Data} - will be used as handler inside the runtime component for -%% every incomming trace message. -%% relayer - the runtime component will relay all comming trace messages to -%% the runtime component Pid. -%% collector - the runtime component is used as tracer or collector of relayed -%% trace messages using the default handler writing them to io. -%% ip | file - will start a tracer port using PortParameters -init_tracing(Pid,TracerData) -> - call(Pid,{init_tracing,TracerData}). -%% ------------------------------------------------------------------------------ - -%% stop_tracing(RTpids)=[{Node,NodeResult},...] -%% RTpids=[RTinfo,...] -%% RTinfo={RTpid,Node} | {{error,Reason},Node} -%% NodeResult={ok,State} | {error,Reason} -%% Sends a request to stop tracing to all nodes in RTpids, in parallel. Stop -%% tracing means that all trace flags are removed and the nodes go to idle -%% state. -stop_tracing_parallel(RTpids) -> - call_parallel(lists:map(fun({Pid,Node})->{Pid,Node,stop_tracing}; - (Error)->Error - end, - RTpids)). -%% ------------------------------------------------------------------------------ - -%% try_to_adopt(Pid,NewTag,Condition)= -%% {node_info,node(),self(),VSN,State,Status,{tag,PreviousTag}}|{error,Reason} -%% NewTag=term(), the identification tag we want the runtime component to use -%% from now on if adoption was successful. -%% Condition='if_ref', only adopt if current tag is NewTag. -%% PreviousTag= the tag the runtime component had before it accepted the -%% adoption. -%% This function shall only be used by a control component wishing to adopt this -%% runtime component. -try_to_adopt(Pid, Tag, Condition) -> - call(Pid,{try_to_adopt,Tag,Condition}). -%% ------------------------------------------------------------------------------ - -%% confirm_connection(Pid,Tag)= {node_info,node(),self(),VSN,State,Status,Tag}| -%% {error,refused}. -%% Must only be used by a control component having been contacted by the runtime -%% component Pid. It confirms to the runtime component that the control component -%% has accepted the connect request. -confirm_connection(Pid,Tag) -> - call(Pid,{confirm_connection,Tag}). -%% ------------------------------------------------------------------------------ - -%% get_node_info(Pid)={node_info,Node,Pid,VSN,State,Status,Tag}. -get_node_info(Pid) -> - call(Pid,get_node_info). -%% ------------------------------------------------------------------------------ - -%% suspend(NodeOrPid,Reason)=ok -%% call_suspend(NodeOrPid,Reason)=ok -%% Makes the runtime component and all of its helpers suspend. suspend/2 is -%% assynchronous. -suspend(NodeOrPid,Reason) -> - cast(NodeOrPid,{suspend,Reason}). - -call_suspend(NodeOrPid,Reason) -> - call(NodeOrPid,{suspend,Reason}). -%% ------------------------------------------------------------------------------ - -%% cancel_suspension(Pid)=ok -%% Function moving the runtime component to status running. Regardless of its -%% current status. -cancel_suspension(Pid) -> - call(Pid,cancel_suspension). -%% ------------------------------------------------------------------------------ - -%% change_options(Pid,Options)=ok -%% Options=list(); see the start_link_XXX functions. -%% Changes options according to Options list. -%% Changing the control component we shall be depending on has no effect. The -%% dependency value in self can however be changed, and takes effect immediately. -change_options(Pid,Options) -> - call(Pid,{change_options,Options}). -%% ------------------------------------------------------------------------------ - -%% clear_all_tp(Pid)=ok -%% Function removing all, both local and global trace-patterns from the node. -clear_all_tp(Pid) -> - call(Pid,clear_all_tp). -%% ------------------------------------------------------------------------------ - -%% clear(Pid,Options)={ok,{new,Status}} -%% Options=[Opt,...] -%% Opt=keep_trace_patterns | keep_log_files -%% Resets the runtime component to state 'new' by stopping all ongoing tracing, -%% closing and removing all associated logfiles. The Options can be used to -%% prevent the runtime component from being totally erased. -clear(Pid,Options) -> - call(Pid,{clear,Options}). -%% ------------------------------------------------------------------------------ - -%% flush(Pid)=ok | {error,Reason} -%% Sends the flush command to the trace-port, if we are using a trace-port and -%% are tracing. -flush(Pid) -> - call(Pid,flush). -%% ------------------------------------------------------------------------------ - -%% trace_patterns_parallel(RTpids,Args,Flags)=[{Node,Answer},...] -%% RTpids=[{RTpid,Node},...] or [{Error,Node},...] -%% Args=[Arg,...] -%% Arg={Mod,Func,Arity,MS}|{Mod,Func,Arity,MS,Opts} -%% Mod=atom()|reg_exp()|{Dir,reg_exp()} -%% Dir=reg_exp() -%% Answer=[Answer,...] -%% Answer=int()|{error,Reason} -%% API function for the control component sending trace-patterns to a list of -%% runtime components. Returns a [{Node,Answer},...] list in the same order. -trace_patterns_parallel(RTpids,Args,Flags) -> % Same args and flags for all. - call_parallel(lists:map(fun({Pid,Node})when is_pid(Pid)->{Pid,Node,{tp,Args,Flags}}; - (Error)-> Error - end, - RTpids)). -%% ------------------------------------------------------------------------------ - -%% trace_flags_parallel(RTpids,Args,How)= -%% trace_flags_parallel(RTpidsArgs,How)= -%% trace_flags_parallel(RTpidsArgsHow)=[{Node,Reply},...] -%% RTpids=[RTpidEntry,...] -%% RTpidEntry={RTpid,Node}|{Error,Node} -%% Error=term(), any term you wish to have as reply in Answer assoc. to Node. -%% Args=[{Process,Flags},...] -%% Process=pid()|registeredname()|'all'|'new'|'existing' -%% Flags=List of the allowed process trace flags. -%% RTpidsArgs=[RTpidArgEntry,...] -%% RTpidArgEntry={RTpid,Node,Args}|{Error,Node} -%% RTpidsArgsHow=[RTpidArgsHowEntry,...] -%% RTpidArgsHowEntry={RTpid,Node,Args,How}|{Error,Node} -%% How=true|false -%% Reply={ok,Answers} -%% Answers=[Answer,...], one for each Args and in the same order. -%% Answer=int()|{error,Reason} -%% API function used by the control component to send flags to a list of runtime -%% components. Returns a list of [{Node,Answer},... ] in the same order. -trace_flags_parallel(RTpids,Args,How) -> % Same args for every node! - call_parallel(lists:map(fun({Pid,Node})when is_pid(Pid)->{Pid,Node,{tf,Args,How}}; - (Error)-> Error - end, - RTpids)). - -trace_flags_parallel(RTpidArgs,How) -> % Different args but same how. - call_parallel(lists:map(fun({Pid,Node,Args})when is_pid(Pid)-> - {Pid,Node,{tf,Args,How}}; - (Error)-> - Error - end, - RTpidArgs)). - -trace_flags_parallel(RTpidArgsHow) -> % Both different args and hows. - call_parallel(lists:map(fun({Pid,Node,Args,How})when is_pid(Pid)-> - {Pid,Node,{tf,Args,How}}; - (Error)-> - Error - end, - RTpidArgsHow)). -%% ------------------------------------------------------------------------------ - -%% meta_pattern(RTpids,Args)=[{Node,Answer},...] -%% RTpids=[{RTpid,Node},...] or [{Error,Node},...] -%% Args={FunctionName,ArgList} -%% FunctionName=atom() -%% ArgList=list(), list of the arguments to FunctionName. -%% Answer=[Answer,...] -%% Answer=int()|{error,Reason} -%% Makes a call to the meta-tracer through its runtime component. Returns a list -%% a answers in the same order as RTpids. Note that if "someone" has discovered -%% that there is an error with a particular node, the error answer can be placed -%% in the RTpids list from the start. -meta_tracer_call_parallel(RTpids,Args) -> % Same args for all nodes. - call_parallel(lists:map(fun({Pid,Node})when is_pid(Pid)-> - {Pid,Node,{meta_tracer_call,Args}}; - (Error)-> - Error - end, - RTpids)). -%% ------------------------------------------------------------------------------ - -%% get_status(Pid)={ok,{State,Status}} -%% State=new|tracing|idle -%% Status=running|{suspended,Reason} -get_status(Pid) -> - call(Pid,get_status). -%% ------------------------------------------------------------------------------ - -%% get_tracerdata(Pid)={ok,TracerData} | {ok,no_tracerdata} | {error,Reason} -%% TracerData=see init_tracing -%% Fetches the current tracerdata from the runtime component. -get_tracerdata(Pid) -> - call(Pid,get_tracerdata). -%% ------------------------------------------------------------------------------ - -%% list_log(Pid)={ok,no_log}|{ok,LogCollection}|{error,Reason} -%% list_log(Pid,TracerData)= -%% LogCollection=[LogTypes,...] -%% LogTypes={trace_log,Dir,Files}|{ti_log,Dir,Files} -%% Dir=string() -%% Files=[FileNameWithoutDir,...] -%% Lists all files associated with the current tracerdata. Or finds out which -%% files there are stored in this node given a tracerdata. -list_logs(Pid) -> - call(Pid,list_logs). -list_logs(Pid,TD) -> - call(Pid,{list_logs,TD}). -%% ------------------------------------------------------------------------------ - -%% fetch_log(Pid,CollectPid)={ok,FetcherPid}|{complete,no_log}|{error,Reason} -%% fetch_log(Pid,CollectPid,Spec)= -%% CollectPid=pid(), the process which will be given the transfered logs. -%% Spec=TracerData|LogCollection -%% Transferes a number of files using ditributed Erlang to CollectPid. This -%% function is supposed to be used internally by a control component. It returns -%% when the transfer is initiated and does not mean it is done or successful. -fetch_log(Pid,CollectPid) -> - call(Pid,{fetch_log,CollectPid}). -fetch_log(Pid,CollectPid,Spec) -> - call(Pid,{fetch_log,CollectPid,Spec}). -%% ------------------------------------------------------------------------------ - -%% delete_log(Pid,TracerDataOrLogList)={ok,Results}|{error,Reason} -%% TracerDataOrLogList=[FileNameWithPath,...]|LogCollection|TracerData -%% Results=[LogType,...] -%% LogType={trace_log,FileSpecs}|{ti_log,FilesSpecs} -%% FilesSpecs=[FileSpec,...] -%% FileSpec={ok,FileName}|{error,{Posix,FileName}} -%% Filename=string(), the filename without dir-path. -delete_log(Pid) -> - call(Pid,delete_logs). -delete_log(Pid,TracerDataOrLogList) -> - call(Pid,{delete_logs,TracerDataOrLogList}). -%% ------------------------------------------------------------------------------ - -%% state(NodeOrPid)=LoopData -%% Returns the loopdata of the runtime component. Only meant for debugging. -state(NodeOrPid) -> - call(NodeOrPid,state). -%% ------------------------------------------------------------------------------ - - -%% ============================================================================== -%% API for local calls made from the same node. E.g autostart. -%% ============================================================================== - -%% init_tracing(TracerData)= -%% See init_tracing/2. -init_tracing(TracerData) -> - call_regname(?MODULE,{init_tracing,TracerData}). -%% ------------------------------------------------------------------------------ - - -%% Meaning that these function does most often not have to be called by a -%% control component because there are more efficient ones above. - -%% tp(Module,Function,Arity,MatchSpec) -> -%% tp(Module,Function,Arity,MatchSpec,Opts) -> -%% tp(PatternList) -> -%% Module = '_'|atom()|ModRegExp|{DirRegExp,ModRegExp} -%% Function == atom() | '_' -%% Arity = integer() | '_' -%% MatchSpec = true | false | [] | matchspec() see ERTS User's guide for a -%% description of match specifications. -%% Opts=list(); 'only_loaded' -%% PatternList = [Pattern], -%% Pattern = {Module,Function,Arity,MatchSpec,Opts}, -%% Set trace pattern (global). -tp(Module,Function,Arity,MatchSpec) -> - tp(Module,Function,Arity,MatchSpec,[]). -tp(Module,Function,Arity,MatchSpec,Opts) -> - call_regname(?MODULE,{tp,[{Module,Function,Arity,MatchSpec,Opts}],[global]}). -tp(PatternList) -> - call_regname(?MODULE,{tp,PatternList,[global]}). -%% ------------------------------------------------------------------------------ - -tpg(Mod,Func,Arity,MatchSpec) -> - tp(Mod,Func,Arity,MatchSpec). -tpg(Mod,Func,Arity,MatchSpec,Opts) -> - tp(Mod,Func,Arity,MatchSpec,Opts). -tpg(PatternList) -> - tp(PatternList). -%% ------------------------------------------------------------------------------ - -%% tpl(Module,Function,Arity,MatchSpec) -> -%% tpl(Module,Function,Arity,MatchSpec,Opts) -> -%% tpl(PatternList) -> -%% Module = Function == atom() | '_' | RegExpMod | {RegExpDir,RegExpMod} -%% Arity = integer() | '_' -%% MatchSpec = true | false | [] | matchspec() see ERTS User's guide for a -%% Opts=list(); 'only_loaded' -%% description of match specifications. -%% PatternList = [Pattern], -%% Pattern = {Module, Function, Arity, MatchSpec}, -%% Set trace pattern (local). -tpl(Module,Function,Arity,MatchSpec) -> - call_regname(?MODULE,{tp,[{Module,Function,Arity,MatchSpec,[]}],[local]}). -tpl(Module,Function,Arity,MatchSpec,Opts) -> - call_regname(?MODULE,{tp,[{Module,Function,Arity,MatchSpec,Opts}],[local]}). -tpl(PatternList) -> - call_regname(?MODULE,{tp,PatternList,[local]}). -%% ------------------------------------------------------------------------------ - -%% ctp(Module,Function,Arity) -> -%% ctp(PatternList)= -%% Module = atom()|'_'|RegExpMod|{RegExpDir,RegExpMod} -%% Function == atom() | '_' -%% Arity = integer() | '_' -%% PatternList=[{Mod,Func,Arity},...] -%% Clear trace pattern (global). -%% Note that it is possible to clear patterns using regexps. But we can for -%% natural reasons only clear patterns for loaded modules. Further more there -%% seems to be a fault in the emulator (<=R10B) crashing if we remove patterns -%% for deleted modules. Therefore we use the only_loaded option. -ctp(Module,Function,Arity) -> - call_regname(?MODULE,{tp,[{Module,Function,Arity,false,[only_loaded]}],[global]}). -ctp(PatternList) -> - call_regname(?MODULE, - {tp, - lists:map(fun({M,F,A})->{M,F,A,false,[only_loaded]} end,PatternList), - [global]}). -%% ------------------------------------------------------------------------------ - -ctpg(Mod,Func,Arity) -> - ctp(Mod,Func,Arity). -ctpg(PatternList) -> - ctp(PatternList). -%% ------------------------------------------------------------------------------ - -%% ctpl(Module,Function,Arity) -> -%% Module = atom()|'_'|RegExpMod|{RegExpDir,RegExpMod} -%% Function == atom() | '_' -%% Arity = integer() | '_' -%% PatternList=[{Mod,Func,Arity},...] -%% Clear trace pattern (local). -ctpl(Module,Function,Arity) -> - call_regname(?MODULE,{tp,[{Module,Function,Arity,false,[only_loaded]}],[local]}). -ctpl(PatternList) -> - call_regname(?MODULE, - {tp, - lists:map(fun({M,F,A})->{M,F,A,false,[only_loaded]} end,PatternList), - [local]}). -%% ------------------------------------------------------------------------------ - -init_tpm(Mod,Func,Arity,CallFunc) -> - call_regname(?MODULE,{meta_tracer_call,{init_tpm,[Mod,Func,Arity,CallFunc]}}). - -init_tpm(Mod,Func,Arity,InitFunc,CallFunc,ReturnFunc,RemoveFunc) -> - call_regname(?MODULE, - {meta_tracer_call, - {init_tpm, - [Mod,Func,Arity,InitFunc,CallFunc,ReturnFunc,RemoveFunc]}}). -%% ------------------------------------------------------------------------------ - -tpm(Mod,Func,Arity,MS) -> - call_regname(?MODULE,{meta_tracer_call,{tpm,[Mod,Func,Arity,MS]}}). -tpm(Mod,Func,Arity,MS,CallFunc) -> - call_regname(?MODULE,{meta_tracer_call,{tpm,[Mod,Func,Arity,MS,CallFunc]}}). -tpm(Mod,Func,Arity,MS,InitFunc,CallFunc,ReturnFunc,RemoveFunc) -> - call_regname(?MODULE, - {meta_tracer_call, - {tpm, - [Mod,Func,Arity,MS,InitFunc,CallFunc,ReturnFunc,RemoveFunc]}}). -%% ------------------------------------------------------------------------------ - -tpm_tracer(Mod,Func,Arity,MS) -> - call_regname(?MODULE,{meta_tracer_call,{tpm_tracer,[Mod,Func,Arity,MS]}}). -tpm_tracer(Mod,Func,Arity,MS,CallFunc) -> - call_regname(?MODULE,{meta_tracer_call,{tpm_tracer,[Mod,Func,Arity,MS,CallFunc]}}). -tpm_tracer(Mod,Func,Arity,MS,InitFunc,CallFunc,ReturnFunc,RemoveFunc) -> - call_regname(?MODULE, - {meta_tracer_call, - {tpm_tracer, - [Mod,Func,Arity,MS,InitFunc,CallFunc,ReturnFunc,RemoveFunc]}}). -%% ------------------------------------------------------------------------------ - -tpm_ms(Mod,Func,Arity,MSname,MS) -> - call_regname(?MODULE,{meta_tracer_call,{tpm_ms,[Mod,Func,Arity,MSname,MS]}}). -%% ------------------------------------------------------------------------------ - -tpm_ms_tracer(Mod,Func,Arity,MSname,MS) -> - call_regname(?MODULE,{meta_tracer_call,{tpm_ms_tracer,[Mod,Func,Arity,MSname,MS]}}). -%% ------------------------------------------------------------------------------ - -ctpm_ms(Mod,Func,Arity,MSname) -> - call_regname(?MODULE,{meta_tracer_call,{ctpm_ms,[Mod,Func,Arity,MSname]}}). -%% ------------------------------------------------------------------------------ - -local_register() -> - call_regname(?MODULE,{meta_tracer_call,{local_register,[]}}). -%% ------------------------------------------------------------------------------ - -global_register() -> - call_regname(?MODULE,{meta_tracer_call,{global_register,[]}}). -%% ------------------------------------------------------------------------------ - -ctpm(Mod,Func,Arity) -> - call_regname(?MODULE,{meta_tracer_call,{ctpm,[Mod,Func,Arity]}}). -%% ------------------------------------------------------------------------------ - -remove_local_register() -> - call_regname(?MODULE,{meta_tracer_call,{remove_local_register,[]}}). -%% ------------------------------------------------------------------------------ - -remove_global_register() -> - call_regname(?MODULE,{meta_tracer_call,{remove_global_register,[]}}). -%% ------------------------------------------------------------------------------ - -%% tf(PidSpec, FlagList) -> -%% tf(TraceConfList) -> -%% TraceConfList = [{PidSpec, FlagList}], -%% FlagList = [Flags], -%% PidSpec = all | new | existing | pid() | registeredname() -%% Flags = all | send | 'receive' | procs | call | silent | return_to | -%% running | garbage_collection | timestamp | cpu_timestamp | arity | -%% set_on_spawn | set_on_first_spawn | set_on_link | set_on_first_link -%% Set trace flags. -tf(PidSpec, FlagList) -> - call_regname(?MODULE,{tf,[{PidSpec,FlagList}],true}). - -tf(TraceConfList) -> - call_regname(?MODULE,{tf,TraceConfList,true}). -%% ------------------------------------------------------------------------------ - -%% ctf(PidSpec, FlagList) -> -%% ctf(TraceConfList) -> -%% TraceConfList = [{PidSpec, FlagList}], -%% FlagList = [Flags], -%% PidSpec = all | new | existing | pid() | registeredname() -%% Flags = all | send | 'receive' | procs | call | silent | return_to | -%% running | garbage_collection | timestamp | cpu_timestamp | arity | -%% set_on_spawn | set_on_first_spawn | set_on_link | set_on_first_link -%% Clear trace flags. -ctf(PidSpec, FlagList) -> - call_regname(?MODULE,{tf,[{PidSpec,FlagList}],false}). - -ctf(TraceConfList) -> - call_regname(?MODULE,{tf_as,TraceConfList,false}). -%% ------------------------------------------------------------------------------ - - -%% ------------------------------------------------------------------------------ -%% Client side functions. -%% ------------------------------------------------------------------------------ - -%% Call function managing the client to server communication. This function may -%% be run by a client on a different node. -%% Note that we must use two different functions for calling a named process and -%% calling the runtime component at a specified node. -call(Pid,Request) when is_pid(Pid) -> - call_2(Pid,Request); -call(Node,Request) when Node==node() -> % To our node! - call_2(?MODULE,Request); -call(Node,Request) when is_atom(Node) -> - call_2({?MODULE,Node},Request); -call(To,_Request) -> - {error,{badarg,To}}. - -call_regname(Name,Request) when is_atom(Name) -> % To a registered name. - call_2(Name,Request). - -call_2(To,Request) -> - MRef=erlang:monitor(process,To), % Use a monitor to avoid waiting for ever. - Ref=make_ref(), - case catch To ! {Request,self(),Ref} of % Can be a remote pid. - {'EXIT',_} -> % If we use registered name. - erlang:demonitor(MRef), % Maybe not necessary!? - receive - {'DOWN',MRef,_Type,_Obj,_Info} -> - true - after - 0 -> - true - end, - {error,not_started}; - _ -> % At least no obvious error. - receive - {Msg,Ref} -> - erlang:demonitor(MRef), - Msg; - {'DOWN',MRef,_Type,_Obj,Info} -> % The runtime component disapeared. - {error,{no_response,Info}} - end - end. -%% ----------------------------------------------------------------------------- - -%% Multicall function taking a list of [{Pid,Node,Request},...] and sends -%% a request to every Pid. This function then also allows you to send multiple -%% requests to the same Pid since it will sit and wait for all replies. -%% Note that RTspec may also be an [{{error,Reason},Node},...]. That tuple will -%% then be used as reply in the reply list. -%% Returns [{Node,Reply},...] for every element in RTspec, in the same order. -call_parallel(RTspec) -> - Ref=make_ref(), - {Nr,Pending}=call_parallel_2(RTspec,Ref,0,[]), - Replies=call_parallel_3(Ref,Pending,Nr,[],[]), - call_parallel_build_reply(RTspec,1,Replies). - -call_parallel_2([{Pid,Node,Request}|Rest],Ref,Nr,Pending) when is_pid(Pid) -> - Pid ! {Request,self(),{Ref,Nr+1}}, - MRef=erlang:monitor(process,Pid), % So we won't wait for ever for it. - call_parallel_2(Rest,Ref,Nr+1,[{Nr+1,Node,MRef}|Pending]); -call_parallel_2([{{error,_Reason},_Node}|Rest],Ref,Nr,Pending) -> - call_parallel_2(Rest,Ref,Nr,Pending); % Just skip it. This is no process. -call_parallel_2([_Faulty|Rest],Ref,Nr,Pending) -> % Should not happend. - call_parallel_2(Rest,Ref,Nr,Pending); % But we choose to skip it instead of crash. -call_parallel_2([],_,Nr,Pending) -> - {Nr,Pending}. - -%% Help function collecting reply-messages sent from the runtime components. We -%% count down until we got a reply for every pending request. Or if we get a DOWN -%% message indicating that the runtime component is no longer present. Note that -%% we can by accident read away DOWN messages not belonging to this procedure. -%% They are collected to be reissued after we are done. -call_parallel_3(_Ref,_Pending,0,Replies,DownMsgs) -> % All expected received. - lists:foreach(fun({MRef,Pid,Info}) -> self() ! {'DOWN',MRef,process,Pid,Info} end, - DownMsgs), % Reissue the down messages! - Replies; -call_parallel_3(Ref,Pending,NrOfPending,Replies,DownMsgs) -> - receive - {Reply,{Ref,Nr}} -> - case lists:keysearch(Nr,1,Pending) of - {value,{_Nr,Node,MRef}} -> - erlang:demonitor(MRef), - call_parallel_3(Ref,Pending,NrOfPending-1, - [{Nr,Node,Reply}|Replies],DownMsgs); - false -> % Really strange! - call_parallel_3(Ref,Pending,NrOfPending,Replies,DownMsgs) - end; - {'DOWN',MRef,process,Pid,Info} -> % Probably process we monitor terminated. - case lists:keysearch(MRef,3,Pending) of - {value,{Nr,Node,_}} -> % Yes it was one of our processes. - call_parallel_3(Ref,Pending,NrOfPending-1, - [{Nr,Node,{error,no_reponse}}|Replies],DownMsgs); - false -> % We picked up a DOWN msg by misstake. - call_parallel_3(Ref,Pending,NrOfPending,Replies, - [{MRef,Pid,Info}|DownMsgs]) - end - end. - -%% Help function which build up the [{Node,Reply},...] list in the same order as RTspec. -call_parallel_build_reply([],_,_) -> - []; -call_parallel_build_reply([{Pid,Node,_Request}|Rest],Nr,Replies) when is_pid(Pid) -> - {value,{_Nr,_Node,Reply}}=lists:keysearch(Nr,1,Replies), - [{Node,Reply}|call_parallel_build_reply(Rest,Nr+1,Replies)]; -call_parallel_build_reply([{{error,Reason},Node}|Rest],Nr,Replies) -> - [{Node,{error,Reason}}|call_parallel_build_reply(Rest,Nr,Replies)]; -call_parallel_build_reply([_Faulty|Rest],Nr,Replies) -> - call_parallel_build_reply(Rest,Nr,Replies). -%% ------------------------------------------------------------------------------ - -cast(Pid,Request) when is_pid(Pid) -> - cast2(Pid,Request); -cast(Node,Request) when Node==node() -> - catch cast2(?MODULE,Request), - ok; -cast(Node,Request) when is_atom(Node) -> - catch cast2({?MODULE,Node},Request), - ok; -cast(BadAddress,_Request) -> - {error,{badarg,BadAddress}}. - -cast2(To,Request) -> - To ! {Request,void,void}. % Mimics the call protocol. -%% ------------------------------------------------------------------------------ - - -%% ============================================================================== -%% Implementation of the runtime component (server side). -%% ============================================================================== - -%% Since the runtime component is not implemented using gen_sever we are "free" -%% to use what ever functionnames we like. - -%% Initial function on which the runtime component is spawned on if started by -%% a controlcomponent. -init(Ctrl, Options, Tag, Parent) when is_list(Options) -> - %% started from controller - process_flag(trap_exit,true), - register(?MODULE,self()), % Will crash if rt is already running - do_clear_trace_patterns(), % Remove potential old patterns left. - LD1=read_option_list(Options, - #rt{state=new, - parent=Parent, - ctrl=Ctrl, - vsn=get_application_vsn(), - tag=Tag}), - OverloadData=initialize_overload(LD1), - CtrlRef=erlang:monitor(process,Ctrl), % Monitor our control component. - loop1(LD1#rt{ctrl_ref=CtrlRef,overload_data=OverloadData}). -%% ---------------------------------------------------------------------------- - -%% Initial function on which the runtime component is spawned on if started -%% by the runtime_tools supervisor. It is here it is determined if we shall -%% autostart. -auto_init(AutoModArgs,Parent) -> - %% autostart - process_flag(trap_exit, true), - register(?MODULE, self()), % Will crash if a rt is already running - AutoMod=get_autostart_module(), % Determine which module to use! - case catch AutoMod:autostart(AutoModArgs) of - {MFA,Options,Tag} -> - do_clear_trace_patterns(), % Remove previously left patterns. - LD1=read_option_list(Options,#rt{state=new, - parent=Parent, - vsn=get_application_vsn(), - tag=Tag}), - case auto_init_connect_control(LD1) of - {ok,LD2} -> % Either connected or running_alone. - OverloadData=initialize_overload(LD2), - case auto_init_check_mfa(MFA) of - {ok,{M,F,A}} -> % We shall start somekind of tracing! - P=spawn_link(M,F,A), % It lives its own life, only link! - loop1(LD2#rt{auto_starter=P,overload_data=OverloadData}); - false -> - loop1(LD2#rt{overload_data=OverloadData}) - end; - stop -> % Not allowed to run alone! - true % Simply terminate. - end; - _ -> % Non existent or faulty autostart mod! - true % Terminate normally. - end. - -auto_init_connect_control(LD1) -> - case auto_init_connect_find_pid(LD1#rt.dependency) of - Pid when is_pid(Pid) -> % There is a control component. - CtrlRef=erlang:monitor(process,Pid), - Pid ! {connect,node(),self(),LD1#rt.vsn,LD1#rt.tag}, - {ok,LD1#rt{ctrl_ref=CtrlRef,ctrl=Pid}}; - _ -> % There is no control component. - do_down_message(LD1) % Will return 'stop' or a LoopData. - end. - -%% Help function which finds the pid of the control component. -auto_init_connect_find_pid({_TimeOut,Node}) when Node==node() -> - whereis(?CTRL); -auto_init_connect_find_pid({_TimeOut,Node}) when is_atom(Node) -> - rpc:call(Node,erlang,whereis,[?CTRL]); -auto_init_connect_find_pid(_) -> % Node is not a proper node. - undefined. % Act as could not find control comp. - -%% Help function checking that the parameter is reasonable to be used as -%% spawn_link argument. -auto_init_check_mfa({M,F,A}) when is_atom(M),is_atom(F),is_list(A) -> - {ok,{M,F,A}}; -auto_init_check_mfa(_) -> - false. - -%% Help function to init_auto which finds out which module to call for -%% guidance on how to proceed. Returns an atom. -get_autostart_module() -> - case application:get_env(inviso_autostart_mod) of - {ok,Mod} when is_atom(Mod) -> - Mod; - _ -> - inviso_autostart % The default autostart module. - end. -%% ---------------------------------------------------------------------------- - - -%% This is the preloop function which performs loadcheck if necessary. Note -%% that it calculates the timeout used in the after in the real loop. There is -%% further no use doing overload checks if we are not tracing or already -%% suspended. There is yet one more situation, we do not want to perform -%% overload checks if the interval is set to infinity. This can be the case if -%% we are using an external source pushing overload information instead. -loop1(LD=#rt{overload=Overload}) -> - if - Overload/=?NO_LOADCHECK,element(2,Overload)/=infinity -> - Now=now(), - if - LD#rt.status==running, - LD#rt.state==tracing, - Now>LD#rt.next_loadcheck -> % Do loadcheck only then! - {NewLD,TimeOut}=do_check_overload(LD,{timeout,LD#rt.overload_data}), - loop(NewLD,TimeOut); - LD#rt.status==running,LD#rt.state==tracing -> - Timeout=calc_diff_to_now(Now,LD#rt.next_loadcheck), - loop(LD,Timeout); - true -> % Do not spend CPU on this! :-) - loop(LD,infinity) - end; - true -> % Either no check or infinity. - loop(LD,infinity) - end. - -loop(LoopData,Timeout) -> - receive - Msg when element(1,Msg)==trace_ts; - element(1,Msg)==trace; - element(1,Msg)==drop; - element(1,Msg)==seq_trace -> - case LoopData#rt.handler of - {HandlerFun,Data} -> - NewData=HandlerFun(Msg,Data), - loop1(LoopData#rt{handler={HandlerFun,NewData}}); - _ -> - loop1(LoopData) - end; - {{tp,Args,Flags},From,Ref} -> - if - LoopData#rt.status==running -> % Not when suspended. - Reply=do_set_trace_patterns(Args,Flags), - if - LoopData#rt.state==new -> % No longer new when tp set. - reply_and_loop({ok,Reply},From,Ref,LoopData#rt{state=idle}); - true -> - reply_and_loop({ok,Reply},From,Ref,LoopData) - end; - true -> % We are suspended! - reply_and_loop({error,suspended},From,Ref,LoopData) - end; - {{tf,Args,How},From,MRef} -> - Reply= - case How of - true -> - if - LoopData#rt.status==running -> - case {LoopData#rt.tracer_port,LoopData#rt.handler} of - {Port,_} when is_port(Port) -> - do_set_trace_flags(Port,Args,How); - {_,{Handler,_D}} when is_function(Handler) -> - do_set_trace_flags(self(),Args,How); - _ -> - {error,no_tracer} - end; - true -> % Can't turn *on* flags if suspended. - {error, suspended} - end; - false -> % No tracer needed when turning off. - do_set_trace_flags(void,Args,How) - end, - reply_and_loop(Reply,From,MRef,LoopData); - {{meta_tracer_call,Args},From,MRef} -> - if - LoopData#rt.status==running -> - case LoopData#rt.meta_tracer of - MPid when is_pid(MPid) -> - Reply=do_meta_pattern(MPid,Args), - reply_and_loop(Reply,From,MRef,LoopData); - _ -> - reply_and_loop({error,no_metatracer},From,MRef,LoopData) - end; - true -> - reply_and_loop({error,suspended},From,MRef,LoopData) - end; - {clear_all_tp,From,MRef} -> - do_clear_trace_patterns(), - reply_and_loop(ok,From,MRef,LoopData); - {{init_tracing,TracerData},From,MRef} -> - {NewLoopData,Reply}= - if - LoopData#rt.status==running -> - if - LoopData#rt.state==tracing -> - {LoopData,{error,already_initiated}}; - true -> % Otherwise, try to init-tracing! - case translate_td(TracerData) of - {ok,LogTD,MetaTD} -> - do_init_tracing(LoopData,TracerData,LogTD,MetaTD); - Error -> - {LoopData,Error} - end - end; - true -> % Can't init tracing if not running. - {LoopData,{error,suspended}} - end, - reply_and_loop(Reply,From,MRef,NewLoopData); - {stop_tracing,From,MRef} -> - case LoopData#rt.state of - tracing -> % Only case we need to do anything. - reply_and_loop({ok,idle},From,MRef,do_stop_tracing(LoopData)); - idle -> % Already idle! - reply_and_loop({ok,idle},From,MRef,LoopData); - new -> % Have actually never traced! - reply_and_loop({ok,new},From,MRef,LoopData) - end; - {{suspend,Reason},From,MRef} -> - if - LoopData#rt.status==running -> - NewLD=do_suspend(LoopData,Reason), - reply_and_loop(ok,From,MRef,NewLD); - true -> % No need suspend if not running! - reply_and_loop(ok,From,MRef,LoopData) - end; - {cancel_suspension,From,MRef} -> - NewLoopData=LoopData#rt{status=running,next_loadcheck=now()}, - send_event(state_change,NewLoopData), - reply_and_loop(ok,From,MRef,NewLoopData); - {{clear,Options},From,MRef} -> - NewLoopData=do_clear(LoopData,Options), - reply_and_loop({ok,{new,NewLoopData#rt.status}},From,MRef,NewLoopData); - {flush,From,MRef} -> - case LoopData#rt.state of - tracing -> % Can only flush if we are tracing. - if - is_port(LoopData#rt.tracer_port) -> - trace_port_control(LoopData#rt.tracer_port,flush), - reply_and_loop(ok,From,MRef,LoopData); - true -> % Not necessary but lets pretend. - reply_and_loop(ok,From,MRef,LoopData) - end; - State -> - reply_and_loop({error,{not_tracing,State}},From,MRef,LoopData) - end; - {list_logs,From,MRef} -> - TracerData=LoopData#rt.tracerdata, % Current tracerdata. - if - TracerData/=undefined -> % There is tracerdata! - reply_and_loop(do_list_logs(TracerData),From,MRef,LoopData); - true -> % Have no current tracerdata! - reply_and_loop({error,no_tracerdata},From,MRef,LoopData) - end; - {{list_logs,TracerData},From,MRef} -> - reply_and_loop(do_list_logs(TracerData),From,MRef,LoopData); - {{fetch_log,CollectPid},From,MRef} -> % Fetch according to current tracerdata. - TracerData=LoopData#rt.tracerdata, % Current tracerdata. - if - TracerData/=undefined -> % There is tracerdata! - {Reply,NewLD}=do_fetch_log(LoopData,CollectPid,TracerData), - reply_and_loop(Reply,From,MRef,NewLD); - true -> % No tracerdata! - reply_and_loop({error,no_tracerdata},From,MRef,LoopData) - end; - {{fetch_log,CollectPid,Spec},From,MRef} -> % Either list of files or tracerdata. - {Reply,NewLD}=do_fetch_log(LoopData,CollectPid,Spec), - reply_and_loop(Reply,From,MRef,NewLD); - {delete_logs,From,MRef} -> - if - LoopData#rt.state==tracing -> % Can't remove then! - reply_and_loop({error,tracing},From,MRef,LoopData); - true -> - TracerData=LoopData#rt.tracerdata, - reply_and_loop(do_delete_logs(TracerData),From,MRef,LoopData) - end; - {{delete_logs,TracerDataOrLogList},From,MRef} -> - if - LoopData#rt.state==tracing -> % Can't remove then! - reply_and_loop({error,tracing},From,MRef,LoopData); - true -> - reply_and_loop(do_delete_logs(TracerDataOrLogList),From,MRef,LoopData) - end; - {get_node_info,From,MRef} -> - Reply=collect_node_info(LoopData), - reply_and_loop(Reply,From,MRef,LoopData); - {{try_to_adopt,Tag,Condition},From,MRef} -> - if - LoopData#rt.ctrl_ref==undefined -> % We have no control component. - {Reply,NewLoopData}=do_try_to_adopt(Tag,Condition,LoopData,From), - reply_and_loop(Reply,From,MRef,NewLoopData); - true -> % We already have a control component. - reply_and_loop({error,refused},From,MRef,LoopData) - end; - {{confirm_connection,_Tag},From,MRef} -> - if - LoopData#rt.ctrl==From -> % It must be from this process! - Reply=collect_node_info(LoopData), - reply_and_loop(Reply,From,MRef,LoopData); - true -> % Strange, some one is joking? - reply_and_loop({error,refused},From,MRef,LoopData) - end; - {{change_options,Options},From,MRef} -> - case do_change_options(Options,LoopData) of - stop -> % Can't run alone with these options! - terminate_overload(LoopData), - From ! {ok,MRef}; % Don't care if From not a proper pid! - NewLoopData when is_record(NewLoopData,rt) -> - reply_and_loop(ok,From,MRef,NewLoopData) - end; - {get_status,From,MRef} -> - Reply={ok,{LoopData#rt.state,LoopData#rt.status}}, - reply_and_loop(Reply,From,MRef,LoopData); - {get_tracerdata,From,MRef} -> - case LoopData#rt.tracerdata of - undefined -> - reply_and_loop({ok,no_tracerdata},From,MRef,LoopData); - TracerData -> - reply_and_loop({ok,TracerData},From,MRef,LoopData) - end; - {state,From,MRef} -> % For debugging purposes. - reply_and_loop(LoopData,From,MRef,LoopData); - - {'DOWN',CtrlRef,process,_,_} when CtrlRef==LoopData#rt.ctrl_ref -> - case do_down_message(LoopData) of - stop -> % inviso_c gone and we must stop! - terminate_overload(LoopData), - exit(running_alone); - {ok,NewLoopData} -> - loop1(NewLoopData) - end; - {'EXIT',Pid,Reason} -> - case act_on_exit(Pid,Reason,LoopData) of - exit -> - terminate_overload(LoopData), - exit(Reason); - NewLoopData when is_record(NewLoopData,rt) -> - loop1(NewLoopData); - {NewLoopData,NewTimeOut} when is_record(NewLoopData,rt) -> - loop(NewLoopData,NewTimeOut) - end; - Other -> % Check if it concerns overload. - if - LoopData#rt.overload/=?NO_LOADCHECK, - LoopData#rt.status==running, - LoopData#rt.state==tracing -> - {NewLD,NewTimeOut}= - do_check_overload(LoopData, - {msg,{Other,LoopData#rt.overload_data}}), - loop(NewLD,NewTimeOut); - true -> - NewTimeOut=calc_diff_to_now(now(),LoopData#rt.next_loadcheck), - loop(LoopData,NewTimeOut) - end - after - Timeout -> - loop1(LoopData) - end. - -reply_and_loop(Reply,To,MRef,LoopData) when is_pid(To) -> - To ! {Reply,MRef}, - loop1(LoopData); -reply_and_loop(_,_,_,LoopData) -> % Used together with incoming casts. - loop1(LoopData). -%% ----------------------------------------------------------------------------- - - -%% ============================================================================= -%% File transfer process implementation. -%% ============================================================================= - -%% Files that are to to be transfered from the runtime component to the control -%% component are done so by reading them as binaries and sending them with -%% normal message passing (over distributed Erlang). -%% Reading the files are done in a process separate to the runtime component, -%% to both make the code more simple. But also to free up the runtime component. -%% -%% This help process must be capable of recognizing the fact that the runtime -%% component has been suspended, and then of course also discontinue any file -%% transfere. -fetch_init(Parent,Files,CollectPid,ChunkSize) -> - process_flag(trap_exit,true), % We must clean-up. - process_flag(priority,low), % Lets be careful. - case fetch_open_file(Files,CollectPid) of - {ok,FileName,FD,RestFiles} -> - MRef=erlang:monitor(process,CollectPid), - fetch_loop(Parent,RestFiles,CollectPid,ChunkSize,FileName,FD,MRef); - done -> - fetch_end(CollectPid); - error -> - fetch_incomplete(CollectPid) - end. - -fetch_loop(Parent,Files,CollectPid,ChunkSize,FName,FD,MRef) -> - receive - {suspend,Parent} -> % The runtime component is suspended. - file:close(FD), % We must clean-up. - fetch_incomplete(CollectPid); - {'DOWN',MRef,process,_,_} -> % The CollectPid terminated! - file:close(FD); % Close file and terminate. - {'EXIT',Parent,_Reason} -> % The runtime component terminated. - file:close(FD), - fetch_incomplete(CollectPid); - _ -> - fetch_loop(Parent,Files,CollectPid,ChunkSize,FName,FD,MRef) - after - 0 -> % If non of the above, get to work! - case file:read(FD,ChunkSize) of - {ok,Bin} -> - fetch_send_chunk(CollectPid,Bin), - case fetch_wait_for_chunk_ack(CollectPid,MRef) of - ok -> % Collector ready to receive next chunk. - fetch_loop(Parent,Files,CollectPid,ChunkSize,FName,FD,MRef); - cancel -> % Send no more files! - file:close(FD), % Close file, send incomplete, terminate! - fetch_incomplete(CollectPid); - 'DOWN' -> % Collector has terminate, stop! - file:close(FD) % Close file and terminate. - end; - eof -> % Ok, go on with the next file. - file:close(FD), - fetch_send_eof(CollectPid), - case fetch_open_file(Files,CollectPid) of - {ok,NewFName,NewFD,RestFiles} -> - fetch_loop(Parent,RestFiles,CollectPid, - ChunkSize,NewFName,NewFD,MRef); - done -> - fetch_end(CollectPid); - error -> - fetch_incomplete(CollectPid) - end; - {error,Reason} -> % Do not continue. - file:close(FD), - fetch_send_readerror(CollectPid,FName,Reason), - fetch_incomplete(CollectPid) - end - end. -%% ----------------------------------------------------------------------------- - -%% Help function which opens the next file to be transferred. It also communicates -%% the opening of the file to the collector process. -%% We know here that it will be a list of three-tuples. But there is no guarantee -%% that Dir or FileName are proper strings. -%% Returns {ok,FileName,FileDescriptor,RemainingFiles} or 'done'. -fetch_open_file([{FType,Dir,FileName}|RestFiles],CollectPid) -> - case catch file:open(filename:join(Dir,FileName),[read,raw,binary]) of - {ok,FD} -> - CollectPid ! {node(),open,{FType,FileName}}, - {ok,FileName,FD,RestFiles}; - {error,_Reason} -> - CollectPid ! {node(),open_failure,{FType,FileName}}, - error; - {'EXIT',_Reason} -> % Faulty Dir or FileName. - CollectPid ! {node(),open_failure,{FType,FileName}}, - error - end; -fetch_open_file([],_CollectPid) -> - done. -%% ----------------------------------------------------------------------------- - -%% A group of help functions sending information to the collector process. -%% Returns nothing significant. -fetch_send_chunk(CollectPid,Bin) -> - CollectPid ! {node(),payload,Bin,self()}. -%% ----------------------------------------------------------------------------- - -fetch_send_eof(CollectPid) -> - CollectPid ! {node(),end_of_file}. -%% ----------------------------------------------------------------------------- - -fetch_end(CollectPid) -> - CollectPid ! {node(),end_of_transmission}. -%% ----------------------------------------------------------------------------- - -fetch_send_readerror(CollectPid,FName,Reason) -> - CollectPid ! {node(),{error,{file_read,{Reason,FName}}}}. -%% ----------------------------------------------------------------------------- - -fetch_incomplete(CollectPid) -> - CollectPid ! {node(),incomplete}. -%% ----------------------------------------------------------------------------- - -%% Help function waiting for the collector to respond that it is ready to receive -%% the next chunk. This is in order to exercise flow control protecting the -%% collector to get swamped if the node where the collector runs is busy. -fetch_wait_for_chunk_ack(CollectPid,MRef) -> - receive - {CollectPid,chunk_ack} -> - ok; - {CollectPid,cancel_transmission} -> % Some problem at collector side. - cancel; - {'DOWN',MRef,process,_,_} -> % The collector terminated. - 'DOWN' - end. -%% ----------------------------------------------------------------------------- - - -%% ============================================================================= -%% First level do-functions, called from the main server loop on incomming -%% requests. -%% ============================================================================= - -%% Function performing the overload check. Returns {NewLoopData,TimeOut}. -%% Note that this function may also cause a suspend to be carried out if the -%% loadcheck turns out negative. -do_check_overload(LD,Data) -> - case do_check_overload_2(LD#rt.overload,Data) of - ignore -> % Load check not performed. - {LD,calc_diff_to_now(now(),LD#rt.next_loadcheck)}; - {ok,Interval} -> % No problem, continue. - NextLoadCheck=add_to_now(now(),Interval), - {LD#rt{next_loadcheck=NextLoadCheck},Interval}; - {suspend,Reason} -> % Emergency! suspend, suspend! - NewLD=do_suspend(LD,Reason), - {NewLD,infinity}; % No need to do load-checks now! - {new,NewData,Interval} -> % The overload was restarted or something. - NextLoadCheck=add_to_now(now(),Interval), - {LD#rt{overload_data=NewData,next_loadcheck=NextLoadCheck},Interval}; - error -> % Inhibit overload check then. - {LD#rt{overload=?NO_LOADCHECK},infinity} - end. - -%% Help function performing an overload check. Returns {ok,Interval}, -%% {suspend,Reason}, 'error' ir 'ignore'. -do_check_overload_2({{Mod,Func},Interval,_,_},Data) -> - do_check_overload_3(Interval,catch Mod:Func(Data)); -do_check_overload_2({Fun,Interval,_,_},Data) when is_function(Fun) -> - do_check_overload_3(Interval,catch Fun(Data)); -do_check_overload_2(_,_) -> % Bad loadcheck configuration. - error. % Stop using load checks then. - -do_check_overload_3(Interval,ok) -> - {ok,Interval}; -do_check_overload_3(Interval,{new,NewData}) -> - {new,NewData,Interval}; -do_check_overload_3(_Interval,{suspend,Reason}) -> - {suspend,Reason}; -do_check_overload_3(_Interval,ignore) -> % Loadcheck not triggered. - ignore; -do_check_overload_3(_Interval,_) -> % Failure or other return value. - error. % Stop doing loadchecks from now on. -%% ------------------------------------------------------------------------------ - -%% Function setting the trace-pattern according to Args and Flags. Note that -%% Args can contain regexps which must be expanded here. -%% Returns a list: [Result], where Result can be: int()|{error,Reason}. -%% Sometimes an error tuple will represent an entire pattern, sometimes the -%% pattern will expand to a number of error-tuples. -do_set_trace_patterns(Args,Flags) -> - Replies=do_set_trace_patterns_2(Args,Flags,[]), - lists:reverse(Replies). - -do_set_trace_patterns_2([{M,F,Arity,MS}|Rest],Flags,Replies) -> % Option-less. - do_set_trace_patterns_2([{M,F,Arity,MS,[]}|Rest],Flags,Replies); -do_set_trace_patterns_2(Mlist = [{M,F,Arity,MS,Opts}|Rest],Flags,Replies) when is_atom(M) -> - case length(Mlist) rem 10 of - 0 -> - timer:sleep(100); - _ -> - ok - end, - %% sleep 100 ms for every 10:th element in the list to let other - %% processes run since this is a potentially - %% heavy operation that might result in an unresponsive Erlang VM for - %% several seconds otherwise - case load_module_on_option(M,Opts) of - true -> % Already present, loaded or no option! - case catch erlang:trace_pattern({M,F,Arity},MS,Flags) of - No when is_integer(No) -> - do_set_trace_patterns_2(Rest,Flags,[No|Replies]); - {'EXIT',Reason} -> - do_set_trace_patterns_2(Rest, - Flags, - [{error,{bad_trace_args,[{M,F,Arity,MS},Reason]}}| - Replies]) - end; - false -> % Module not present, or not found! - do_set_trace_patterns_2(Rest,Flags,[0|Replies]) - end; -do_set_trace_patterns_2([{M,F,Arity,MS,Opts}|Rest],Flags,Replies) when is_list(M) -> - do_set_trace_patterns_2([{{void,M},F,Arity,MS,Opts}|Rest],Flags,Replies); -do_set_trace_patterns_2([{{Dir,M},F,Arity,MS,Opts}|Rest],Flags,Replies) - when is_list(Dir),is_list(M) -> - case check_pattern_parameters('_',F,Arity,MS) of % We don't want to repeat bad params. - true -> - case inviso_rt_lib:expand_regexp(Dir,M,Opts) of % Get a list of real modulnames. - Mods when is_list(Mods) -> - MoreReplies= - do_set_trace_patterns_2(lists:map(fun(Mod)-> - {Mod,F,Arity,MS,Opts} - end, - Mods), - Flags, - Replies), - do_set_trace_patterns_2(Rest,Flags,MoreReplies); - {error,Reason} -> - do_set_trace_patterns_2(Rest,Flags,[{error,Reason}|Replies]) - end; - false -> % Bad pattern parameters. - do_set_trace_patterns_2(Rest, - Flags, - [{error,{bad_trace_args,{M,F,Arity,MS}}}|Replies]) - end; -do_set_trace_patterns_2([Arg|Rest],Flags,Replies) -> - do_set_trace_patterns_2(Rest,Flags,[{error,{bad_trace_args,Arg}}|Replies]); -do_set_trace_patterns_2([],_Flags,Replies) -> - Replies. -%% ----------------------------------------------------------------------------- - -%% Help function which sets the trace flags for all processes specifed in Args. -%% Args shall be a list of {ProcessSpecification,ProcessTraceFlags}. -%% Returns {ok,Answers} where Answers is a list of integer and error descriptions. -%% Note that a process specification may be a particular pid or a {global,Name}. -%% In the case the process does not exist we will fake a zero instead of an -%% error. -do_set_trace_flags(Tracer,Args,How) -> - Fun=fun({Proc,Flags}) -> - case check_traceflag_pidspec(Proc) of - {ok,Proc2} -> % Reg-names converted. - case check_flags(Flags) of - Flags2 when is_list(Flags2) -> % No error! - case (catch - case How of - true -> - erlang:trace(Proc2, - true, - [{tracer,Tracer}|Flags2]); - false -> % No tracer of turning off. - erlang:trace(Proc2, - false, - Flags2) - end) of - N when is_integer(N) -> - N; - {'EXIT',Reason} -> - if - is_pid(Proc2) -> - 0; % Proc2 not alive or not at this node! - true -> % Otherwise, just error! - {error, - {bad_trace_args, - [Reason,Proc2,How,Flags2,Tracer]}} - end - end; - FlagError -> - FlagError - end; - false -> % Skip it. - 0; % Indicate that zero processes matched. - {error,Reason} -> % Bad process specification. - {error,{bad_process,[Reason,Proc]}} - end; - (Faulty) -> - {error,{bad_process,Faulty}} - end, - {ok,lists:map(Fun,Args)}. -%% ------------------------------------------------------------------------------ - -%% Function calling API:s in the trace information server. Note that we have -%% given the responsibility to form a correct functionsname and argument list -%% to the caller. -%% Returns whatever the called function returns. -do_meta_pattern(MPid,{FuncName,ArgList}) -> - case catch apply(inviso_rt_meta,FuncName,[MPid|ArgList]) of - {'EXIT',_Reason} -> - {error,{badarg,{FuncName,ArgList}}}; - Result -> - Result - end; -do_meta_pattern(_MPid,BadArgs) -> - {error,{bad_args,BadArgs}}. -%% ------------------------------------------------------------------------------ - -%% Function removing *all* patterns. Beaware that the one for local patterns -%% causes a walkthrough of all loaded modules. -do_clear_trace_patterns() -> - erlang:trace_pattern({'_','_','_'},false,[local]), %% inc. meta, call_count - erlang:trace_pattern({'_','_','_'},false,[global]). -%% ------------------------------------------------------------------------------ - -%% Function that takes TracerData and initializes the tracing. That can be -%% opening appropriate logfiles, starting meta-tracer. There must be one -%% clause here for every "type" of logging we want to be able to do. -%% Returns the Reply to be forwarded to the caller. -do_init_tracing(LoopData,TD,{HandlerFun,Data},TiTD) when is_function(HandlerFun) -> - {NewLoopData,Reply}= - case do_init_metatracing(TiTD,self()) of - {ok,MetaPid} -> - {LoopData#rt{handler={HandlerFun,Data}, - tracerdata=TD, - meta_tracer=MetaPid, - state=tracing}, - {ok,[{trace_log,ok},{ti_log,ok}]}}; - false -> % No meta tracing requested. - {LoopData#rt{handler={HandlerFun,Data}, - tracerdata=TD, - state=tracing}, - {ok,[{trace_log,ok}]}}; - {error,Reason} -> % Problems starting meta tracing. - {LoopData#rt{handler={HandlerFun,Data}, - tracerdata=TD, - state=tracing}, - {ok,[{trace_log,ok},{ti_log,{error,Reason}}]}} - end, - send_event(state_change,NewLoopData), % Send to subscribing processes. - {NewLoopData,Reply}; -do_init_tracing(LoopData,TD,{Type,Parameters},TiTD) when Type==ip;Type==file -> - case check_traceport_parameters(Type,Parameters) of - ok -> - case catch trace_port(Type,Parameters) of - Fun when is_function(Fun) -> - case catch Fun() of - Port when is_port(Port) -> % Ok, our trace-port is open. - {NewLoopData,Reply}= - case do_init_metatracing(TiTD,Port) of - {ok,MetaPid} -> - {LoopData#rt{tracer_port=Port, - tracerdata=TD, - meta_tracer=MetaPid, - state=tracing}, - {ok,[{trace_log,ok},{ti_log,ok}]}}; - false -> % No meta tracing requested. - {LoopData#rt{tracer_port=Port, - tracerdata=TD, - state=tracing}, - {ok,[{trace_log,ok}]}}; - {error,Reason} -> % Problems starting meta tracing. - {LoopData#rt{tracer_port=Port, - tracerdata=TD, - state=tracing}, - {ok,[{trace_log,ok},{ti_log,{error,Reason}}]}} - end, - send_event(state_change,NewLoopData), - {NewLoopData,Reply}; - {'EXIT',Reason} -> - {LoopData,{error,{bad_port_fun,[Parameters,Reason]}}} - end; - {'EXIT',Reason} -> - {LoopData,{error,{bad_port_args,[Parameters,Reason]}}} - end; - {error,Reason} -> % Bad traceport parameters. - {LoopData,{error,Reason}} - end. - -%% Help function that starts the meta-tracing. Note that the runtime component -%% will becom linked to it. -%% Currently the meta tracer handles two types, 'file' and 'relay'. -%% Note that Tracer tells the meta tracer where regular trace messages shall be -%% sent. This is because the meta tracer is capable of appending a {tracer,Tracer} -%% action term to meta match specs. -do_init_metatracing(LogSpec={_Type,_Arg},Tracer) -> - case inviso_rt_meta:start(LogSpec,Tracer) of - {ok,MetaPid} -> - {ok,MetaPid}; - {error,Reason} -> - {error,Reason} - end; -do_init_metatracing({Type,Arg,{InitPublLDmfa,RemovePublLDmf,CleanPublLDmf}},Tracer)-> - case inviso_rt_meta:start({Type,Arg},Tracer,InitPublLDmfa,RemovePublLDmf,CleanPublLDmf) of - {ok,MetaPid} -> - {ok,MetaPid}; - {error,Reason} -> - {error,Reason} - end; -do_init_metatracing(void,_) -> % Means no meta tracer. - false. -%% ----------------------------------------------------------------------------- - -%% Function that stops all tracing and closes all open files. This function -%% can't fail :-) It tries as hard as it can. -%% This function also kills the autostarter process if one exists. Otherwise it -%% will not be possible from a control component to end an ongoing autostarted -%% tracing. -%% Returns a new loopdata structure since stopping tracing involves updating it. -do_stop_tracing(LoopData) -> - do_stop_tracing_kill_autostarter(LoopData#rt.auto_starter), - do_clear_trace_flags(), % Do not generate any more traces. - NewLoopData1=do_stop_tracing_tracelog(LoopData), - NewLoopData2=do_stop_tracing_metatracing(NewLoopData1), - NewLoopData3=NewLoopData2#rt{state=idle,auto_starter=undefined}, - send_event(state_change,NewLoopData3), - NewLoopData3. - -do_stop_tracing_tracelog(LoopData=#rt{tracer_port=Port}) when is_port(Port) -> - trace_port_control(Port,flush), % Write buffered trace messages. - catch port_close(Port), - LoopData#rt{tracer_port=undefined}; -do_stop_tracing_tracelog(LoopData) -> - LoopData#rt{handler=undefined}. - -do_stop_tracing_metatracing(LoopData=#rt{meta_tracer=MPid}) when is_pid(MPid) -> - inviso_rt_meta:stop(MPid), - LoopData#rt{meta_tracer=undefined}; -do_stop_tracing_metatracing(LoopData) -> % No meta tracer running! - LoopData. - -%% Help function killing the autostarter, if one is active. -do_stop_tracing_kill_autostarter(P) when is_pid(P) -> - exit(P,stop_tracing); -do_stop_tracing_kill_autostarter(_) -> % No autostarter, do nothing. - true. -%% ----------------------------------------------------------------------------- - -%% Help function implementing suspending the runtime component. -%% Returns a new loopdata structure. -do_suspend(LD,Reason) -> - do_clear_trace_flags(), % If no process flags, no output! - do_suspend_metatracer(LD#rt.meta_tracer), - do_suspend_fetchers(LD#rt.fetchers), - do_stop_tracing_kill_autostarter(LD#rt.auto_starter), - NewLD=LD#rt{fetchers=[],status={suspended,Reason},auto_starter=undefined}, - send_event(state_change,NewLD), % Notify subscribers. - NewLD. - -do_suspend_metatracer(MetaTracer) when is_pid(MetaTracer) -> - inviso_rt_meta:suspend(MetaTracer); % This makes it suspended. -do_suspend_metatracer(_) -> - true. - -do_suspend_fetchers([FetcherPid|Rest]) -> - FetcherPid ! {suspend,self()}, % This makes it terminate. - do_suspend_fetchers(Rest); -do_suspend_fetchers([]) -> - true. -%% ------------------------------------------------------------------------------ - -%% Function that stops all tracing, removes all trace-patterns and removes all -%% logfiles. The idea is to return the runtime component to the 'new' state. -do_clear(LoopData,Opts) when is_list(Opts) -> - NewLoopData=do_stop_tracing(LoopData), % First stop tracing, if tracing. - case lists:member(keep_trace_patterns,Opts) of - false -> - do_clear_trace_patterns(); - _ -> - true - end, - case lists:member(keep_log_files,Opts) of - false -> - if - NewLoopData#rt.tracerdata/=undefined -> - do_delete_logs(NewLoopData#rt.tracerdata); - true -> % If no tracerdata, nothing to remove! - true % Do nothing then. - end; - _ -> - true - end, - NewLoopData#rt{state=new,tracerdata=undefined}; -do_clear(LoopData,_Opts) -> % Faulty Opts. - do_clear(LoopData,[]). % Then just ignore the options. -%% ----------------------------------------------------------------------------- - -%% Function which takes a tracerdata, either our own or a "suggested" -%% and tries to find the corresponding files. Note that the return value only -%% contains "types" of logs that the tracerdata is pointing out. Hence -%% is there no ti-log, no one will be mentioned in the return value. -do_list_logs(TracerData) -> % Handles both list and tuple. - case translate_td(TracerData) of - {ok,LogTD,TiTD} -> - {TraceDir,TraceLogs}=list_logs_tracelog(LogTD), - {TiDir,TiLogs}=list_logs_tilog(TiTD), - case {TraceLogs,TiLogs} of - {no_log,no_log} -> % Tracerdata not generating logs! - {ok,no_log}; - {_,no_log} -> % No ti logs. - {ok,[{trace_log,TraceDir,TraceLogs}]}; - {no_log,_} -> % Only ti-logs, unusual! - {ok,[{ti_log,TiDir,TiLogs}]}; - _ -> % Both trace and ti logs. - {ok,[{trace_log,TraceDir,TraceLogs},{ti_log,TiDir,TiLogs}]} - end; - {error,Reason} -> - {error,Reason} - end. -%% ----------------------------------------------------------------------------- - -%% Help function implementing fetching logfiles using distributed Erlang. -%% This function works for both situations, a list of specific files are -%% requested, or a tracerdata is specified. -%% Returns {Reply,NewLoopData}. -do_fetch_log(LD,CollectPid,What) -> - if - LD#rt.state/=tracing -> - case is_list_of_files_or_tracerdata(What) of - files -> - FetcherPid=do_fetch_log_listoffiles(CollectPid,What), - {{ok,FetcherPid},add_fetcher_ld(FetcherPid,LD)}; - tracerdata -> - case do_fetch_log_tracerdata(CollectPid,What) of - {Reply,FetcherPid} when is_pid(FetcherPid) -> - {Reply,add_fetcher_ld(FetcherPid,LD)}; - {Reply,_} -> % No fetch process was started. - {Reply,LD} - end; - false -> % It is an empty list! - {{complete,no_log},LD}; - error -> % Incorrect parameter. - {{error,badarg},LD} - end; - true -> % No transfere during tracing. - {{error,tracing},LD} - end. - -%% Function taking tracerdata to find out what files to send over to the RemotePid. -%% Note that we will not go back to the loop function from here but rather call -%% the fetch_loop instead, prepresenting the fetch-log state. Unless we encounter -%% a problem. -do_fetch_log_tracerdata(CollectPid,TracerData) -> - case do_list_logs(TracerData) of - {ok,no_log} -> - {{complete,no_log},void}; - {ok,Logs} -> % Ok, some trace_log and ti_log. - FetcherPid=do_fetch_log_listoffiles(CollectPid,Logs), - {{ok,FetcherPid},FetcherPid}; - {error,Reason} -> % Problem with tracerdata! - {{error,Reason},void} - end. - -do_fetch_log_listoffiles(CollectPid,FileSpec) -> - ExpandedFileSpec=do_fetch_log_expand_filespec(FileSpec), -%% !!! try out different ChunkSizes -% ChunkSize = 60, -% ChunkSize = 7*1024, - ChunkSize=1024, - _Fetcher=spawn_link(?MODULE, - fetch_init, - [self(),ExpandedFileSpec,CollectPid,ChunkSize]). - -%% Help function which expands the list of logs to have tags in front of every -%% file, as required by the fetch_loop. -do_fetch_log_expand_filespec(Logs) -> - TraceLogs= - case lists:keysearch(trace_log,1,Logs) of - {value,{_,Dir1,Logs1}} -> % There is a list of trace-logs. - lists:map(fun(File)->{trace_log,Dir1,File} end,Logs1); - false -> % No trace-logs! - [] - end, - TiLogs= - case lists:keysearch(ti_log,1,Logs) of - {value,{_,Dir2,Logs2}} -> - lists:map(fun(File)->{ti_log,Dir2,File} end,Logs2); - false -> - [] - end, - TiLogs++TraceLogs. - -%% ------------------------------------------------------------------------------ - -%% Function that removes all logfiles associated with a certain tracerdata. -do_delete_logs(TracerDataOrLogList) -> - case is_list_of_files_or_tracerdata(TracerDataOrLogList) of - tracerdata -> - case translate_td(TracerDataOrLogList) of - {ok,LogTD,TiTD} -> - case {list_logs_tracelog(LogTD),list_logs_tilog(TiTD)} of - {{_,no_log},{_,no_log}} -> % No logs nowhere! - {ok,no_log}; - {{LogDir,LogFiles},{_,no_log}} -> % No ti. - {ok,[{trace_log,delete_files(LogDir,LogFiles)}]}; - {{_,no_log},{TiDir,TiFiles}} -> - {ok,[{ti_log,delete_files(TiDir,TiFiles)}]}; - {{LogDir,LogFiles},{TiDir,TiFiles}} -> - {ok,[{trace_log,delete_files(LogDir,LogFiles)}, - {ti_log,delete_files(TiDir,TiFiles)}]} - end; - {error,Reason} -> - {error,Reason} - end; - files -> % It is [{trace_log,Dir,Files},.. - if - is_list(hd(TracerDataOrLogList)) -> % Just a list of files. - {ok,delete_files(".",TracerDataOrLogList)}; - is_tuple(hd(TracerDataOrLogList)) -> % A "modern" logspec. - case {lists:keysearch(trace_log,1,TracerDataOrLogList), - lists:keysearch(ti_log,1,TracerDataOrLogList)} of - {false,false} -> % Hmm, no logs specified! - {ok,[]}; % Easy response! - {{value,{_,LogDir,LogFiles}},false} -> - {ok,[{trace_log,delete_files(LogDir,LogFiles)}]}; - {false,{value,{_,TiDir,TiFiles}}} -> - {ok,[{ti_log,delete_files(TiDir,TiFiles)}]}; - {{value,{_,LogDir,LogFiles}},{value,{_,TiDir,TiFiles}}} -> - {ok,[{trace_log,delete_files(LogDir,LogFiles)}, - {ti_log,delete_files(TiDir,TiFiles)}]} - end - end; - false -> % Can't tell which! - {ok,[]}; - error -> - {error,{badarg,TracerDataOrLogList}} - end. -%% ----------------------------------------------------------------------------- - -%% Function handling the request when a control component wishing to take -%% control over this already existing control component. It does not matter -%% what state it is in. It can very well already be tracing. -%% Returns {Reply,NewLoopData}. -%% Where the Reply tells the control component wether it took control of it -%% or not. {node_info,node(),self(),Vsn,State,Status,{tag,Tag}} means that we -%% can be adopted (and more precisely considers ourselves being adopted now). -do_try_to_adopt(Tag,if_ref,LoopData=#rt{tag=Tag},_Ctrl) -> - {{error,{wrong_reference,LoopData#rt.tag}},LoopData}; -do_try_to_adopt(NewTag,_Condition,LoopData,CtrlPid) -> - case LoopData#rt.timer_ref of % Do we have a running-alone timer? - undefined -> % No we don't. - true; - TimerRef -> - timer:cancel(TimerRef) - end, - CtrlRef=erlang:monitor(process,CtrlPid), % Lets monitor our new "master"! - {DepVal,_}=LoopData#rt.dependency, - {node_info,Node,Pid,VSN,State,Status,Tag}=collect_node_info(LoopData), - NewLoopData= - LoopData#rt{dependency={DepVal,node(CtrlPid)}, - ctrl=CtrlPid, - ctrl_ref=CtrlRef, % Monitoring our new master. - tag=NewTag, % Use this tag from now on. - timer_ref=undefined}, - {{node_info,Node,Pid,VSN,State,Status,{tag,Tag}},NewLoopData}. -%% ----------------------------------------------------------------------------- - -%% Function changing parameters accoring to a new options list. Note that we -%% can not change control component if the one we have is still working. -%% We can however of course change how this runtime component will react to -%% a running alone scenario. -%% Returns 'stop' or NewLoopData. -do_change_options(Options,LoopData) -> - NewLoopData=read_option_list(Options,LoopData), - if - NewLoopData/=LoopData -> % Some options changed. - case do_change_options_ctrl(LoopData,NewLoopData) of - stop -> - stop; - {ok,NewLoopData2} -> - NewLoopData3=do_change_options_overload(LoopData,NewLoopData2), - NewLoopData3#rt{next_loadcheck=now()} % Force a load check next. - end; - true -> - LoopData - end. - -%% Help function which sets up the new dependencies. Note that we only do that -%% if do not have a working control component. -%% Returns {ok,NewLoopData} or 'stop'. -do_change_options_ctrl(OldLD,NewLD) -> - if - OldLD#rt.timer_ref/=undefined -> % No control and waiting to terminate. - timer:cancel(OldLD#rt.timer_ref), - do_down_message(NewLD#rt{timer_ref=undefined}); - OldLD#rt.ctrl==undefiend -> % No control component. - do_down_message(NewLD); - true -> % We have a working control component! - {ok,NewLD} - end. - -do_change_options_overload(OldLD,NewLD) -> - if - OldLD#rt.overload/=NewLD#rt.overload -> - terminate_overload(OldLD), - NewOverloadData=initialize_overload(NewLD), - NewLD#rt{overload_data=NewOverloadData}; - true -> % No changes done. - NewLD - end. -%% ----------------------------------------------------------------------------- - -%% Help function handling an incoming DOWN message from our control component. -%% If the runtime component is not allowed to run without a control component, it -%% simply terminates which closes the trace-port and process trace flags are -%% therefore automatically removed. -%% Returns 'stop' or a {ok,NewLoopData} structure. -do_down_message(LoopData) -> - case LoopData#rt.dependency of - {0,_} -> % Not allowed to run without controller. - stop; - {infinity,_} -> % Don't care. Just remove the controller. - {ok,LoopData#rt{ctrl=undefined,ctrl_ref=undefined}}; - {TimeOut,_} -> % Allowed to run TimeOut ms alone. - {ok,TimerRef}=timer:exit_after(TimeOut,self(),running_alone), - {ok,LoopData#rt{timer_ref=TimerRef,ctrl=undefined,ctrl_ref=undefined}} - end. -%% ----------------------------------------------------------------------------- - -%% Function handling incomming exit signals. We can expect exit signals from the -%% following: Our parent supervisor (runtime_tools_sup), a meta-tracer process, -%% a logfile fetcher process, or the auto_starter. -%% A trace-port may also generate an exit signal. -%% In addition it is possible that an overload mechanism generates exit-signals. -%% We can also get the running_alone exit signal from our self. This is the -%% situation if our control component has terminated and this runtime component -%% is not allowed to exist on its own for ever. -%% Also note that after we have stopped tracing, for any reason, it is not -%% impossible that we receive the EXIT signals from still working parts that -%% we are now shuting down. This is no problem, the code will mearly update -%% the loopdata structure once again. -%% Returns 'exit' indicating that the runtime component shall terminate now, -%% {NewLoopData,NewTimeOut} if the exit-signal resulted in an overload check, or -%% a new loopdata structure shall we ignore the exit, or it simply resulted in -%% a state-change. -act_on_exit(Parent,_Reason,#rt{parent=Parent}) -> - exit; -act_on_exit(_Pid,running_alone,_LoopData) -> - exit; -act_on_exit(MetaTracer,_Reason,LoopData=#rt{meta_tracer=MetaTracer}) -> - LoopData#rt{meta_tracer=undefined}; % It does not exit anylonger. -act_on_exit(Port,Reason,LoopData=#rt{tracer_port=Port}) -> - send_event({port_down,node(),Reason},LoopData), - _NewLoopData=do_stop_tracing(LoopData); -act_on_exit(AutoStarter,_Reason,LoopData=#rt{auto_starter=AutoStarter}) -> - LoopData#rt{auto_starter=undefined}; % The autostarter has terminated. -act_on_exit(Pid,Reason,LoopData) -> - case remove_fetcher_ld(Pid,LoopData) of - {true,NewLoopData} -> % Yes it really was a fetcher. - NewLoopData; - false -> % No it was not a fetcher. - act_on_exit_overload(Pid,Reason,LoopData) - end. - -%% Help function checking if this exit has anything to do with an overload -%% mechanism. Note that here we run the overload mechanism regardless of -%% if we are tracing or not. This because an exit signal from the overload -%% must most likely always be handled. -act_on_exit_overload(Pid,Reason,LoopData) -> - if - LoopData#rt.overload/=?NO_LOADCHECK -> - {_NewLD,_NewTimeOut}= - do_check_overload(LoopData, - {'EXIT',{Pid,Reason,LoopData#rt.overload_data}}); - true -> % Overload not in use. - LoopData - end. -%% ----------------------------------------------------------------------------- - - - - - - - - - - - - - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - -%% ============================================================================== -%% Various help functions. -%% ============================================================================== - -%% Help function which calculates a new now-tuple by adding Interval milliseconds -%% to the first argument. Note that Interval may be 'infinity' too. -%% Returns a new now-tuple or "bigvalue" which is greater than any now-tuple. -add_to_now({MegSec,Sec,MicroSec},Interval) when is_integer(Interval) -> - NewSec=Sec+(Interval div 1000), - if - NewSec>=1000000 -> - {MegSec+1,NewSec-1000000,MicroSec}; - true -> - {MegSec,NewSec,MicroSec} - end; -add_to_now(_,infinity) -> - "bigvalue". -%% ------------------------------------------------------------------------------ - -%% Help function calculating the difference in milliseconds between its first -%% and second argument. This is useful when calculating an after timeout value -%% from current now() and next_loadcheck value. -calc_diff_to_now(T1={_,_,_},T2={_,_,_}) -> - TimeOut1=timer:now_diff(T2,T1), % The difference in microseconds. - if - TimeOut1<0 -> - 0; - true -> % Make milliseconds out of it. - TimeOut1 div 1000 - end; -calc_diff_to_now(_T1,_) -> % Next loadcheck is not activated. - infinity. % The the after timeout is infinity. -%% ------------------------------------------------------------------------------ - - -%% Help function returning information about this runtime component. -collect_node_info(#rt{vsn=VSN,state=State,status=Status,tag=Tag}) -> - {node_info,node(),self(),VSN,State,Status,Tag}. -%% ------------------------------------------------------------------------------ - -%% Help function sending information to the control component that state/status -%% change has occurred. Returns nothing significant. -send_event(state_change,LoopData=#rt{ctrl=CtrlPid}) when is_pid(CtrlPid) -> - Event={trace_event,{state_change,node(),{LoopData#rt.state,LoopData#rt.status}}}, - CtrlPid ! Event; -send_event(Event,#rt{ctrl=CtrlPid}) when is_pid(CtrlPid) -> - CtrlPid ! {event,Event}; -send_event(_,_) -> % We have no control to send to! - true. % Maybe tracing alone after autostart. -%% ------------------------------------------------------------------------------ - -%% Help function initializing the overload protection mechanism. This may be -%% necessary if it is a port program or similar. Returns {ok,Data} or 'void'. -%% The datastructure vill be given to LoadMF as argument whenever loadchecks -%% are done. -initialize_overload(#rt{overload={_MF,_Interval,{M,F,Args},_RemoveMFA}}) -> - case catch apply(M,F,Args) of - {ok,Data} -> - Data; - _ -> % 'EXIT' or other faulty returnvalue. - void - end; -initialize_overload(_) -> - void. -%% ------------------------------------------------------------------------------ - -%% Help function which terminates an overload protection mechanism. -%% Returns nothing significant. -terminate_overload(#rt{overload={_MF,_Interval,_InitMFA,{M,F,Args}}, - overload_data=Data}) -> - catch apply(M,F,[Data|Args]), % Interested in the side-effect. - true; -terminate_overload(_) -> - true. -%% ------------------------------------------------------------------------------ - - -%% Help function which checks that a process specified for trace flags is correct. -%% Either the built-in "aliases" for groups of processes, a pid, a locally registered -%% name. This function also works for globally registered names. It must then -%% first be established that the process is local for this node before setting any -%% process flags. -%% Returns {ok,PidSpec}, 'false' or {error,Reason}. -check_traceflag_pidspec(all) -> {ok,all}; -check_traceflag_pidspec(new) -> {ok,new}; -check_traceflag_pidspec(existing) -> {ok,existing}; -check_traceflag_pidspec(Name) when is_atom(Name) -> - check_traceflag_pidspec({local,Name}); -check_traceflag_pidspec({local,A}) when is_atom(A) -> - case whereis(A) of - undefined -> % Then it is considered faulty. - {error,{nonexistent_name,A}}; - Pid when is_pid(Pid) -> - {ok,Pid} - end; -check_traceflag_pidspec({global,Name}) when is_atom(Name) -> - case global:whereis_name(Name) of - undefined -> % Then the name does not exist at all. - {error,{nonexistent_name,{global,Name}}}; - Pid when is_pid(Pid) -> % Ok, but must check that it is here. - if - node()==node(Pid) -> - {ok,Pid}; - true -> % Pid is not at this node. - false % Not an error but cant be used. - end - end; -check_traceflag_pidspec(Pid) when is_pid(Pid) -> - {ok,Pid}; -check_traceflag_pidspec(Proc) -> - {error,{faulty,Proc}}. -%% ------------------------------------------------------------------------------ - -%% Help function removing all trace flags from all processes. Useful in connection -%% with suspend. Returns nothing significant. -do_clear_trace_flags() -> - erlang:trace(all, false, [all]). -%% ------------------------------------------------------------------------------ - -%% Help function which checks that only valid process trace flags are mentioned. -%% In order to create better fault reports. -%% Returns a list of the approved flags, or {error,Reason}. -check_flags(Flags) -> - check_flags_2(Flags,Flags). - -check_flags_2([send|Rest],Flags) -> check_flags_2(Rest,Flags); -check_flags_2(['receive'|Rest],Flags) -> check_flags_2(Rest,Flags); -check_flags_2([call|Rest],Flags) -> check_flags_2(Rest,Flags); -check_flags_2([return_to|Rest],Flags) -> check_flags_2(Rest,Flags); -check_flags_2([procs|Rest],Flags) -> check_flags_2(Rest,Flags); -check_flags_2([garbage_collection|Rest],Flags) -> check_flags_2(Rest,Flags); -check_flags_2([running|Rest],Flags) -> check_flags_2(Rest,Flags); -check_flags_2([set_on_spawn|Rest],Flags) -> check_flags_2(Rest,Flags); -check_flags_2([set_on_first_spawn|Rest],Flags) -> check_flags_2(Rest,Flags); -check_flags_2([set_on_link|Rest],Flags) -> check_flags_2(Rest,Flags); -check_flags_2([timestamp|Rest],Flags) -> check_flags_2(Rest,Flags); -check_flags_2([arity|Rest],Flags) -> check_flags_2(Rest,Flags); -check_flags_2([silent|Rest],Flags) -> check_flags_2(Rest,Flags); -check_flags_2([],Flags) -> Flags; -check_flags_2([Faulty|_],_Flags) -> {error,{bad_flag,Faulty}}. -%% ------------------------------------------------------------------------------ - -%% Help function which checks parameters to erlang:trace_pattern. The purpose of -%% the function is to avoid to get multiple error return values in the return -%% list for a pattern used together with a regexp expanded module name. -check_pattern_parameters(Mod,Func,Arity,MS) -> - MSresult = check_MS(MS), - MFAresult = check_MFA(Mod,Func,Arity), - MFAresult and MSresult. - -check_MS(MS) when is_list(MS) -> true; -check_MS(true) -> true; -check_MS(false) -> true. - -check_MFA('_','_','_') -> true; -check_MFA(Mod,'_','_') when is_atom(Mod) -> true; -check_MFA(Mod,'_',A) when is_atom(Mod), is_integer(A) -> false; -check_MFA(Mod,F,'_') when is_atom(Mod), is_atom(F) -> true; -check_MFA(Mod,F,A) when is_atom(Mod), is_atom(F), is_integer(A) -> true. - -%% ----------------------------------------------------------------------------- - -%% Help function finding out if Mod is loaded, and if not, if it can successfully -%% be loaded. The Opts list can prevent modules from being loaded. -%% Returns 'true' or 'false'. -load_module_on_option(Mod,Opts) when is_list(Opts) -> - case lists:member(no_loadcheck,Opts) of - true -> % Then just skip this, return true. - true; - false -> - case erlang:module_loaded(Mod) of - true -> - true; % It is loaded, do no more. - false -> - case lists:member(only_loaded,Opts) of - true -> % Then, make no attempts to load. - false; - false -> % Try to load! - case code:ensure_loaded(Mod) of - {module,_Mod} -> % Successfully loaded! - true; - {error,_Reason} -> - false - end - end - end - end; -load_module_on_option(Mod,_Opts) -> % Most likely Opts not a list! - load_module_on_option(Mod,[]). % Call without options. -%% ----------------------------------------------------------------------------- - -%% Help function taking a tuplelist of options turning them into a loopdata -%% structure. Returns the loopdata structure with the new values changed. -read_option_list([],LD) -> % Done, return loopdata. - LD; -read_option_list([{dependency,{Value,Node}}|Rest],LD) -> - read_option_list(Rest,LD#rt{dependency={Value,Node}}); -read_option_list([{dependency,Value}|Rest],LD) when is_integer(Value);Value==infinity -> - read_option_list(Rest,LD#rt{dependency={Value,node()}}); -read_option_list([overload|Rest],LD) -> % So that we can remove loadcheck. - read_option_list(Rest,LD#rt{overload=?NO_LOADCHECK}); -read_option_list([{overload,{MF,Interval}}|Rest],LD) - when is_integer(Interval);Interval==infinity -> - read_option_list(Rest,LD#rt{overload={MF,Interval,void,void}}); -read_option_list([{overload,{MF,Interval,InitMFA,RemoveMFA}}|Rest],LD) - when is_integer(Interval);Interval==infinity -> - read_option_list(Rest,LD#rt{overload={MF,Interval,InitMFA,RemoveMFA}}); -read_option_list([{overload,Interval}|Rest],LD) - when is_integer(Interval);Interval==infinity -> - read_option_list(Rest,LD#rt{overload={fun ?DEFAULT_OVERLOAD_FUNC/1, - Interval, - void, - void}}); -read_option_list([_|Rest],LD) -> % Unknown option. - read_option_list(Rest,LD). -%% ----------------------------------------------------------------------------- - -%% Help function which returns the version number for the runtime_tools -%% application. Since it is called from within the runtime_tools application -%% we can be "sure" that it really exists. -get_application_vsn() -> - {value,{_,_,VSN}}=lists:keysearch(runtime_tools,1,application:loaded_applications()), - VSN. -%% ----------------------------------------------------------------------------- - -%% Help function that examines an argument to determine if it is a list of files -%% or tracerdata. This since they are both complex structures, looking alike. -%% Returns 'tracerdata', 'files', 'false' or 'error'. Error is returned if it -%% can not be decided which it is. -is_list_of_files_or_tracerdata(What) -> - case inviso_rt_lib:is_tracerdata(What) of - true -> - tracerdata; - false -> - if - What==[] -> - false; - is_list(What),is_list(hd(What)) -> - files; - is_list(What) -> - case lists:keysearch(trace_log,1,What) of - {value,_} -> - files; - false -> - case lists:keysearch(ti_log,1,What) of - {value,_} -> - files; - false -> - error % Neither tracerdata nor list of files. - end - end; - true -> - error - end - end. -%% ------------------------------------------------------------------------------ - -%% Help function which removes all files in the ListOfFiles, assuming they -%% are located in Dir. -%% Returns a list of [{ok,FileName},...{error,Reason},...] -delete_files(Dir,ListOfFiles) -> - delete_files_2(Dir,ListOfFiles, []). - -delete_files_2(Dir,[File|Tail],Reply) when is_list(Dir),is_list(File) -> - case catch file:delete(filename:join(Dir,File)) of - ok -> - delete_files_2(Dir,Tail,[{ok,File}|Reply]); - {error,Posix} -> - delete_files_2(Dir,Tail,[{error,{Posix,File}}|Reply]); - {'EXIT',_Reason} -> % Probably not proper string. - delete_files_2(Dir,Tail,[{error,{badarg,[Dir,File]}}|Reply]) - end; -delete_files_2(Dir,[Faulty|Tail],Reply) -> - delete_files_2(Dir,Tail,[{error,{badarg,[Dir,Faulty]}}|Reply]); -delete_files_2(_,[],Reply) -> - Reply. -%% ----------------------------------------------------------------------------- - -%% Help function which lists all trace logs belonging to this tracerdata. -%% Note that this function operates on internal LogTD structures. -list_logs_tracelog({file,FileName}) when is_list(FileName) -> - case file:read_file_info(FileName) of - {ok,_} -> % The file exists. - {filename:dirname(FileName),[filename:basename(FileName)]}; - _ -> % The file does not exist - {filename:dirname(FileName),[]} - end; -list_logs_tracelog({file,Wrap}) when is_tuple(Wrap),element(2,Wrap)==wrap -> - case {element(1,Wrap),element(3,Wrap)} of - {FileName,Tail} when is_list(FileName),is_list(Tail) -> - case catch {filename:dirname(FileName),list_wrapset(FileName,Tail)} of - {'EXIT',_Reason} -> % Garbage in either lists. - {"",no_log}; % Interpret as no log for tracerdata. - Tuple -> - Tuple - end; - _ -> - {"",no_log} - end; -list_logs_tracelog(void) -> % Trace log not used. - {"",no_log}; -list_logs_tracelog(_) -> % Some fun or similar. - {"",no_log}. % Then there are no files to report. -%% ----------------------------------------------------------------------------- - -%% Help function which lists all ti-files belonging to this tracerdata. -%% Note that this function operates on the internal TiTD structure. -list_logs_tilog(TiTD) - when tuple_size(TiTD)>=2,element(1,TiTD)==file,is_list(element(2,TiTD)) -> - FileName=element(2,TiTD), - case file:read_file_info(FileName) of - {ok,_} -> % Yes the file exists. - {filename:dirname(FileName),[filename:basename(FileName)]}; - _ -> - {filename:dirname(FileName),[]} - end; -list_logs_tilog(void) -> % Internal representation for - {"",no_log}; % ti-file not in use. -list_logs_tilog(_) -> - {"",no_log}. -%% ----------------------------------------------------------------------------- - -%% Help function which lists all files belonging to the wrap-set specified by -%% Prefix and Suffix. Note that there can be a directory in Prefix as well. -%% Will fail if either of Prefix or Suffix are not proper strings. -%% Returns a list of files, without dirname. -list_wrapset(Prefix,Suffix) -> - Name=filename:basename(Prefix), - Dirname=filename:dirname(Prefix), - case file:list_dir(Dirname) of - {ok,Files} -> - RegExp="^"++list_wrapset_escapes(Name)++"[0-9]+"++ - list_wrapset_escapes(Suffix)++"$", - list_wrapset_2(Files,RegExp); - {error,_Reason} -> % Translate this to no files! - [] - end. - -list_wrapset_2([File|Rest],RegExp) -> - Length=length(File), - case re:run(File,RegExp) of - {match,[{0,Length}]} -> % This is a member of the set. - [File|list_wrapset_2(Rest,RegExp)]; - _ -> - list_wrapset_2(Rest,RegExp) - end; -list_wrapset_2([],_) -> - []. - -%% Help function which inserts escape characters infront of characters which -%% will otherwise be missinterpreted by the regexp function as meta rather than -%% just the character itself. -list_wrapset_escapes([$.|Rest]) -> - [$\\,$.|list_wrapset_escapes(Rest)]; -list_wrapset_escapes([Char|Rest]) -> - [Char|list_wrapset_escapes(Rest)]; -list_wrapset_escapes([]) -> - []. -%% ----------------------------------------------------------------------------- - - - - - - -%% ============================================================================== -%% Handler functions for implementing simple trace-message handlers. -%% ============================================================================== -%% -%% A handler must be a function taking two arguments. The first is the trace- -%% message. The second is datastructure used by the handler. The handler shall -%% returns (possibly) new datastructure. - -%% ------------------------------------------------------------------------------ -%% Function implementing a relayer. This function is used to creat a fun handler -%% if the relay option is used in tracer-data. -%% ------------------------------------------------------------------------------ -relay_handler(Msg,Tracer) -> - Tracer ! Msg, - Tracer. - -%% ------------------------------------------------------------------------------ -%% Function implementing a default terminal io handler. -%% ------------------------------------------------------------------------------ - -dhandler(end_of_trace, Out) -> - Out; -dhandler(Trace, Out) when element(1, Trace) == trace, - tuple_size(Trace) >= 3 -> - dhandler1(Trace, tuple_size(Trace), Out); -dhandler(Trace, Out) when element(1, Trace) == trace_ts, - tuple_size(Trace) >= 4 -> - dhandler1(Trace, tuple_size(Trace)-1, Out); -dhandler(Trace, Out) when element(1, Trace) == drop, - tuple_size(Trace) == 2 -> - io:format(Out, "*** Dropped ~p messages.~n", [element(2,Trace)]), - Out; -dhandler(Trace, Out) when element(1, Trace) == seq_trace, - tuple_size(Trace) >= 3 -> - SeqTraceInfo = case Trace of - {seq_trace, Lbl, STI, TS} -> - io:format(Out, "SeqTrace ~p [~p]: ", - [TS, Lbl]), - STI; - {seq_trace, Lbl, STI} -> - io:format(Out, "SeqTrace [~p]: ", - [Lbl]), - STI - end, - case SeqTraceInfo of - {send, Ser, Fr, To, Mes} -> - io:format(Out, "(~p) ~p ! ~p [Serial: ~p]~n", - [Fr, To, Mes, Ser]); - {'receive', Ser, Fr, To, Mes} -> - io:format(Out, "(~p) << ~p [Serial: ~p, From: ~p]~n", - [To, Mes, Ser, Fr]); - {print, Ser, Fr, _, Info} -> - io:format(Out, "-> ~p [Serial: ~p, From: ~p]~n", - [Info, Ser, Fr]); - Else -> - io:format(Out, "~p~n", [Else]) - end, - Out; -dhandler(_Trace, Out) -> - Out. - -dhandler1(Trace, Size, Out) -> -%%%! Self = self(), - From = element(2, Trace), - case element(3, Trace) of - 'receive' -> - case element(4, Trace) of - {dbg,ok} -> ok; - Message -> io:format(Out, "(~p) << ~p~n", [From,Message]) - end; - 'send' -> - Message = element(4, Trace), - case element(5, Trace) of -%%%! This causes messages to disappear when used by ttb (observer). Tests -%%%! so far show that there is no difference in results with dbg even if I -%%%! comment it out, so I hope this is only some old code which isn't -%%%! needed anymore... /siri -%%%! Self -> ok; - To -> io:format(Out, "(~p) ~p ! ~p~n", [From,To,Message]) - end; - call -> - case element(4, Trace) of - MFA when Size == 5 -> - Message = element(5, Trace), - io:format(Out, "(~p) call ~s (~p)~n", - [From,ffunc(MFA),Message]); - MFA -> - io:format(Out, "(~p) call ~s~n", [From,ffunc(MFA)]) - end; - return -> %% To be deleted... - case element(4, Trace) of - MFA when Size == 5 -> - Ret = element(5, Trace), - io:format(Out, "(~p) old_ret ~s -> ~p~n", - [From,ffunc(MFA),Ret]); - MFA -> - io:format(Out, "(~p) old_ret ~s~n", [From,ffunc(MFA)]) - end; - return_from -> - MFA = element(4, Trace), - Ret = element(5, Trace), - io:format(Out, "(~p) returned from ~s -> ~p~n", - [From,ffunc(MFA),Ret]); - return_to -> - MFA = element(4, Trace), - io:format(Out, "(~p) returning to ~s~n", [From,ffunc(MFA)]); - spawn when Size == 5 -> - Pid = element(4, Trace), - MFA = element(5, Trace), - io:format(Out, "(~p) spawn ~p as ~s~n", [From,Pid,ffunc(MFA)]); - Op -> - io:format(Out, "(~p) ~p ~s~n", [From,Op,ftup(Trace,4,Size)]) - end, - Out. - - -%%% These f* functions returns non-flat strings - -%% {M,F,[A1, A2, ..., AN]} -> "M:F(A1, A2, ..., AN)" -%% {M,F,A} -> "M:F/A" -ffunc({M,F,Argl}) when is_list(Argl) -> - io_lib:format("~p:~p(~s)", [M, F, fargs(Argl)]); -ffunc({M,F,Arity}) -> - io_lib:format("~p:~p/~p", [M,F,Arity]); -ffunc(X) -> io_lib:format("~p", [X]). - -%% Integer -> "Integer" -%% [A1, A2, ..., AN] -> "A1, A2, ..., AN" -fargs(Arity) when is_integer(Arity) -> integer_to_list(Arity); -fargs([]) -> []; -fargs([A]) -> io_lib:format("~p", [A]); %% last arg -fargs([A|Args]) -> [io_lib:format("~p,", [A]) | fargs(Args)]; -fargs(A) -> io_lib:format("~p", [A]). % last or only arg - -%% {A_1, A_2, ..., A_N} -> "A_Index A_Index+1 ... A_Size" -ftup(Trace, Index, Index) -> - io_lib:format("~p", [element(Index, Trace)]); -ftup(Trace, Index, Size) -> - [io_lib:format("~p ", [element(Index, Trace)]) - | ftup(Trace, Index+1, Size)]. -%% ------------------------------------------------------------------------------ - -%% ============================================================================== -%% Functions handling the trace-port. Copied from dbg.erl -%% ============================================================================== - -trace_port_control(Port, flush) -> - case trace_port_control(Port, $f, "") of - {ok, [0]} -> ok; - {ok, _} -> {error, not_supported_by_trace_driver}; - Other -> Other - end. - -trace_port_control(Port, Command, Arg) when is_port(Port)-> - case catch port_control(Port, Command, Arg) of - {'EXIT', _} -> {error, {no_trace_driver, node()}}; - Result -> Result - end. - - -trace_port(file, {Filename, wrap, Tail}) -> - trace_port(file, {Filename, wrap, Tail, 128*1024}); -trace_port(file, {Filename, wrap, Tail, WrapSize}) -> - trace_port(file, {Filename, wrap, Tail, WrapSize, 8}); -trace_port(file, {Filename, wrap, Tail, WrapSize, WrapCnt}) - when is_list(Tail), - is_integer(WrapSize), WrapSize >= 0, WrapSize < (1 bsl 32), - is_integer(WrapCnt), WrapCnt >= 1, WrapCnt < (1 bsl 32) -> - trace_port1(file, Filename, {wrap, Tail, WrapSize, WrapCnt, 0}); -trace_port(file, {Filename, wrap, Tail, {time, WrapTime}, WrapCnt}) - when is_list(Tail), - is_integer(WrapTime), WrapTime >= 1, WrapTime < (1 bsl 32), - is_integer(WrapCnt), WrapCnt >= 1, WrapCnt < (1 bsl 32) -> - trace_port1(file, Filename, {wrap, Tail, 0, WrapCnt, WrapTime}); -trace_port(file, Filename) when is_list(Filename) -> - trace_port1(file, Filename, nowrap); - -trace_port(ip, Portno) when is_integer(Portno) -> - trace_port(ip,{Portno,50}); - -trace_port(ip, {Portno, Qsiz}) when is_integer(Portno), is_integer(Qsiz) -> - fun() -> - Driver = "trace_ip_drv", - Dir1 = filename:join(code:priv_dir(runtime_tools), "lib"), - case catch erl_ddll:load_driver(Dir1, Driver) of - ok -> - ok; - _ -> - Dir2 = filename:join( - Dir1, - erlang:system_info(system_architecture)), - catch erl_ddll:load_driver(Dir2, Driver) - end, - L = lists:flatten( - io_lib:format("~s ~p ~p 2", - [Driver, Portno, Qsiz])), - open_port({spawn, L}, [eof]) - end. - -trace_port1(file, Filename, Options) -> - Driver = "trace_file_drv", - fun() -> - Name = filename:absname(Filename), - %% Absname is needed since the driver uses - %% the supplied name without further investigations, - %% and if the name is relative the resulting path - %% might be too long which can cause a bus error - %% on vxworks instead of a nice error code return. - %% Also, the absname must be found inside the fun, - %% in case the actual node where the port shall be - %% started is on another node (or even another host) - {Wrap, Tail} = - case Options of - {wrap, T, WrapSize, WrapCnt, WrapTime} -> - {lists:flatten( - io_lib:format("w ~p ~p ~p ~p ", - [WrapSize, WrapCnt, WrapTime, - length(Name)])), - T}; - nowrap -> - {"", ""} - end, - Command = Driver ++ " " ++ Wrap ++ "n " ++ Name ++ Tail, - Dir1 = filename:join(code:priv_dir(runtime_tools), "lib"), - case catch erl_ddll:load_driver(Dir1, Driver) of - ok -> - ok; - _ -> - Dir2 = filename:join( - Dir1, - erlang:system_info(system_architecture)), - catch erl_ddll:load_driver(Dir2, Driver) - end, - if element(1, Options) == wrap -> - %% Delete all files from any previous wrap log - Files = wrap_postsort(wrap_presort(Name, Tail)), - lists:foreach( - fun(N) -> file:delete(N) end, - Files); - true -> ok - end, - open_port({spawn, Command}, [eof]) - end. - -%% Find all possible wrap log files. -%% Returns: a list of sort converted filenames. -%% -%% The sort conversion is done by extracting the wrap sequence counter -%% from the filename, and calling wrap_encode/2. -wrap_presort(Filename, Tail) -> - Name = filename:basename(Filename), - Dirname = filename:dirname(Filename), - case file:list_dir(Dirname) of - {ok, Files} -> - lists:zf( - fun(N) -> - case match_front(N, Name) of - false -> - false; - X -> - case match_rear(X, Tail) of - false -> - false; - C -> % Counter - case match_0_9(C) of - true -> - {true, -% filename:join(Dirname, N)} - wrap_encode( - filename:join(Dirname, N), - C)}; - false -> - false - end - end - end - end, - Files); - _ -> - [] - end. - -%% Extract the filenames from a list of sort converted ones. -wrap_postsort(Files) -> - lists:map(fun wrap_name/1, Files). - -wrap_encode(N, C) -> - {list_to_integer(C), N}. - -wrap_name({_C, N}) -> - N. - -%% Returns what is left of ListA when removing all matching -%% elements from ListB, or false if some element did not match, -%% or if ListA runs out of elements before ListB. -match_front(ListA, []) when is_list(ListA) -> - ListA; -match_front([], ListB) when is_list(ListB) -> - false; -match_front([Hd|TlA], [Hd|TlB]) -> - match_front(TlA,TlB); -match_front([_HdA|_], [_HdB|_]) -> - false. - -%% Reversed version of match_front/2 -match_rear(ListA, ListB) when is_list(ListA), is_list(ListB) -> - case match_front(lists:reverse(ListA), lists:reverse(ListB)) of - false -> - false; - List -> - lists:reverse(List) - end. - -%% Returns true if the non-empty list arguments contains all -%% characters $0 .. $9. -match_0_9([]) -> - false; -match_0_9([H]) when is_integer(H), $0 =< H, H =< $9 -> - true; -match_0_9([H|T]) when is_integer(H), $0 =< H, H =< $9 -> - match_0_9(T); -match_0_9(L) when is_list(L) -> - false. -%% ----------------------------------------------------------------------------- - - -%% ----------------------------------------------------------------------------- -%% Functions working on the tracerdata structure. -%% ----------------------------------------------------------------------------- - -%% Tracerdata is the structure which specifies to where tracing is logged at this -%% runtime component. It may now (and in the future specify) several things. -%% Currently it can consist of: -%% LogTD: specifying how trace-log data shall be handled. -%% TiTD : trace information, specifying how trace information shall be handled. -%% -%% Tracerdata may also contain quick or standard forms of LogTD and/or TiTD. -%% For instance if a standard handler-fun shall be used. The handler fun is not -%% part of the tracerdata but rather specified by a constant. - - -%% Help function that translates an input-tracerdata to useful internal formats. -%% This since the tracerdata may consist of specifications which shall be -%% translated into funs or similar. -%% Returns {ok,LogTD,TiTD} or {error,Reason}. -%% Note that TiTD may be 'void' since TiTD is not mandatory. -translate_td(TracerData) when is_list(TracerData) -> % Both log and ti. - case translate_td_logtd(get_trace_log_tracerdata(TracerData)) of - {ok,LogTD} -> - case translate_td_titd(get_ti_log_tracerdata(TracerData)) of - {ok,TiTD} -> - {ok,LogTD,TiTD}; - {error,Reason} -> - {error,Reason} - end; - {error,Reason} -> - {error,Reason} - end; -translate_td(TracerData) -> % The it is just LogTD!? - case translate_td_logtd(TracerData) of - {ok,LogTD} -> - {ok,LogTD,void}; - {error,Reason} -> - {error,Reason} - end. -%% ----------------------------------------------------------------------------- - -%% Help function translating trace-log tracerdata. -translate_td_logtd(collector) -> % This rt will act as receiver. - {ok,{fun dhandler/2,user}}; % Simple terminal io. -translate_td_logtd({relayer,Tracer}) when is_pid(Tracer) -> - {ok,{fun relay_handler/2,Tracer}}; % Relay trace-msg to Tracer-pid. -translate_td_logtd({HandlerFun,Data}) when is_function(HandlerFun) -> - {ok,{HandlerFun,Data}}; % Own invented fun. -translate_td_logtd({Type,Parameters}) when Type==ip;Type==file -> - {ok,{Type,Parameters}}; % Built in trace-port -translate_td_logtd(false) -> % Unusual but no trace log. - {ok,void}; -translate_td_logtd(Arg) -> - {error,{bad_log_td,Arg}}. -%% ----------------------------------------------------------------------------- - -%% Help function translating ti-log tracerdata. -translate_td_titd(TiTD={file,FileName}) when is_list(FileName) -> - {ok,TiTD}; -translate_td_titd({file,FileName, - {InitPublLDmfa={M1,F1,L1}, - RemovePublLDmf={M2,F2}, - CleanPublLDmf={M3,F3}}}) - when is_list(FileName),is_atom(M1),is_atom(F1),is_atom(M2),is_atom(F2),is_list(L1),is_atom(M3),is_atom(F3) -> - {ok,{file,FileName,{InitPublLDmfa,RemovePublLDmf,CleanPublLDmf}}}; -translate_td_titd({file,FileName, - {InitPublLDmfa={M1,F1,L1}, - void, - CleanPublLDmf={M3,F3}}}) - when is_list(FileName),is_atom(M1),is_atom(F1),is_list(L1),is_atom(M3),is_atom(F3) -> - {ok,{file,FileName,{InitPublLDmfa,void,CleanPublLDmf}}}; -translate_td_titd(false) -> % Means no ti-tracerdata. - {ok,void}; -translate_td_titd(TiTD) -> - {error,{bad_ti_td,TiTD}}. -%% ----------------------------------------------------------------------------- - -%% This function retrieves the trace-log part of a TracerData list structure. -%% Returns TraceLogTD or 'false'. -get_trace_log_tracerdata(TracerData) -> - case lists:keysearch(trace,1,TracerData) of - {value,{_,LogTD}} -> - LogTD; - false -> - false - end. -%% ----------------------------------------------------------------------------- - -%% This function retrieves the ti-log part of a TracerData list structure. -%% Returns TiLogTD or 'false'. -get_ti_log_tracerdata(TracerData) -> - case lists:keysearch(ti,1,TracerData) of - {value,{_,TiTD}} -> - TiTD; - false -> - false - end. -%% ----------------------------------------------------------------------------- - -%% Help function which checks that parameters to the built in trace-port are -%% sane. -check_traceport_parameters(Type,Args) -> - case {Type,Args} of - {file,{FileName,wrap,Tail}} when is_list(FileName),is_list(Tail) -> - ok; - {file,{FileName,wrap,Tail,WrapSize}} - when is_list(FileName), - is_list(Tail), - is_integer(WrapSize),WrapSize>=0,WrapSize< (1 bsl 32) -> - ok; - {file,{FileName,wrap,Tail,WrapSize,WrapCnt}} - when is_list(FileName),is_list(Tail), - is_integer(WrapSize), WrapSize >= 0, WrapSize < (1 bsl 32), - is_integer(WrapCnt), WrapCnt >= 1, WrapCnt < (1 bsl 32) -> - ok; - {file,{FileName,wrap,Tail,{time,WrapTime},WrapCnt}} - when is_list(FileName),is_list(Tail), - is_integer(WrapTime), WrapTime >= 1, WrapTime < (1 bsl 32), - is_integer(WrapCnt), WrapCnt >= 1, WrapCnt < (1 bsl 32) -> - ok; - {file,FileName} when is_list(FileName) -> - ok; - {ip,Portno} when is_integer(Portno),Portno=<16#FFFF -> - ok; - {ip,{Portno,Qsiz}} when is_integer(Portno),Portno=<16#FFFF,is_integer(Qsiz) -> - ok; - _ -> - {error,{trace_port_args,[Type,Args]}} - end. -%% ----------------------------------------------------------------------------- - - -%% ----------------------------------------------------------------------------- -%% Default overload functionality. -%% ----------------------------------------------------------------------------- - -%% A default overload protection function. An overload function must take -%% one argument and return 'ok' or {suspend,SuspendReason}. -default_overload_func(_) -> - case process_info(self(),message_queue_len) of - {message_queue_len,N} when N > 1000 -> - {suspend,rt_max_queue_len}; - _ -> - ok - end. -%% ----------------------------------------------------------------------------- - -%% ============================================================================= -%% Functions working on the internal loopdata structure. -%% ============================================================================= - -%% Help function simply adding Fetcher as a fetcher process to the loopdata. -%% Returns a new loopdata structure. -add_fetcher_ld(Fetcher,LD) -> - LD#rt{fetchers=[Fetcher|LD#rt.fetchers]}. -%% ----------------------------------------------------------------------------- - -%% Help function investigating if the first argument is a known fetcher process -%% or not. If it is, it also removed it from the fetchers list in the loopdata -%% structure. -%% Returns {true,NewLoopData} or 'false'. -remove_fetcher_ld(Fetcher,LD) -> - NewFetchers=lists:delete(Fetcher,LD#rt.fetchers), - if - NewFetchers/=LD#rt.fetchers -> - {true,LD#rt{fetchers=NewFetchers}}; - true -> % No it was not a fetcher process. - false - end. -%% ----------------------------------------------------------------------------- - -%%% end of file - diff --git a/lib/runtime_tools/src/inviso_rt_lib.erl b/lib/runtime_tools/src/inviso_rt_lib.erl deleted file mode 100644 index 5dfe14068a..0000000000 --- a/lib/runtime_tools/src/inviso_rt_lib.erl +++ /dev/null @@ -1,474 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2005-2011. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% -%% ------------------------------------------------------------------------------ -%% File : inviso_rt_lib.erl -%% Author : Lennart �hman <[email protected]> -%% Description : -%% -%% Created : 27 Sep 2005 by Lennart �hman <[email protected]> -%% ------------------------------------------------------------------------------ --module(inviso_rt_lib). - --export([expand_regexp/2,expand_regexp/3,expand_regexp/4]). --export([is_tracerdata/1]). --export([transform/2]). - --export([rpc/4,rpc/5,match_modules/2,match_modules/3]). --export([debug/3]). - -%% ------------------------------------------------------------------------------ - -%% ============================================================================== -%% Exported API functions. -%% ============================================================================== - -%% ------------------------------------------------------------------------------ -%% expand_regexp(Nodes,RegExpDir,RegExpMod,Opts) = [{Node,Answer},...] | {error,Reason} -%% expand_regexp(Nodes,RegExpMod,Opts) = [{Node,Answer},...] | {error,Reason} -%% expand_regexp(RegExpDir,RegExpMod,Opts) = ListOfModules | {error,Reason} -%% expand_regexp(RegExpMod,Opts) = ListOfModules | {error,Reason} -%% Nodes=List of all nodes (atoms) where to expand. -%% RegExpDir=Reg.exp (string) specifying directories. -%% RegExpMod=Reg.exp (string) specifying module names. -%% Node=node name (atom). -%% Opts=[Opt,...] -%% Opt=only_loaded -%% Answer=List of modules (atoms) | 'badrpc' -%% -%% Expands, concurrently, the regular expression on Nodes and returns a list -%% of what modules it expanded to on the different nodes. Note that it may -%% differ between Erlang nodes depending on whether the modules are the same -%% or not. Also note that all modules becomes loaded as a result. -%% RegExpDir can further limit the modules. It introduces the requirement that -%% a module must be loaded from a directory with a path satisfying the RegExpDir. -%% All regular expression are according to the standard lib regexp module. -expand_regexp(RegExpMod,Opts) when is_list(RegExpMod),is_list(Opts) -> - match_modules(RegExpMod,Opts); -expand_regexp(RegExpMod,Opts) -> - {error,{badarg,[RegExpMod,Opts]}}. -expand_regexp(NodesOrRegExpDir,RegExpMod,Opts) - when is_list(NodesOrRegExpDir),is_list(RegExpMod),is_list(Opts) -> - case is_list_of_atoms(NodesOrRegExpDir) of - true -> % Interpret as list of nodes. - lists:foreach(fun(N)->spawn(?MODULE,rpc,[self(),N,RegExpMod,Opts]) end, - NodesOrRegExpDir), - expand_regexp_answers(NodesOrRegExpDir,[]); - false -> % Interpret as a string. - match_modules(NodesOrRegExpDir,RegExpMod,Opts) - end; -expand_regexp(NodesOrRegExpDir,RegExpMod,Opts) -> - {error,{badarg,[NodesOrRegExpDir,RegExpMod,Opts]}}. -expand_regexp(Nodes,RegExpDir,RegExpMod,Opts) - when is_list(Nodes),is_list(RegExpDir),is_list(RegExpMod),is_list(Opts) -> - lists:foreach(fun(N)-> - spawn(?MODULE,rpc,[self(),N,RegExpDir,RegExpMod,Opts]) - end, - Nodes), - expand_regexp_answers(Nodes,[]); -expand_regexp(Nodes,RegExpDir,RegExpMod,Opts) -> - {error,{badarg,[Nodes,RegExpDir,RegExpMod,Opts]}}. - -expand_regexp_answers([],Answers) -> Answers; % List of [{Node,Answer},...]. -expand_regexp_answers(Nodes,Answers) -> - receive - {?MODULE,Node,Answer} -> - expand_regexp_answers(lists:delete(Node,Nodes),[{Node,Answer}|Answers]) - end. -%% ------------------------------------------------------------------------------ - -%% is_tracerdata(TracerData)=true|false -%% Answers the question if TracerData is proper tracerdata. Note that true can be -%% returned if it resembles tracerdata very closely. -is_tracerdata({Fun,_Data}) when is_function(Fun) -> true; -is_tracerdata({relayer,To}) when is_pid(To);is_atom(To) -> true; -is_tracerdata(collector) -> true; -is_tracerdata({file,Param}) when is_tuple(Param);is_list(Param) -> true; -is_tracerdata({ip,_Param}) -> true; -is_tracerdata([{trace,LogTD}|Rest]) -> - case is_tracerdata(LogTD) of - true -> - is_tracerdata(Rest); - false -> - false - end; -is_tracerdata([{ti,TiData}|Rest]) -> - case is_tidata(TiData) of - true -> - is_tracerdata(Rest); - false -> - false - end; -is_tracerdata([]) -> - true; -is_tracerdata(_) -> - false. - -is_tidata({file,FileName}) when is_list(FileName) -> true; -is_tidata({file,FileName,{M,F,Args}}) when is_list(FileName),is_atom(M),is_atom(F),is_list(Args) -> - true; -is_tidata(_) -> false. -%% ------------------------------------------------------------------------------ - - -%% ============================================================================== -%% Help functions. -%% ============================================================================== - -%% Help function intended to be run in its own process. Will report with -%% a message when done. -%% This function will be spawned on. -rpc(Parent,Node,RegExpMod,Opts) -> - case rpc:call(Node,?MODULE,match_modules,[RegExpMod,Opts]) of - {badrpc,_Reason} -> % The node is probably not healthy. - Parent ! {?MODULE,Node,badrpc}; - Modules -> - Parent ! {?MODULE,Node,Modules} - end. - -rpc(Parent,Node,RegExpDir,RegExpMod,Opts) -> - case rpc:call(Node,?MODULE,match_modules,[RegExpDir,RegExpMod,Opts]) of - {badrpc,_Reason} -> % The node is probably not healthy. - Parent ! {?MODULE,Node,badrpc}; - Modules -> - Parent ! {?MODULE,Node,Modules} - end. -%% ------------------------------------------------------------------------------ - - -%% ============================================================================== -%% Exported function which actually shall be in code.erl. -%% ============================================================================== - -%% match_modules(RegExpMod,Actions) = [Module,...] | {error,Reason} -%% match_modules(RegExpDir,RegExpMod,Actions)=[Module,...] | {error,Reason} -%% RegExpMod=Erlang regular expression describing module names (string). -%% RegExpDir=Erlang regular expression describing directory paths(string) | -%% void -%% Actions=List of;'only_loaded'. -%% -%% Function which matches a regular expresion against module names. The function -%% can also match the directory from where the module is loaded or will be loaded -%% against a regular expresion for directory paths. -%% The function uses the same strategy as code-loading if the same module is -%% discovered in several places. -%% (1) An already loaded module shadows all other occurancies. -%% (2) .beams found in by a path shadows .beams found by paths later in the -%% code paths. -%% -%% Description of actions: -%% only_loaded: Only consider modules which are loaded. -match_modules(RegExpMod,Actions) -> - match_modules(void,RegExpMod,Actions). -match_modules(RegExpDir,RegExpMod,Actions) -> - AllLoaded=code:all_loaded(), - Mods1=handle_expand_regexp_2(AllLoaded,RegExpDir,RegExpMod,[]), - case lists:member(only_loaded,Actions) of % Shall we do not loaded too? - false -> % Ok, search all paths too then. - Paths=code:get_path(), - handle_expand_regexp_3(Paths,RegExpDir,RegExpMod,AllLoaded,Mods1); - true -> % Only loaded modules then. - Mods1 - end. - - -%% Help function which traverses all loaded modules and determines -%% which shall be returned. First we check that the module satisfies the -%% module-regexp. Then we, if a dir reg-exp is given, checks that the -%% module is loaded from an approved path. Note that if it can not be -%% determined from where it was loaded (like preloaded or cover-compiled -%% etc), but dir reg-exps are used. That module will be excluded. -%% Returns a list of modules. -handle_expand_regexp_2([{Mod,Path}|Rest],RegExpDir,RegExpMod,Result) -> - ModStr=atom_to_list(Mod), - ModLen=length(ModStr), - case re:run(ModStr,RegExpMod) of - {match,[{0,ModLen}]} -> % Ok, The regexp matches the module. - if - is_list(RegExpDir),is_atom(Path) -> % Preloaded or covercompiled... - handle_expand_regexp_2(Rest,RegExpDir,RegExpMod,Result); - is_list(RegExpDir),is_list(Path) -> % Dir reg-exp is used! - PathOnly=filename:dirname(Path), % Must remove beam-file name. - case re:run(PathOnly,RegExpDir,[{capture,none}]) of - match -> % Did find a match, that is enough! - handle_expand_regexp_2(Rest,RegExpDir,RegExpMod,[Mod|Result]); - _ -> % Either error or nomatch. - handle_expand_regexp_2(Rest,RegExpDir,RegExpMod,Result) - end; - true -> % Otherwise already done! - handle_expand_regexp_2(Rest,RegExpDir,RegExpMod,[Mod|Result]) - end; - _ -> % Then Mod is not part of the set. - handle_expand_regexp_2(Rest,RegExpDir,RegExpMod,Result) - end; -handle_expand_regexp_2([],_,_,Result) -> Result. - -%% Help function which traverses all paths and looks for modules satisfying -%% the module reg.exp. -%% Returns a list of unique module names. -handle_expand_regexp_3([Path|Rest],RegExpDir,RegExpMod,AllLoaded,Result) -> - if - is_list(RegExpDir) -> % We must consider the directory name. - AbsPath= - case filename:pathtype(Path) of - absolute -> % Is already abs. - Path; - relative -> % Then it must be made absolute. - filename:absname(Path); - volumerelative -> % Only on Windows!? - filename:absname(Path) - end, - case re:run(AbsPath,RegExpDir,[{capture,none}]) of - match -> % Ok, the directory is allowed. - NewResult=handle_expand_regexp_3_1(Path,RegExpMod,AllLoaded,Result), - handle_expand_regexp_3(Rest,RegExpDir,RegExpMod,AllLoaded,NewResult); - _ -> % This directory does not qualify. - handle_expand_regexp_3(Rest,RegExpDir,RegExpMod,AllLoaded,Result) - end; - true -> % RegExpDir is not used! - NewResult=handle_expand_regexp_3_1(Path,RegExpMod,AllLoaded,Result), - handle_expand_regexp_3(Rest,RegExpDir,RegExpMod,AllLoaded,NewResult) - end; -handle_expand_regexp_3([],_,_,_,Result) -> Result. - -handle_expand_regexp_3_1(Path,RegExpMod,AllLoaded,Result) -> - case file:list_dir(Path) of - {ok,FileNames} -> - handle_expand_regexp_3_2(FileNames,RegExpMod,AllLoaded,Result); - {error,_Reason} -> % Bad path!? Skip it. - Result - end. - -handle_expand_regexp_3_2([File|Rest],RegExpMod,AllLoaded,Result) -> - case filename:extension(File) of - ".beam" -> % It is a beam-file. Consider it! - ModStr=filename:basename(File,".beam"), - Mod=list_to_atom(ModStr), - case {lists:keysearch(Mod,1,AllLoaded),lists:member(Mod,Result)} of - {false,false} -> % This module is not tried before. - ModLen=length(ModStr), - case re:run(ModStr,RegExpMod) of - {match,[{0,ModLen}]} -> % This module satisfies the regexp. - handle_expand_regexp_3_2(Rest,RegExpMod,AllLoaded,[Mod|Result]); - _ -> % Error or not perfect match. - handle_expand_regexp_3_2(Rest,RegExpMod,AllLoaded,Result) - end; - {_,_} -> % This module is already tested. - handle_expand_regexp_3_2(Rest,RegExpMod,AllLoaded,Result) - end; - _ -> % Not a beam-file, skip it. - handle_expand_regexp_3_2(Rest,RegExpMod,AllLoaded,Result) - end; -handle_expand_regexp_3_2([],_,_,Result) -> Result. -%% ------------------------------------------------------------------------------ - -%% Help function which finds out if its argument is a list of zero or more -%% atoms. -%% Returns 'true' or 'false'. -is_list_of_atoms([A|Rest]) when is_atom(A) -> - is_list_of_atoms(Rest); -is_list_of_atoms([_|_]) -> - false; -is_list_of_atoms([]) -> - true. -%% ------------------------------------------------------------------------------ - - -%% ============================================================================= -%% Functions transforming function calls in trace-case file. -%% ============================================================================= - -%% transform(Exprs,Translations)=NewExprs -%% Exprs=list(); List of abstract format erlang terms, as returned by -%% io:parse_erl_exprs/2. -%% Translations=list(); List of translations from function calls to other -%% function calls. [{Mod,Func,Arity,{NewMod,NewFunc,ParamTransformMF}},...] -%% Mod can actually be omitted, ParamTransformMF shall be {M,F} where F is -%% a function taking one argument (the parameter list), and returning the -%% new parameter list. It can also be anything else should no transformation -%% of the parameters be the case. -%% -%% Function that transforms function calls in a trace-case file. The transform/2 -%% can only transform shallow function calls. I.e where both module and function -%% name are specified as atoms. Any binding-environment is not examined. -transform([Expr|Rest],Translations) -> - [transform_2(Expr,Translations)|transform(Rest,Translations)]; -transform([],_) -> - []. - -%% Help function handling a single expr. -transform_2({call,L1,{remote,L2,ModExpr,FuncExpr},Params},Translations) -> - case transform_2(ModExpr,Translations) of - {atom,L3,M} -> - case transform_2(FuncExpr,Translations) of - {atom,L4,F} -> % Now we have a M:F/Arity! - case do_call_translation(M,F,Params,Translations) of - {ok,NewM,NewF,NewP} -> - NewParams=transform(NewP,Translations), - {call,L1,{remote,L2,{atom,L3,NewM},{atom,L4,NewF}},NewParams}; - false -> % No translation or faulty. - NewParams=transform(Params,Translations), - {call,L1,{remote,L2,ModExpr,FuncExpr},NewParams} - end; - NewFuncExpr -> % Not translated to a shallow term. - NewParams=transform(Params,Translations), - {call,L1,{remote,L2,ModExpr,NewFuncExpr},NewParams} - end; - NewModExpr -> % Not translated to a shallow term. - NewFuncExpr=transform_2(FuncExpr,Translations), - NewParams=transform(Params,Translations), - {call,L1,{remote,L2,NewModExpr,NewFuncExpr},NewParams} - end; -transform_2({call,L1,FuncExpr,Params},Translations) -> - case transform_2(FuncExpr,Translations) of - {atom,L3,F} -> % Now we have a M:F/Arity! - case do_call_translation(F,Params,Translations) of - {ok,NewM,NewF,NewP} -> % It is turned into a global call. - NewParams=transform(NewP,Translations), - {call,L1,{remote,L1,{atom,L3,NewM},{atom,L3,NewF}},NewParams}; - false -> % No translation or faulty. - NewParams=transform(Params,Translations), - {call,L1,FuncExpr,NewParams} - end; - NewFuncExpr -> % Not translated to a shallow term. - NewParams=transform(Params,Translations), - {call,L1,NewFuncExpr,NewParams} - end; -transform_2({match,L,P,E},Translations) -> - NewPattern=transform_2(P,Translations), - NewExpr=transform_2(E,Translations), - {match,L,NewPattern,NewExpr}; -transform_2({op,L,Op,Arg1,Arg2},Translations) -> - NewArg1=transform_2(Arg1,Translations), - NewArg2=transform_2(Arg2,Translations), - {op,L,Op,NewArg1,NewArg2}; -transform_2({op,L,Op,Arg},Translations) -> - NewArg=transform_2(Arg,Translations), - {op,L,Op,NewArg}; -transform_2({block,L,Body},Translations) -> - NewBody=transform(Body,Translations), - {block,L,NewBody}; -transform_2({'if',L,Clauses},Translations) -> - NewClauses=transform_clauses(Clauses,Translations), - {'if',L,NewClauses}; -transform_2({'case',L,Func,Clauses},Translations) -> - NewFunc=transform_2(Func,Translations), - NewClauses=transform_clauses(Clauses,Translations), - {'case',L,NewFunc,NewClauses}; -transform_2({'fun',L,{clauses,Clauses}},Translations) -> - NewClauses=transform_clauses(Clauses,Translations), - {'fun',L,NewClauses}; -transform_2({lc,L,Items,GeneratorsFilters},Translations) -> - NewItem=transform_2(Items,Translations), - NewGensAndFilters=transform_gensandfilters(GeneratorsFilters,Translations), - {lc,L,NewItem,NewGensAndFilters}; -transform_2({'catch',L,Expr},Translations) -> - NewExpr=transform_2(Expr,Translations), - {'catch',L,NewExpr}; -transform_2({tuple,L,Elements},Translations) -> - NewElements=transform(Elements,Translations), - {tuple,L,NewElements}; -transform_2({cons,L,Element,Tail},Translations) -> - NewElement=transform_2(Element,Translations), - NewTail=transform_2(Tail,Translations), - {cons,L,NewElement,NewTail}; -transform_2({nil,L},_) -> - {nil,L}; -transform_2({bin,L,Elements},Translations) -> - NewElements=transform_binary(Elements,Translations), - {bin,L,NewElements}; -transform_2(Expr,_) -> % Can be a var for instance. - Expr. - -transform_binary([{bin_element,L,Val,Size,TSL}|Rest],Translations) -> - NewVal=transform_2(Val,Translations), - NewSize=transform_2(Size,Translations), - [{bin_element,L,NewVal,NewSize,TSL}|transform_binary(Rest,Translations)]; -transform_binary([],_) -> - []. - -transform_clauses([{clause,L,Pattern,Guards,Body}|Rest],Translations) -> - NewPattern=transform(Pattern,Translations), - NewBody=transform(Body,Translations), - [{clause,L,NewPattern,Guards,NewBody}|transform_clauses(Rest,Translations)]; -transform_clauses([],_Translations) -> - []. - -transform_gensandfilters([{generator,L,Pattern,Exprs}|Rest],Translations) -> - NewExprs=transform(Exprs,Translations), - [{generator,L,Pattern,NewExprs}|transform_gensandfilters(Rest,Translations)]; -transform_gensandfilters([Expr|Rest],Translations) -> - [transform_2(Expr,Translations)|transform_gensandfilters(Rest,Translations)]; -transform_gensandfilters([],_) -> - []. -%% ------------------------------------------------------------------------------ - -%% This is the heart of the translation functionality. Here we actually try to -%% replace calls to certain functions with other calls. This can include removing -%% arguments. -do_call_translation(M,F,Params,Translations) -> - case lists:keysearch({M,F,length(Params)},1,Translations) of - {value,{_,{NewM,NewF,ArgFun}}} -> % Lets transform the function. - do_call_translation_2(Params,NewM,NewF,ArgFun); - _ -> - false % No translations at all. - end. -do_call_translation(F,Params,Translations) -> - case lists:keysearch({F,length(Params)},1,Translations) of - {value,{_,{NewM,NewF,ArgFun}}} -> % Lets transform the function. - do_call_translation_2(Params,NewM,NewF,ArgFun); - _ -> - false % No translations at all. - end. - -do_call_translation_2(Params,NewM,NewF,ArgFun) -> - case ArgFun of - {M,F} when is_atom(M),is_atom(F) -> - case catch M:F(Params) of - {'EXIT',_Reason} -> - false; % If it does not work, skipp it. - MungedParams when is_list(MungedParams) -> - {ok,NewM,NewF,MungedParams}; - _ -> - false - end; - _ -> % No munging of parameters. - {ok,NewM,NewF,Params} - end. -%% ------------------------------------------------------------------------------ - - -%% ============================================================================= -%% Functions for the runtime component internal debugging system. -%% ============================================================================= - -%% The debug system is meant to provide tracing of ttb at different levels. -%% -%% debug(What,Level,Description) -> nothing significant. -%% What : controls what kind of event. This can both be certain parts of ttb -%% as well as certain levels (info to catastrophy). -%% Level: Determines if What shall be printed or not. -%% Description: this is what happend. -debug(off,_What,_Description) -> - true; % Debug is off, no action. -debug(On,What,Description) -> - debug_2(On,What,Description). - -debug_2(_,What,Description) -> - io:format("INVISO DEBUG:~w, ~p~n",[What,Description]). -%% ----------------------------------------------------------------------------- diff --git a/lib/runtime_tools/src/inviso_rt_meta.erl b/lib/runtime_tools/src/inviso_rt_meta.erl deleted file mode 100644 index 6865dc2242..0000000000 --- a/lib/runtime_tools/src/inviso_rt_meta.erl +++ /dev/null @@ -1,1207 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2006-2009. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% -%% Author: Lennart �hman, [email protected] -%% -%% This module implements the meta tracer process belonging to the -%% runtime component. Its main purpose is to write the ti-file (traceinformation). -%% The ti-file contains translations between process id:s and what ever "you" -%% want to read in the merged and formatted logfile. -%% This process interacts with the runtime component process. -%% -%% Currently it handles the following types of ti-files: -%% Plain raw, binary log. -%% Relay to other inviso_rt_meta process on another node. -%% -%% The TI file will be on binary format and each entry is: -%% <<LengthIndicator:32, {Pid,Alias,Op,NowStamp} >> -%% Pid=pid(), or if OP==unalias pid()|any_other_than_pid() -%% Op=alias|unalias -%% ----------------------------------------------------------------------------- --module(inviso_rt_meta). - -%% ----------------------------------------------------------------------------- -%% API exports. -%% ----------------------------------------------------------------------------- - --export([start/2,start/5]). --export([stop/1,suspend/1]). --export([init_tpm/5,init_tpm/8]). --export([tpm/5,tpm/6,tpm/9,tpm_tracer/5,tpm_tracer/6,tpm_tracer/9]). --export([tpm_ms/6,tpm_ms_tracer/6,ctpm_ms/5,ctpm/4]). --export([local_register/1,global_register/1]). --export([remove_local_register/1,remove_global_register/1]). - --export([write_ti/1]). - --export([get_tracer/0,tpm_ms/5,tpm_ms_tracer/5,list_tpm_ms/3,ctpm_ms/4]). - --export([metacast_call/5,metacast_return_from/6]). --export([get_state/1]). -%% ----------------------------------------------------------------------------- - -%% ----------------------------------------------------------------------------- -%% Internal exports. -%% ----------------------------------------------------------------------------- - --export([init/6]). --export([init_std_publld/2,clean_std_publld/1]). -%% ----------------------------------------------------------------------------- - -%% ----------------------------------------------------------------------------- -%% Constants. -%% ----------------------------------------------------------------------------- - --define(NAMED_MS_TAB,inviso_rt_meta_named_ms). - -%% ----------------------------------------------------------------------------- - - -%% ============================================================================= -%% Exported API (Meant to be used by a runtime component). -%% ============================================================================= - -%% start(TiData,Tracer)={ok,Pid} | {error,Reason} -%% start(TiData,Tracer,InitPublLDmfa,RemovePublLDmfa,CleanPublLDmf)= -%% {ok,Pid} | {error,Reason} -%% TiData={file,FileName}|{relay,Node} -%% Tracer=pid()|port() -%% FileName=string() -%% InitPublLDmfa={Mod,Func,ArgList} -%% RemovePublLDmf={Mod,Func} | void -%% RemovePublLDmf(PublLD)->nothing significant. -%% These functions are called to create and destroy the public loopdata -%% structure available to the meta-trace CallFunc and ReturnFunc. -%% CleanPublLDmf={Mod,Func} -%% This function will periodically be called to clean the public LD from -%% pending meta-trace messages waiting for a corresponding return_from -%% message. -%% -%% Starts a meta-tracer process, opening the ti-file specified in TiData. PublLD -%% is used to communicate data, typically between a call and return_from. -%% If no special initialization function is specified a standard one is used. -%% Note that the meta tracer function must know "who" is the regular tracer -%% (process or port). This because it must be possible to append {tracer,Tracer} -%% in meta match specs. -start(TiData,Tracer) -> - Pid=spawn_link(?MODULE, - init, - [self(), - TiData, - Tracer, - {?MODULE,init_std_publld,[2,[]]}, - void, - {?MODULE,clean_std_publld}]), - wait_for_reply(Pid). -start(TiData,Tracer,InitPublLDmfa,RemovePublLDmf,CleanPublLDmf) -> - Pid=spawn_link(?MODULE, - init, - [self(),TiData,Tracer,InitPublLDmfa,RemovePublLDmf,CleanPublLDmf]), - wait_for_reply(Pid). - -wait_for_reply(Pid) -> - receive - {Pid,ok} -> - {ok,Pid}; - {Pid,{error,Reason}} -> - {error,Reason} - after - 10000 -> % After very long time. - exit(Pid,kill), % It must be hanging. - {error,time_out} - end. -%% ----------------------------------------------------------------------------- - -%% stop(Pid)=ok -%% Pid=Adders to the meta tracer, pid(). -%% Shutsdown the metatracer. -stop(Pid) -> - Pid ! {stop,self()}, - ok. -%% ----------------------------------------------------------------------------- - -%% suspend(Pid)=ok -%% Pid=Adders to the meta tracer, pid(). -%% Suspends the meta tracer by removing all meta trace patterns. -suspend(Pid) -> - Pid ! {suspend,self()}, - ok. -%% ----------------------------------------------------------------------------- - -%% init_tpm(Pid,Mod,Func,Arity,CallFunc)= -%% init_tpm(Pid,Mod,Func,Arity,InitFunc,CallFunc,ReturnFunc,RemoveFunc)=ok|{error,Reason}. -%% Pid=Address to meta tracer process, pid(). -%% Mod,Func=Pointing out the function which shall be meta traced, atom(). -%% Arity=As above, integer(). -%% InitFunc,RemoveFunc={Module,Function}|fun(), functions being called when -%% to initialize the public loopdata structure, and to reset it. -%% InitFunc(Mod,Func,Arity,PublLD)->{ok,NewPublLD,Output} -%% Supposed to initialize whatever needs to be done before -%% handling any incoming meta-trace message for the Mod:Func/Arity. -%% RemoveFunc(Mod,Func,Arity,PublLD)->{ok,NewPublLD} -%% Called when meta tracing of Mod:Func/Arity is stopped. It is supposed -%% to clear datastructures away from the PublLD. -%% Initializes the public loopdata for this function. Note that we can not use wildcards -%% here (even if it is perfectly legal in Erlang). It also sets the CallFunc and -%% ReturnFunc for the meta traced function. The function is hence ready to be -%% meta traced with either tpm/5 or tpm_ms/5. -%% This function is synchronous, waiting for a reply from the meta server. -init_tpm(Pid,Mod,Func,Arity,CallFunc) -> - init_tpm(Pid,Mod,Func,Arity,void,CallFunc,void,void). -init_tpm(Pid,Mod,Func,Arity,InitFunc,CallFunc,ReturnFunc,RemoveFunc) -> - send_wait(Pid, - {init_tpm,{Mod,Func,Arity},InitFunc,CallFunc,ReturnFunc,RemoveFunc}). -%% ----------------------------------------------------------------------------- - -%% tpm(Pid,Mod,Func,Arity,MatchSpec)={ok,N}|{error,Reason} -%% tpm(Pid,Mod,Func,Arity,MatchSpec,CallFunc)={ok,N}|{error,Reason} -%% tpm(Pid,Mod,Func,Arity,MatchSpec,InitFunc,CallFunc,ReturnFunc,RemoveFunc)= -%% Pid=Address to meta tracer process, pid(). -%% Mod,Func=Pointing out the function which shall be meta traced, atom(). -%% Arity=As above, integer(). -%% MatchSpec=List of match specification, possibly empty. Remember {return_trace} -%% if expecting return_from messages. -%% InitFunc,CallFunc,ReturnFunc,RemoveFunc={Module,Function}|fun(), -%% functions being called when these functions are called by the meta trace -%% server at certain events. -%% CallFunc(CallingPid,ActualArgList,PublLD)->{ok,NewPrivLD,Output} -%% ReturnFunc(CallingPid,ReturnValue,PublLD)->{ok,NewPrivLD,Output} -%% When a call respectively return_from trace message arrives for the meta -%% traced function, the corresponding function is called. -%% The ReturnFunc must handle the fact that a return_from message arrives -%% for a call which was never noticed. This because the message queue of the -%% meta tracer may have been emptied. -%% Reason=badarg | -%% Output=Characters to be written to the ti-file, bin() | 'void' -%% The tpm/5 function simply starts meta tracing for the function. It must -%% previously have been initialized. -%% tpm/6 & /9 initializes the function and starts meta tracing. -tpm(Pid,Mod,Func,Arity,MatchSpec) - when is_atom(Mod),is_atom(Func),is_integer(Arity),is_list(MatchSpec),Mod/='_',Func/='_'-> - send_wait(Pid,{tpm,{Mod,Func,Arity,MatchSpec}}); -tpm(_,_,_,_,_) -> - {error,badarg}. - -tpm(Pid,Mod,Func,Arity,MatchSpec,CallFunc) -> - tpm(Pid,Mod,Func,Arity,MatchSpec,void,CallFunc,void,void). - -tpm(Pid,Mod,Func,Arity,MatchSpec,InitFunc,CallFunc,ReturnFunc,RemoveFunc) - when is_atom(Mod),is_atom(Func),is_integer(Arity),is_list(MatchSpec),Mod/='_',Func/='_' -> - send_wait(Pid,{tpm,{Mod,Func,Arity,MatchSpec},InitFunc,CallFunc,ReturnFunc,RemoveFunc}); -tpm(_,_,_,_,_,_,_,_,_) -> - {error,badarg}. -%% ----------------------------------------------------------------------------- - -%% Same as tpm/X but the meta tracer will automatically append {tracer,Tracer} -%% to the enable list in a {trace,Disable,Enable} match spec action term. -tpm_tracer(Pid,Mod,Func,Arity,MatchSpec) - when is_atom(Mod),is_atom(Func),is_integer(Arity),is_list(MatchSpec),Mod/='_',Func/='_'-> - send_wait(Pid,{tpm_tracer,{Mod,Func,Arity,MatchSpec}}); -tpm_tracer(_,_,_,_,_) -> - {error,badarg}. - -tpm_tracer(Pid,Mod,Func,Arity,MatchSpec,CallFunc) -> - tpm_tracer(Pid,Mod,Func,Arity,MatchSpec,void,CallFunc,void,void). - -tpm_tracer(Pid,Mod,Func,Arity,MatchSpec,InitFunc,CallFunc,ReturnFunc,RemoveFunc) - when is_atom(Mod),is_atom(Func),is_integer(Arity),is_list(MatchSpec),Mod/='_',Func/='_' -> - send_wait(Pid,{tpm_tracer, - {Mod,Func,Arity,MatchSpec}, - InitFunc,CallFunc,ReturnFunc,RemoveFunc}); -tpm_tracer(_,_,_,_,_,_,_,_,_) -> - {error,badarg}. -%% ----------------------------------------------------------------------------- - -%% tpm_ms(Pid,Mod,Func,Arity,MSname,MS)={ok,N}|{error,Reason} -%% Pid=Address to meta tracer process, pid(). -%% Mod,Func=Pointing out the function to which we shall add a match-spec., atom(). -%% Arity=As above, integer(). -%% MSname=A name to be used if this MS shall be removed later. term(). -%% MatchSpec=List of match specification, Remember {return_trace} -%% if expecting return_from messages. -%% This function adds a list of match-specs to the already existing ones. It -%% uses an internal database to keep track of existing match-specs. If the -%% match-spec does not result in any meta traced functions (for whatever reason), -%% the MS is not saved in the database. The previously known match-specs are -%% not removed. -tpm_ms(Pid,Mod,Func,Arity,MSname,MS) -> - send_wait(Pid,{tpm_ms,{Mod,Func,Arity},MSname,MS}). -%% ----------------------------------------------------------------------------- - -%% Same as tpm_ms/6 but the meta tracer will automatically append {tracer,Tracer} -%% to the enable list in a {trace,Disable,Enable} match spec action term. -tpm_ms_tracer(Pid,Mod,Func,Arity,MSname,MS) -> - send_wait(Pid,{tpm_ms_tracer,{Mod,Func,Arity},MSname,MS}). -%% ----------------------------------------------------------------------------- - -%% ctpm_ms(Pid,Mod,Func,Arity)=ok -%% -%% Removes a names match-spec from the meta traced function. Note that is never -%% a fault to remove an MS. Not even from a function which is non existant. -ctpm_ms(Pid,Mod,Func,Arity,MSname) -> - send_wait(Pid,{ctpm_ms,{Mod,Func,Arity},MSname}). -%% ----------------------------------------------------------------------------- - -%% Quick versions for erlang:register/2 which also uses a default CallFunc -%% and a default ReturnFunc. -local_register(Pid) -> - Res1=tpm(Pid, - erlang,register,2,[{'_',[],[{exception_trace}]}], - fun metafunc_init/4,fun local_register_call/3, - fun local_register_return/3,void), - Res2=tpm(Pid, - erlang,unregister,1,[], - void,fun local_unregister_call/3,void,void), - {Res1,Res2}. -%% ----------------------------------------------------------------------------- - -%% Quick version for global:register_name/2, /3. -global_register(Pid) -> - Res1=tpm(Pid,global,handle_call,3,[{[{register,'_','_','_'},'_','_'],[],[]}], - void,fun global_register_call/3,void,void), - Res2=tpm(Pid,global,delete_global_name,2,[], - void,fun global_unregister_call/3,void,void), - {Res1,Res2}. -%% ----------------------------------------------------------------------------- - -%% ctpm(Pid,Mod,Func,Arity)=ok|{error,bad_mfa} -%% -%% Removes the meta trace pattern for the function, means stops generating output -%% for this function. The public LD may be cleared by the previously entered -%% RemoveFunc. -ctpm(Pid,Mod,Func,Arity) -> - send_wait(Pid,{ctpm,{Mod,Func,Arity}}). -%% ----------------------------------------------------------------------------- - -%% remove_local_register(Pid)={Res1,Res2} -%% Res1,Res2=ok|{error,Reason} -remove_local_register(Pid) -> - Res1=ctpm(Pid,erlang,register,2), - Res2=ctpm(Pid,erlang,unregister,1), - {Res1,Res2}. -%% ----------------------------------------------------------------------------- - -%% remove_global_register(Pid)={Res1,Res2} -%% Res1,Res2=ok|{error,Reason} -remove_global_register(Pid) -> - Res1=ctpm(Pid,global,handle_call,3), - Res2=ctpm(Pid,global,delete_global_name,2), - {Res1,Res2}. -%% ----------------------------------------------------------------------------- - -%% Exported help functions which may be used in programming CallFunc and/or -%% ReturnFunc. Useful if the call is done on one node but must trigger the -%% start of something at other nodes. -metacast_call(Nodes,OrigPid,M,F,Args) -> - multicast(Nodes,{trace_ts,OrigPid,call,{M,F,Args},void}), - ok. - -metacast_return_from(Nodes,OrigPid,M,F,Arity,Value) -> - multicast(Nodes,{trace_ts,OrigPid,return_from,{M,F,Arity},Value,void}), - ok. - -multicast([Node|Rest],Msg) -> - {?MODULE,Node} ! Msg, - multicast(Rest,Msg); -multicast([],_) -> - true. -%% ----------------------------------------------------------------------------- - -%% get_states(Pid)={ok,LD,PubLD}. -get_state(Pid) -> - send_wait(Pid,get_state). -%% ----------------------------------------------------------------------------- - - -send_wait(To,Msg) -> - Ref=make_ref(), - MRef=erlang:monitor(process,To), - To ! {Msg,Ref,self()}, - receive - {inviso_rt_meta_reply,Ref,Reply} -> - erlang:demonitor(MRef), - Reply; - {'DOWN',MRef,_,_To,_Reason} -> - {error,no_metatracer} - end. - -reply(To,Ref,Reply) -> - To ! {inviso_rt_meta_reply,Ref,Reply}. -%% ----------------------------------------------------------------------------- - -%% ============================================================================= -%% Special API. -%% ============================================================================= - -%% write_ti(OutPut)= -%% OutPut=binary() -%% Makes an extra entry into the trace information file (ti-file). This is useful -%% if a pid-alias association is learned in another way than through a meta traced -%% function call. Note that this API can only be used locally at the node in -%% question. -write_ti(OutPut) -> - catch ?MODULE ! {write_ti,OutPut}. -%% ----------------------------------------------------------------------------- - - -%% ============================================================================= -%% API intended to be used on CallFuncs and RemoveFuncs. -%% ============================================================================= - -%% The reason there must be a special API for CallFuncs and RemoveFuncs are is -%% that those functions are executed inside *this* process context. Hence they -%% can not make function calls requiering this process to receive messages. - -%% Returns the tracer used for regular tracing. The reason this is implemented -%% in this way is that this function is intended to be used in meta trace call- -%% back functions. And there we can not have message passing API:s to the meta -%% trace(!). -get_tracer() -> - get(tracer). -%% ----------------------------------------------------------------------------- - -%% Function equivalent to inviso_rt:tpm_ms/6. This function can *only* be used -%% inside a CallFunc or a RemoveFunc. -tpm_ms(Mod,Func,Arity,MSname,MS) -> - case check_mfarity_exists(Mod,Func,Arity) of - yes -> % Ok, and args must be ok then also. - {ok,h_tpm_ms(Mod,Func,Arity,MSname,MS)}; - no -> - {error,not_initiated} - end. -%% ----------------------------------------------------------------------------- - -tpm_ms_tracer(Mod,Func,Arity,MSname,MS) -> - case check_mfarity_exists(Mod,Func,Arity) of - yes -> % Ok, and args must be ok then also. - NewMS=add_tracer(MS,get_tracer()), - {ok,h_tpm_ms(Mod,Func,Arity,MSname,NewMS)}; - no -> - {error,not_initiated} - end. -%% ----------------------------------------------------------------------------- - -%% Function that returns all MSname in use for Mod:Func/Arity -list_tpm_ms(Mod,Func,Arity) -> - {ok,h_list_tpm_ms(Mod,Func,Arity)}. -%% ----------------------------------------------------------------------------- - -%% Function equivalent to inviso_rt:ctpm_ms/5. This function can *only* be used -%% inside a CallFunc or a RemoveFunc. -ctpm_ms(Mod,Func,Arity,MSname) -> - h_ctpm_ms(Mod,Func,Arity,MSname), - ok. -%% ----------------------------------------------------------------------------- - - -%% ============================================================================= -%% The server implemenation. -%% ============================================================================= - -init(Parent,TiData,Tracer,InitPublLDmfa,RemovePublLDmf,CleanPublLDmf) -> - process_flag(priority,high), % Since we may receive from many procs. - register(?MODULE,self()), % So we can act as relay receiver. - case open_traceinfo_file(TiData) of - {ok,TI} -> % The ti.-file. - TId=ets:new(?NAMED_MS_TAB,[named_table,set,protected]), - PublLD=do_init_publ_ld(InitPublLDmfa), - Parent ! {self(),ok}, - put(tracer,Tracer), % Uggly quick fix! - loop(Parent, - Tracer, - TI, - mk_new_ld(InitPublLDmfa,RemovePublLDmf,CleanPublLDmf,TId), - PublLD, - now()); - {error,Reason} -> - Parent ! {self(),{error,Reason}} - end. -%% ----------------------------------------------------------------------------- - -loop(Parent,Tracer,TI,LD,PrevPublLD,PrevCleanTime) -> - {PublLD,CleanTime}=throw_old_failed(get_cleanpublldmf_ld(LD),PrevPublLD,PrevCleanTime), - receive - {{init_tpm,{Mod,Func,Arity},InitFunc,CallFunc,ReturnFunc,RemoveFunc},Ref,Parent} -> - case check_mfarity_exists(Mod,Func,Arity) of - no -> % Good then we can add it! - case check_tpm_args(Mod,Func,Arity) of - true -> % Args are ok. - {NewLD,NewPublLD}= - h_init_tpm(Mod,Func,Arity, - InitFunc,CallFunc,ReturnFunc,RemoveFunc, - TI,LD,PublLD), - reply(Parent,Ref,ok), - loop(Parent,Tracer,TI,NewLD,NewPublLD,CleanTime); - false -> % Faulty arguments, - reply(Parent,Ref,{error,bad_mfa}), - loop(Parent,Tracer,TI,LD,PublLD,CleanTime) - end; - yes -> % If it already exists, cant init again. - reply(Parent,Ref,{error,already_initiated}), - loop(Parent,Tracer,TI,LD,PublLD,CleanTime) - end; - {{tpm,{Mod,Func,Arity,MS},InitFunc,CallFunc,ReturnFunc,RemoveFunc},Ref,Parent} -> - case check_mfarity_exists(Mod,Func,Arity) of - no -> % Good then we can add it! - case check_tpm_args(Mod,Func,Arity) of - true -> % Args are ok. - {NewLD,NewPublLD,N}= - h_tpm(Mod,Func,Arity,MS, - InitFunc,CallFunc,ReturnFunc,RemoveFunc, - TI,LD,PublLD), - reply(Parent,Ref,{ok,N}), - loop(Parent,Tracer,TI,NewLD,NewPublLD,CleanTime); - false -> - reply(Parent,Ref,{error,bad_mfa}), - loop(Parent,Tracer,TI,LD,PublLD,CleanTime) - end; - yes -> - reply(Parent,Ref,{error,already_initiated}), - loop(Parent,Tracer,TI,LD,PublLD,CleanTime) - end; - {{tpm,{Mod,Func,Arity,MS}},Ref,Parent} -> - case check_mfarity_exists(Mod,Func,Arity) of - yes -> % Ok, and args must be ok then also. - {NewLD,N}=h_tpm(Mod,Func,Arity,MS,LD), - reply(Parent,Ref,{ok,N}), - loop(Parent,Tracer,TI,NewLD,PublLD,CleanTime); - no -> % Must be initiated before. - reply(Parent,Ref,{error,not_initiated}), - loop(Parent,Tracer,TI,LD,PublLD,CleanTime) - end; - {{tpm_tracer,{Mod,Func,Arity,MS},InitFunc,CallFunc,ReturnFunc,RemoveFunc},Ref,Parent} -> - case check_mfarity_exists(Mod,Func,Arity) of - no -> % Good then we can add it! - case check_tpm_args(Mod,Func,Arity) of - true -> % Args are ok. - NewMS=add_tracer(MS,Tracer), - {NewLD,NewPublLD,N}= - h_tpm(Mod,Func,Arity,NewMS, - InitFunc,CallFunc,ReturnFunc,RemoveFunc, - TI,LD,PublLD), - reply(Parent,Ref,{ok,N}), - loop(Parent,Tracer,TI,NewLD,NewPublLD,CleanTime); - false -> - reply(Parent,Ref,{error,bad_mfa}), - loop(Parent,Tracer,TI,LD,PublLD,CleanTime) - end; - yes -> - reply(Parent,Ref,{error,already_initiated}), - loop(Parent,Tracer,TI,LD,PublLD,CleanTime) - end; - {{tpm_tracer,{Mod,Func,Arity,MS}},Ref,Parent} -> - case check_mfarity_exists(Mod,Func,Arity) of - yes -> % Ok, and args must be ok then also. - NewMS=add_tracer(MS,Tracer), - {NewLD,N}=h_tpm(Mod,Func,Arity,NewMS,LD), - reply(Parent,Ref,{ok,N}), - loop(Parent,Tracer,TI,NewLD,PublLD,CleanTime); - no -> % Must be initiated before. - reply(Parent,Ref,{error,not_initiated}), - loop(Parent,Tracer,TI,LD,PublLD,CleanTime) - end; - {{tpm_ms,{Mod,Func,Arity},MSname,MS},Ref,Parent} -> - case check_mfarity_exists(Mod,Func,Arity) of - yes -> % Ok, and args must be ok then also. - reply(Parent,Ref,{ok,h_tpm_ms(Mod,Func,Arity,MSname,MS)}), - loop(Parent,Tracer,TI,LD,PublLD,CleanTime); - no -> - reply(Parent,Ref,{error,not_initiated}), - loop(Parent,Tracer,TI,LD,PublLD,CleanTime) - end; - {{tpm_ms_tracer,{Mod,Func,Arity},MSname,MS},Ref,Parent} -> - case check_mfarity_exists(Mod,Func,Arity) of - yes -> % Ok, and args must be ok then also. - NewMS=add_tracer(MS,Tracer), - reply(Parent,Ref,{ok,h_tpm_ms(Mod,Func,Arity,MSname,NewMS)}), - loop(Parent,Tracer,TI,LD,PublLD,CleanTime); - no -> - reply(Parent,Ref,{error,not_initiated}), - loop(Parent,Tracer,TI,LD,PublLD,CleanTime) - end; - {{ctpm_ms,{Mod,Func,Arity},MSname},Ref,Parent} -> - reply(Parent,Ref,ok), - h_ctpm_ms(Mod,Func,Arity,MSname), - loop(Parent,Tracer,TI,LD,PublLD,CleanTime); - {{ctpm,{Mod,Func,Arity}},Ref,Parent} -> - case get_remove_func_ld(Mod,Func,Arity,LD) of - false -> % Incorrect Mod:Func/Arity! - reply(Parent,Ref,{error,bad_mfa}), - loop(Parent,Tracer,TI,LD,PublLD,CleanTime); % Do nothing! - MF -> % {M,F}, Func or 'void'. - catch erlang:trace_pattern({Mod,Func,Arity},false,[meta]), - NewPublLD=do_removefunc(MF,Mod,Func,Arity,PublLD), - NewLD=ctpm_ld(Mod,Func,Arity,LD), - reply(Parent,Ref,ok), - loop(Parent,Tracer,TI,NewLD,NewPublLD,CleanTime) - end; - {suspend,Parent} -> % Removes all meta trace patterns. - stop_all_meta_tracing(get_all_meta_funcs_ld(LD),PublLD,LD), - do_remove_publ_ld(get_removepublldmf_ld(LD),PublLD), - NewPublLD=do_init_publ_ld(get_initpublldmfa_ld(LD)), - loop(Parent,Tracer,TI,reset_ld(LD),NewPublLD,CleanTime); - {stop,Parent} -> % Make a controlled shutdown. - stop_all_meta_tracing(get_all_meta_funcs_ld(LD),PublLD,LD), - do_remove_publ_ld(get_removepublldmf_ld(LD),PublLD), - close_traceinfo_file(TI); % And then simply terminate. - {trace_ts,Pid,call,{M,F,Args},TS} -> - case handle_meta(get_call_func_ld(M,F,length(Args),LD),Pid,{call,Args,TS},PublLD) of - {ok,NewPublLD,Output} when is_binary(Output);is_list(Output) -> - write_output(TI,Output), - loop(Parent,Tracer,TI,LD,NewPublLD,CleanTime); - {ok,NewPublLD,_} -> % No output to the ti-file this time. - loop(Parent,Tracer,TI,LD,NewPublLD,CleanTime); - _ -> % Not handled correct, not much to do. - loop(Parent,Tracer,TI,LD,PublLD,CleanTime) - end; - {trace_ts,Pid,TypeTag,{M,F,Arity},Value,TS} - when TypeTag==return_from;TypeTag==exception_from -> - case handle_meta(get_return_func_ld(M,F,Arity,LD),Pid,{TypeTag,Value,TS},PublLD) of - {ok,NewPublLD,Output} when is_binary(Output);is_list(Output) -> - write_output(TI,Output), - loop(Parent,Tracer,TI,LD,NewPublLD,CleanTime); - {ok,NewPublLD,_} -> % No output to the ti-file this time. - loop(Parent,Tracer,TI,LD,NewPublLD,CleanTime); - _ -> % Not handled correct, not much to do. - loop(Parent,Tracer,TI,LD,PublLD,CleanTime) - end; - {relayed_meta,Bin} -> - write_output(TI,Bin), - loop(Parent,Tracer,TI,LD,PublLD,CleanTime); - {write_ti,OutPut} -> - write_output(TI,OutPut), - loop(Parent,Tracer,TI,LD,PublLD,CleanTime); - {get_state,Ref,From} -> % Debug function. - reply(From,Ref,{ok,LD,PublLD}), - loop(Parent,Tracer,TI,LD,PublLD,CleanTime); - _Other -> - loop(Parent,Tracer,TI,LD,PublLD,CleanTime) - end. - - -%% ============================================================================= -%% First level help functions. -%% ============================================================================= - -%% Function which opens the trace-information file(s). It must understand -%% the tidata specification which is part of the tracerdata given to the -%% runtime component during init_tracing. -%% It must return an internal notation of the time of file open and a -%% useful descriptor the write_output function can use. -%% Returns {ok,TiDescriptor} or {error,Reason}. -open_traceinfo_file({file,FileName}) -> % A plain raw binary file. - case file:open(FileName,[write,raw,binary]) of - {ok,FD} -> - {ok,{file,FD}}; - {error,Reason} -> - {error,{open,[FileName,Reason]}} - end; -open_traceinfo_file({relay,ToNode}) -> % Use distributed Erlang. - {ok,{relay,ToNode}}; -open_traceinfo_file(IncorrectTI) -> - {error,{badarg,IncorrectTI}}. -%% ----------------------------------------------------------------------------- - -close_traceinfo_file({file,FD}) -> - file:close(FD); -close_traceinfo_file(_) -> - ok. -%% ----------------------------------------------------------------------------- - -%% Help function handling initializing meta tracing of a function. -%% Returns {NewLD,NewPublLD}. -h_init_tpm(Mod,Func,Arity,InitFunc,CallFunc,ReturnFunc,RemoveFunc,TI,LD,PublLD) -> - case do_initfunc(InitFunc,Mod,Func,Arity,PublLD) of - {NewPublLD,Output} -> - write_output(TI,Output), - NewLD=init_tpm_ld(Mod,Func,Arity,CallFunc,ReturnFunc,RemoveFunc,LD), - {NewLD,NewPublLD}; - false -> % The initfunc did not do anything. - NewLD=init_tpm_ld(Mod,Func,Arity,CallFunc,ReturnFunc,RemoveFunc,LD), - {NewLD,PublLD} - end. -%% ----------------------------------------------------------------------------- - -%% Help function handling initializing meta tracing of a function and also -%% set the meta trace pattern as specified. -%% Returns {NewLD,NewPublLD,N}. -h_tpm(Mod,Func,Arity,MS,InitFunc,CallFunc,ReturnFunc,RemoveFunc,TI,LD,PublLD) -> - {NewLD,NewPublLD}= - h_init_tpm(Mod,Func,Arity,InitFunc,CallFunc,ReturnFunc,RemoveFunc,TI,LD,PublLD), - case set_meta_tracing(Mod,Func,Arity,MS) of - true -> % Ok, set one pattern. - {NewLD,NewPublLD,1}; - false -> - {NewLD,NewPublLD,0} - end. -%% ----------------------------------------------------------------------------- - -%% Help function handling setting meta trace patter for a function which has -%% already been intialized. Note that we must remove all potentially stored -%% match-specs, if this function has been given match-specs before with -%% tpm_ms. -%% Returns a {NewLD,N}. -h_tpm(Mod,Func,Arity,MS,LD) -> - case set_meta_tracing(Mod,Func,Arity,MS) of - true -> - {remove_ms_ld(Mod,Func,Arity,LD),1}; - false -> - {LD,0} - end. -%% ----------------------------------------------------------------------------- - -%% Help function that adds a match-spec to Mod:Func/Arity. It is not defined -%% in which order the match-specs will be given to the BIF. -%% Note that if an MS with the same name as an exiting is inserted, the previous -%% match-spec will be removed. -%% Very important to realise is that the empty meta match spec [] imposes no -%% restrictions what so ever on the generating of meta trace call messages. -%% Uncontrolled sending of such messages may quickly drain power from the system. -%% Since an empty match-spec will "disappear" when added to other match specs, -%% the empty match is transformed to what it actually is: [{'_',[],[]}]. -%% Returns 0 or 1 indicating failure or success. -h_tpm_ms(Mod,Func,Arity,MSname,MS) -> - MSsNames=get_ms_ld(Mod,Func,Arity), % Fetch all previous match-specs. - TransformedMS=h_tpm_ms_convert_null_ms(MS), - MSsNames1=lists:keydelete(MSname,1,MSsNames), % If it already existed, it is gone! - NewMSs=lists:flatten([TransformedMS,lists:map(fun({_Name,MSx})->MSx end,MSsNames1)]), - case set_meta_tracing(Mod,Func,Arity,NewMSs) of - true -> % We only save the MS if it was good. - put_ms_ld(Mod,Func,Arity,MSname,TransformedMS,MSsNames1), - 1; - false -> - 0 - end. - -%% Help function converting the null match spec into, still a null match spec, -%% on a proper match spec format. This because it will otherwise be difficult -%% to see the difference between no active tpm_ms and all a set of null ms. -h_tpm_ms_convert_null_ms([]) -> - [{'_',[],[]}]; -h_tpm_ms_convert_null_ms(MS) -> - MS. -%% ----------------------------------------------------------------------------- - -%% Help function returning a list of all names used for match-functions for -%% the Mod:Func/Arity in question. -h_list_tpm_ms(Mod,Func,Arity) -> - MSsNames=get_ms_ld(Mod,Func,Arity), % A list of {MSname,MS}. - lists:map(fun({MSname,_})->MSname end,MSsNames). -%% ----------------------------------------------------------------------------- - -%% Function that removes a named match-spec. Returns nothing significant. -%% Note that if we end up with no match-specs, we must remove the meta trace -%% patten all together. That is bringing the function back to just initiated. -h_ctpm_ms(Mod,Func,Arity,MSname) -> - case get_ms_ld(Mod,Func,Arity) of - [] -> % The name does certainly not exist! - true; % We don't have to do anything. - MSsNames -> - case lists:keysearch(MSname,1,MSsNames) of - {value,{_,_MS}} -> % Ok, we must do something! - NewMSsNames=lists:keydelete(MSname,1,MSsNames), - case lists:flatten(lists:map(fun({_Name,MS})->MS end,NewMSsNames)) of - [] -> % This means stop meta tracing. - set_meta_tracing(Mod,Func,Arity,false); - NewMSs -> - set_meta_tracing(Mod,Func,Arity,NewMSs) - end, - set_ms_ld(Mod,Func,Arity,NewMSsNames); - false -> % But this name does not exist. - true % So we do not have to do anything. - end - end. -%% ----------------------------------------------------------------------------- - -%% Function that checks the arguments to the meta trace pattern. The reason we -%% must do this is that we can only allow meta tracing on specific functions and -%% not using wildpatterns. Otherwise the meta trace server will not understand -%% which callfunc for instance to call when a meta-trace message is generated -%% for a function. -%% Returns 'true' or 'false'. -check_tpm_args(Mod,Func,Arity) - when is_atom(Mod),is_atom(Func),is_integer(Arity),Mod/='_',Func/='_' -> - true; -check_tpm_args(_,_,_) -> - false. -%% ----------------------------------------------------------------------------- - -%% Help function which calls the actual BIF setting meta-trace-patterns. -%% Returns 'true' or 'false'. -set_meta_tracing(Mod,Func,Arity,MS) when is_atom(Mod) -> - case erlang:module_loaded(Mod) of - true -> - set_meta_tracing_2(Mod,Func,Arity,MS); - false -> % The module is not loaded. - case code:ensure_loaded(Mod) of - {module,_Mod} -> - set_meta_tracing_2(Mod,Func,Arity,MS); - {error,_Reason} -> % Could not load the module. - false % No use try to trace. - end - end; -set_meta_tracing(_,_,_,_) -> - false. - -set_meta_tracing_2(Mod,Func,Arity,MS) -> - case catch erlang:trace_pattern({Mod,Func,Arity},MS,[meta]) of - 0 -> % Hmm, nothing happend :-) - false; - N when is_integer(N) -> % The normal case, some functions were hit. - true; - {'EXIT',_Reason} -> - false - end. -%% ----------------------------------------------------------------------------- - -%% Help function which removes all meta trace pattern for the functions mentioned -%% in the list being first argument. It also executes the remove funcs for each -%% and every no longer meta traced function. This done since some of the remove -%% functions may do side-effects (like deleteing ETS tables). -%% Returns nothing significant. -stop_all_meta_tracing([{M,F,Arity}|Rest],PublLD,LD) -> - catch erlang:trace_pattern({M,F,Arity},false,[meta]), - NewPublLD=do_removefunc(get_remove_func_ld(M,F,Arity,LD),M,F,Arity,PublLD), - stop_all_meta_tracing(Rest,NewPublLD,LD); -stop_all_meta_tracing([],_,_) -> - true. -%% ----------------------------------------------------------------------------- - -%% This function calls the function registered to be handler for a certain -%% meta-traced function. Such a function or fun must take three arguments -%% and return {ok,NewPrivLD,OutPutBinary} or 'false'. OutPutBinary may be -%% something else, and is then ignored. -handle_meta({M,F},Pid,Arg1,PrivLD) -> - (catch M:F(Pid,Arg1,PrivLD)); -handle_meta(Fun,Pid,Arg1,PrivLD) when is_function(Fun) -> - (catch Fun(Pid,Arg1,PrivLD)); -handle_meta(_,_,_,_) -> % Don't know how to do this. - false. -%% ----------------------------------------------------------------------------- - -%% Help function writing output from a callback function to the ti-file. -%% Output can be a binary or a list of binaries. -write_output(TI,[OutPut|Rest]) -> - write_output(TI,OutPut), - write_output(TI,Rest); -write_output({file,FD},Bin) when is_binary(Bin) -> % Plain direct-binary file - Size=byte_size(Bin), - file:write(FD,list_to_binary([<<0,Size:32>>,Bin])); -write_output({relay,ToNode},Bin) when is_atom(ToNode),is_binary(Bin) -> - {inviso_rt_meta,ToNode} ! {relayed_meta,Bin}; -write_output(_,_) -> % Don't understand, just skip. - true. -%% ----------------------------------------------------------------------------- - - -%% ============================================================================= -%% Various help functions. -%% ============================================================================= - -%% Help function initializing the public loopdata structure. Note that if the -%% supplied InitPublLDmfa is faulty we let the structure become the error. -%% The error will most likely turn up in an error report somewhere, eventually. -do_init_publ_ld({M,F,Args}) when is_atom(M),is_atom(F),is_list(Args) -> - case catch apply(M,F,Args) of - {'EXIT',_Reason} -> - {error,init_publ_ld_func}; % Let the struct be this error! - InitialPublLD -> - InitialPublLD - end; -do_init_publ_ld(_) -> - {error,init_publ_ld_func}. -%% ----------------------------------------------------------------------------- - -%% Help function which removes the public loopdata structure. The function does -%% not necessarily have to exist. Returns nothing significant. -do_remove_publ_ld({M,F},PublLD) when is_atom(M),is_atom(F) -> - catch M:F(PublLD); -do_remove_publ_ld(_,_) -> - true. -%% ----------------------------------------------------------------------------- - -%% Hlp function initializing a particular meta traced function into the public -%% loopdata. Note that the function is not mandatory. -%% Returns {NewPublLD,Output} or 'false'. -do_initfunc({M,F},Mod,Func,Arity,PublLD) when is_atom(M),is_atom(F) -> - case catch M:F(Mod,Func,Arity,PublLD) of - {ok,NewPublLD,Output} -> - {NewPublLD,Output}; - _ -> % Everything else is an error. - false % Act as no initialization function. - end; -do_initfunc(Fun,Mod,Func,Arity,PublLD) when is_function(Fun) -> - case catch Fun(Mod,Func,Arity,PublLD) of - {ok,NewPublLD,Output} -> - {NewPublLD,Output}; - _ -> % Everything else is an error. - false % Act as no initialization function. - end; -do_initfunc(_,_,_,_,_) -> % Perhaps too generous, should be 'void' only. - false. -%% ----------------------------------------------------------------------------- - -%% Help function removing a particular meta traced function from the public -%% loopdata. Note that we do not make much noice should the call back function -%% be faulty. -do_removefunc({M,F},Mod,Func,Arity,PublLD) when is_atom(M),is_atom(F) -> - case catch M:F(Mod,Func,Arity,PublLD) of - {ok,NewPublLD} -> - NewPublLD; - _ -> % Everything else is an error. - PublLD % Act as no initialization function. - end; -do_removefunc(Fun,Mod,Func,Arity,PublLD) when is_function(Fun) -> - case catch Fun(Mod,Func,Arity,PublLD) of - {ok,NewPublLD} -> - NewPublLD; - _ -> % Everything else is an error. - PublLD % Act as no initialization function. - end; -do_removefunc(_,_,_,_,PublLD) -> - PublLD. -%% ----------------------------------------------------------------------------- - -%% Function that, if the time has come, goes through the priv-ld structure and -%% cleans away entryn left behind. The usual cause is that the function call -%% caused an exception and there were therefore no matching return_from. -%% Returns {NewPrivLD,now()}. -throw_old_failed({M,F},PrivLD,PrevClean) -> - case difference_in_now(PrevClean,now(),60) of % We clean once every minute. - true -> - case catch apply(M,F,[PrivLD]) of - {'EXIT',_Reason} -> % Something went wrong, ignore it. - {PrivLD,now()}; % Just keep the old priv-ld. - NewPrivLD -> % The function must return a priv-ld. - {NewPrivLD,now()} - end; - false -> % Not time yet! - {PrivLD,PrevClean} - end. -%% ----------------------------------------------------------------------------- - -%% Help function comparing two now timestamps. Returns true or false depending -%% on if S2 is more than DiffS seconds after S1. Only works for differences -%% less than 1 million seconds. -difference_in_now({MegaS1,S1,_},{MegaS2,S2,_},DiffS) -> - if - MegaS1+1<MegaS2 -> % More than 1 Mega sec. difference. - true; - MegaS1==MegaS2,S1+DiffS<S2 -> - true; - MegaS1+1==MegaS2,S1+DiffS<S2+1000000 -> - true; - true -> - false - end. -%% ----------------------------------------------------------------------------- - -%% This help function adds a {tracer,Tracer} to the enable-list in a 'trace' -%% match spec action. The reason for this is that the author of the a meta -%% match spec meant to turn tracing on for the process executing the match spec -%% can not know the tracer. This since the match spec is most likely authored -%% at the control component's node, and not here. -%% Note the double tuple necessary to make it just precise a tuple! -%% Returns a new match spec. -add_tracer([MS1|Rest],Tracer) -> - [add_tracer_2(MS1,Tracer)|add_tracer(Rest,Tracer)]; -add_tracer([],_) -> - []; -add_tracer(NotList,_Tracer) -> % Can be 'false', but also an error. - NotList. - -add_tracer_2({Head,Cond,Body},Tracer) -> - {Head,Cond,add_tracer_3(Body,Tracer)}; -add_tracer_2(Faulty,_Tracer) -> - Faulty. - -add_tracer_3([{trace,Disable,Enable}|Rest],Tracer) when is_list(Enable) -> - [{trace,Disable,Enable++[{{tracer,Tracer}}]}|Rest]; -add_tracer_3([ActionTerm|Rest],Tracer) -> - [ActionTerm|add_tracer_3(Rest,Tracer)]; -add_tracer_3([],_Tracer) -> - []; -add_tracer_3(FaultyBody,_Tracer) -> - FaultyBody. -%% ----------------------------------------------------------------------------- - -%% ----------------------------------------------------------------------------- -%% Help functions handling internal loopdata. -%% ----------------------------------------------------------------------------- - --record(ld,{init_publ_ld_mfa, % {M,F,Args} - remove_publ_ld_mf, % {M,F} | void - clean_publ_ld_mf, % {Mod,Func} - ms_mfarities=notable, % ETS holding names match functions. - call_mfarities=[], % [{{M,F,Arity},2-TupleOrFun},...] - return_mfarities=[], % [{{M,F,Arity},2-TupleOrFun},...] - remove_mfarities=[] - }). - -mk_new_ld(InitPublLDmfa,RemovePublLDmf,CleanPublLDmf,TId) -> - #ld{ - init_publ_ld_mfa=InitPublLDmfa, - remove_publ_ld_mf=RemovePublLDmf, - clean_publ_ld_mf=CleanPublLDmf, - ms_mfarities=TId - }. -%% ----------------------------------------------------------------------------- - -%% Function which restores the internal loop data to somekind of initial state. -%% This is useful when tracing has been suspended. -reset_ld(#ld{init_publ_ld_mfa=InitPublLDmfa, - remove_publ_ld_mf=RemovePublLDmf, - clean_publ_ld_mf=CleanPublLDmf, - ms_mfarities=TId}) -> - ets:match_delete(TId,{'_','_'}), % Empty the table. - #ld{init_publ_ld_mfa=InitPublLDmfa, - remove_publ_ld_mf=RemovePublLDmf, - clean_publ_ld_mf=CleanPublLDmf, - ms_mfarities=TId}. -%% ----------------------------------------------------------------------------- - -get_initpublldmfa_ld(#ld{init_publ_ld_mfa=InitPublLDmfa}) -> - InitPublLDmfa. -%% ----------------------------------------------------------------------------- - -get_removepublldmf_ld(#ld{remove_publ_ld_mf=RemovePublLDmf}) -> - RemovePublLDmf. -%% ----------------------------------------------------------------------------- - -get_cleanpublldmf_ld(#ld{clean_publ_ld_mf=CleanPublLDmf}) -> - CleanPublLDmf. -%% ----------------------------------------------------------------------------- - -%% Help function adding data associated with a meta traced function to the -%% internal loopdata. Called when meta tracing is activated for M:F/Arity. -init_tpm_ld(M,F,Arity,CallFunc,ReturnFunc,RemoveFunc,LD) -> - ets:insert(LD#ld.ms_mfarities,{{M,F,Arity},[]}), - CallFuncs=LD#ld.call_mfarities, - ReturnFuncs=LD#ld.return_mfarities, - RemoveFuncs=LD#ld.remove_mfarities, - LD#ld{call_mfarities=[{{M,F,Arity},CallFunc}|CallFuncs], - return_mfarities=[{{M,F,Arity},ReturnFunc}|ReturnFuncs], - remove_mfarities=[{{M,F,Arity},RemoveFunc}|RemoveFuncs]}. -%% ----------------------------------------------------------------------------- - -%% Help function which answers the question if we have already initiated the -%% function. It is done by looking in the ETS-table with named match-functions. -%% If there is an entry in the set-type table for M:F/Arity, the function is -%% initiated. -%% Returns 'yes' or 'no'. -check_mfarity_exists(M,F,Arity) -> - case ets:lookup(?NAMED_MS_TAB,{M,F,Arity}) of - [] -> - no; - [_] -> - yes - end. -%% ----------------------------------------------------------------------------- - -%% Help function adding an entry with [{MSname,MSlist}|MSsNames] for M:F/Arity. -%% Note that any already existing entry is removed. -%% Returns nothing significant. -put_ms_ld(M,F,Arity,MSname,MS,MSsNames) -> - ets:insert(?NAMED_MS_TAB,{{M,F,Arity},[{MSname,MS}|MSsNames]}). -%% ----------------------------------------------------------------------------- - -%% Help function taking a list of {MSname,MSs} and storing them in the -%% internal loop data structure. The storage is actually implemented as an ETS -%% table. Any previous list of {MSname,MSs} associated with this {M,F,Arity} will -%% be lost. Returns nothing significant. -set_ms_ld(M,F,Arity,MSsNames) -> - ets:insert(?NAMED_MS_TAB,{{M,F,Arity},MSsNames}). -%% ----------------------------------------------------------------------------- - -%% Help function fetching a list of {MSname,MatchSpecs} for a M:F/Arity. The -%% match-functions are stored in an ETS table searchable on {M,F,Arity}. -get_ms_ld(M,F,Arity) -> - case ets:lookup(?NAMED_MS_TAB,{M,F,Arity}) of - [{_MFArity,MSsNames}] -> - MSsNames; - [] -> - [] - end. -%% ----------------------------------------------------------------------------- - -%% Help function removing all saved match-specs for a certain M:F/Arity. -%% Returns a new loopdata structure. -remove_ms_ld(M,F,Arity,LD) -> - ets:delete(LD#ld.ms_mfarities,{M,F,Arity}), - LD. -%% ----------------------------------------------------------------------------- - -%% Help function which removes all information about a meta traced function from -%% the internal loopdata. Returns a new loopdata structure. -ctpm_ld(M,F,Arity,LD) -> - ets:delete(LD#ld.ms_mfarities,{M,F,Arity}), - NewCallFuncs=lists:keydelete({M,F,Arity},1,LD#ld.call_mfarities), - NewReturnFuncs=lists:keydelete({M,F,Arity},1,LD#ld.return_mfarities), - NewRemoveFuncs=lists:keydelete({M,F,Arity},1,LD#ld.remove_mfarities), - LD#ld{call_mfarities=NewCallFuncs, - return_mfarities=NewReturnFuncs, - remove_mfarities=NewRemoveFuncs}. -%% ----------------------------------------------------------------------------- - -get_call_func_ld(M,F,Arity,#ld{call_mfarities=CallFuncs}) -> - case lists:keysearch({M,F,Arity},1,CallFuncs) of - {value,{_,MF}} -> - MF; - false -> - false - end. -%% ----------------------------------------------------------------------------- - -get_return_func_ld(M,F,Arity,#ld{return_mfarities=CallFuncs}) -> - case lists:keysearch({M,F,Arity},1,CallFuncs) of - {value,{_,MF}} -> - MF; - false -> - false - end. -%% ----------------------------------------------------------------------------- - -get_remove_func_ld(M,F,Arity,#ld{remove_mfarities=RemoveFuncs}) -> - case lists:keysearch({M,F,Arity},1,RemoveFuncs) of - {value,{_,MF}} -> - MF; - false -> - false - end. -%% ----------------------------------------------------------------------------- - -%% Function returning a list of all {Mod,Func,Arity} which are currently meta -%% traced. It does do by listifying the call_mfarities field in the internal -%% loopdata. -get_all_meta_funcs_ld(#ld{call_mfarities=CallFuncs}) -> - lists:map(fun({MFArity,_})->MFArity end,CallFuncs). -%% ----------------------------------------------------------------------------- - - -%% ============================================================================= -%% Functions for the standard PublLD structure. -%% -%% It is tuple {Part1,GlobalData} where Part1 is of length at least 2. -%% Where each field is a list of tuples. The last item in each tuple shall be -%% a now tuple, making it possible to clean it away should it be too old to be -%% relevant (there was no return_from message due to a failure). -%% Other fields can be used for other functions. -%% The GlobalData is not cleaned but instead meant to store data must be passed -%% to each CallFunc when a meta trace message arrives. -%% ============================================================================= - -%% Function returning our standard priv-loopdata structure. -init_std_publld(Size,GlobalData) -> - {list_to_tuple(lists:duplicate(Size,[])),GlobalData}. -%% ----------------------------------------------------------------------------- - -%% Function capable of cleaning out a standard publ-ld. The last element of each -%% tuple must be the now item. -%% Returns a new publ-ld structure. -clean_std_publld({Part1,GlobalData}) -> - {clean_std_publld_2(Part1,now(),tuple_size(Part1),[]),GlobalData}. - -clean_std_publld_2(_,_,0,Accum) -> - list_to_tuple(Accum); -clean_std_publld_2(PublLD,Now,Index,Accum) -> - NewTupleList=clean_std_publld_3(element(Index,PublLD),Now), - clean_std_publld_2(PublLD,Now,Index-1,[NewTupleList|Accum]). - -clean_std_publld_3([Tuple|Rest],Now) -> - PrevNow=element(tuple_size(Tuple),Tuple), % Last item shall be the now item. - case difference_in_now(PrevNow,Now,30) of - true -> % Remove it then! - clean_std_publld_3(Rest,Now); - false -> % Keep it! - [Tuple|clean_std_publld_3(Rest,Now)] - end; -clean_std_publld_3([],_) -> - []. -%% ----------------------------------------------------------------------------- - -%% ============================================================================= -%% Functions used as handling functions (as funs) for registered process names. -%% (Given that we use the standard priv-ld, otherwise you must do your own!). -%% ============================================================================= - -%% Call-back for initializing the meta traced functions there are quick functions -%% for. Returns a new public loop data structure. -metafunc_init(erlang,register,2,{Part1,GlobalData}) -> - {setelement(1,Part1,[]),GlobalData}. -%% ----------------------------------------------------------------------------- - -%% Call-function for erlang:register/2. -%% This function adds the call to register/2 to a standard priv-ld structure. -%% Note that we *must* search for previous entries from the same process. If such -%% still in structure it means a failed register/2 call. It must first be removed -%% so it can not be mixed up with this one. Since meta-trace message will arrive -%% in order, there was no return_from message for that call if we are here now. -local_register_call(CallingPid,{call,[Alias,Pid],TS},{Part1,GlobalData}) -> - TupleList=element(1,Part1), % The register/2 entry in a std. priv-ld. - NewTupleList=lists:keydelete(CallingPid,1,TupleList), % If present, remove previous call. - {ok, - {setelement(1,Part1,[{CallingPid,{Alias,Pid},TS}|NewTupleList]),GlobalData}, - void}. - -%% Return-function for the erlang:register/2 BIF. -%% This function formulates the output and removes the corresponding call entry -%% from the standard priv-ld structure. -local_register_return(CallingPid,{return_from,_Val,_TS},PublLD={Part1,GlobalData}) -> - TupleList=element(1,Part1), % The register/2 entry in a std. priv-ld. - case lists:keysearch(CallingPid,1,TupleList) of - {value,{_,{Alias,Pid},NowTS}} -> - NewTupleList=lists:keydelete(CallingPid,1,TupleList), - {ok, - {setelement(1,Part1,NewTupleList),GlobalData}, - term_to_binary({Pid,Alias,alias,NowTS})}; - false -> % Strange, then don't know what to do. - {ok,PublLD,void} % Do nothing seems safe. - end; -local_register_return(CallingPid,{exception_from,_Val,_TS},{Part1,GlobalData}) -> - TupleList=element(1,Part1), % The register/2 entry in a std. priv-ld. - NewTupleList=lists:keydelete(CallingPid,1,TupleList), - {ok,{setelement(1,Part1,NewTupleList),GlobalData},void}; % No association then. -local_register_return(_,_,PublLD) -> % Don't understand this. - {ok,PublLD,void}. - -%% When unregister/1 us called we simply want a unalias entry in the ti-file. -%% We can unfortunately not connect it with a certain pid. -local_unregister_call(_CallingPid,{_TypeTag,[Alias],TS},PublLD) -> - {ok,PublLD,term_to_binary({undefined,Alias,unalias,TS})}. -%% ----------------------------------------------------------------------------- - -%% Call-function for global:register_name/2,/3. -%% This function is actually the call function for the handle_call/3 in the -%% global server. Note that we must check that we only do this on the node -%% where Pid actually resides. -global_register_call(_CallingPid,{call,[{register,Alias,P,_},_,_],TS},PublLD) - when node(P)==node()-> - {ok,PublLD,term_to_binary({P,{global,Alias},alias,TS})}; -global_register_call(_CallingPid,_,PublLD) -> - {ok,PublLD,void}. - -%% Call-function for global:unregister_name. It acutally checks on the use of -%% global:delete_global_name/2 which is called when ever a global name is removed. -global_unregister_call(_CallingPid,{call,[Alias,P],TS},PublLD) when node(P)==node()-> - {ok,PublLD,term_to_binary({P,{global,Alias},unalias,TS})}; -global_unregister_call(_CallingPid,_,PublLD) -> - {ok,PublLD,void}. -%% ----------------------------------------------------------------------------- - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - diff --git a/lib/runtime_tools/src/msacc.erl b/lib/runtime_tools/src/msacc.erl new file mode 100644 index 0000000000..0d9b2690e5 --- /dev/null +++ b/lib/runtime_tools/src/msacc.erl @@ -0,0 +1,355 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2014-2016. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +%% +%% @doc Microstate accounting utility function +%% +%% This module provides a user interface for analysing +%% erlang:statistics(microstate_accounting) data. +%% + +-module(msacc). +-export([available/0, start/0, start/1, stop/0, reset/0, to_file/1, + from_file/1, stats/0, stats/2, print/0, print/1, print/2, + print/3]). + +-type msacc_data() :: [msacc_data_thread()]. + +-type msacc_data_thread() :: #{ '$type' := msacc_data, + type := msacc_type(), id := msacc_id(), + counters := msacc_data_counters() }. +-type msacc_data_counters() :: #{ msacc_state() => non_neg_integer()}. + +-type msacc_stats() :: [msacc_stats_thread()]. +-type msacc_stats_thread() :: #{ '$type' := msacc_stats, + type := msacc_type(), id := msacc_id(), + system := float(), + counters := msacc_stats_counters()}. +-type msacc_stats_counters() :: #{ msacc_state() => #{ thread := float(), + system := float()}}. + + +-type msacc_type() :: scheduler | aux | async. +-type msacc_id() :: non_neg_integer(). +-type msacc_state() :: alloc | aux | bif | busy_wait | check_io | + emulator | ets | gc | gc_fullsweep | nif | + other | port | send | sleep | timers. + +-type msacc_print_options() :: #{ system => boolean() }. + +-spec available() -> boolean(). +available() -> + try + [_|_] = erlang:statistics(microstate_accounting), + true + catch _:_ -> + false + end. + +-spec start() -> boolean(). +start() -> + erlang:system_flag(microstate_accounting, true). + +-spec stop() -> boolean(). +stop() -> + erlang:system_flag(microstate_accounting, false). + +-spec reset() -> boolean(). +reset() -> + erlang:system_flag(microstate_accounting, reset). + +-spec start(Time) -> true when + Time :: timeout(). +start(Tmo) -> + stop(), reset(), start(), + timer:sleep(Tmo), + stop(). + +-spec to_file(Filename) -> ok | {error, file:posix()} when + Filename :: file:name_all(). +to_file(Filename) -> + file:write_file(Filename, io_lib:format("~p.~n",[stats()])). + +-spec from_file(Filename) -> msacc_data() when + Filename :: file:name_all(). +from_file(Filename) -> + {ok, [Stats]} = file:consult(Filename), + Stats. + +-spec print() -> ok. +print() -> + print(stats()). + +-spec print(DataOrStats) -> ok when + DataOrStats :: msacc_data() | msacc_stats(). +print(Stats) -> + print(Stats, #{}). + +-spec print(DataOrStats, Options) -> ok when + DataOrStats :: msacc_data() | msacc_stats(), + Options :: msacc_print_options(). +print(Stats, Options) -> + print(group_leader(), Stats, Options). + +-spec print(FileOrDevice, DataOrStats, Options) -> ok when + FileOrDevice :: file:filename() | io:device(), + DataOrStats :: msacc_data() | msacc_stats(), + Options :: msacc_print_options(). +print(Filename, Stats, Options) when is_list(Filename) -> + case file:open(Filename,[write]) of + {ok, D} -> print(D, Stats, Options),file:close(D); + Error -> Error + end; +print(Device, Stats, Options) -> + DefaultOpts = #{ system => false }, + print_int(Device, Stats, maps:merge(DefaultOpts, Options)). +print_int(Device, [#{ '$type' := msacc_data, id := _Id }|_] = Stats, Options) -> + TypeStats = stats(type, Stats), + io:format(Device, "~s", [print_stats_overview(Stats, Options)]), + io:format(Device, "~s", [print_stats_header(Stats, Options)]), + io:format(Device, "~s", [print_stats_threads( + stats(realtime, Stats), Options)]), + io:format(Device, "~s", [print_stats_type( + stats(realtime, TypeStats), Options)]); +print_int(Device, [#{ '$type' := msacc_data }|_] = Stats, Options) -> + io:format(Device, "~s", [print_stats_header(Stats, Options)]), + io:format(Device, "~s", [print_stats_type( + stats(realtime, Stats), Options)]); +print_int(Device, [#{ '$type' := msacc_stats, id := _Id }|_] = Stats,Options) -> + io:format(Device, "~s", [print_stats_header(Stats, Options)]), + io:format(Device, "~s", [print_stats_threads(Stats, Options)]), + io:format(Device, "~s", [print_stats_type( + msacc:stats(type, Stats), Options)]); +print_int(Device, [#{ '$type' := msacc_stats }|_] = Stats, Options) -> + io:format(Device, "~s", [print_stats_header(Stats, Options)]), + io:format(Device, "~s", [print_stats_type(Stats, Options)]). + + +-spec stats() -> msacc_data(). +stats() -> + Fun = fun F(K,{PerfCount,StateCount}) -> + %% Need to handle ERTS_MSACC_STATE_COUNTERS + {F(K,PerfCount),StateCount}; + F(_K,PerfCount) -> + erlang:convert_time_unit(PerfCount, perf_counter, 1000000) + end, + UsStats = lists:map( + fun(#{ counters := Cnt } = M) -> + UsCnt = maps:map(Fun,Cnt), + M#{ '$type' => msacc_data, counters := UsCnt } + end, erlang:statistics(microstate_accounting)), + statssort(UsStats). + +-spec stats(Analysis, Stats) -> non_neg_integer() when + Analysis :: system_realtime | system_runtime, + Stats :: msacc_data(); + (Analysis, Stats) -> msacc_stats() when + Analysis :: realtime | runtime, + Stats :: msacc_data(); + (Analysis, StatsOrData) -> msacc_data() | msacc_stats() when + Analysis :: type, + StatsOrData :: msacc_data() | msacc_stats(). +stats(system_realtime, Stats) -> + lists:foldl(fun(#{ counters := Cnt }, Acc) -> + get_total(Cnt, Acc) + end, 0, Stats); +stats(system_runtime, Stats) -> + lists:foldl(fun(#{ counters := Cnt }, Acc) -> + get_total(maps:remove(sleep, Cnt), Acc) + end, 0, Stats); +stats(realtime, Stats) -> + RealTime = stats(system_realtime, Stats), + statssort([get_thread_perc(Thread, RealTime) || Thread <- Stats]); +stats(runtime, Stats) -> + RunTime = stats(system_runtime, Stats), + statssort([get_thread_perc(T#{ counters := maps:remove(sleep,Cnt)}, RunTime) + || T = #{ counters := Cnt } <- Stats]); +stats(type, Stats) -> + statssort(merge_threads(Stats, [])). + +print_stats_overview(Stats, _Options) -> + RunTime = stats(system_runtime, Stats), + RealTime = stats(system_realtime, Stats) div length(Stats), + SchedStats = [S || #{ type := scheduler } = S <- Stats], + AvgSchedRunTime = stats(system_runtime, SchedStats) div length(SchedStats), + NumSize = if + RealTime > RunTime -> length(integer_to_list(RealTime)); + true -> length(integer_to_list(RunTime)) + end, + [io_lib:format("Average thread real-time : ~*B us~n", + [NumSize, RealTime]), + io_lib:format("Accumulated system run-time : ~*B us~n", + [NumSize, RunTime]), + io_lib:format("Average scheduler run-time : ~*B us~n", + [NumSize, AvgSchedRunTime]), + io_lib:format("~n",[])]. + +print_stats_threads(Stats, Options) -> + [io_lib:format("~nStats per thread:~n", []), + [print_thread_info(Thread, Options) || Thread <- Stats]]. + +print_stats_type(Stats, Options) -> + [io_lib:format("~nStats per type:~n", []), + [print_thread_info(Thread, Options) || Thread <- Stats]]. + + +print_stats_header([#{ counters := Cnt }|_], #{ system := PrintSys }) -> + [io_lib:format("~14s", ["Thread"]), + map(fun(Counter, _) when PrintSys-> + io_lib:format("~9s ", [atom_to_list(Counter)]); + (Counter, _) -> + io_lib:format("~9s", [atom_to_list(Counter)]) + end, Cnt), + io_lib:format("~n",[])]. + +print_thread_info(#{ '$type' := msacc_stats, + counters := Cnt } = Thread, #{ system := PrintSys }) -> + [case maps:find(id, Thread) of + error -> + io_lib:format("~14s", [atom_to_list(maps:get(type, Thread))]); + {ok, Id} -> + io_lib:format("~10s(~2B)", [atom_to_list(maps:get(type,Thread)),Id]) + end, + map(fun(_Key, #{ thread := ThreadPerc, system := SystemPerc }) when PrintSys -> + io_lib:format("~6.2f%(~4.1f%)", [ThreadPerc, SystemPerc]); + (_Key, #{ thread := ThreadPerc }) -> + io_lib:format("~8.2f%", [ThreadPerc]) + end, Cnt), + io_lib:format("~n",[])]. + +get_total(Cnt, Base) -> + maps:fold(fun(_, {Val,_}, Time) -> + %% Have to handle ERTS_MSACC_STATE_COUNTERS + Time + Val; + (_, Val, Time) -> Time + Val + end, Base, Cnt). + +get_thread_perc(#{ '$type' := msacc_data, counters := Cnt } = Thread, + SystemTime) -> + ThreadTime = get_total(Cnt, 0), + Thread#{ '$type' := msacc_stats, + system => percentage(ThreadTime,SystemTime), + counters => get_thread_perc(Cnt, ThreadTime, SystemTime)}. +get_thread_perc(Cnt, ThreadTime, SystemTime) -> + maps:map(fun F(Key, {Val, C}) -> + M = F(Key, Val), + M#{ cnt => C }; + F(_Key, Val) -> + #{ thread => percentage(Val, ThreadTime), + system => percentage(Val, SystemTime) } + end, Cnt). + +%% This code is a little bit messy as it has to be able to deal with +%% both [msacc_data()] and [msacc_stats()]. +merge_threads([#{ '$type' := msacc_stats, + type := Type, + counters := Cnt } = M0|R], Acc) -> + case keyfind(type, Type, Acc) of + false -> + merge_threads(R, [maps:remove(id,M0#{ threads => 1 })|Acc]); + #{ '$type' := msacc_stats, counters := Cnt0, + threads := Threads, system := System } = M -> + NewMap = M#{ counters := add_counters(Cnt, Cnt0), + system := System + maps:get(system, M0), + threads := Threads + 1}, + NewAcc = keyreplace(type, Type, NewMap, Acc), + merge_threads(R, NewAcc) + end; +merge_threads([], [#{ '$type' := msacc_stats, + system := System, + threads := Threads, + counters := Cnt} = M0|R]) -> + Counters = maps:map(fun(_,#{ thread := Thr } = Map) -> + Map#{ thread := Thr / Threads } + end, Cnt), + M = maps:remove(threads, M0), + [M#{ system := System, counters := Counters} | merge_threads([],R)]; +merge_threads([], []) -> + []; +%% The clauses below deal with msacc_data() +merge_threads([#{ '$type' := msacc_data, + type := Type, + counters := Cnt } = M0|R], Acc) -> + case keyfind(type, Type, Acc) of + false -> + merge_threads(R, [maps:remove(id,M0)|Acc]); + #{ '$type' := msacc_data, counters := Cnt0 } = M -> + NewMap = M#{ counters := add_counters(Cnt, Cnt0) }, + NewAcc = keyreplace(type, Type, NewMap, Acc), + merge_threads(R, NewAcc) + end; +merge_threads([], Acc) -> + Acc. + +add_counters(M1, M2) -> + maps:map( + fun(Key, #{ thread := Thr1, system := Sys1, cnt := Cnt1}) -> + %% Have to handle ERTS_MSACC_STATE_COUNTERS + #{ thread := Thr2, system := Sys2, cnt := Cnt2} = maps:get(Key, M2), + #{ thread => Thr1 + Thr2, system => Sys1 + Sys2, + cnt => Cnt1 + Cnt2 }; + (Key, #{ thread := Thr1, system := Sys1}) -> + #{ thread := Thr2, system := Sys2} = maps:get(Key, M2), + #{ thread => Thr1 + Thr2, system => Sys1 + Sys2}; + (Key, {V1,C1}) -> + %% Have to handle ERTS_MSACC_STATE_COUNTERS + {V2,C2} = maps:get(Key, M2),{V1+V2,C1+C2}; + (Key, V1) -> maps:get(Key, M2) + V1 + end, M1). + +percentage(Divident, Divisor) -> + if Divisor == 0 andalso Divident /= 0 -> + 100.0; + Divisor == 0 -> + 0.0; + true -> + Divident / Divisor * 100 + end. + +keyfind(Key, Value, [H|T]) -> + case maps:find(Key, H) of + {ok, Value} -> + H; + _ -> + keyfind(Key, Value, T) + end; +keyfind(_, _, []) -> + false. + +keyreplace(Key, Value, NewMap, [H|T]) -> + case maps:find(Key, H) of + {ok, Value} -> + [NewMap|T]; + _ -> + [H|keyreplace(Key, Value, NewMap, T)] + end; +keyreplace(_, _, _, []) -> + []. + +statssort(Stats) -> + lists:sort(fun(#{ type := Type1, id := Id1}, + #{ type := Type2, id := Id2}) -> + {Type1, Id1} < {Type2, Id2}; + (#{ type := Type1}, #{ type := Type2}) -> + Type1 < Type2 + end, Stats). + +map(Fun,Map) -> + [ Fun(K,V) || {K,V} <- maps:to_list(Map) ]. diff --git a/lib/runtime_tools/src/observer_backend.erl b/lib/runtime_tools/src/observer_backend.erl index 01e99f3f5e..b27bc63d15 100644 --- a/lib/runtime_tools/src/observer_backend.erl +++ b/lib/runtime_tools/src/observer_backend.erl @@ -1,18 +1,19 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2012. All Rights Reserved. +%% Copyright Ericsson AB 2002-2016. All Rights Reserved. %% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. %% %% %CopyrightEnd% %% @@ -22,7 +23,8 @@ -export([vsn/0]). %% observer stuff --export([sys_info/0, get_table/3, get_table_list/2, fetch_stats/2]). +-export([sys_info/0, get_port_list/0, + get_table/3, get_table_list/2, fetch_stats/2]). %% etop stuff -export([etop_collect/1]). @@ -49,6 +51,17 @@ vsn() -> %% observer backend %% sys_info() -> + MemInfo = try erlang:memory() of + Mem -> Mem + catch _:_ -> [] + end, + + SchedulersOnline = erlang:system_info(schedulers_online), + SchedulersAvailable = case erlang:system_info(multi_scheduling) of + enabled -> SchedulersOnline; + _ -> 1 + end, + {{_,Input},{_,Output}} = erlang:statistics(io), [{process_count, erlang:system_info(process_count)}, {process_limit, erlang:system_info(process_limit)}, @@ -56,9 +69,13 @@ sys_info() -> {run_queue, erlang:statistics(run_queue)}, {io_input, Input}, {io_output, Output}, + {logical_processors, erlang:system_info(logical_processors)}, - {logical_processors_available, erlang:system_info(logical_processors_available)}, {logical_processors_online, erlang:system_info(logical_processors_online)}, + {logical_processors_available, erlang:system_info(logical_processors_available)}, + {schedulers, erlang:system_info(schedulers)}, + {schedulers_online, SchedulersOnline}, + {schedulers_available, SchedulersAvailable}, {otp_release, erlang:system_info(otp_release)}, {version, erlang:system_info(version)}, @@ -68,9 +85,16 @@ sys_info() -> {threads, erlang:system_info(threads)}, {thread_pool_size, erlang:system_info(thread_pool_size)}, {wordsize_internal, erlang:system_info({wordsize, internal})}, - {wordsize_external, erlang:system_info({wordsize, external})} | - erlang:memory() - ]. + {wordsize_external, erlang:system_info({wordsize, external})}, + {alloc_info, alloc_info()} + | MemInfo]. + +alloc_info() -> + AlcuAllocs = erlang:system_info(alloc_util_allocators), + try erlang:system_info({allocator_sizes, AlcuAllocs}) of + Allocators -> Allocators + catch _:_ -> [] + end. get_table(Parent, Table, Module) -> spawn(fun() -> @@ -83,7 +107,7 @@ get_table2(Parent, Table, Type) -> ets -> ets:info(Table, size); mnesia -> mnesia:table_info(Table, size) end, - case Size > 0 of + case Size =/= undefined andalso Size > 0 of false -> Parent ! {self(), '$end_of_table'}, normal; @@ -116,6 +140,60 @@ get_mnesia_loop(Parent, {Match, Cont}) -> Parent ! {self(), Match}, get_mnesia_loop(Parent, mnesia:select(Cont)). +get_port_list() -> + ExtraItems = [monitors,monitored_by,parallelism,locking,queue_size,memory], + [begin + [{port_id,P}|erlang:port_info(P)] ++ + port_info(P,ExtraItems) ++ + inet_port_extra(erlang:port_info(P, name), P) + end || P <- erlang:ports()]. + +port_info(P,[Item|Items]) -> + case erlang:port_info(P,Item) of + undefined -> port_info(P,Items); + Value -> [Value|port_info(P,Items)] + end; +port_info(_,[]) -> + []. + +inet_port_extra({_,Type},Port) when Type =:= "udp_inet"; + Type =:= "tcp_inet"; + Type =:= "sctp_inet" -> + Data = + case inet:getstat(Port) of + {ok, Stats} -> [{statistics, Stats}]; + _ -> [] + end ++ + case inet:peername(Port) of + {ok, {RAddr,RPort}} when is_tuple(RAddr), is_integer(RPort) -> + [{remote_address,RAddr},{remote_port,RPort}]; + {ok, RAddr} -> + [{remote_address,RAddr}]; + {error, _} -> [] + end ++ + case inet:sockname(Port) of + {ok, {LAddr,LPort}} when is_tuple(LAddr), is_integer(LPort) -> + [{local_address,LAddr},{local_port,LPort}]; + {ok, LAddr} -> + [{local_address,LAddr}]; + {error, _} -> [] + end ++ + case inet:getopts(Port, + [active, broadcast, buffer, delay_send, + deliver, dontroute, exit_on_close, + header, high_msgq_watermark, high_watermark, + ipv6_v6only, keepalive, linger, low_msgq_watermark, + low_watermark, mode, netns, nodelay, packet, + packet_size, priority, read_packets, recbuf, + reuseaddr, send_timeout, send_timeout_close, + show_econnreset, sndbuf, tos, tclass]) of + {ok, Opts} -> [{options, Opts}]; + {error, _} -> [] + end, + [{inet,Data}]; +inet_port_extra(_,_) -> + []. + get_table_list(ets, Opts) -> HideUnread = proplists:get_value(unread_hidden, Opts, true), HideSys = proplists:get_value(sys_hidden, Opts, true), @@ -199,34 +277,57 @@ get_table_list(mnesia, Opts) -> lists:foldl(Info, [], mnesia:system_info(tables)). fetch_stats(Parent, Time) -> - erlang:system_flag(scheduler_wall_time, true), process_flag(trap_exit, true), - fetch_stats_loop(Parent, Time), - erlang:system_flag(scheduler_wall_time, false). + fetch_stats_loop(Parent, Time). fetch_stats_loop(Parent, Time) -> + erlang:system_flag(scheduler_wall_time, true), receive - _Msg -> normal + _Msg -> + %% erlang:system_flag(scheduler_wall_time, false) + ok after Time -> _M = Parent ! {stats, 1, erlang:statistics(scheduler_wall_time), erlang:statistics(io), - erlang:memory()}, - fetch_stats(Parent, Time) + try erlang:memory() catch _:_ -> [] end}, + fetch_stats_loop(Parent, Time) end. %% %% etop backend %% etop_collect(Collector) -> + %% If this is the first time and the scheduler_wall_time flag is + %% false, SchedulerWallTime will be 'undefined' (and show 0 cpu + %% utilization in etop). Next time the flag will be true and then + %% there will be a measurement. + SchedulerWallTime = erlang:statistics(scheduler_wall_time), ProcInfo = etop_collect(processes(), []), - Collector ! {self(),#etop_info{now = now(), + + Collector ! {self(),#etop_info{now = erlang:timestamp(), n_procs = length(ProcInfo), run_queue = erlang:statistics(run_queue), - wall_clock = erlang:statistics(wall_clock), - runtime = erlang:statistics(runtime), + runtime = SchedulerWallTime, memi = etop_memi(), procinfo = ProcInfo - }}. + }}, + + case SchedulerWallTime of + undefined -> + erlang:system_flag(scheduler_wall_time,true), + spawn(fun() -> flag_holder_proc(Collector) end), + ok; + _ -> + ok + end. + +flag_holder_proc(Collector) -> + Ref = erlang:monitor(process,Collector), + receive + {'DOWN',Ref,_,_,_} -> + %% erlang:system_flag(scheduler_wall_time,false) + ok + end. etop_memi() -> try @@ -251,7 +352,7 @@ etop_collect([P|Ps], Acc) -> [{registered_name,Reg},{initial_call,Initial},{memory,Mem}, {reductions,Reds},{current_function,Current},{message_queue_len,Qlen}] -> Name = case Reg of - [] -> Initial; + [] -> initial_call(Initial, P); _ -> Reg end, Info = #etop_proc_info{pid=P,mem=Mem,reds=Reds,name=Name, @@ -260,6 +361,11 @@ etop_collect([P|Ps], Acc) -> end; etop_collect([], Acc) -> Acc. +initial_call({proc_lib, init_p, _}, Pid) -> + proc_lib:translate_initial_call(Pid); +initial_call(Initial, _Pid) -> + Initial. + %% %% ttb backend %% @@ -283,8 +389,8 @@ ttb_init_node(MetaFile_0,PI,Traci) -> MetaPid ! {metadata,Traci}, case PI of true -> - Proci = pnames(), - MetaPid ! {metadata,Proci}; + MetaPid ! {metadata,pnames()}, + ok; false -> ok end, @@ -303,7 +409,8 @@ ttb_meta_tracer(MetaFile,PI,Parent,SessionData) -> erlang:trace_pattern({erlang,spawn_link,3},ReturnMS,[meta]), erlang:trace_pattern({erlang,spawn_opt,1},ReturnMS,[meta]), erlang:trace_pattern({erlang,register,2},[],[meta]), - erlang:trace_pattern({global,register_name,2},[],[meta]); + erlang:trace_pattern({global,register_name,2},[],[meta]), + ok; false -> ok end, @@ -311,7 +418,8 @@ ttb_meta_tracer(MetaFile,PI,Parent,SessionData) -> case proplists:get_value(overload_check, SessionData) of {Ms, M, F} -> catch M:F(init), - erlang:send_after(Ms, self(), overload_check); + erlang:send_after(Ms, self(), overload_check), + ok; _ -> ok end, @@ -320,10 +428,10 @@ ttb_meta_tracer(MetaFile,PI,Parent,SessionData) -> ttb_meta_tracer_loop(MetaFile,PI,Acc,State) -> receive {trace_ts,_,call,{erlang,register,[Name,Pid]},_} -> - ttb_store_meta({pid,{Pid,Name}},MetaFile), + ok = ttb_store_meta({pid,{Pid,Name}},MetaFile), ttb_meta_tracer_loop(MetaFile,PI,Acc,State); {trace_ts,_,call,{global,register_name,[Name,Pid]},_} -> - ttb_store_meta({pid,{Pid,{global,Name}}},MetaFile), + ok = ttb_store_meta({pid,{Pid,{global,Name}}},MetaFile), ttb_meta_tracer_loop(MetaFile,PI,Acc,State); {trace_ts,CallingPid,call,{erlang,spawn_opt,[{M,F,Args,_}]},_} -> MFA = {M,F,length(Args)}, @@ -339,7 +447,7 @@ ttb_meta_tracer_loop(MetaFile,PI,Acc,State) -> NewAcc = dict:update(CallingPid, fun([H|T]) -> - ttb_store_meta({pid,{NewPid,H}},MetaFile), + ok = ttb_store_meta({pid,{NewPid,H}},MetaFile), T end, Acc), @@ -357,22 +465,22 @@ ttb_meta_tracer_loop(MetaFile,PI,Acc,State) -> NewAcc = dict:update(CallingPid, fun([H|T]) -> - ttb_store_meta({pid,{NewPid,H}},MetaFile), + ok = ttb_store_meta({pid,{NewPid,H}},MetaFile), T end, Acc), ttb_meta_tracer_loop(MetaFile,PI,NewAcc,State); {metadata,Data} when is_list(Data) -> - ttb_store_meta(Data,MetaFile), + ok = ttb_store_meta(Data,MetaFile), ttb_meta_tracer_loop(MetaFile,PI,Acc,State); {metadata,Key,Fun} when is_function(Fun) -> - ttb_store_meta([{Key,Fun()}],MetaFile), + ok = ttb_store_meta([{Key,Fun()}],MetaFile), ttb_meta_tracer_loop(MetaFile,PI,Acc,State); {metadata,Key,What} -> - ttb_store_meta([{Key,What}],MetaFile), + ok = ttb_store_meta([{Key,What}],MetaFile), ttb_meta_tracer_loop(MetaFile,PI,Acc,State); overload_check -> {Ms, M, F} = proplists:get_value(overload_check, State), @@ -388,7 +496,7 @@ ttb_meta_tracer_loop(MetaFile,PI,Acc,State) -> ttb_meta_tracer_loop(MetaFile,PI,Acc, State) end; {'DOWN', _, _, _, _} -> - stop_seq_trace(), + _ = stop_seq_trace(), self() ! stop, ttb_meta_tracer_loop(MetaFile,PI,Acc, State); stop when PI=:=true -> @@ -477,7 +585,7 @@ ttb_store_meta(Data,MetaFile) -> ttb_store_meta([Data],MetaFile). ttb_write_binary(Fd,[H|T]) -> - file:write(Fd,ttb_make_binary(H)), + ok = file:write(Fd,ttb_make_binary(H)), ttb_write_binary(Fd,T); ttb_write_binary(_Fd,[]) -> ok. @@ -534,9 +642,9 @@ ttb_fetch(MetaFile,{Port,Host}) -> send_files({Sock,Host},[File|Files]) -> {ok,Fd} = file:open(File,[raw,read,binary]), - gen_tcp:send(Sock,<<1,(list_to_binary(filename:basename(File)))/binary>>), + ok = gen_tcp:send(Sock,<<1,(list_to_binary(filename:basename(File)))/binary>>), send_chunks(Sock,Fd), - file:delete(File), + ok = file:delete(File), send_files({Sock,Host},Files); send_files({_Sock,_Host},[]) -> done. diff --git a/lib/runtime_tools/src/percept_profile.erl b/lib/runtime_tools/src/percept_profile.erl index cdc7a0fca1..1e8e913b80 100644 --- a/lib/runtime_tools/src/percept_profile.erl +++ b/lib/runtime_tools/src/percept_profile.erl @@ -1,18 +1,19 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2010. All Rights Reserved. +%% Copyright Ericsson AB 2008-2016. All Rights Reserved. %% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at %% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. %% %% %CopyrightEnd% %% @@ -86,7 +87,7 @@ start(Filename, Options) -> start(Filename, {Module, Function, Args}, Options) -> case whereis(percept_port) of undefined -> - profile_to_file(Filename, Options), + {ok, _} = profile_to_file(Filename, Options), erlang:apply(Module, Function, Args), stop(); Port -> @@ -112,14 +113,14 @@ deliver_all_trace() -> -spec stop() -> 'ok' | {'error', 'not_started'}. stop() -> - erlang:system_profile(undefined, [runnable_ports, runnable_procs]), + _ = erlang:system_profile(undefined, [runnable_ports, runnable_procs]), erlang:trace(all, false, [procs, ports, timestamp]), deliver_all_trace(), case whereis(percept_port) of undefined -> {error, not_started}; Port -> - erlang:port_command(Port, erlang:term_to_binary({profile_stop, erlang:now()})), + erlang:port_command(Port, erlang:term_to_binary({profile_stop, erlang:timestamp()})), %% trace delivered? erlang:port_close(Port), ok @@ -139,7 +140,7 @@ profile_to_file(Filename, Opts) -> erlang:system_flag(multi_scheduling, block), Port = (dbg:trace_port(file, Filename))(), % Send start time - erlang:port_command(Port, erlang:term_to_binary({profile_start, erlang:now()})), + erlang:port_command(Port, erlang:term_to_binary({profile_start, erlang:timestamp()})), erlang:system_flag(multi_scheduling, unblock), %% Register Port @@ -157,7 +158,8 @@ set_tracer(Port, Opts) -> {TOpts, POpts} = parse_profile_options(Opts), % Setup profiling and tracing erlang:trace(all, true, [{tracer, Port}, timestamp | TOpts]), - erlang:system_profile(Port, POpts). + _ = erlang:system_profile(Port, POpts), + ok. %% parse_profile_options diff --git a/lib/runtime_tools/src/runtime_tools.app.src b/lib/runtime_tools/src/runtime_tools.app.src index 1152f7259d..690c61a4c3 100644 --- a/lib/runtime_tools/src/runtime_tools.app.src +++ b/lib/runtime_tools/src/runtime_tools.app.src @@ -1,33 +1,34 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2012. All Rights Reserved. +%% Copyright Ericsson AB 1999-2016. All Rights Reserved. %% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. %% %% %CopyrightEnd% %% {application, runtime_tools, - [{description, "RUNTIME_TOOLS version 1"}, + [{description, "RUNTIME_TOOLS"}, {vsn, "%VSN%"}, - {modules, [dbg,observer_backend,percept_profile, - inviso_rt,inviso_rt_lib,inviso_rt_meta, - inviso_as_lib,inviso_autostart,inviso_autostart_server, + {modules, [appmon_info, dbg,observer_backend,percept_profile, runtime_tools,runtime_tools_sup,erts_alloc_config, - ttb_autostart,dyntrace]}, - {registered, [runtime_tools_sup,inviso_rt,inviso_rt_meta]}, + ttb_autostart,dyntrace,system_information, + msacc]}, + {registered, [runtime_tools_sup]}, {applications, [kernel, stdlib]}, -% {env, [{inviso_autostart_mod,your_own_autostart_module}]}, {env, []}, - {mod, {runtime_tools, []}}]}. + {mod, {runtime_tools, []}}, + {runtime_dependencies, ["stdlib-3.0","mnesia-4.12","kernel-5.0", + "erts-8.0"]}]}. diff --git a/lib/runtime_tools/src/runtime_tools.appup.src b/lib/runtime_tools/src/runtime_tools.appup.src index 7a435e9b22..a42673c87e 100644 --- a/lib/runtime_tools/src/runtime_tools.appup.src +++ b/lib/runtime_tools/src/runtime_tools.appup.src @@ -1,19 +1,22 @@ -%% +%% -*- erlang -*- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. +%% Copyright Ericsson AB 2001-2016. All Rights Reserved. %% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. %% %% %CopyrightEnd% -%% -{"%VSN%",[],[]}. +{"%VSN%", + [{<<".*">>,[{restart_application, runtime_tools}]}], + [{<<".*">>,[{restart_application, runtime_tools}]}] +}. diff --git a/lib/runtime_tools/src/runtime_tools.erl b/lib/runtime_tools/src/runtime_tools.erl index 2181244610..52ae5cc0eb 100644 --- a/lib/runtime_tools/src/runtime_tools.erl +++ b/lib/runtime_tools/src/runtime_tools.erl @@ -1,18 +1,19 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% Copyright Ericsson AB 2005-2016. All Rights Reserved. %% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. %% %% %CopyrightEnd% %% diff --git a/lib/runtime_tools/src/runtime_tools_sup.erl b/lib/runtime_tools/src/runtime_tools_sup.erl index 913719c449..efa37de42d 100644 --- a/lib/runtime_tools/src/runtime_tools_sup.erl +++ b/lib/runtime_tools/src/runtime_tools_sup.erl @@ -1,24 +1,25 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2011. All Rights Reserved. +%% Copyright Ericsson AB 2006-2016. All Rights Reserved. %% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. %% %% %CopyrightEnd% %% %% ------------------------------------------------------------------------------ %% File : runtime_tools_sup.erl -%% Author : Lennart �hman <[email protected]> +%% Author : Lennart Öhman <[email protected]> -module(runtime_tools_sup). -behaviour(supervisor). @@ -31,15 +32,11 @@ %% ============================================================================= %% The runtime tools top most supervisor starts: -%% -The inviso runtime component. This is the only way to get the runtime component -%% started automatically (if for instance autostart is wanted). -%% Note that it is not impossible that the runtime component terminates it self -%% should it discover that no autostart is configured. -init(AutoModArgs) -> +%% -The ttb_autostart component. This is used for tracing at startup +%% using observer/ttb. +init(_AutoModArgs) -> Flags = {one_for_one, 0, 3600}, - Children = [{inviso_rt, {inviso_rt, start_link_auto, [AutoModArgs]}, - temporary, 3000, worker, [inviso_rt]}, - {ttb_autostart, {ttb_autostart, start_link, []}, + Children = [{ttb_autostart, {ttb_autostart, start_link, []}, temporary, 3000, worker, [ttb_autostart]}], {ok, {Flags, Children}}. %% ----------------------------------------------------------------------------- diff --git a/lib/runtime_tools/src/system_information.erl b/lib/runtime_tools/src/system_information.erl new file mode 100644 index 0000000000..df25297eb9 --- /dev/null +++ b/lib/runtime_tools/src/system_information.erl @@ -0,0 +1,834 @@ +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2013. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + + +%% The main purpose of system_information is to aggregate all information +%% deemed useful for investigation, i.e. system_information:report/0. + +%% The server and all other utilities surrounding this is for inspecting +%% reported values. Functions will be added to this as time goes by. + +-module(system_information). +-behaviour(gen_server). + +%% API +-export([report/0, + from_file/1, + to_file/1]). + +-export([start/0, stop/0, + load_report/0, load_report/2, + applications/0, applications/1, + application/1, application/2, + environment/0, environment/1, + module/1, module/2, + modules/1, + sanity_check/0]). + +%% gen_server callbacks +-export([init/1, + handle_call/3, + handle_cast/2, + handle_info/2, + terminate/2, + code_change/3]). + +-define(SERVER, ?MODULE). + +%% change version if parsing of file changes +-define(REPORT_FILE_VSN, "1.0"). + +-record(state, { + report + }). + +%%=================================================================== +%% API +%%=================================================================== + +start() -> + gen_server:start({local, ?SERVER}, ?MODULE, [], []). + + +stop() -> + gen_server:call(?SERVER, stop, infinity). + +load_report() -> load_report(data, report()). + +load_report(file, File) -> load_report(data, from_file(File)); +load_report(data, Report) -> + ok = start_internal(), gen_server:call(?SERVER, {load_report, Report}, infinity). + +report() -> [ + {init_arguments, init:get_arguments()}, + {code_paths, code:get_path()}, + {code, code()}, + {system_info, erlang_system_info()}, + {erts_compile_info, erlang:system_info(compile_info)}, + {beam_dynamic_libraries, get_dynamic_libraries()}, + {environment_erts, os_getenv_erts_specific()}, + {environment, [split_env(Env) || Env <- os:getenv()]}, + {sanity_check, sanity_check()} + ]. + +-spec to_file(FileName) -> ok | {error, Reason} when + FileName :: file:name_all(), + Reason :: file:posix() | badarg | terminated | system_limit. + +to_file(File) -> + file:write_file(File, iolist_to_binary([ + io_lib:format("{system_information_version, ~p}.~n", [ + ?REPORT_FILE_VSN + ]), + io_lib:format("{system_information, ~p}.~n", [ + report() + ]) + ])). + +from_file(File) -> + case file:consult(File) of + {ok, Data} -> + case get_value([system_information_version], Data) of + ?REPORT_FILE_VSN -> + get_value([system_information], Data); + Vsn -> + erlang:error({unknown_version, Vsn}) + end; + _ -> + erlang:error(bad_report_file) + end. + +applications() -> applications([]). +applications(Opts) when is_list(Opts) -> + gen_server:call(?SERVER, {applications, Opts}, infinity). + +application(App) when is_atom(App) -> application(App, []). +application(App, Opts) when is_atom(App), is_list(Opts) -> + gen_server:call(?SERVER, {application, App, Opts}, infinity). + +environment() -> environment([]). +environment(Opts) when is_list(Opts) -> + gen_server:call(?SERVER, {environment, Opts}, infinity). + +module(M) when is_atom(M) -> module(M, []). +module(M, Opts) when is_atom(M), is_list(Opts) -> + gen_server:call(?SERVER, {module, M, Opts}, infinity). + +modules(Opt) when is_atom(Opt) -> + gen_server:call(?SERVER, {modules, Opt}, infinity). + + +-spec sanity_check() -> ok | {failed, Failures} when + Application :: atom(), + ApplicationVersion :: string(), + MissingRuntimeDependencies :: {missing_runtime_dependencies, + ApplicationVersion, + [ApplicationVersion]}, + InvalidApplicationVersion :: {invalid_application_version, + ApplicationVersion}, + InvalidAppFile :: {invalid_app_file, Application}, + Failure :: MissingRuntimeDependencies + | InvalidApplicationVersion + | InvalidAppFile, + Failures :: [Failure]. + +sanity_check() -> + case check_runtime_dependencies() of + [] -> ok; + Issues -> {failed, Issues} + end. + +%%=================================================================== +%% gen_server callbacks +%%=================================================================== + +init([]) -> + {ok, #state{}}. + +handle_call(stop, _From, S) -> + {stop, normal, ok, S}; + +handle_call({load_report, Report}, _From, S) -> + Version = get_value([system_info, system_version], Report), + io:format("Loaded report from system version: ~s~n", [Version]), + {reply, ok, S#state{ report = Report }}; + +handle_call(_Req, _From, #state{ report = undefined } = S) -> + {reply, {error, report_not_loaded}, S}; + +handle_call({applications, Opts}, _From, #state{ report = Report } = S) -> + ok = print_applications(get_value([code], Report), Opts), + {reply, ok, S}; + +handle_call({application, App, Opts}, _From, #state{ report = Report } = S) -> + Data = get_value([App], [AppInfo||{application, AppInfo}<-get_value([code], Report)]), + ok = print_application({App, Data}, Opts), + {reply, ok, S}; + + +handle_call({environment, Opts}, _From, #state{ report = Report } = S) -> + Choices = case proplists:get_bool(full, Opts) of + true -> [environment]; + false -> [environment_erts] + end, + ok = print_environments(get_value(Choices, Report), Opts), + {reply, ok, S}; + + +handle_call({module, M, Opts}, _From, #state{ report = Report } = S) -> + Mods = find_modules_from_code(M, get_value([code], Report)), + print_modules_from_code(M, Mods, Opts), + {reply, ok, S}; + +handle_call({modules, native}, _From, #state{ report = Report } = S) -> + Codes = get_native_modules_from_code(get_value([code],Report)), + io:format("~p~n", [Codes]), + {reply, ok, S}; + + +handle_call(_Request, _From, State) -> + {reply, ok, State}. + +handle_cast(_Msg, State) -> + {noreply, State}. + +handle_info(_Info, State) -> + {noreply, State}. + +terminate(_Reason, _State) -> + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%%=================================================================== +%% Internal functions +%%=================================================================== + +start_internal() -> + case start() of + {ok,_} -> ok; + {error, {already_started,_}} -> ok; + Error -> Error + end. + +%% handle report values + +get_value([], Data) -> Data; +get_value([K|Ks], Data) -> + get_value(Ks, proplists:get_value(K, Data, [])). + +find_modules_from_code(M, [{code, Info}|Codes]) -> + case find_modules(M, get_value([modules], Info)) of + [] -> find_modules_from_code(M, Codes); + Mods -> + Path = get_value([path], Info), + [{Path, Mods}|find_modules_from_code(M, Codes)] + end; +find_modules_from_code(M, [{application, {App, Info}}|Codes]) -> + case find_modules(M, get_value([modules], Info)) of + [] -> find_modules_from_code(M, Codes); + Mods -> + Path = get_value([path], Info), + Vsn = get_value([vsn], Info), + [{App, Vsn, Path, Mods}|find_modules_from_code(M, Codes)] + end; +find_modules_from_code(_, []) -> []. + +find_modules(M, [{M, _}=Info|Ms]) -> [Info|find_modules(M,Ms)]; +find_modules(M, [_|Ms]) -> find_modules(M, Ms); +find_modules(_, []) -> []. + +get_native_modules_from_code([{application, {App, Info}}|Cs]) -> + case get_native_modules(get_value([modules], Info)) of + [] -> get_native_modules_from_code(Cs); + Mods -> + Path = get_value([path], Info), + Vsn = get_value([vsn], Info), + [{App, Vsn, Path, Mods}|get_native_modules_from_code(Cs)] + end; +get_native_modules_from_code([{code, Info}|Cs]) -> + case get_native_modules(get_value([modules], Info)) of + [] -> get_native_modules_from_code(Cs); + Mods -> + Path = get_value([path], Info), + [{Path, Mods}|get_native_modules_from_code(Cs)] + end; +get_native_modules_from_code([]) -> []. + +get_native_modules([]) -> []; +get_native_modules([{Mod, Info}|Ms]) -> + case proplists:get_value(native, Info) of + false -> get_native_modules(Ms); + _ -> [Mod|get_native_modules(Ms)] + end. + + +%% print information + +print_applications([{application, App}|Apps], Opts) -> + print_application(App, Opts), + print_applications(Apps, Opts); +print_applications([{code,_}|Apps], Opts) -> + print_applications(Apps, Opts); +print_applications([], _) -> + ok. + +print_application({App, Info}, Opts) -> + Vsn = get_value([vsn], Info), + io:format(" * ~w-~s~n", [App, Vsn]), + case proplists:get_bool(full, Opts) of + true -> + _ = [ begin + print_module(Minfo) + end || Minfo <- get_value([modules], Info) ], + ok; + false -> + ok + end. + +print_environments([Env|Envs],Opts) -> + print_environment(Env,Opts), + print_environments(Envs,Opts); +print_environments([],_) -> + ok. + +print_environment({_Key, false},_) -> ok; +print_environment({Key, Value},_) -> + io:format(" - ~s = ~ts~n", [Key, Value]). + +print_modules_from_code(M, [Info|Ms], Opts) -> + print_module_from_code(M, Info), + case proplists:get_bool(full, Opts) of + true -> print_modules_from_code(M, Ms, Opts); + false -> ok + end; +print_modules_from_code(_, [], _) -> + ok. + +print_module_from_code(M, {Path, [{M,ModInfo}]}) -> + io:format(" from path \"~ts\" (no application):~n", [Path]), + io:format(" - compiler: ~s~n", [get_value([compiler], ModInfo)]), + io:format(" - md5: ~s~n", [get_value([md5], ModInfo)]), + io:format(" - native: ~w~n", [get_value([native], ModInfo)]), + io:format(" - loaded: ~w~n", [get_value([loaded], ModInfo)]), + ok; +print_module_from_code(M, {App,Vsn,Path,[{M,ModInfo}]}) -> + io:format(" from path \"~ts\" (~w-~s):~n", [Path,App,Vsn]), + io:format(" - compiler: ~s~n", [get_value([compiler], ModInfo)]), + io:format(" - md5: ~s~n", [get_value([md5], ModInfo)]), + io:format(" - native: ~w~n", [get_value([native], ModInfo)]), + io:format(" - loaded: ~w~n", [get_value([loaded], ModInfo)]), + ok. + +print_module({Mod, ModInfo}) -> + io:format(" - ~w:~n", [Mod]), + io:format(" - compiler: ~s~n", [get_value([compiler], ModInfo)]), + io:format(" - md5: ~s~n", [get_value([md5], ModInfo)]), + io:format(" - native: ~w~n", [get_value([native], ModInfo)]), + io:format(" - loaded: ~w~n", [get_value([loaded], ModInfo)]), + ok. + + + +%% get useful information from erlang:system_info/1 + +erlang_system_info() -> + erlang_system_info([ + allocator, + check_io, + otp_release, + port_limit, + process_limit, + % procs, % not needed + smp_support, + system_version, + system_architecture, + threads, + thread_pool_size, + {wordsize,internal}, + {wordsize,external}, + {cpu_topology, defined}, + {cpu_topology, detected}, + scheduler_bind_type, + scheduler_bindings, + compat_rel, + schedulers_state, + build_type, + logical_processors, + logical_processors_online, + logical_processors_available, + driver_version, + nif_version, + emu_args, + ethread_info, + beam_jump_table, + taints + ]). + +erlang_system_info([]) -> []; +erlang_system_info([Type|Types]) -> + [{Type, erlang:system_info(Type)}|erlang_system_info(Types)]. + + +%% get known useful erts environment + +os_getenv_erts_specific() -> + os_getenv_erts_specific([ + "BINDIR", + "DIALYZER_EMULATOR", + "CERL_DETACHED_PROG", + "EMU", + "ERL_CONSOLE_MODE", + "ERL_CRASH_DUMP", + "ERL_CRASH_DUMP_NICE", + "ERL_CRASH_DUMP_SECONDS", + "ERL_EPMD_PORT", + "ERL_EMULATOR_DLL", + "ERL_FULLSWEEP_AFTER", + "ERL_LIBS", + "ERL_MALLOC_LIB", + "ERL_MAX_PORTS", + "ERL_MAX_ETS_TABLES", + "ERL_NO_VFORK", + "ERL_NO_KERNEL_POLL", + "ERL_THREAD_POOL_SIZE", + "ERLC_EMULATOR", + "ESCRIPT_EMULATOR", + "HOME", + "HOMEDRIVE", + "HOMEPATH", + "LANG", + "LC_ALL", + "LC_CTYPE", + "PATH", + "PROGNAME", + "RELDIR", + "ROOTDIR", + "TERM", + %"VALGRIND_LOG_XML", + + %% heart + "COMSPEC", + "HEART_COMMAND", + + %% run_erl + "RUN_ERL_LOG_ALIVE_MINUTES", + "RUN_ERL_LOG_ACTIVITY_MINUTES", + "RUN_ERL_LOG_ALIVE_FORMAT", + "RUN_ERL_LOG_ALIVE_IN_UTC", + "RUN_ERL_LOG_GENERATIONS", + "RUN_ERL_LOG_MAXSIZE", + "RUN_ERL_DISABLE_FLOWCNTRL", + + %% driver getenv + "CALLER_DRV_USE_OUTPUTV", + "ERL_INET_GETHOST_DEBUG", + "ERL_EFILE_THREAD_SHORT_CIRCUIT", + "ERL_WINDOW_TITLE", + "ERL_ABORT_ON_FAILURE", + "TTYSL_DEBUG_LOG" + ]). + +os_getenv_erts_specific([]) -> []; +os_getenv_erts_specific([Key|Keys]) -> + [{Key, os:getenv(Key)}|os_getenv_erts_specific(Keys)]. + +split_env(Env) -> + split_env(Env, []). + +split_env([$=|Vs], Key) -> {lists:reverse(Key), Vs}; +split_env([I|Vs], Key) -> split_env(Vs, [I|Key]); +split_env([], KV) -> lists:reverse(KV). % should not happen. + +%% get applications + +code() -> + % order is important + get_code_from_paths(code:get_path()). + +get_code_from_paths([]) -> []; +get_code_from_paths([Path|Paths]) -> + case is_application_path(Path) of + true -> + [{application, get_application_from_path(Path)}|get_code_from_paths(Paths)]; + false -> + [{code, [ + {path, Path}, + {modules, get_modules_from_path(Path)} + ]}|get_code_from_paths(Paths)] + end. + +is_application_path(Path) -> + case filelib:wildcard(filename:join(Path, "*.app")) of + [] -> false; + _ -> true + end. + +get_application_from_path(Path) -> + [Appfile|_] = filelib:wildcard(filename:join(Path, "*.app")), + case file:consult(Appfile) of + {ok, [{application, App, Info}]} -> + {App, [ + {description, proplists:get_value(description, Info, [])}, + {vsn, proplists:get_value(vsn, Info, [])}, + {path, Path}, + {runtime_dependencies, + proplists:get_value(runtime_dependencies, Info, [])}, + {modules, get_modules_from_path(Path)} + ]} + end. + +get_modules_from_path(Path) -> + [ + begin + {ok,{Mod, Md5}} = beam_lib:md5(Beam), + Loaded = case code:is_loaded(Mod) of + false -> false; + _ -> true + end, + {Mod, [ + {loaded, Loaded}, + {native, beam_is_native_compiled(Beam)}, + {compiler, get_compiler_version(Beam)}, + {md5, hexstring(Md5)} + ]} + end || Beam <- filelib:wildcard(filename:join(Path, "*.beam")) + ]. + +hexstring(Bin) when is_binary(Bin) -> + lists:flatten([io_lib:format("~2.16.0b", [V]) || <<V>> <= Bin]). + +%% inspect beam files for information + +get_compiler_version(Beam) -> + case beam_lib:chunks(Beam, [compile_info]) of + {ok,{_,[{compile_info, Info}]}} -> + proplists:get_value(version, Info); + _ -> undefined + end. + +%% we don't know the specific chunk names of native code +%% we don't want to load the code to check it +beam_is_native_compiled(Beam) -> + Chunks = get_value([chunks], beam_lib:info(Beam)), + case check_known_hipe_chunks(Chunks) of + [] -> false; + [Arch] -> {true, Arch}; + Archs -> {true, Archs} + end. + + +check_known_hipe_chunks([{Tag,_,_}|Cs]) -> + case is_chunk_tag_hipe_arch(Tag) of + false -> check_known_hipe_chunks(Cs); + {true, Arch} -> [Arch|check_known_hipe_chunks(Cs)] + end; +check_known_hipe_chunks([]) -> []. + +%% these values are taken from hipe_unified_loader +%% perhaps these should be exported in that module? + +-define(HS8P_TAG,"HS8P"). +-define(HPPC_TAG,"HPPC"). +-define(HP64_TAG,"HP64"). +-define(HARM_TAG,"HARM"). +-define(HX86_TAG,"HX86"). +-define(HA64_TAG,"HA64"). + +is_chunk_tag_hipe_arch(Tag) -> + case Tag of + ?HA64_TAG -> {true, amd64}; %% HiPE, x86_64, (implicit: 64-bit, Unix) + ?HARM_TAG -> {true, arm}; %% HiPE, arm, v5 (implicit: 32-bit, Linux) + ?HPPC_TAG -> {true, powerpc}; %% HiPE, PowerPC (implicit: 32-bit, Linux) + ?HP64_TAG -> {true, ppc64}; %% HiPE, ppc64 (implicit: 64-bit, Linux) + ?HS8P_TAG -> {true, ultrasparc}; %% HiPE, SPARC, V8+ (implicit: 32-bit) + %% Future: HSV9 %% HiPE, SPARC, V9 (implicit: 64-bit) + %% HW32 %% HiPE, x86, Win32 + _ -> false + end. + + +get_dynamic_libraries() -> + Beam = filename:join([os:getenv("BINDIR"),get_beam_name()]), + case os:type() of + {unix, darwin} -> os:cmd("otool -L " ++ Beam); + _ -> os:cmd("ldd " ++ Beam) + end. + +get_beam_name() -> + Type = case erlang:system_info(build_type) of + opt -> ""; + TypeName -> "." ++ atom_to_list(TypeName) + end, + Flavor = case erlang:system_info(smp_support) of + false -> ""; + true -> ".smp" + end, + Beam = os:getenv("EMU", "beam"), + Beam ++ Type ++ Flavor. + +%% Check runtime dependencies... + +vsnstr2vsn(VsnStr) -> + list_to_tuple(lists:map(fun (Part) -> + list_to_integer(Part) + end, + string:tokens(VsnStr, "."))). + +rtdepstrs2rtdeps([]) -> + []; +rtdepstrs2rtdeps([RTDep | RTDeps]) -> + [AppStr, VsnStr] = string:tokens(RTDep, "-"), + [{list_to_atom(AppStr), vsnstr2vsn(VsnStr)} | rtdepstrs2rtdeps(RTDeps)]. + +build_app_table([], AppTab) -> + AppTab; +build_app_table([App | Apps], AppTab0) -> + AppTab1 = try + %% We may have multiple application versions installed + %% of the same application! It is therefore important + %% to look up the application version that actually will + %% be used via code server. + AppFile = code:where_is_file(atom_to_list(App) ++ ".app"), + {ok, [{application, App, Info}]} = file:consult(AppFile), + VsnStr = proplists:get_value(vsn, Info), + Vsn = vsnstr2vsn(VsnStr), + RTDepStrs = proplists:get_value(runtime_dependencies, + Info, []), + RTDeps = rtdepstrs2rtdeps(RTDepStrs), + gb_trees:insert(App, {Vsn, RTDeps}, AppTab0) + catch + _ : _ -> + AppTab0 + end, + build_app_table(Apps, AppTab1). + +meets_min_req(Vsn, Vsn) -> + true; +meets_min_req({X}, VsnReq) -> + meets_min_req({X, 0, 0}, VsnReq); +meets_min_req({X, Y}, VsnReq) -> + meets_min_req({X, Y, 0}, VsnReq); +meets_min_req(Vsn, {X}) -> + meets_min_req(Vsn, {X, 0, 0}); +meets_min_req(Vsn, {X, Y}) -> + meets_min_req(Vsn, {X, Y, 0}); +meets_min_req({X, _Y, _Z}, {XReq, _YReq, _ZReq}) when X > XReq -> + true; +meets_min_req({X, Y, _Z}, {X, YReq, _ZReq}) when Y > YReq -> + true; +meets_min_req({X, Y, Z}, {X, Y, ZReq}) when Z > ZReq -> + true; +meets_min_req({_X, _Y, _Z}, {_XReq, _YReq, _ZReq}) -> + false; +meets_min_req(Vsn, VsnReq) -> + gp_meets_min_req(mk_gp_vsn_list(Vsn), mk_gp_vsn_list(VsnReq)). + +gp_meets_min_req([X, Y, Z | _Vs], [X, Y, Z]) -> + true; +gp_meets_min_req([X, Y, Z | _Vs], [XReq, YReq, ZReq]) -> + meets_min_req({X, Y, Z}, {XReq, YReq, ZReq}); +gp_meets_min_req([X, Y, Z | Vs], [X, Y, Z | VReqs]) -> + gp_meets_min_req_tail(Vs, VReqs); +gp_meets_min_req(_Vsn, _VReq) -> + %% Versions on different version branches, i.e., the minimum + %% required functionality is not included in Vsn. + false. + +gp_meets_min_req_tail([V | Vs], [V | VReqs]) -> + gp_meets_min_req_tail(Vs, VReqs); +gp_meets_min_req_tail([], []) -> + true; +gp_meets_min_req_tail([_V | _Vs], []) -> + true; +gp_meets_min_req_tail([V | _Vs], [VReq]) when V > VReq -> + true; +gp_meets_min_req_tail(_Vs, _VReqs) -> + %% Versions on different version branches, i.e., the minimum + %% required functionality is not included in Vsn. + false. + +mk_gp_vsn_list(Vsn) -> + [X, Y, Z | Tail] = tuple_to_list(Vsn), + [X, Y, Z | remove_trailing_zeroes(Tail)]. + +remove_trailing_zeroes([]) -> + []; +remove_trailing_zeroes([0 | Vs]) -> + case remove_trailing_zeroes(Vs) of + [] -> []; + NewVs -> [0 | NewVs] + end; +remove_trailing_zeroes([V | Vs]) -> + [V | remove_trailing_zeroes(Vs)]. + +mk_app_vsn_str({App, Vsn}) -> + mk_app_vsn_str(App, Vsn). + +mk_app_vsn_str(App, Vsn) -> + VsnList = tuple_to_list(Vsn), + lists:flatten([atom_to_list(App), + $-, + integer_to_list(hd(VsnList)), + lists:map(fun (Part) -> + [$., integer_to_list(Part)] + end, tl(VsnList))]). + +otp_17_0_vsns_orddict() -> + [{asn1,{3,0}}, + {common_test,{1,8}}, + {compiler,{5,0}}, + {cosEvent,{2,1,15}}, + {cosEventDomain,{1,1,14}}, + {cosFileTransfer,{1,1,16}}, + {cosNotification,{1,1,21}}, + {cosProperty,{1,1,17}}, + {cosTime,{1,1,14}}, + {cosTransactions,{1,2,14}}, + {crypto,{3,3}}, + {debugger,{4,0}}, + {dialyzer,{2,7}}, + {diameter,{1,6}}, + {edoc,{0,7,13}}, + {eldap,{1,0,3}}, + {erl_docgen,{0,3,5}}, + {erl_interface,{3,7,16}}, + {erts,{6,0}}, + {et,{1,5}}, + {eunit,{2,2,7}}, + {gs,{1,5,16}}, + {hipe,{3,10,3}}, + {ic,{4,3,5}}, + {inets,{5,10}}, + {jinterface,{1,5,9}}, + {kernel,{3,0}}, + {megaco,{3,17,1}}, + {mnesia,{4,12}}, + {observer,{2,0}}, + {odbc,{2,10,20}}, + {orber,{3,6,27}}, + {os_mon,{2,2,15}}, + {ose,{1,0}}, + {otp_mibs,{1,0,9}}, + {parsetools,{2,0,11}}, + {percept,{0,8,9}}, + {public_key,{0,22}}, + {reltool,{0,6,5}}, + {runtime_tools,{1,8,14}}, + {sasl,{2,4}}, + {snmp,{4,25,1}}, + {ssh,{3,0,1}}, + {ssl,{5,3,4}}, + {stdlib,{2,0}}, + {syntax_tools,{1,6,14}}, + {test_server,{3,7}}, + {tools,{2,6,14}}, + {typer,{0,9,6}}, + {webtool,{0,8,10}}, + {wx,{1,2}}, + {xmerl,{1,3,7}}]. + +otp_17_0_vsns_tab() -> + gb_trees:from_orddict(otp_17_0_vsns_orddict()). + +check_runtime_dependency({App, DepVsn}, AppTab) -> + case gb_trees:lookup(App, AppTab) of + none -> + false; + {value, {Vsn, _}} -> + meets_min_req(Vsn, DepVsn) + end. + +check_runtime_dependencies(App, AppTab, OtpMinVsnTab) -> + case gb_trees:lookup(App, AppTab) of + none -> + [{invalid_app_file, App}]; + {value, {Vsn, RTDeps}} -> + RTD = case lists:foldl( + fun (RTDep, Acc) -> + case check_runtime_dependency(RTDep, AppTab) of + true -> + Acc; + false -> + [mk_app_vsn_str(RTDep) | Acc] + end + end, + [], + RTDeps) of + [] -> + []; + MissingDeps -> + [{missing_runtime_dependencies, + mk_app_vsn_str(App, Vsn), + MissingDeps}] + end, + case gb_trees:lookup(App, OtpMinVsnTab) of + none -> + RTD; + {value, MinVsn} -> + case meets_min_req(Vsn, MinVsn) of + true -> + RTD; + false -> + [{invalid_application_version, + mk_app_vsn_str(App, Vsn)} | RTD] + end + end + end. + +app_file_to_app(AF) -> + list_to_atom(filename:basename(AF, ".app")). + +get_apps() -> + get_apps(code:get_path(), []). + +get_apps([], Apps) -> + lists:usort(Apps); +get_apps([Path|Paths], Apps) -> + case filelib:wildcard(filename:join(Path, "*.app")) of + [] -> + %% Not app or invalid app + get_apps(Paths, Apps); + [AppFile] -> + get_apps(Paths, [app_file_to_app(AppFile) | Apps]); + [_AppFile| _] = AppFiles -> + %% Strange with multple .app files... Lets put them + %% all in the list and see what we get... + lists:map(fun (AF) -> + app_file_to_app(AF) + end, AppFiles) ++ Apps + end. + +check_runtime_dependencies() -> + OtpMinVsnTab = otp_17_0_vsns_tab(), + Apps = get_apps(), + AppTab = build_app_table(Apps, gb_trees:empty()), + lists:foldl(fun (App, Acc) -> + case check_runtime_dependencies(App, + AppTab, + OtpMinVsnTab) of + [] -> Acc; + Issues -> Issues ++ Acc + end + end, + [], + Apps). + +%% End of runtime dependency checks diff --git a/lib/runtime_tools/test/Makefile b/lib/runtime_tools/test/Makefile index 4979b9c7b1..61377ea09e 100644 --- a/lib/runtime_tools/test/Makefile +++ b/lib/runtime_tools/test/Makefile @@ -4,11 +4,12 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk MODULES = \ dyntrace_SUITE \ + dyntrace_lttng_SUITE \ runtime_tools_SUITE \ - inviso_testmodule1_foo \ - inviso_SUITE \ + system_information_SUITE \ dbg_SUITE \ - erts_alloc_config_SUITE + erts_alloc_config_SUITE \ + msacc_SUITE ERL_FILES= $(MODULES:%=%.erl) @@ -27,7 +28,7 @@ RELSYSDIR = $(RELEASE_PATH)/runtime_tools_test # ---------------------------------------------------- ERL_MAKE_FLAGS += -ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include +ERL_COMPILE_FLAGS += EBIN = . diff --git a/lib/runtime_tools/test/dbg_SUITE.erl b/lib/runtime_tools/test/dbg_SUITE.erl index bd908c1f3a..4b0864858c 100644 --- a/lib/runtime_tools/test/dbg_SUITE.erl +++ b/lib/runtime_tools/test/dbg_SUITE.erl @@ -1,302 +1,513 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2011. All Rights Reserved. +%% Copyright Ericsson AB 2010-2016. All Rights Reserved. %% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at %% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. %% %% %CopyrightEnd% %% -module(dbg_SUITE). %% Test functions --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2, - big/1, tiny/1, simple/1, message/1, distributed/1, - ip_port/1, file_port/1, file_port2/1, file_port_schedfix/1, - ip_port_busy/1, wrap_port/1, wrap_port_time/1, - with_seq_trace/1, dead_suspend/1, local_trace/1, - saved_patterns/1]). --export([init_per_testcase/2, end_per_testcase/2]). +-export([all/0, suite/0, + big/1, tiny/1, simple/1, message/1, distributed/1, port/1, + send/1, recv/1, + ip_port/1, file_port/1, file_port2/1, file_port_schedfix/1, + ip_port_busy/1, wrap_port/1, wrap_port_time/1, + with_seq_trace/1, dead_suspend/1, local_trace/1, + saved_patterns/1, tracer_exit_on_stop/1, + erl_tracer/1, distributed_erl_tracer/1]). -export([tracee1/1, tracee2/1]). -export([dummy/0, exported/1]). +-export([enabled/3, trace/5, load_nif/1]). --include_lib("test_server/include/test_server.hrl"). --define(default_timeout, ?t:minutes(1)). - -init_per_testcase(_Case, Config) -> - ?line Dog=test_server:timetrap(?default_timeout), - [{watchdog, Dog}|Config]. -end_per_testcase(_Case, Config) -> - Dog=?config(watchdog, Config), - test_server:timetrap_cancel(Dog), - ok. +-include_lib("common_test/include/ct.hrl"). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap, {minutes, 1}}]. all() -> - [big, tiny, simple, message, distributed, ip_port, + [big, tiny, simple, message, distributed, port, ip_port, + send, recv, file_port, file_port2, file_port_schedfix, ip_port_busy, wrap_port, wrap_port_time, with_seq_trace, dead_suspend, - local_trace, saved_patterns]. - -groups() -> - []. - -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. + local_trace, saved_patterns, tracer_exit_on_stop, + erl_tracer, distributed_erl_tracer]. -init_per_group(_GroupName, Config) -> - Config. -end_per_group(_GroupName, Config) -> - Config. - - -big(suite) -> []; -big(doc) -> ["Rudimentary interface test"]; +%% Rudimentary interface test big(Config) when is_list(Config) -> - ?line {ok,OldCurDir} = file:get_cwd(), - Datadir=?config(data_dir, Config), - Privdir=?config(priv_dir, Config), - ?line ok=file:set_cwd(Privdir), + {ok,OldCurDir} = file:get_cwd(), + Datadir=proplists:get_value(data_dir, Config), + Privdir=proplists:get_value(priv_dir, Config), + ok=file:set_cwd(Privdir), try - %% make sure dbg is stopped (and returns correctly) - ?line ok = dbg:stop(), - - %% compile test module and make sure it is loaded. - ?line {ok,Mod} = compile:file(Datadir++"/dbg_test",[trace]), - ?line code:purge(dbg_test), - ?line {module, Mod}=code:load_file(dbg_test), - - %% run/debug a named test function. - ?line Pid = spawn_link(dbg_test, loop, [Config]), - ?line true = register(dbg_test_loop, Pid), - ?line {ok,_} = dbg:tracer(), - ?line {ok,[{matched, _node, 1}]} = dbg:p(dbg_test_loop, [m,p,c]), - ?line ok = dbg:c(dbg_test, test, [Config]), - ?line ok = dbg:i(), - ?line dbg_test_loop ! {dbg_test, stop}, - unregister(dbg_test_loop), - ?line ok = dbg:stop(), - - %% run/debug a Pid. - ?line Pid2=spawn_link(dbg_test,loop,[Config]), - ?line {ok,_} = dbg:tracer(), - ?line {ok,[{matched, _node, 1}]} = dbg:p(Pid2,[s,r,p]), - ?line ok = dbg:c(dbg_test, test, [Config]), - ?line ok = dbg:i(), - ?line Pid2 ! {dbg_test, stop}, - - ?line ok=file:set_cwd(OldCurDir) + %% make sure dbg is stopped (and returns correctly) + ok = dbg:stop(), + + %% compile test module and make sure it is loaded. + {ok,Mod} = compile:file(Datadir++"/dbg_test",[trace]), + code:purge(dbg_test), + {module, Mod}=code:load_file(dbg_test), + + %% run/debug a named test function. + Pid = spawn_link(dbg_test, loop, [Config]), + true = register(dbg_test_loop, Pid), + {ok,_} = dbg:tracer(), + {ok,[{matched, _node, 1}]} = dbg:p(dbg_test_loop, [m,p,c]), + ok = dbg:c(dbg_test, test, [Config]), + ok = dbg:i(), + dbg_test_loop ! {dbg_test, stop}, + unregister(dbg_test_loop), + ok = dbg:stop(), + + %% run/debug a Pid. + Pid2=spawn_link(dbg_test,loop,[Config]), + {ok,_} = dbg:tracer(), + {ok,[{matched, _node, 1}]} = dbg:p(Pid2,[s,r,p]), + ok = dbg:c(dbg_test, test, [Config]), + ok = dbg:i(), + Pid2 ! {dbg_test, stop}, + + ok=file:set_cwd(OldCurDir) after - ?line dbg:stop() + dbg:stop() end, ok. -tiny(suite) -> []; -tiny(doc) -> ["Rudimentary interface test"]; +%% Rudimentary interface test tiny(Config) when is_list(Config) -> - ?line {ok,OldCurDir} = file:get_cwd(), - Datadir=?config(data_dir, Config), - Privdir=?config(priv_dir, Config), - ?line ok=file:set_cwd(Privdir), + {ok,OldCurDir} = file:get_cwd(), + Datadir=proplists:get_value(data_dir, Config), + Privdir=proplists:get_value(priv_dir, Config), + ok=file:set_cwd(Privdir), try - %% compile test module and make sure it is loaded. - ?line {ok, Mod} = compile:file(Datadir++"/dbg_test",[trace]), - ?line code:purge(dbg_test), - ?line {module, Mod}=code:load_file(dbg_test), - - ?line Pid=spawn_link(dbg_test,loop,[Config]), - if - is_pid(Pid) -> - ?line dbg:tracer(), - ?line {ok,[{matched, _node, 1}]} = dbg:p(Pid,[s,r,m,p,c]), - ?line ok = dbg:c(dbg_test,test,[Config]), - ?line ok = dbg:i(), - ?line Pid ! {dbg_test, stop}; - true -> - ?line ok=file:set_cwd(OldCurDir), - ?t:fail("Could not spawn external test process.~n"), - failure - end + %% compile test module and make sure it is loaded. + {ok, Mod} = compile:file(Datadir++"/dbg_test",[trace]), + code:purge(dbg_test), + {module, Mod}=code:load_file(dbg_test), + + Pid=spawn_link(dbg_test,loop,[Config]), + if + is_pid(Pid) -> + dbg:tracer(), + {ok,[{matched, _node, 1}]} = dbg:p(Pid,[s,r,m,p,c]), + ok = dbg:c(dbg_test,test,[Config]), + ok = dbg:i(), + Pid ! {dbg_test, stop}; + true -> + ok=file:set_cwd(OldCurDir), + ct:fail("Could not spawn external test process.~n"), + failure + end after - ?line ok = dbg:stop(), - ?line ok = file:set_cwd(OldCurDir) + ok = dbg:stop(), + ok = file:set_cwd(OldCurDir) end, ok. -simple(suite) -> - []; -simple(doc) -> - ["Simple interface test with own handler"]; +%% Simple interface test with own handler simple(Config) when is_list(Config) -> try - ?line start(), - ?line dbg:p(self(),call), - ?line dbg:tp(dbg,ltp,[]), - ?line dbg:ltp(), - ?line stop(), - ?line S = self(), - ?line [{trace,S,call,{dbg,ltp,[]}}] = flush() + start(), + dbg:p(self(),call), + dbg:tp(dbg,ltp,[]), + dbg:ltp(), + stop(), + S = self(), + [{trace,S,call,{dbg,ltp,[]}}] = flush() after - ?line dbg:stop() + dbg:stop() end, ok. -message(suite) -> - []; -message(doc) -> - ["Simple interface test with pam code that appends a message"]; +%% Simple interface test with pam code that appends a message message(Config) when is_list(Config) -> - ?line {ok, _} = start(), + {ok, _} = start(), try - ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call), - ?line {ok, X} = dbg:tp(dbg,ltp,[{'_',[],[{message, {self}}]}]), - ?line {value, {saved, Saved}} = lists:keysearch(saved, 1, X), - ?line {ok, Y} = dbg:tp(dbg,ln,Saved), - ?line {value, {saved, Saved}} = lists:keysearch(saved, 1, Y), - ?line ok = dbg:ltp(), - ?line ok = dbg:ln() + {ok, [{matched, _node, 1}]} = dbg:p(self(),call), + {ok, X} = dbg:tp(dbg,ltp,[{'_',[],[{message, {self}}]}]), + {value, {saved, Saved}} = lists:keysearch(saved, 1, X), + {ok, Y} = dbg:tp(dbg,ln,Saved), + {value, {saved, Saved}} = lists:keysearch(saved, 1, Y), + ok = dbg:ltp(), + ok = dbg:ln() after - ?line stop() + stop() end, - ?line S = self(), - ?line [{trace,S,call,{dbg,ltp,[]},S}, - {trace,S,call,{dbg,ln,[]},S}] = flush(), + S = self(), + [{trace,S,call,{dbg,ltp,[]},S}, + {trace,S,call,{dbg,ln,[]},S}] = flush(), ok. -distributed(suite) -> - []; -distributed(doc) -> - ["Simple test of distributed tracing"]; +send(Config) when is_list(Config) -> + {ok, _} = start(), + Node = start_slave(), + rpc:call(Node, code, add_patha, + [filename:join(proplists:get_value(data_dir, Config), "..")]), + try + Echo = fun F() -> + receive {From, M} -> + From ! M, + F() + end + end, + Rcvr = spawn_link(Echo), + RemoteRcvr = spawn_link(Node, Echo), + + {ok, [{matched, _, 1}]} = dbg:p(Rcvr, send), + + send_test(Rcvr, make_ref(), true), + + %% Test that the test case process is the receiving process + send_test(Rcvr, [{[self(),'_'],[],[]}]), + + %% Test that self() is not the receiving process + {ok, [{matched, _node, 1}, {saved, 2}]} = + dbg:tpe(send, [{['$1','_'],[{'==','$1',{self}}],[]}]), + send_test(Rcvr, make_ref(), false), + + %% Test that self() is the sending process + send_test(Rcvr, [{['_','_'],[{'==',Rcvr,{self}}],[]}]), + + %% Test attaching a message + send_test(Rcvr, [{['_','_'],[{'==',Rcvr,{self}}],[{message, hello}]}], + make_ref(), hello), + + %% Test using a saved trace pattern + send_test(Rcvr, 2, make_ref(), false), + + %% Test clearing of trace pattern + {ok, [{matched, _node, 1}]} = dbg:ctpe(send), + send_test(Rcvr, make_ref(), true), + + %% Test complex message inspection + Ref = make_ref(), + send_test(Rcvr, + [{['_','$2'],[{'==',Ref,{element,1,{element,2,'$2'}}}],[]}], + {test, {Ref}, <<0:(8*1024)>>}, true), + + send_test(Rcvr, {test, {make_ref()}, <<0:(8*1024)>>}, false), + + %% Test send to remote process + remote_send_test(Rcvr, RemoteRcvr, [], make_ref(), true), + + remote_send_test(Rcvr, RemoteRcvr, + [{['$1','_'],[{'==',{node, '$1'},{node}}],[]}], + make_ref(), false), + + remote_send_test(Rcvr, RemoteRcvr, + [{['$1','_'],[{'==',{node, '$1'},Node}],[]}], + make_ref(), true), + + %% Test that distributed dbg works + dbg:tracer(Node, process, {fun myhandler/2, self()}), + Rcvr2 = spawn_link(Echo), + RemoteRcvr2 = spawn_link(Node, Echo), + dbg:p(Rcvr2, [send]), + dbg:p(RemoteRcvr2, [send]), + dbg:tpe(send, [{['_', hej],[],[]}]), + + send_test(Rcvr2, make_ref(), false), + send_test(RemoteRcvr2, make_ref(), false), + send_test(Rcvr2, hej, true), + send_test(RemoteRcvr2, hej, true), + + ok + + after + stop() + end. + +send_test(Pid, Pattern, Msg, TraceEvent) -> + {ok, [{matched, _, _}, _]} = dbg:tpe(send, Pattern), + send_test(Pid, Msg, TraceEvent). +send_test(Pid, Pattern) -> + send_test(Pid, Pattern, make_ref(), true). +send_test(Pid, Msg, TraceEvent) -> + S = self(), + Pid ! {S, Msg}, + receive Msg -> ok end, + send_test_rcv(Pid, Msg, S, TraceEvent). + +remote_send_test(Pid, RPid, Pattern, Msg, TraceEvent) -> + dbg:tpe(send, Pattern), + TMsg = {self(), Msg}, + Pid ! {RPid, TMsg}, + receive Msg -> ok end, + send_test_rcv(Pid, TMsg, RPid, TraceEvent). + +send_test_rcv(Pid, Msg, S, TraceEvent) -> + case flush() of + [] when not TraceEvent -> + ok; + [{trace, Pid, send, Msg, S}] when TraceEvent -> + ok; + [{trace, Pid, send, Msg, S, Message}] when TraceEvent == Message -> + ok; + Else -> + ct:fail({got_unexpected_message, Else}) + end. + +recv(Config) when is_list(Config) -> + {ok, _} = start(), + Node = start_slave(), + rpc:call(Node, code, add_patha, + [filename:join(proplists:get_value(data_dir, Config), "..")]), + try + Echo = fun F() -> + receive {From, M} -> + From ! M, + F() + end + end, + Rcvr = spawn_link(Echo), + RemoteRcvr = spawn_link(Node, Echo), + + {ok, [{matched, _, 1}]} = dbg:p(Rcvr, 'receive'), + + recv_test(Rcvr, make_ref(), true), + + %% Test that the test case process is the sending process + recv_test(Rcvr, [{[node(), self(), '_'],[],[]}]), + + %% Test that self() is the not sending process + {ok, [{matched, _node, 1}, {saved, 2}]} = + dbg:tpe('receive', [{[node(), '$1','_'],[{'==','$1',{self}}],[]}]), + recv_test(Rcvr, make_ref(), false), + + %% Test that self() is the receiving process + recv_test(Rcvr, [{'_',[{'==',Rcvr,{self}}],[]}]), + + %% Test attaching a message + recv_test(Rcvr, [{'_',[{'==',Rcvr,{self}}],[{message, hello}]}], + make_ref(), hello), + + %% Test using a saved trace pattern + recv_test(Rcvr, 2, make_ref(), false), + + %% Test clearing of trace pattern + {ok, [{matched, _node, 1}]} = dbg:ctpe('receive'), + recv_test(Rcvr, make_ref(), true), + + %% Test complex message inspection + Ref = make_ref(), + recv_test(Rcvr, + [{[node(), '_','$2'],[{'==',Ref,{element,1, + {element,2, + {element,2,'$2'}}}}],[]}], + {test, {Ref}, <<0:(8*1024)>>}, true), + + recv_test(Rcvr, {test, {make_ref()}, <<0:(8*1024)>>}, false), + + %% Test recv to remote process + remote_recv_test(RemoteRcvr, Rcvr, [], make_ref(), true), + + remote_recv_test(RemoteRcvr, Rcvr, + [{['$1',undefined,'_'],[{'==','$1',{node}}],[]}], + make_ref(), false), + + remote_recv_test(RemoteRcvr, Rcvr, + [{['$1',undefined,'_'],[{'==','$1',Node}],[]}], + make_ref(), true), + + %% Test that distributed dbg works + dbg:tracer(Node, process, {fun myhandler/2, self()}), + Rcvr2 = spawn_link(Echo), + RemoteRcvr2 = spawn_link(Node, Echo), + dbg:p(Rcvr2, ['receive']), + dbg:p(RemoteRcvr2, ['receive']), + dbg:tpe('receive', [{[node(), '_', '$1'],[{'==',{element,2,'$1'}, hej}],[]}]), + + recv_test(Rcvr2, make_ref(), false), + recv_test(RemoteRcvr2, make_ref(), false), + recv_test(Rcvr2, hej, true), + recv_test(RemoteRcvr2, hej, true), + + ok + + after + stop() + end. + +recv_test(Pid, Pattern, Msg, TraceEvent) -> + {ok, [{matched, _, _}, _]} = dbg:tpe('receive', Pattern), + recv_test(Pid, Msg, TraceEvent). +recv_test(Pid, Pattern) -> + recv_test(Pid, Pattern, make_ref(), true). +recv_test(Pid, Msg, TraceEvent) -> + S = self(), + Pid ! {S, Msg}, + receive Msg -> ok end, + recv_test_rcv(Pid, {S, Msg}, TraceEvent). + +remote_recv_test(RPid, Pid, Pattern, Msg, TraceEvent) -> + dbg:tpe('receive', Pattern), + TMsg = {self(), Msg}, + RPid ! {Pid, TMsg}, + receive Msg -> ok end, + recv_test_rcv(Pid, TMsg, TraceEvent). + +recv_test_rcv(Pid, Msg, TraceEvent) -> + case flush() of + [] when not TraceEvent -> + ok; + [{trace, Pid, 'receive', Msg}] when TraceEvent -> + ok; + [{trace, Pid, 'receive', Msg, Message}] when TraceEvent == Message -> + ok; + Else -> + ct:fail({got_unexpected_message, Else}) + end. + +%% Simple test of distributed tracing distributed(Config) when is_list(Config) -> - ?line {ok, _} = start(), - ?line Node = start_slave(), + {ok, _} = start(), + Node = start_slave(), try - ?line RexPid = rpc:call(Node, erlang, whereis, [rex]), - ?line RexPidList = pid_to_list(RexPid), - ?line {ok, Node} = dbg:n(Node), - ?line {ok, X} = dbg:p(all,call), - ?line {value, {matched, Node, _}} = lists:keysearch(Node, 2, X), - ?line {ok, Y} = dbg:p(RexPidList, s), - ?line {value, {matched, Node, 1}} = lists:keysearch(Node, 2, Y), - ?line {ok, Z} = dbg:tp(dbg,ltp,[]), - ?line {value, {matched, Node, 1}} = lists:keysearch(Node, 2, Z), - ?line dbg:cn(Node), - ?line dbg:tp(dbg,ln,[]), - ?line ok = rpc:call(Node, dbg, ltp, []), - ?line ok = rpc:call(Node, dbg, ln, []), - ?line ok = dbg:ln(), - ?line S = self(), - ?line {TraceSend, TraceCall} = - lists:partition(fun ({trace,RP,send,_,_}) when RP =:= RexPid -> true; - (_) -> false end, - flush()), - ?line [_|_] = TraceSend, - ?line [{trace,Pid,call,{dbg,ltp,[]}}, - {trace,S,call,{dbg,ln,[]}}] = TraceCall, - ?line Node = node(Pid), - %% - ?line stop() + RexPid = rpc:call(Node, erlang, whereis, [rex]), + RexPidList = pid_to_list(RexPid), + {ok, Node} = dbg:n(Node), + {ok, X} = dbg:p(all,call), + {value, {matched, Node, _}} = lists:keysearch(Node, 2, X), + {ok, Y} = dbg:p(RexPidList, s), + {value, {matched, Node, 1}} = lists:keysearch(Node, 2, Y), + {ok, Z} = dbg:tp(dbg,ltp,[]), + {value, {matched, Node, 1}} = lists:keysearch(Node, 2, Z), + dbg:cn(Node), + dbg:tp(dbg,ln,[]), + ok = rpc:block_call(Node, dbg, ltp, []), + ok = rpc:block_call(Node, dbg, ln, []), + ok = dbg:ln(), + S = self(), + {TraceSend, TraceCall} = + lists:partition(fun ({trace,RP,send,_,_}) when RP =:= RexPid -> true; + (_) -> false end, + flush()), + [_|_] = TraceSend, + [{trace,Pid,call,{dbg,ltp,[]}}, + {trace,S,call,{dbg,ln,[]}}] = TraceCall, + Node = node(Pid), + %% + stop() after - ?line stop_slave(Node), - ?line stop() + stop_slave(Node), + stop() end, ok. -local_trace(suite) -> - []; -local_trace(doc) -> - ["Tests tracing of local function calls."]; +%% Tests tracing of local function calls. local_trace(Config) when is_list(Config) -> - ?line {ok, _} = start(), + {ok, _} = start(), try - ?line S = self(), - ?line %% Split "<X.Y.Z>" into {X, Y, Z} - ?line "<"++L1 = L = pid_to_list(S), - ?line NoDot = fun ($.) -> false; (_) -> true end, - ?line {LX,"."++L2} = lists:splitwith(NoDot, L1), - ?line {LY,"."++L3} = lists:splitwith(NoDot, L2), - ?line ">"++L4 = lists:reverse(L3), - ?line LZ = lists:reverse(L4), - ?line X = 0 = list_to_integer(LX), - ?line Y = list_to_integer(LY), - ?line Z = list_to_integer(LZ), - ?line XYZ = {X, Y, Z}, - ?line io:format("Self = ~w = ~w~n", [S,XYZ]), - ?line {ok, [{matched, _node, 1}]} = dbg:p(S,call), - ?line {ok, [{matched, _node, 1}]} = dbg:p(XYZ,call), - if Z =:= 0 -> - ?line {ok, [{matched, _node, 1}]} = dbg:p(Y,call); - true -> ok - end, - ?line {ok, [{matched, _node, 1}]} = dbg:p(L,call), - ?line {ok, _} = dbg:tpl(?MODULE,not_exported,[]), - ?line 4 = not_exported(2), - ?line [{trace,S,call,{?MODULE,not_exported,[2]}}] = flush(), - ?line {ok, _} = dbg:tp(?MODULE,exported,[]), - ?line 4 = ?MODULE:exported(2), - ?line [{trace,S,call,{?MODULE,exported,[2]}}, - {trace,S,call,{?MODULE,not_exported,[2]}}] = flush(), - ?line {ok, _} = dbg:ctpl(?MODULE), - ?line 4 = ?MODULE:exported(2), - ?line [{trace,S,call,{?MODULE,exported,[2]}}] = flush(), - ?line {ok, _} = dbg:tpl(?MODULE,not_exported,[]), - ?line {ok, _} = dbg:ctp(?MODULE), - ?line 4 = ?MODULE:exported(2), - ?line [] = flush(), - ?line {ok, _} = dbg:tpl(?MODULE,not_exported,x), - ?line catch ?MODULE:exported(x), - ?line [{trace,S,call,{dbg_SUITE,not_exported,[x]}}, - {trace,S,exception_from, - {dbg_SUITE,not_exported,1}, - {error,badarith}}] = flush() + S = self(), + %% Split "<X.Y.Z>" into {X, Y, Z} + "<"++L1 = L = pid_to_list(S), + NoDot = fun ($.) -> false; (_) -> true end, + {LX,"."++L2} = lists:splitwith(NoDot, L1), + {LY,"."++L3} = lists:splitwith(NoDot, L2), + ">"++L4 = lists:reverse(L3), + LZ = lists:reverse(L4), + X = 0 = list_to_integer(LX), + Y = list_to_integer(LY), + Z = list_to_integer(LZ), + XYZ = {X, Y, Z}, + io:format("Self = ~w = ~w~n", [S,XYZ]), + {ok, [{matched, _node, 1}]} = dbg:p(S,call), + {ok, [{matched, _node, 1}]} = dbg:p(XYZ,call), + if Z =:= 0 -> + {ok, [{matched, _node, 1}]} = dbg:p(Y,call); + true -> ok + end, + {ok, [{matched, _node, 1}]} = dbg:p(L,call), + {ok, _} = dbg:tpl(?MODULE,not_exported,[]), + 4 = not_exported(2), + [{trace,S,call,{?MODULE,not_exported,[2]}}] = flush(), + {ok, _} = dbg:tp(?MODULE,exported,[]), + 4 = ?MODULE:exported(2), + [{trace,S,call,{?MODULE,exported,[2]}}, + {trace,S,call,{?MODULE,not_exported,[2]}}] = flush(), + {ok, _} = dbg:ctpl(?MODULE), + 4 = ?MODULE:exported(2), + [{trace,S,call,{?MODULE,exported,[2]}}] = flush(), + {ok, _} = dbg:tpl(?MODULE,not_exported,[]), + {ok, _} = dbg:ctp(?MODULE), + 4 = ?MODULE:exported(2), + [] = flush(), + {ok, _} = dbg:tpl(?MODULE,not_exported,x), + catch ?MODULE:exported(x), + [{trace,S,call,{dbg_SUITE,not_exported,[x]}}, + {trace,S,exception_from, + {dbg_SUITE,not_exported,1}, + {error,badarith}}] = flush() after - ?line stop() + stop() end, ok. -saved_patterns(suite) -> - []; -saved_patterns(doc) -> - ["Tests saving of match_spec's."]; +%% Test that tracing on port works +port(Config) when is_list(Config) -> + try + S = self(), + start(), + TestFile = filename:join(proplists:get_value(priv_dir, Config),"port_test"), + Fun = dbg:trace_port(file, TestFile), + + %% Do a run to get rid of all extra port operations + port_close(Fun()), + + dbg:p(new,ports), + Port = Fun(), + port_close(Port), + stop(), + + TraceFileDrv = list_to_atom(lists:flatten(["trace_file_drv n ",TestFile])), + [{trace,Port,open,S,TraceFileDrv}, + {trace,Port,getting_linked,S}, + {trace,Port,closed,normal}, + {trace,Port,unlink,S}] = flush() + after + dbg:stop() + end, + ok. + +%% Tests saving of match_spec's. saved_patterns(Config) when is_list(Config) -> - ?line dbg:stop(), - ?line {ok,[{saved,1}]} = - dbg:tp(dbg,ctp,1,[{'_',[],[{message, blahonga}]}]), - ?line {ok,[{saved,2}]} = - dbg:tp(dbg,ctp,1,[{['_'],[],[{message, blahonga}]}]), - ?line Privdir=?config(priv_dir, Config), - ?line file:make_dir(Privdir), - ?line File = filename:join([Privdir, "blahonga.ms"]), - ?line dbg:wtp(File), - ?line dbg:stop(), - ?line dbg:ctp('_','_','_'), - ?line {ok, _} = start(), + dbg:stop(), + {ok,[{saved,1}]} = + dbg:tp(dbg,ctp,1,[{'_',[],[{message, blahonga}]}]), + {ok,[{saved,2}]} = + dbg:tp(dbg,ctp,1,[{['_'],[],[{message, blahonga}]}]), + Privdir=proplists:get_value(priv_dir, Config), + file:make_dir(Privdir), + File = filename:join([Privdir, "blahonga.ms"]), + dbg:wtp(File), + dbg:stop(), + dbg:ctp('_','_','_'), + {ok, _} = start(), try - ?line dbg:rtp(File), - ?line {ok,[{matched,_node,1},{saved,1}]} = dbg:tp(dbg,ltp,0,1), - ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call), - ?line dbg:ltp(), - ?line S = self(), - ?line [{trace,S,call,{dbg,ltp,[]},blahonga}] = flush() + dbg:rtp(File), + {ok,[{matched,_node,1},{saved,1}]} = dbg:tp(dbg,ltp,0,1), + {ok, [{matched, _node, 1}]} = dbg:p(self(),call), + dbg:ltp(), + S = self(), + [{trace,S,call,{dbg,ltp,[]},blahonga}] = flush() after - ?line stop() + stop() end, ok. @@ -308,153 +519,132 @@ not_exported(N) -> exported(N) -> not_exported(N). -ip_port(suite) -> - []; -ip_port(doc) -> - ["Test tracing to IP port"]; +%% Test tracing to IP port ip_port(Config) when is_list(Config) -> - ?line stop(), - ?line Port = dbg:trace_port(ip, 0), - ?line {ok, _} = dbg:tracer(port, Port), + stop(), + Port = dbg:trace_port(ip, 0), + {ok, _} = dbg:tracer(port, Port), try - ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call), - ?line {ok, X} = dbg:tp(dbg, ltp,[{'_',[],[{message, {self}}]}]), - ?line {value, {saved, _Saved}} = lists:keysearch(saved, 1, X), - ?line {ok, Y} = dbg:tp(dbg, ln, [{'_',[],[{message, hej}]}]), - ?line {value, {saved, _}} = lists:keysearch(saved, 1, Y), - ?line ok = dbg:ltp(), - ?line ok = dbg:ln(), - ?line {ok, IpPort} = dbg:trace_port_control(get_listen_port), - ?line io:format("IpPort = ~p~n", [IpPort]), - ?line dbg:trace_client(ip, IpPort, {fun myhandler/2, self()}), - ?line S = self(), - ?line [{trace,S,call,{dbg,ltp,[]},S}, - {trace,S,call,{dbg,ln,[]},hej}] = flush() + {ok, [{matched, _node, 1}]} = dbg:p(self(),call), + {ok, X} = dbg:tp(dbg, ltp,[{'_',[],[{message, {self}}]}]), + {value, {saved, _Saved}} = lists:keysearch(saved, 1, X), + {ok, Y} = dbg:tp(dbg, ln, [{'_',[],[{message, hej}]}]), + {value, {saved, _}} = lists:keysearch(saved, 1, Y), + ok = dbg:ltp(), + ok = dbg:ln(), + {ok, IpPort} = dbg:trace_port_control(get_listen_port), + io:format("IpPort = ~p~n", [IpPort]), + dbg:trace_client(ip, IpPort, {fun myhandler/2, self()}), + S = self(), + [{trace,S,call,{dbg,ltp,[]},S}, + {trace,S,call,{dbg,ln,[]},hej}] = flush() after - ?line stop() + stop() end, ok. -ip_port_busy(suite) -> - []; -ip_port_busy(doc) -> - ["Test that the dbg server does not hang if the tracer don't start ", - "(OTP-3592)"]; +%% Test that the dbg server does not hang if the tracer don't start (OTP-3592) ip_port_busy(Config) when is_list(Config) -> - ?line stop(), - ?line Tracer = dbg:trace_port(ip, 4745), - ?line Port = Tracer(), - ?line {error, Reason} = dbg:tracer(port, Tracer), + stop(), + Tracer = dbg:trace_port(ip, 4745), + Port = Tracer(), + {error, Reason} = dbg:tracer(port, Tracer), try - ?line io:format("Error reason = ~p~n", [Reason]), - ?line true = port_close(Port) + io:format("Error reason = ~p~n", [Reason]), + true = port_close(Port) after - ?line dbg:stop() + dbg:stop() end, - ?line ok. + ok. -file_port(suite) -> - []; -file_port(doc) -> - ["Test tracing to file port (simple)"]; +%% Test tracing to file port (simple) file_port(Config) when is_list(Config) -> - ?line stop(), - ?line {A,B,C} = erlang:now(), - ?line FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++ "-" ++ - integer_to_list(B) ++ "-" ++ integer_to_list(C), - ?line FName = filename:join([?config(data_dir, Config), FTMP]), - ?line Port = dbg:trace_port(file, FName), - ?line {ok, _} = dbg:tracer(port, Port), + stop(), + {A,B,C} = erlang:now(), + FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++ "-" ++ + integer_to_list(B) ++ "-" ++ integer_to_list(C), + FName = filename:join([proplists:get_value(data_dir, Config), FTMP]), + Port = dbg:trace_port(file, FName), + {ok, _} = dbg:tracer(port, Port), try - ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call), - ?line {ok, X} = dbg:tp(dbg, ltp,[{'_',[],[{message, {self}}]}]), - ?line {value, {saved, _Saved}} = lists:keysearch(saved, 1, X), - ?line {ok, Y} = dbg:tp(dbg, ln, [{'_',[],[{message, hej}]}]), - ?line {value, {saved, _}} = lists:keysearch(saved, 1, Y), - ?line ok = dbg:ltp(), - ?line ok = dbg:ln(), - ?line stop(), - ?line dbg:trace_client(file, FName, {fun myhandler/2, self()}), - ?line S = self(), - ?line [{trace,S,call,{dbg,ltp,[]},S}, - {trace,S,call,{dbg,ln,[]},hej}, - end_of_trace] = flush() + {ok, [{matched, _node, 1}]} = dbg:p(self(),call), + {ok, X} = dbg:tp(dbg, ltp,[{'_',[],[{message, {self}}]}]), + {value, {saved, _Saved}} = lists:keysearch(saved, 1, X), + {ok, Y} = dbg:tp(dbg, ln, [{'_',[],[{message, hej}]}]), + {value, {saved, _}} = lists:keysearch(saved, 1, Y), + ok = dbg:ltp(), + ok = dbg:ln(), + stop(), + dbg:trace_client(file, FName, {fun myhandler/2, self()}), + S = self(), + [{trace,S,call,{dbg,ltp,[]},S}, + {trace,S,call,{dbg,ln,[]},hej}, + end_of_trace] = flush() after - ?line stop(), - ?line file:delete(FName) + stop(), + file:delete(FName) end, ok. -file_port2(suite) -> - []; -file_port2(doc) -> - ["Test tracing to file port with 'follow_file'"]; +%% Test tracing to file port with 'follow_file' file_port2(Config) when is_list(Config) -> - case os:type() of - vxworks -> - {skipped, "VxWorks NFS cache ruins it all."}; - _ -> - ?line stop(), - ?line {A,B,C} = erlang:now(), - ?line FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++ - "-" ++ integer_to_list(B) ++ "-" ++ integer_to_list(C), - ?line FName = filename:join([?config(data_dir, Config), FTMP]), - %% Ok, lets try with flush and follow_file, not a chance on VxWorks - %% with NFS caching... - ?line Port2 = dbg:trace_port(file, FName), - ?line {ok, _} = dbg:tracer(port, Port2), - try - ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call), - ?line {ok, _} = dbg:tp(dbg, ltp,[{'_',[],[{message, {self}}]}]), - ?line {ok, _} = dbg:tp(dbg, ln, [{'_',[],[{message, hej}]}]), - ?line ok = dbg:ltp(), - ?line ok = dbg:flush_trace_port(), - ?line dbg:trace_client(follow_file, FName, - {fun myhandler/2, self()}), - ?line S = self(), - ?line [{trace,S,call,{dbg,ltp,[]},S}] = flush(), - ?line ok = dbg:ln(), - ?line ok = dbg:flush_trace_port(), - ?line receive after 1000 -> ok end, %% Polls every second... - ?line [{trace,S,call,{dbg,ln,[]},hej}] = flush(), - ?line stop(), - ?line [] = flush() - after - ?line stop(), - ?line file:delete(FName) - end, - ok - end. + stop(), + {A,B,C} = erlang:now(), + FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++ + "-" ++ integer_to_list(B) ++ "-" ++ integer_to_list(C), + FName = filename:join([proplists:get_value(data_dir, Config), FTMP]), + %% Ok, lets try with flush and follow_file, not a chance on VxWorks + %% with NFS caching... + Port2 = dbg:trace_port(file, FName), + {ok, _} = dbg:tracer(port, Port2), + try + {ok, [{matched, _node, 1}]} = dbg:p(self(),call), + {ok, _} = dbg:tp(dbg, ltp,[{'_',[],[{message, {self}}]}]), + {ok, _} = dbg:tp(dbg, ln, [{'_',[],[{message, hej}]}]), + ok = dbg:ltp(), + ok = dbg:flush_trace_port(), + dbg:trace_client(follow_file, FName, + {fun myhandler/2, self()}), + S = self(), + [{trace,S,call,{dbg,ltp,[]},S}] = flush(), + ok = dbg:ln(), + ok = dbg:flush_trace_port(), + receive after 1000 -> ok end, %% Polls every second... + [{trace,S,call,{dbg,ln,[]},hej}] = flush(), + stop(), + [] = flush() + after + stop(), + file:delete(FName) + end, + ok. -file_port_schedfix(suite) -> - []; -file_port_schedfix(doc) -> - ["Test that the scheduling timestamp fix for trace flag 'running' works."]; +%% Test that the scheduling timestamp fix for trace flag 'running' works. file_port_schedfix(Config) when is_list(Config) -> - ?line case (catch erlang:system_info(smp_support)) of - true -> - {skip, "No schedule fix on SMP"}; - _ -> - try - file_port_schedfix1(Config) - after - dbg:stop() - end - end. + case (catch erlang:system_info(smp_support)) of + true -> + {skip, "No schedule fix on SMP"}; + _ -> + try + file_port_schedfix1(Config) + after + dbg:stop() + end + end. file_port_schedfix1(Config) when is_list(Config) -> - ?line stop(), - ?line {A,B,C} = erlang:now(), - ?line FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++ - "-" ++ integer_to_list(B) ++ "-" ++ integer_to_list(C), - ?line FName = filename:join([?config(data_dir, Config), FTMP]), + stop(), + {A,B,C} = erlang:now(), + FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++ + "-" ++ integer_to_list(B) ++ "-" ++ integer_to_list(C), + FName = filename:join([proplists:get_value(data_dir, Config), FTMP]), %% - ?line Port = dbg:trace_port(file, {FName, wrap, ".wraplog", 8*1024, 4}), - ?line {ok, _} = dbg:tracer(port, Port), - ?line {ok,[{matched,_node,0}]} = dbg:p(new,[running,procs,send,timestamp]), + Port = dbg:trace_port(file, {FName, wrap, ".wraplog", 8*1024, 4}), + {ok, _} = dbg:tracer(port, Port), + {ok,[{matched,_node,0}]} = dbg:p(new,[running,procs,send,timestamp]), %% %% Generate the trace data %% @@ -475,146 +665,135 @@ file_port_schedfix1(Config) when is_list(Config) -> %% execution time. Wallclock. A normal result is about 10 times more %% without schedule in - schedule out compensation (OTP-3938). %% - ?line ok = token_volleyball(3, 4, 8), + ok = token_volleyball(3, 4, 8), + %% + {ok,[{matched,_,_}]} = dbg:p(all, [clear]), + stop(), %% - ?line {ok,[{matched,_,_}]} = dbg:p(all, [clear]), - ?line stop(), - % Some debug code to run on all platforms, for finding the fault on genny - % Dont touch please /PaN - ?line io:format("Trace dump by PaN BEGIN~n"), - ?line dbg:trace_client(file,{FName, wrap, ".wraplog"},{fun(end_of_trace,Pid)-> Pid ! done; (Mesg,Pid) -> io:format("~w~n",[Mesg]),Pid end,self()}), - receive done -> ok end, - ?line io:format("Trace dump by PaN END~n"), - %% %% Get the trace result %% - ?line Tag = make_ref(), - ?line dbg:trace_client(file, {FName, wrap, ".wraplog"}, - {fun schedstat_handler/2, {self(), Tag, []}}), - ?line Result = - receive - {Tag, D} -> - lists:map( - fun({Pid, {A1, B1, C1}}) -> - {Pid, C1/1000000 + B1 + A1*1000000} - end, - D) - end, - ?line ok = io:format("Result=~p", [Result]), -% erlang:display({?MODULE, ?LINE, Result}), + Tag = make_ref(), + dbg:trace_client(file, {FName, wrap, ".wraplog"}, + {fun schedstat_handler/2, {self(), Tag, []}}), + Result = + receive + {Tag, D} -> + lists:map( + fun({Pid, {A1, B1, C1}}) -> + {Pid, C1/1000000 + B1 + A1*1000000} + end, + D) + end, + ok = io:format("Result=~p", [Result]), + % erlang:display({?MODULE, ?LINE, Result}), %% %% Analyze the result %% - ?line {Min, Max} = - lists:foldl( - fun({_Pid, M}, {Mi, Ma}) -> - {if M < Mi -> M; true -> Mi end, - if M > Ma -> M; true -> Ma end} - end, - {void, 0}, - Result), + {Min, Max} = lists:foldl(fun({_Pid, M}, {Mi, Ma}) -> + {if M < Mi -> M; true -> Mi end, + if M > Ma -> M; true -> Ma end} + end, + {void, 0}, + Result), % More PaN debug - ?line io:format("Min = ~f, Max = ~f~n",[Min,Max]), + io:format("Min = ~f, Max = ~f~n",[Min,Max]), %% %% Cleanup %% - ?line ToBeDeleted = filelib:wildcard(FName++"*"++".wraplog"), - ?line lists:map({file, delete}, ToBeDeleted), -% io:format("ToBeDeleted=~p", [ToBeDeleted]), + ToBeDeleted = filelib:wildcard(FName++"*"++".wraplog"), + lists:map(fun file:delete/1, ToBeDeleted), + % io:format("ToBeDeleted=~p", [ToBeDeleted]), %% %% Present the result %% P = (Max / Min - 1) * 100, BottomLine = lists:flatten(io_lib:format("~.2f %", [P])), if P > 100 -> - Reason = {BottomLine, '>', "100%"}, - erlang:display({file_port_schedfix, fail, Reason}), - test_server:fail(Reason); + Reason = {BottomLine, '>', "100%"}, + erlang:display({file_port_schedfix, fail, Reason}), + ct:fail(Reason); true -> - {comment, BottomLine} + {comment, BottomLine} end. -wrap_port(suite) -> - []; -wrap_port(doc) -> - ["Test tracing to wrapping file port"]; +%% Test tracing to wrapping file port wrap_port(Config) when is_list(Config) -> - ?line Self = self(), - ?line stop(), - ?line {A,B,C} = erlang:now(), - ?line FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++ "-" ++ - integer_to_list(B) ++ "-" ++ integer_to_list(C) ++ "-", - ?line FName = filename:join([?config(data_dir, Config), FTMP]), - ?line FNameWildcard = FName++"*"++".trace", + Self = self(), + stop(), + {A,B,C} = erlang:now(), + FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++ "-" ++ + integer_to_list(B) ++ "-" ++ integer_to_list(C) ++ "-", + FName = filename:join([proplists:get_value(data_dir, Config), FTMP]), + FNameWildcard = FName++"*"++".trace", %% WrapSize=0 and WrapCnt=11 will force the trace to wrap after %% every trace message, and to contain only the last 10 entries %% after trace stop since the last file will be empty waiting %% for its first trace message. - ?line WrapSize = 0, - ?line WrapCnt = 11, - ?line WrapFilesSpec = {FName, wrap, ".trace", WrapSize, WrapCnt}, - ?line wrap_port_init(WrapFilesSpec), + WrapSize = 0, + WrapCnt = 11, + WrapFilesSpec = {FName, wrap, ".trace", WrapSize, WrapCnt}, + wrap_port_init(WrapFilesSpec), %% The number of iterations, N, is tested to place wrap the log, %% giving a gap in the filename sequence at index 3. %% This should be a difficult case for %% the trace_client file sorting functionality. N = 7, - ?line lists:foreach( - fun(Cnt) -> - ?MODULE:tracee1(Cnt), - ?MODULE:tracee2(Cnt) - end, - lists:seq(1, N)), - ?line stop(), + lists:foreach( + fun(Cnt) -> + ?MODULE:tracee1(Cnt), + ?MODULE:tracee2(Cnt) + end, + lists:seq(1, N)), + stop(), try - ?line Files1 = filelib:wildcard(FNameWildcard), - ?line io:format("~p~n", [Files1]), - ?line Tc1 = dbg:trace_client(file, WrapFilesSpec, - {fun myhandler/2, {wait_for_go,Self}}), - ?line Tref1 = erlang:monitor(process, Tc1), - Tc1 ! {go,Self}, - ?line [{'DOWN',Tref1,_,_,normal}, - end_of_trace - |Result] = lists:reverse(flush()), - ?line M = N - (WrapCnt-1) div 2, - ?line M = wrap_port_result(Result, Self, N), - %% - %% Start a new wrap log with the same name to verify that - %% all files are cleared at wrap log start. Only produce - %% two trace messages to also place the gap at index 3, - %% so the trace log will be misinterpreted. - %% - ?line wrap_port_init(WrapFilesSpec), - ?line Files2 = filelib:wildcard(FNameWildcard), - ?line io:format("~p~n", [Files2]), - ?line -1 = ?MODULE:tracee1(-1), - ?line -1 = ?MODULE:tracee2(-1), - ?line stop(), - ?line Files = filelib:wildcard(FNameWildcard), - ?line io:format("~p~n", [Files]), - ?line Tc2 = dbg:trace_client(file, WrapFilesSpec, - {fun myhandler/2, {wait_for_go,Self}}), - ?line Tref2 = erlang:monitor(process, Tc2), - Tc2 ! {go,Self}, - ?line [{trace,Self,call,{?MODULE,tracee1,[-1]},Self}, - {trace,Self,call,{?MODULE,tracee2,[-1]},hej}, - end_of_trace, - {'DOWN',Tref2,_,_,normal}] = flush(), - %% - ?line lists:map(fun(F) -> file:delete(F) end, Files) + Files1 = filelib:wildcard(FNameWildcard), + io:format("~p~n", [Files1]), + Tc1 = dbg:trace_client(file, WrapFilesSpec, + {fun myhandler/2, {wait_for_go,Self}}), + Tref1 = erlang:monitor(process, Tc1), + Tc1 ! {go,Self}, + [{'DOWN',Tref1,_,_,normal}, + end_of_trace + |Result] = lists:reverse(flush()), + M = N - (WrapCnt-1) div 2, + M = wrap_port_result(Result, Self, N), + %% + %% Start a new wrap log with the same name to verify that + %% all files are cleared at wrap log start. Only produce + %% two trace messages to also place the gap at index 3, + %% so the trace log will be misinterpreted. + %% + wrap_port_init(WrapFilesSpec), + Files2 = filelib:wildcard(FNameWildcard), + io:format("~p~n", [Files2]), + -1 = ?MODULE:tracee1(-1), + -1 = ?MODULE:tracee2(-1), + stop(), + Files = filelib:wildcard(FNameWildcard), + io:format("~p~n", [Files]), + Tc2 = dbg:trace_client(file, WrapFilesSpec, + {fun myhandler/2, {wait_for_go,Self}}), + Tref2 = erlang:monitor(process, Tc2), + Tc2 ! {go,Self}, + [{trace,Self,call,{?MODULE,tracee1,[-1]},Self}, + {trace,Self,call,{?MODULE,tracee2,[-1]},hej}, + end_of_trace, + {'DOWN',Tref2,_,_,normal}] = flush(), + %% + lists:map(fun(F) -> file:delete(F) end, Files) after - ?line stop() + stop() end, ok. wrap_port_init(WrapFilesSpec) -> - ?line Port = dbg:trace_port(file, WrapFilesSpec), - ?line {ok, _} = dbg:tracer(port, Port), - ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call), - ?line {ok, X} = dbg:tp(?MODULE, tracee1,[{'_',[],[{message, {self}}]}]), - ?line {value, {saved, _Saved}} = lists:keysearch(saved, 1, X), - ?line {ok, Y} = dbg:tp(?MODULE, tracee2, [{'_',[],[{message, hej}]}]), - ?line {value, {saved, _}} = lists:keysearch(saved, 1, Y), + Port = dbg:trace_port(file, WrapFilesSpec), + {ok, _} = dbg:tracer(port, Port), + {ok, [{matched, _node, 1}]} = dbg:p(self(),call), + {ok, X} = dbg:tp(?MODULE, tracee1,[{'_',[],[{message, {self}}]}]), + {value, {saved, _Saved}} = lists:keysearch(saved, 1, X), + {ok, Y} = dbg:tp(?MODULE, tracee2, [{'_',[],[{message, hej}]}]), + {value, {saved, _}} = lists:keysearch(saved, 1, Y), ok. tracee1(X) -> @@ -626,106 +805,96 @@ tracee2(X) -> wrap_port_result([], _S, M) -> M; wrap_port_result([{trace, S, call, {?MODULE, tracee2, [M]}, hej}, - {trace, S, call, {?MODULE, tracee1, [M]}, S} | Tail], - S, - M) -> + {trace, S, call, {?MODULE, tracee1, [M]}, S} | Tail], + S, + M) -> wrap_port_result(Tail, S, M-1). -wrap_port_time(suite) -> - []; -wrap_port_time(doc) -> - ["Test tracing to time limited wrapping file port"]; +%% Test tracing to time limited wrapping file port wrap_port_time(Config) when is_list(Config) -> - ?line stop(), - ?line {A,B,C} = erlang:now(), - ?line FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++ "-" ++ - integer_to_list(B) ++ "-" ++ integer_to_list(C) ++ "-", - ?line FName = filename:join([?config(data_dir, Config), FTMP]), + stop(), + {A,B,C} = erlang:now(), + FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++ "-" ++ + integer_to_list(B) ++ "-" ++ integer_to_list(C) ++ "-", + FName = filename:join([proplists:get_value(data_dir, Config), FTMP]), %% WrapTime=2 and WrapCnt=4 will force the trace to wrap after %% every 2 seconds, and to contain between 3*2 and 4*2 seconds %% of trace entries. - ?line WrapFilesSpec = {FName, wrap, ".trace", {time, 2000}, 4}, - ?line Port = dbg:trace_port(file, WrapFilesSpec), - ?line {ok, _} = dbg:tracer(port, Port), + WrapFilesSpec = {FName, wrap, ".trace", {time, 2000}, 4}, + Port = dbg:trace_port(file, WrapFilesSpec), + {ok, _} = dbg:tracer(port, Port), try - ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call), - ?line {ok, X} = dbg:tp(?MODULE, tracee1,[{'_',[],[{message, {self}}]}]), - ?line {value, {saved, _Saved1}} = lists:keysearch(saved, 1, X), - ?line {ok, Y} = dbg:tp(?MODULE, tracee2, [{'_',[],[{message, hej}]}]), - ?line {value, {saved, _Saved2}} = lists:keysearch(saved, 1, Y), - %% The delays in the iterations places two trace messages in each - %% trace file, but the last which is empty waiting for its first - %% trace message. The number of iterations is chosen so that - %% one trace file has been wasted, and therefore the first pair - %% of trace messages. - ?line lists:foreach( - fun(Cnt) -> - receive after 1000 -> ok end, - ?MODULE:tracee1(Cnt), - ?MODULE:tracee2(Cnt), - receive after 1100 -> ok end - end, - lists:seq(1, 4)), - ?line stop(), - ?line Files = filelib:wildcard(FName ++ "*" ++ ".trace"), - ?line io:format("~p~n", [Files]), - ?line dbg:trace_client(file, WrapFilesSpec, {fun myhandler/2, self()}), - ?line S = self(), - ?line [{trace, S, call, {?MODULE, tracee1, [2]}, S}, - {trace, S, call, {?MODULE, tracee2, [2]}, hej}, - {trace, S, call, {?MODULE, tracee1, [3]}, S}, - {trace, S, call, {?MODULE, tracee2, [3]}, hej}, - {trace, S, call, {?MODULE, tracee1, [4]}, S}, - {trace, S, call, {?MODULE, tracee2, [4]}, hej}, - end_of_trace] = flush(), - ?line lists:map(fun(F) -> file:delete(F) end, Files) + {ok, [{matched, _node, 1}]} = dbg:p(self(),call), + {ok, X} = dbg:tp(?MODULE, tracee1,[{'_',[],[{message, {self}}]}]), + {value, {saved, _Saved1}} = lists:keysearch(saved, 1, X), + {ok, Y} = dbg:tp(?MODULE, tracee2, [{'_',[],[{message, hej}]}]), + {value, {saved, _Saved2}} = lists:keysearch(saved, 1, Y), + %% The delays in the iterations places two trace messages in each + %% trace file, but the last which is empty waiting for its first + %% trace message. The number of iterations is chosen so that + %% one trace file has been wasted, and therefore the first pair + %% of trace messages. + lists:foreach( + fun(Cnt) -> + receive after 1000 -> ok end, + ?MODULE:tracee1(Cnt), + ?MODULE:tracee2(Cnt), + receive after 1100 -> ok end + end, + lists:seq(1, 4)), + stop(), + Files = filelib:wildcard(FName ++ "*" ++ ".trace"), + io:format("~p~n", [Files]), + dbg:trace_client(file, WrapFilesSpec, {fun myhandler/2, self()}), + S = self(), + [{trace, S, call, {?MODULE, tracee1, [2]}, S}, + {trace, S, call, {?MODULE, tracee2, [2]}, hej}, + {trace, S, call, {?MODULE, tracee1, [3]}, S}, + {trace, S, call, {?MODULE, tracee2, [3]}, hej}, + {trace, S, call, {?MODULE, tracee1, [4]}, S}, + {trace, S, call, {?MODULE, tracee2, [4]}, hej}, + end_of_trace] = flush(), + lists:map(fun(F) -> file:delete(F) end, Files) after - ?line stop() + stop() end, ok. -with_seq_trace(suite) -> - []; -with_seq_trace(doc) -> - ["Test ordinary tracing combined with seq_trace"]; +%% Test ordinary tracing combined with seq_trace with_seq_trace(Config) when is_list(Config) -> try - ?line {ok, Server} = start(), - ?line {ok, Tracer} = dbg:get_tracer(), - ?line {ok, X} = dbg:tp(dbg, get_tracer, [{[],[], - [{set_seq_token, send, true}]}]), - ?line {value, {saved, _}} = lists:keysearch(saved, 1, X), - ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call), - ?line seq_trace:set_system_tracer(Tracer), - ?line dbg:get_tracer(), - receive - after 1 -> - ok - end, - ?line S = self(), - ?line ThisNode = node(), - ?line [{trace,S,call,{dbg,get_tracer,[]}}, - {seq_trace,0,{send,_,S,Server,{S,{get_tracer,ThisNode}}}}, - {seq_trace,0,{send,_,Server,S,{dbg,{ok,Tracer}}}}] = - flush() + {ok, Server} = start(), + {ok, Tracer} = dbg:get_tracer(), + {ok, X} = dbg:tp(dbg, get_tracer, [{[],[], + [{set_seq_token, send, true}]}]), + {value, {saved, _}} = lists:keysearch(saved, 1, X), + {ok, [{matched, _node, 1}]} = dbg:p(self(),call), + seq_trace:set_system_tracer(Tracer), + dbg:get_tracer(), + receive + after 1 -> + ok + end, + S = self(), + ThisNode = node(), + [{trace,S,call,{dbg,get_tracer,[]}}, + {seq_trace,0,{send,_,S,Server,{S,{get_tracer,ThisNode}}}}, + {seq_trace,0,{send,_,Server,S,{dbg,{ok,Tracer}}}}] = + flush() after - ?line stop() + stop() end, ok. -dead_suspend(suite) -> - []; -dead_suspend(doc) -> - ["Test that trace messages concerning a now dead process does " - "not crash dbg."]; +%% Test that trace messages concerning a now dead process does not crash dbg. dead_suspend(Config) when is_list(Config) -> - ?line start(), + start(), try - survived = run_dead_suspend() + survived = run_dead_suspend() after - ?line stop() + stop() end. run_dead_suspend() -> @@ -738,15 +907,119 @@ run_dead_suspend() -> spawn(?MODULE, dummy, []), receive after 1000 -> ok end, case whereis(dbg) of - undefined -> - died; - _ -> - survived + undefined -> + died; + _ -> + survived end. dummy() -> ok. +%% Test that a tracer process does not ignore an exit signal message when it has +%% received (but not handled) trace messages +tracer_exit_on_stop(_) -> + %% Tracer blocks waiting for fun to complete so that the trace message and + %% the exit signal message from the dbg process are in its message queue. + Fun = fun() -> + ?MODULE:dummy(), + Ref = erlang:trace_delivered(self()), + receive {trace_delivered, _, Ref} -> stop() end + end, + {ok, _} = dbg:tracer(process, {fun spawn_once_handler/2, {self(), Fun}}), + {ok, Tracer} = dbg:get_tracer(), + MRef = monitor(process, Tracer), + {ok, _} = dbg:p(self(), [call]), + {ok, _} = dbg:p(new, [call]), + {ok, _} = dbg:tp(?MODULE, dummy, []), + ?MODULE:dummy(), + receive {'DOWN', MRef, _, _, normal} -> ok end, + [{trace,_,call,{?MODULE, dummy,[]}}, + {trace,_,call,{?MODULE, dummy,[]}}] = flush(), + ok. + +spawn_once_handler(Event, {Pid, done} = State) -> + Pid ! Event, + State; +spawn_once_handler(Event, {Pid, Fun}) -> + {_, Ref} = spawn_monitor(Fun), + receive + {'DOWN', Ref, _, _, _} -> + Pid ! Event, + {Pid, done} + end. + +%% Test that erl_tracer modules work correctly +erl_tracer(Config) -> + stop(), + + ok = load_nif(Config), + + Self = self(), + {ok, _} = dbg:tracer(module, {?MODULE, Self}), + {ok, {?MODULE, Self}} = dbg:get_tracer(), + {ok, _} = dbg:p(self(), [c, timestamp]), + {ok, _} = dbg:tp(?MODULE, dummy, []), + ok = ?MODULE:dummy(), + [{Self, call, Self, Self, {?MODULE, dummy, []}, #{}}] = flush(), + ok. + +%% Test that distributed erl_tracer modules work +distributed_erl_tracer(Config) -> + stop(), + + S = self(), + + ok = load_nif(Config), + + LNode = node(), + RNode = start_slave(), + true = rpc:call(RNode, code, add_patha, [filename:join(proplists:get_value(data_dir, Config), "..")]), + ok = rpc:call(RNode, ?MODULE, load_nif, [Config]), + + NifProxy = fun() -> + register(nif_proxy, self()), + receive M -> S ! M end + end, + + LNifProxy = spawn_link(LNode, NifProxy), + RNifProxy = spawn_link(RNode, NifProxy), + + TracerFun = fun() -> {?MODULE, whereis(nif_proxy)} end, + + {ok, _} = dbg:tracer(LNode, module, TracerFun), + {ok, _} = dbg:tracer(RNode, module, TracerFun), + + {ok, [{matched, _, _}, {matched, _, _}]} = dbg:p(all,c), + {ok, [_, _]} = dbg:tp(?MODULE, dummy, []), + + {ok, {?MODULE, LNifProxy}} = dbg:get_tracer(LNode), + {ok, {?MODULE, RNifProxy}} = dbg:get_tracer(RNode), + + LCall = spawn_link(LNode, fun() -> ?MODULE:dummy() end), + [{LCall, call, LNifProxy, LCall, {?MODULE, dummy, []}, #{}}] = flush(), + + RCall = spawn_link(RNode, fun() -> ?MODULE:dummy() end), + [{RCall, call, RNifProxy, RCall, {?MODULE, dummy, []}, #{}}] = flush(), + + + ok. + +load_nif(Config) -> + SoFile = atom_to_list(?MODULE), + DataDir = proplists:get_value(data_dir, Config), + case erlang:load_nif(filename:join(DataDir, SoFile) , 0) of + {error, {reload, _}} -> + ok; + ok -> + ok + end. + +enabled(_, _, _) -> + erlang:nif_error(nif_not_loaded). + +trace(_, _, _, _, _) -> + erlang:nif_error(nif_not_loaded). %% %% Support functions @@ -766,38 +1039,38 @@ wait_node(_,0) -> no; wait_node(Node, N) -> case net_adm:ping(Node) of - pong -> - ok; - pang -> - receive - after 1000 -> - ok - end, - wait_node(Node, N - 1) + pong -> + ok; + pang -> + receive + after 1000 -> + ok + end, + wait_node(Node, N - 1) end. myhandler(Message, {wait_for_go,Pid}) -> receive - {go,Pid} -> - myhandler(Message, Pid) + {go,Pid} -> + myhandler(Message, Pid) end; myhandler(Message, Relay) -> Relay ! Message, case Message of - end_of_trace -> - ok; - _ -> - Relay + end_of_trace -> + ok; + _ -> + Relay end. flush() -> flush([]). flush(Acc) -> receive - X -> - flush(Acc ++ [X]) + X -> + flush(Acc ++ [X]) after 1000 -> - Acc + Acc end. start() -> @@ -811,88 +1084,92 @@ stop() -> schedstat_handler(TraceMsg, {Parent, Tag, Data} = State) -> case TraceMsg of - {trace_ts, Pid, in, _, Ts} -> - NewData = - case lists:keysearch(Pid, 1, Data) of - {value, {Pid, Acc}} -> - [{Pid, Acc, Ts} | lists:keydelete(Pid, 1, Data)]; - false -> - [{Pid, {0, 0, 0}, Ts} | Data]; - Other -> - exit(Parent, {?MODULE, ?LINE, Other}), - erlang:display({?MODULE, ?LINE, Other}), - Data - end, - {Parent, Tag, NewData}; - {trace_ts, Pid, out, _, {A3, B3, C3}} -> - NewData = - case lists:keysearch(Pid, 1, Data) of - {value, {Pid, {A1, B1, C1}, {A2, B2, C2}}} -> - [{Pid, {A3-A2+A1, B3-B2+B1, C3-C2+C1}} | - lists:keydelete(Pid, 1, Data)]; - Other -> - exit(Parent, {?MODULE, ?LINE, Other}), - erlang:display({?MODULE, ?LINE, Other}), - Data - end, - {Parent, Tag, NewData}; - {trace_ts, Pid, exit, normal, {A3, B3, C3}} -> - NewData = - case lists:keysearch(Pid, 1, Data) of - {value, {Pid, {A1, B1, C1}, {A2, B2, C2}}} -> - [{Pid, {A3-A2+A1, B3-B2+B1, C3-C2+C1}} | - lists:keydelete(Pid, 1, Data)]; - {value, {Pid, _Acc}} -> - Data; - false -> - [{Pid, {0, 0, 0}} | Data]; - Other -> - exit(Parent, {?MODULE, ?LINE, Other}), - erlang:display({?MODULE, ?LINE, Other}), - Data - end, - {Parent, Tag, NewData}; - {trace_ts, _Pid, send, _Msg, _OtherPid, _Ts} -> - State; - end_of_trace -> - Parent ! {Tag, Data}, - State + {trace_ts, Pid, in, _, Ts} -> + NewData = + case lists:keysearch(Pid, 1, Data) of + {value, {Pid, Acc}} -> + [{Pid, Acc, Ts} | lists:keydelete(Pid, 1, Data)]; + false -> + [{Pid, {0, 0, 0}, Ts} | Data]; + Other -> + exit(Parent, {?MODULE, ?LINE, Other}), + erlang:display({?MODULE, ?LINE, Other}), + Data + end, + {Parent, Tag, NewData}; + {trace_ts, Pid, out, _, {A3, B3, C3}} -> + NewData = + case lists:keysearch(Pid, 1, Data) of + {value, {Pid, {A1, B1, C1}, {A2, B2, C2}}} -> + [{Pid, {A3-A2+A1, B3-B2+B1, C3-C2+C1}} | + lists:keydelete(Pid, 1, Data)]; + Other -> + exit(Parent, {?MODULE, ?LINE, Other}), + erlang:display({?MODULE, ?LINE, Other}), + Data + end, + {Parent, Tag, NewData}; + {trace_ts,_Pid,spawned,_OtherPid,_,_Ts} -> + State; + {trace_ts,_Pid,getting_linked,_OtherPid,_Ts} -> + State; + {trace_ts, Pid, exit, normal, {A3, B3, C3}} -> + NewData = + case lists:keysearch(Pid, 1, Data) of + {value, {Pid, {A1, B1, C1}, {A2, B2, C2}}} -> + [{Pid, {A3-A2+A1, B3-B2+B1, C3-C2+C1}} | + lists:keydelete(Pid, 1, Data)]; + {value, {Pid, _Acc}} -> + Data; + false -> + [{Pid, {0, 0, 0}} | Data]; + Other -> + exit(Parent, {?MODULE, ?LINE, Other}), + erlang:display({?MODULE, ?LINE, Other}), + Data + end, + {Parent, Tag, NewData}; + {trace_ts, _Pid, send, _Msg, _OtherPid, _Ts} -> + State; + end_of_trace -> + Parent ! {Tag, Data}, + State end. pass_token(Token, Next, Loops) -> receive - {Token, 1} = Msg -> - sendloop(Loops), - Next ! Msg; - {Token, _Cnt} = Msg-> - sendloop(Loops), - Next ! Msg, - pass_token(Token, Next, Loops) + {Token, 1} = Msg -> + sendloop(Loops), + Next ! Msg; + {Token, _Cnt} = Msg-> + sendloop(Loops), + Next ! Msg, + pass_token(Token, Next, Loops) end. pass_token(Token, Final, Cnt, Loops) -> receive - {Token, start, Next} -> - sendloop(Loops), - Msg = {Token, Cnt}, - Next ! Msg, - pass_token(Token, Final, Next, Cnt, Loops) + {Token, start, Next} -> + sendloop(Loops), + Msg = {Token, Cnt}, + Next ! Msg, + pass_token(Token, Final, Next, Cnt, Loops) end. pass_token(Token, Final, Next, Cnt, Loops) -> receive - {Token, 1} -> - sendloop(Loops), - Msg = {Token, done}, - Final ! Msg; - {Token, Cnt} -> - sendloop(Loops), - NextCnt = Cnt-1, - Msg = {Token, NextCnt}, - Next ! Msg, - pass_token(Token, Final, Next, NextCnt, Loops) + {Token, 1} -> + sendloop(Loops), + Msg = {Token, done}, + Final ! Msg; + {Token, Cnt} -> + sendloop(Loops), + NextCnt = Cnt-1, + Msg = {Token, NextCnt}, + Next ! Msg, + pass_token(Token, Final, Next, NextCnt, Loops) end. sendloop(Loops) -> diff --git a/lib/runtime_tools/test/dbg_SUITE_data/Makefile.src b/lib/runtime_tools/test/dbg_SUITE_data/Makefile.src new file mode 100644 index 0000000000..f3d63bd4d1 --- /dev/null +++ b/lib/runtime_tools/test/dbg_SUITE_data/Makefile.src @@ -0,0 +1,8 @@ + +NIF_LIBS = dbg_SUITE@dll@ + +all: $(NIF_LIBS) + +@SHLIB_RULES@ + +$(NIF_LIBS): dbg_SUITE.c diff --git a/lib/runtime_tools/test/dbg_SUITE_data/dbg_SUITE.c b/lib/runtime_tools/test/dbg_SUITE_data/dbg_SUITE.c new file mode 100644 index 0000000000..ec00c68049 --- /dev/null +++ b/lib/runtime_tools/test/dbg_SUITE_data/dbg_SUITE.c @@ -0,0 +1,113 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2009-2016. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * %CopyrightEnd% + */ + +#include "erl_nif.h" + +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include <limits.h> + +/* NIF interface declarations */ +static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info); +static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info); +static void unload(ErlNifEnv* env, void* priv_data); + +/* The NIFs: */ +static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); + +static ErlNifFunc nif_funcs[] = { + {"enabled", 3, enabled}, + {"trace", 5, trace} +}; + +ERL_NIF_INIT(dbg_SUITE, nif_funcs, load, NULL, upgrade, unload) + +static ERL_NIF_TERM atom_trace; +static ERL_NIF_TERM atom_ok; + +#define ASSERT(expr) assert(expr) + +static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) +{ + + atom_trace = enif_make_atom(env, "trace"); + atom_ok = enif_make_atom(env, "ok"); + + *priv_data = NULL; + + return 0; +} + +static void unload(ErlNifEnv* env, void* priv_data) +{ + +} + +static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, + ERL_NIF_TERM load_info) +{ + if (*old_priv_data != NULL) { + return -1; /* Don't know how to do that */ + } + if (*priv_data != NULL) { + return -1; /* Don't know how to do that */ + } + if (load(env, priv_data, load_info)) { + return -1; + } + return 0; +} + +static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + int state_arity; + const ERL_NIF_TERM *state_tuple; + ERL_NIF_TERM value; + ASSERT(argc == 3); + + + return atom_trace; +} + +static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + int state_arity; + ErlNifPid self, to; + ERL_NIF_TERM *tuple, msg; + ASSERT(argc == 5); + + tuple = enif_alloc(sizeof(ERL_NIF_TERM)*(argc+1)); + memcpy(tuple+1,argv,sizeof(ERL_NIF_TERM)*argc); + + if (enif_self(env, &self)) { + tuple[0] = enif_make_pid(env, &self); + } else { + tuple[0] = enif_make_atom(env, "undefined"); + } + + msg = enif_make_tuple_from_array(env, tuple, argc + 1); + enif_get_local_pid(env, argv[1], &to); + enif_send(env, &to, NULL, msg); + enif_free(tuple); + + return atom_ok; +} diff --git a/lib/runtime_tools/test/dbg_SUITE_data/dbg_test.erl b/lib/runtime_tools/test/dbg_SUITE_data/dbg_test.erl index 2edbf6f99a..68ece5936e 100644 --- a/lib/runtime_tools/test/dbg_SUITE_data/dbg_test.erl +++ b/lib/runtime_tools/test/dbg_SUITE_data/dbg_test.erl @@ -1,18 +1,19 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010. All Rights Reserved. +%% Copyright Ericsson AB 2010-2016. All Rights Reserved. %% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at %% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. %% %% %CopyrightEnd% %% diff --git a/lib/runtime_tools/test/dbg_SUITE_data/exref_td.erl b/lib/runtime_tools/test/dbg_SUITE_data/exref_td.erl index 85faf620aa..d91fb41440 100644 --- a/lib/runtime_tools/test/dbg_SUITE_data/exref_td.erl +++ b/lib/runtime_tools/test/dbg_SUITE_data/exref_td.erl @@ -1,18 +1,19 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010. All Rights Reserved. +%% Copyright Ericsson AB 2010-2016. All Rights Reserved. %% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at %% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. %% %% %CopyrightEnd% %% diff --git a/lib/runtime_tools/test/dyntrace_SUITE.erl b/lib/runtime_tools/test/dyntrace_SUITE.erl index 0e4f369ed0..7be2f49a8b 100644 --- a/lib/runtime_tools/test/dyntrace_SUITE.erl +++ b/lib/runtime_tools/test/dyntrace_SUITE.erl @@ -1,44 +1,33 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2012. All Rights Reserved. +%% Copyright Ericsson AB 2012-2016. All Rights Reserved. %% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at %% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. %% %% %CopyrightEnd% %% -module(dyntrace_SUITE). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2]). --export([init_per_testcase/2, end_per_testcase/2]). +-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1]). %% Test cases -export([smoke/1,process/1]). -%% Default timetrap timeout (set in init_per_testcase) --define(default_timeout, ?t:minutes(1)). - -init_per_testcase(_Case, Config) -> - Dog = test_server:timetrap(?default_timeout), - [{watchdog,Dog}|Config]. - -end_per_testcase(_Case, Config) -> - Dog = ?config(watchdog, Config), - ?t:timetrap_cancel(Dog), - ok. - -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap, {minutes, 1}}]. all() -> case erlang:system_info(dynamic_trace) of @@ -47,7 +36,9 @@ all() -> dtrace -> [{group,smoke}]; systemtap -> - {skip,"SystemTap tests currently not supported"} + {skip,"SystemTap tests currently not supported"}; + lttng -> + {skip,"LTTng tests currently not supported"} end. groups() -> @@ -70,14 +61,8 @@ init_per_suite(Config) -> end_per_suite(_Config) -> ok. -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - smoke(Config) -> - Emu = ?t:lookup_config(emu_name, Config), + Emu = test_server:lookup_config(emu_name, Config), BinEmu = list_to_binary(Emu), case erlang:system_info(dynamic_trace) of dtrace -> @@ -104,8 +89,7 @@ process(_Config) -> {probe,"process-hibernate"}, {action,[{printf,["hibernate %s %s\n",{arg,0},{arg,1}]}]}, {probe,"process-exit"}, - {action,[{printf,["exit %s %s\n",{arg,0},{arg,1}]}]} - ], + {action,[{printf,["exit %s %s\n",{arg,0},{arg,1}]}]}], F = fun() -> {Pid,Ref} = spawn_monitor(fun my_process/0), Pid ! hibernate, diff --git a/lib/runtime_tools/test/dyntrace_lttng_SUITE.erl b/lib/runtime_tools/test/dyntrace_lttng_SUITE.erl new file mode 100644 index 0000000000..a98ac6e99c --- /dev/null +++ b/lib/runtime_tools/test/dyntrace_lttng_SUITE.erl @@ -0,0 +1,383 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2012-2016. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +-module(dyntrace_lttng_SUITE). +-include_lib("common_test/include/ct.hrl"). + +-export([all/0, suite/0]). +-export([init_per_suite/1, end_per_suite/1]). +-export([init_per_testcase/2, end_per_testcase/2]). + +%% Test cases +-export([t_lttng_list/1, + t_procs/1, + t_ports/1, + t_running_process/1, + t_running_port/1, + t_call/1, + t_call_return_to/1, + t_call_silent/1, + t_send/1, + t_receive/1, + t_garbage_collection/1, + t_all/1]). + +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap, {seconds, 10}}]. + +all() -> + [t_lttng_list, + t_procs, + t_ports, + t_running_process, + t_running_port, + t_call, + t_call_return_to, + t_call_silent, + t_send, + t_receive, + t_garbage_collection, + t_all]. + + +init_per_suite(Config) -> + case erlang:system_info(dynamic_trace) of + lttng -> + ensure_lttng_stopped("--all"), + Config; + _ -> + {skip, "No LTTng configured on system."} + end. + +end_per_suite(_Config) -> + ensure_lttng_stopped("--all"), + ok. + +init_per_testcase(Case, Config) -> + %% ensure loaded + _ = dyntrace:module_info(), + Name = atom_to_list(Case), + ok = ensure_lttng_started(Name, Config), + [{session, Name}|Config]. + +end_per_testcase(Case, _Config) -> + Name = atom_to_list(Case), + ok = ensure_lttng_stopped(Name), + ok. + +%% tracepoints +%% +%% org_erlang_dyntrace:gc_major_end +%% org_erlang_dyntrace:gc_major_start +%% org_erlang_dyntrace:gc_minor_end +%% org_erlang_dyntrace:gc_minor_start +%% org_erlang_dyntrace:message_receive +%% org_erlang_dyntrace:message_send +%% -org_erlang_dyntrace:message_queued +%% org_erlang_dyntrace:function_exception +%% org_erlang_dyntrace:function_return +%% org_erlang_dyntrace:function_call +%% org_erlang_dyntrace:port_link +%% org_erlang_dyntrace:port_exit +%% org_erlang_dyntrace:port_open +%% org_erlang_dyntrace:port_scheduled +%% org_erlang_dyntrace:process_scheduled +%% org_erlang_dyntrace:process_register +%% org_erlang_dyntrace:process_exit +%% org_erlang_dyntrace:process_link +%% org_erlang_dyntrace:process_spawn +%% +%% Testcases +%% + +t_lttng_list(_Config) -> + {ok, _} = cmd("lttng list -u"), + ok. + +t_procs(Config) when is_list(Config) -> + ok = lttng_start_event("org_erlang_dyntrace:process_*", Config), + _ = erlang:trace(new, true, [{tracer, dyntrace, []},procs]), + + Pid = spawn_link(fun() -> waiter() end), + Pid ! {self(), ok}, + ok = receive {Pid,ok} -> ok end, + timer:sleep(1000), + + _ = erlang:trace(all, false, [procs]), + Res = lttng_stop_and_view(Config), + ok = check_tracepoint("org_erlang_dyntrace:process_spawn", Res), + ok = check_tracepoint("org_erlang_dyntrace:process_link", Res), + ok = check_tracepoint("org_erlang_dyntrace:process_exit", Res), + ok = check_tracepoint("org_erlang_dyntrace:process_register", Res), + ok. + +t_ports(Config) when is_list(Config) -> + ok = lttng_start_event("org_erlang_dyntrace:port_*", Config), + _ = erlang:trace(new, true, [{tracer, dyntrace, []},ports]), + + _ = os:cmd("ls"), + + _ = erlang:trace(all, false, [{tracer, dyntrace, []},ports]), + Res = lttng_stop_and_view(Config), + ok = check_tracepoint("org_erlang_dyntrace:port_open", Res), + ok = check_tracepoint("org_erlang_dyntrace:port_link", Res), + ok = check_tracepoint("org_erlang_dyntrace:port_exit", Res), + ok. + +t_running_process(Config) when is_list(Config) -> + ok = lttng_start_event("org_erlang_dyntrace:process_scheduled", Config), + _ = erlang:trace(new, true, [{tracer, dyntrace, []},running]), + + Pid = spawn_link(fun() -> waiter() end), + Pid ! {self(), ok}, + ok = receive {Pid,ok} -> ok end, + timer:sleep(1000), + + _ = erlang:trace(all, false, [running]), + Res = lttng_stop_and_view(Config), + ok = check_tracepoint("org_erlang_dyntrace:process_scheduled", Res), + ok. + +t_running_port(Config) when is_list(Config) -> + ok = lttng_start_event("org_erlang_dyntrace:port_scheduled", Config), + _ = erlang:trace(new, true, [{tracer, dyntrace, []},running_ports]), + + _ = os:cmd("ls"), + _ = os:cmd("ls"), + + _ = erlang:trace(all, false, [running_ports]), + Res = lttng_stop_and_view(Config), + ok = check_tracepoint("org_erlang_dyntrace:port_scheduled", Res), + ok. + + +t_call(Config) when is_list(Config) -> + ok = lttng_start_event("org_erlang_dyntrace:function_*", Config), + _ = erlang:trace(new, true, [{tracer, dyntrace, []}, call]), + _ = erlang:trace_pattern({?MODULE, '_', '_'}, [{'_',[],[{exception_trace}]}], [local]), + + DontLink = spawn(fun() -> foo_clause_exception(nope) end), + Pid = spawn_link(fun() -> waiter() end), + Pid ! {self(), ok}, + ok = receive {Pid,ok} -> ok end, + + timer:sleep(10), + undefined = erlang:process_info(DontLink), + + _ = erlang:trace_pattern({?MODULE, '_', '_'}, false, [local]), + _ = erlang:trace(all, false, [call]), + Res = lttng_stop_and_view(Config), + ok = check_tracepoint("org_erlang_dyntrace:function_call", Res), + ok = check_tracepoint("org_erlang_dyntrace:function_return", Res), + ok = check_tracepoint("org_erlang_dyntrace:function_exception", Res), + ok. + +t_send(Config) when is_list(Config) -> + ok = lttng_start_event("org_erlang_dyntrace:message_send", Config), + _ = erlang:trace(new, true, [{tracer, dyntrace, []},send]), + + Pid = spawn_link(fun() -> waiter() end), + Pid ! {self(), ok}, + ok = receive {Pid,ok} -> ok end, + _ = os:cmd("ls"), + timer:sleep(10), + + _ = erlang:trace(all, false, [send]), + Res = lttng_stop_and_view(Config), + ok = check_tracepoint("org_erlang_dyntrace:message_send", Res), + ok. + +t_call_return_to(Config) when is_list(Config) -> + ok = lttng_start_event("org_erlang_dyntrace:function_*", Config), + _ = erlang:trace(new, true, [{tracer, dyntrace, []}, call, return_to]), + _ = erlang:trace_pattern({lists, '_', '_'}, true, [local]), + _ = erlang:trace_pattern({?MODULE, '_', '_'}, true, [local]), + + Pid = spawn_link(fun() -> gcfier(10) end), + Pid ! {self(), ok}, + ok = receive {Pid,ok} -> ok end, + timer:sleep(10), + + _ = erlang:trace_pattern({?MODULE, '_', '_'}, false, [local]), + _ = erlang:trace_pattern({lists, '_', '_'}, false, [local]), + _ = erlang:trace(all, false, [call,return_to]), + Res = lttng_stop_and_view(Config), + ok = check_tracepoint("org_erlang_dyntrace:function_call", Res), + ok. + +t_call_silent(Config) when is_list(Config) -> + ok = lttng_start_event("org_erlang_dyntrace:function_*", Config), + _ = erlang:trace(new, true, [{tracer, dyntrace, []}, call, silent]), + _ = erlang:trace_pattern({?MODULE, '_', '_'}, [{'_',[],[{exception_trace}]}], [local]), + + DontLink = spawn(fun() -> foo_clause_exception(nope) end), + Pid = spawn_link(fun() -> waiter() end), + Pid ! {self(), ok}, + ok = receive {Pid,ok} -> ok end, + + timer:sleep(10), + undefined = erlang:process_info(DontLink), + + _ = erlang:trace_pattern({?MODULE, '_', '_'}, false, [local]), + _ = erlang:trace(all, false, [call]), + Res = lttng_stop_and_view(Config), + notfound = check_tracepoint("org_erlang_dyntrace:function_call", Res), + notfound = check_tracepoint("org_erlang_dyntrace:function_return", Res), + notfound = check_tracepoint("org_erlang_dyntrace:function_exception", Res), + ok. + + +t_receive(Config) when is_list(Config) -> + ok = lttng_start_event("org_erlang_dyntrace:message_receive", Config), + _ = erlang:trace(new, true, [{tracer, dyntrace, []},'receive']), + timer:sleep(20), + + Pid1 = spawn_link(fun() -> waiter() end), + Pid1 ! {self(), ok}, + ok = receive {Pid1,ok} -> ok end, + + Pid2 = spawn_link(fun() -> waiter() end), + Pid2 ! {self(), ok}, + ok = receive {Pid2,ok} -> ok end, + + timer:sleep(10), + _ = erlang:trace(all, false, ['receive']), + Res = lttng_stop_and_view(Config), + ok = check_tracepoint("org_erlang_dyntrace:message_receive", Res), + ok. + +t_garbage_collection(Config) when is_list(Config) -> + ok = lttng_start_event("org_erlang_dyntrace:gc_*", Config), + _ = erlang:trace(new, true, [{tracer, dyntrace, []},garbage_collection]), + + Pid = spawn_link(fun() -> gcfier() end), + Pid ! {self(), ok}, + ok = receive {Pid,ok} -> ok end, + timer:sleep(10), + _ = erlang:trace(all, false, [garbage_collection]), + Res = lttng_stop_and_view(Config), + ok = check_tracepoint("org_erlang_dyntrace:gc_major_start", Res), + ok = check_tracepoint("org_erlang_dyntrace:gc_major_end", Res), + ok = check_tracepoint("org_erlang_dyntrace:gc_minor_start", Res), + ok = check_tracepoint("org_erlang_dyntrace:gc_minor_end", Res), + ok. + +t_all(Config) when is_list(Config) -> + ok = lttng_start_event("org_erlang_dyntrace:*", Config), + _ = erlang:trace(new, true, [{tracer, dyntrace, []},all]), + + Pid1 = spawn_link(fun() -> waiter() end), + Pid1 ! {self(), ok}, + ok = receive {Pid1,ok} -> ok end, + + Pid2 = spawn_link(fun() -> gcfier() end), + Pid2 ! {self(), ok}, + ok = receive {Pid2,ok} -> ok end, + _ = os:cmd("ls"), + _ = os:cmd("ls"), + timer:sleep(10), + + _ = erlang:trace(all, false, [all]), + Res = lttng_stop_and_view(Config), + + ok = check_tracepoint("org_erlang_dyntrace:process_spawn", Res), + ok = check_tracepoint("org_erlang_dyntrace:process_link", Res), + ok = check_tracepoint("org_erlang_dyntrace:process_exit", Res), + ok = check_tracepoint("org_erlang_dyntrace:process_register", Res), + ok = check_tracepoint("org_erlang_dyntrace:port_open", Res), + ok = check_tracepoint("org_erlang_dyntrace:port_link", Res), + ok = check_tracepoint("org_erlang_dyntrace:port_exit", Res), + ok = check_tracepoint("org_erlang_dyntrace:process_scheduled", Res), + ok = check_tracepoint("org_erlang_dyntrace:port_scheduled", Res), + ok = check_tracepoint("org_erlang_dyntrace:message_send", Res), + ok = check_tracepoint("org_erlang_dyntrace:message_receive", Res), + ok = check_tracepoint("org_erlang_dyntrace:gc_major_start", Res), + ok = check_tracepoint("org_erlang_dyntrace:gc_major_end", Res), + ok = check_tracepoint("org_erlang_dyntrace:gc_minor_start", Res), + ok = check_tracepoint("org_erlang_dyntrace:gc_minor_end", Res), + ok. + + +%% aux + +gcfier() -> + gcfier(10000). +gcfier(N) -> + receive + {Pid, ok} -> + _ = lists:reverse(lists:seq(1,N)), + true = erlang:garbage_collect(), + Pid ! {self(), ok} + end. + + +waiter() -> + true = register(?MODULE, self()), + receive + {Pid, ok} -> + Child = spawn(fun() -> receive ok -> ok end end), + link(Child), + unlink(Child), + _ = lists:seq(1,1000), + Child ! ok, + true = unregister(?MODULE), + Pid ! {self(),ok} + end. + +foo_clause_exception({1,2}) -> badness. + +%% lttng +lttng_stop_and_view(Config) -> + Path = proplists:get_value(priv_dir, Config), + Name = proplists:get_value(session, Config), + {ok,_} = cmd("lttng stop " ++ Name), + {ok,Res} = cmd("lttng view " ++ Name ++ " --trace-path=" ++ Path), + Res. + +check_tracepoint(TP, Data) -> + case re:run(Data, TP, [global]) of + {match, _} -> ok; + _ -> notfound + end. + +lttng_start_event(Event, Config) -> + Name = proplists:get_value(session, Config), + {ok, _} = cmd("lttng enable-event -u " ++ Event ++ " --session=" ++ Name), + {ok, _} = cmd("lttng start " ++ Name), + ok. + +ensure_lttng_started(Name, Config) -> + Out = case proplists:get_value(priv_dir, Config) of + undefined -> []; + Path -> "--output="++Path++" " + end, + {ok,_} = cmd("lttng create " ++ Out ++ Name), + ok. + +ensure_lttng_stopped(Name) -> + {ok,_} = cmd("lttng stop"), + {ok,_} = cmd("lttng destroy " ++ Name), + ok. + +cmd(Cmd) -> + io:format("<< ~ts~n", [Cmd]), + Res = os:cmd(Cmd), + io:format(">> ~ts~n", [Res]), + {ok,Res}. diff --git a/lib/runtime_tools/test/erts_alloc_config_SUITE.erl b/lib/runtime_tools/test/erts_alloc_config_SUITE.erl index 8ea04e1767..6ae51d9a26 100644 --- a/lib/runtime_tools/test/erts_alloc_config_SUITE.erl +++ b/lib/runtime_tools/test/erts_alloc_config_SUITE.erl @@ -1,18 +1,19 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2011. All Rights Reserved. +%% Copyright Ericsson AB 2010-2016. All Rights Reserved. %% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at %% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. %% %% %CopyrightEnd% %% @@ -21,12 +22,10 @@ %-define(line_trace, 1). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). %-compile(export_all). --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2, - init_per_testcase/2, end_per_testcase/2]). +-export([all/0, suite/0, init_per_testcase/2, end_per_testcase/2]). %% Testcases -export([basic/1]). @@ -34,88 +33,63 @@ %% internal export -export([make_basic_config/1]). --define(DEFAULT_TIMEOUT, ?t:minutes(2)). - -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap, {minutes, 2}}]. all() -> [basic]. -groups() -> - []. - -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - - init_per_testcase(Case, Config) when is_list(Config) -> [{testcase, Case}, - {watchdog, ?t:timetrap(?DEFAULT_TIMEOUT)}, {erl_flags_env, save_env()} | Config]. end_per_testcase(_Case, Config) when is_list(Config) -> - ?t:timetrap_cancel(?config(watchdog, Config)), - restore_env(?config(erl_flags_env, Config)), + restore_env(proplists:get_value(erl_flags_env, Config)), ok. %%% %%% The test cases ------------------------------------------------------------ %%% -basic(doc) -> []; -basic(suite) -> []; basic(Config) when is_list(Config) -> - ?line ErtsAllocConfig = privfile("generated", Config), + ErtsAllocConfig = privfile("generated", Config), SbctMod = " +MBsbct 1024 +MHsbct 4096", %% Make sure we have enabled allocators - ZFlgs = case os:getenv("ERL_ZFLAGS") of - FlgString when is_list(FlgString) -> - FlgString; - _ -> - "" - end ++ " +Mea max +Mea config", + ZFlgs = os:getenv("ERL_ZFLAGS", "") ++ " +Mea max +Mea config", - ?line os:putenv("ERL_ZFLAGS", ZFlgs ++ SbctMod), + os:putenv("ERL_ZFLAGS", ZFlgs ++ SbctMod), - ?line {ok, Node1} = start_node(Config), - ?line ok = rpc:call(Node1, ?MODULE, make_basic_config, [ErtsAllocConfig]), - ?line stop_node(Node1), + {ok, Node1} = start_node(Config), + ok = rpc:call(Node1, ?MODULE, make_basic_config, [ErtsAllocConfig]), + stop_node(Node1), - ?line display_file(ErtsAllocConfig), + display_file(ErtsAllocConfig), - ?line ManualConfig = privfile("manual", Config), - ?line {ok, IOD} = file:open(ManualConfig, [write]), - ?line io:format(IOD, "~s", ["+MBsbct 2048"]), - ?line file:close(IOD), - ?line display_file(ManualConfig), + ManualConfig = privfile("manual", Config), + {ok, IOD} = file:open(ManualConfig, [write]), + io:format(IOD, "~s", ["+MBsbct 2048"]), + file:close(IOD), + display_file(ManualConfig), - ?line os:putenv("ERL_ZFLAGS", ZFlgs), + os:putenv("ERL_ZFLAGS", ZFlgs), - ?line {ok, Node2} = start_node(Config, - "-args_file " ++ ErtsAllocConfig - ++ " -args_file " ++ ManualConfig), + {ok, Node2} = start_node(Config, + "-args_file " ++ ErtsAllocConfig + ++ " -args_file " ++ ManualConfig), - ?line {_, _, _, Cfg} = rpc:call(Node2, erlang, system_info, [allocator]), + {_, _, _, Cfg} = rpc:call(Node2, erlang, system_info, [allocator]), - ?line stop_node(Node2), + stop_node(Node2), - ?line {value,{binary_alloc, BCfg}} = lists:keysearch(binary_alloc, 1, Cfg), - ?line {value,{sbct, 2097152}} = lists:keysearch(sbct, 1, BCfg), - ?line {value,{eheap_alloc, HCfg}} = lists:keysearch(eheap_alloc, 1, Cfg), - ?line {value,{sbct, 4194304}} = lists:keysearch(sbct, 1, HCfg), + {value,{binary_alloc, BCfg}} = lists:keysearch(binary_alloc, 1, Cfg), + {value,{sbct, 2097152}} = lists:keysearch(sbct, 1, BCfg), + {value,{eheap_alloc, HCfg}} = lists:keysearch(eheap_alloc, 1, Cfg), + {value,{sbct, 4194304}} = lists:keysearch(sbct, 1, HCfg), - ?line ok. + ok. make_basic_config(ErtsAllocConfig) -> %% Save some different scenarios @@ -123,35 +97,35 @@ make_basic_config(ErtsAllocConfig) -> SSBegun = make_ref(), SSDone = make_ref(), SSFun = fun (F) -> - receive - SSDone -> - ok = erts_alloc_config:save_scenario(), - Tester ! SSDone - after 500 -> - ok = erts_alloc_config:save_scenario(), - F(F) - end - end, + receive + SSDone -> + ok = erts_alloc_config:save_scenario(), + Tester ! SSDone + after 500 -> + ok = erts_alloc_config:save_scenario(), + F(F) + end + end, SS = spawn_link(fun () -> - ok = erts_alloc_config:save_scenario(), - Tester ! SSBegun, - SSFun(SSFun) - end), + ok = erts_alloc_config:save_scenario(), + Tester ! SSBegun, + SSFun(SSFun) + end), receive SSBegun -> ok end, Ref = make_ref(), Tab = ets:new(?MODULE, [bag, public]), Ps = lists:map( - fun (_) -> - spawn_link( - fun () -> - ets:insert(Tab, - {self(), - lists:seq(1, 1000)}), - receive after 1000 -> ok end, - Tester ! {Ref, self()} - end) - end, - lists:seq(1, 10000)), + fun (_) -> + spawn_link( + fun () -> + ets:insert(Tab, + {self(), + lists:seq(1, 1000)}), + receive after 1000 -> ok end, + Tester ! {Ref, self()} + end) + end, + lists:seq(1, 10000)), lists:foreach(fun (P) -> receive {Ref, P} -> ok end end, Ps), ets:delete(Tab), SS ! SSDone, @@ -166,35 +140,35 @@ make_basic_config(ErtsAllocConfig) -> %% display_file(FileName) -> - ?t:format("filename: ~s~n", [FileName]), + io:format("filename: ~s~n", [FileName]), {ok, Bin} = file:read_file(FileName), io:format("~s", [binary_to_list(Bin)]), - ?t:format("eof: ~s~n", [FileName]), + io:format("eof: ~s~n", [FileName]), ok. mk_name(Config) when is_list(Config) -> {A, B, C} = now(), list_to_atom(atom_to_list(?MODULE) - ++ "-" ++ atom_to_list(?config(testcase, Config)) - ++ "-" ++ integer_to_list(A) - ++ "-" ++ integer_to_list(B) - ++ "-" ++ integer_to_list(C)). + ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config)) + ++ "-" ++ integer_to_list(A) + ++ "-" ++ integer_to_list(B) + ++ "-" ++ integer_to_list(C)). start_node(Config) -> start_node(Config, ""). start_node(Config, Args) -> - ?line Pa = filename:dirname(code:which(?MODULE)), - ?line ?t:start_node(mk_name(Config), - slave, - [{args, "-pa " ++ Pa ++ " " ++ Args}]). + Pa = filename:dirname(code:which(?MODULE)), + test_server:start_node(mk_name(Config), + slave, + [{args, "-pa " ++ Pa ++ " " ++ Args}]). stop_node(Node) -> - ?line true = ?t:stop_node(Node). + true = test_server:stop_node(Node). privfile(Name, Config) -> - filename:join([?config(priv_dir, Config), - atom_to_list(?config(testcase, Config)) ++ "." ++ Name]). + filename:join([proplists:get_value(priv_dir, Config), + atom_to_list(proplists:get_value(testcase, Config)) ++ "." ++ Name]). save_env() -> {erl_flags, @@ -207,15 +181,15 @@ restore_env(EVar, false) when is_list(EVar) -> restore_env(EVar, ""); restore_env(EVar, "") when is_list(EVar) -> case os:getenv(EVar) of - false -> ok; - "" -> ok; - " " -> ok; - _ -> os:putenv(EVar, " ") + false -> ok; + "" -> ok; + " " -> ok; + _ -> os:putenv(EVar, " ") end; restore_env(EVar, Value) when is_list(EVar), is_list(Value) -> case os:getenv(EVar) of - Value -> ok; - _ -> os:putenv(EVar, Value) + Value -> ok; + _ -> os:putenv(EVar, Value) end. restore_env({erl_flags, AFlgs, Flgs, RFlgs, ZFlgs}) -> diff --git a/lib/runtime_tools/test/inviso_SUITE.erl b/lib/runtime_tools/test/inviso_SUITE.erl deleted file mode 100644 index c64c40b945..0000000000 --- a/lib/runtime_tools/test/inviso_SUITE.erl +++ /dev/null @@ -1,2838 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010-2012. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% -%% Description: -%% Test suite for inviso (basic parts, i.e not inviso tools). Note that -%% inviso basic parts have modules in both the runtime_tools and -%% inviso applications. -%% -%% Authors: -%% Ann-Marie L�f, [email protected] -%% Lennart �hman, [email protected] -%% ----------------------------------------------------------------------------- - --module(inviso_SUITE). --compile(export_all). - --include_lib("common_test/include/ct.hrl"). --include_lib("kernel/include/file.hrl"). - --define(l,?line). - -suite() -> [{ct_hooks,[ts_install_cth]}]. - -all() -> - [basic_dist_trace_1, basic_dist_trace_2, - basic_dist_trace_3, basic_dist_trace_ti_1, - basic_dist_trace_ti_2, basic_dist_trace_ti_3, - suspend_dist_trace_ti_1, suspend_dist_trace_ti_2, - meta_cleanfunc_dist_1, basic_handlerfun_dist_1, - delete_log_dist_1, autostart_dist_1, autostart_dist_2, - autostart_dist_3, running_alone_dist_1, - running_alone_dist_2, running_alone_dist_3, - running_alone_dist_4, running_alone_dist_5, - overload_dist_1, overload_dist_2, overload_dist_3, - overload_dist_4, overload_dist_5, subscribe_dist_1, - lfm_trace_dist_1, lfm_trace_ti_dist_2, - handle_logfile_sort_wrapset, fetch_log_dist_trace_1, - fetch_log_dist_trace_2, fetch_log_dist_trace_3, - fetch_log_dist_error_1, fetch_log_dist_error_2, - expand_regexp_dist_1, only_loaded_dist_1]. - -groups() -> - []. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - - - -init_per_suite(Config) -> - case test_server:is_native(lists) of - true -> - {skip,"Native libs -- tracing doesn't work"}; - false -> - %% We never know who messed up this node before this suite! :-) - erlang:trace_pattern({'_','_','_'},[],[local]), - erlang:trace_pattern({'_','_','_'},[],[global]), - erlang:trace(all,false,[all]), - - ok=application:start(runtime_tools), - Config - end. - -end_per_suite(_Config) -> - ?l ok=application:stop(runtime_tools). - - -%% For each distributed testcase, we need two other distributed nodes to run the -%% runtime components on. Since they are freshly started every time there is no -%% need to clean them up first. -init_per_testcase(_Case,Config) -> - ?l TH=test_server:timetrap(100000), - ?l {ok,Node1}=test_server:start_node(inviso1,peer,[]), - ?l {ok,Node2}=test_server:start_node(inviso2,peer,[]), - ?l SuiteDir=filename:dirname(code:which(?MODULE)), - - %% Otherwise peer nodes will not find this module! - ?l true=rpc:call(Node1,code,add_patha,[SuiteDir]), - ?l true=rpc:call(Node2,code,add_patha,[SuiteDir]), - - ?l start_side_effect_logger(node()), - ?l start_side_effect_logger(Node1), - ?l start_side_effect_logger(Node2), - - - %% SPECIAL FOR MY PRIVATE TEST ENVIROMENT -% ?l rpc:call(Node1,code,add_patha,["/clearcase/otp/tools/runtime_tools/ebin"]), -% ?l rpc:call(Node1,code,add_patha,["/clearcase/otp/tools/inviso/ebin"]), -% ?l rpc:call(Node2,code,add_patha,["/clearcase/otp/tools/runtime_tools/ebin"]), -% ?l rpc:call(Node2,code,add_patha,["/clearcase/otp/tools/inviso/ebin"]), - -% %% SPECIAL FOR MY PRIVATE TEST ENVIROMENT, windows. -% ?l rpc:call(Node1,code,add_patha,["Z:/DATA/PROJECTS/inviso_project/runtime_tools/ebin"]), -% ?l rpc:call(Node1,code,add_patha,["Z:/DATA/PROJECTS/inviso_project/inviso/ebin"]), -% ?l rpc:call(Node2,code,add_patha,["Z:/DATA/PROJECTS/inviso_project/runtime_tools/ebin"]), -% ?l rpc:call(Node2,code,add_patha,["Z:/DATA/PROJECTS/inviso_project/inviso/ebin"]), - - ?l ok=rpc:call(Node1,application,start,[runtime_tools]), - ?l ok=rpc:call(Node2,application,start,[runtime_tools]), - ?l timer:sleep(100), % Problem with autostarted runtime. - %% The following is a test that the inviso_rt processes which are autostarted - %% are now gone. - - ?l ok=poll(rpc,call,[Node1,erlang,whereis,[inviso_rt]],undefined,20), - ?l ok=poll(rpc,call,[Node2,erlang,whereis,[inviso_rt]],undefined,20), - -% ?l ok=poll(rpc,call,[Node1,supervisor,which_children,[runtime_tools_sup]],[],20), -% ?l ok=poll(rpc,call,[Node2,supervisor,which_children,[runtime_tools_sup]],[],20), - NewConfig1=insert_remotenode_config(inviso1,Node1,Config), - NewConfig2=insert_remotenode_config(inviso2,Node2,NewConfig1), - insert_timetraphandle_config(TH,NewConfig2). -%% ----------------------------------------------------------------------------- - -end_per_testcase(Case,Config) -> - ?l test_server:stop_node(get_remotenode_config(inviso1,Config)), - ?l test_server:stop_node(get_remotenode_config(inviso2,Config)), - - case whereis(inviso_c) of - undefined -> % Should not exist. - true; - Pid when is_pid(Pid) -> % But if it exists... - exit(Pid,kill), % Remove it! - io:format("Had to kill the control component in end_per_testcase,~p.~n",[Case]) - end, - case whereis(inviso_rt) of - undefined -> % Should not exist. - true; - Pid2 when is_pid(Pid2) -> % But if it exists... - exit(Pid2,kill), % Remove it! - io:format("Had to kill local runtime component in end_per_testcase,~p.~n",[Case]) - end, - ?l process_killer([inviso_test_proc, - inviso_tab_proc, - inviso_collector_proc, - global_inviso_test_proc]), - ?l test_server:timetrap_cancel(get_timetraphandle_config(Config)), - - NewConfig1=remove_remotenode_config(inviso1,Config), - NewConfig2=remove_remotenode_config(inviso2,NewConfig1), - remove_timetraphandle_config(NewConfig2). -%% ----------------------------------------------------------------------------- - -%% ============================================================================== -%% Testcases. -%% ============================================================================== - -%% TEST CASE: Basic, distributed, trace only. -basic_dist_trace_1(suite) -> []; -basic_dist_trace_1(doc) -> - ["Basic case, start of distributed tracing, using only trac."]; -basic_dist_trace_1(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList=lists:map(fun(N)->{N,{file,filename:join([PrivDir, - "tf1_"++ - atom_to_list(N) - ])}} end, - Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}), - activate_local_tracing(Nodes), - deactivate_local_tracing(Nodes), - stop_tracing(Nodes), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - - -%% TEST CASE: Basic, distributed, activate global tracing for functions in modules -%% pointed out using a regexp. No tracing will be done. -basic_dist_trace_2(suite) -> []; -basic_dist_trace_2(doc) -> - [""]; -basic_dist_trace_2(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList=lists:map(fun(N)->{N,{file,filename:join([PrivDir, - "tf1a_"++ - atom_to_list(N) - ])}} end, - Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}), - Funcs1=activate_global_tracing_regexp(Nodes), - deactivate_global_tracing_regexp(Nodes,Funcs1), - stop_tracing(Nodes), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Basic, distributed, activate global tracing for functions in modules -%% pointed out using a dir-regexp. No tracing will be done. -basic_dist_trace_3(suite) -> []; -basic_dist_trace_3(doc) -> - [""]; -basic_dist_trace_3(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList=lists:map(fun(N)->{N,{file,filename:join([PrivDir, - "tf1b_"++ - atom_to_list(N) - ])}} end, - Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}), - Funcs1=activate_global_tracing_regexp_dir(Nodes), - deactivate_global_tracing_regexp_dir(Nodes,Funcs1), - stop_tracing(Nodes), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Basic, distributed, trace and ti. -basic_dist_trace_ti_1(suite) -> []; -basic_dist_trace_ti_1(doc) -> - [""]; -basic_dist_trace_ti_1(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataFun= - fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf2_"++atom_to_list(N)])}}, - {ti,{file,filename:join([PrivDir,"tf2_"++atom_to_list(N)++".ti"])}}]} - end, - TracerDataList=lists:map(TracerDataFun,Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), - activate_local_tracing(Nodes), - activate_meta_tracing(Nodes), - ?l true=(is_pid(whereis(inviso_rt))), - ?l true=(is_pid(whereis(inviso_rt_meta))), - deactivate_meta_tracing(Nodes), - deactivate_local_tracing(Nodes), - stop_tracing(Nodes), - ?l true=(is_pid(whereis(inviso_rt))), % Shall still be running. - ?l ok=poll(erlang,whereis,[inviso_rt_meta],undefined,3), - stop(Nodes), - timer:sleep(200), % Give it time to terminate. - ?l ok=poll(erlang,whereis,[inviso_rt],undefined,3),% Shall be gone now. - ?l undefined=whereis(inviso_rt_meta), % Still gone. - ok. -%% ----------------------------------------------------------------------------- - -%% Test CASE: Testing that the tpm_tracer functionality works. That is appending -%% {tracer,Tracer} to a meta match spec. -basic_dist_trace_ti_2(suite) -> []; -basic_dist_trace_ti_2(doc) -> - [""]; -basic_dist_trace_ti_2(Config) when is_list(Config) -> - case erlang:system_info(version) of - "5.4"++_ -> % Perhaps not perfect, but work now :-) - {skip,"Old emulator"}; - _ -> - basic_dist_trace_ti_2_do(Config) - end. - -basic_dist_trace_ti_2_do(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataFun= - fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf3_"++atom_to_list(N)])}}, - {ti,{file,filename:join([PrivDir,"tf3_"++atom_to_list(N)++".ti"])}}]} - end, - TracerDataList=lists:map(TracerDataFun,Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), - activate_deactivate_meta_tracing_tracer(Nodes), - stop_tracing(Nodes), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Basic, distributed, trace and ti, where we try to use ctp_all to -%% check that all global and local patterns are removed but that meta patterns -%% remain. -%% This test also checks that if the meta tracer is terminated an error value -%% is generated when trying to do meta tracing at that node. -basic_dist_trace_ti_3(suite) -> []; -basic_dist_trace_ti_3(doc) -> - [""]; -basic_dist_trace_ti_3(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataFun= - fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf4_"++atom_to_list(N)])}}, - {ti,{file,filename:join([PrivDir,"tf4_"++atom_to_list(N)++".ti"])}}]} - end, - TracerDataList=lists:map(TracerDataFun,Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), - activate_local_tracing(Nodes), - activate_global_tracing(Nodes), - activate_meta_tracing(Nodes), - ?l true=(is_pid(whereis(inviso_rt))), - ?l true=(is_pid(whereis(inviso_rt_meta))), - ?l {ok,NodeResults1}=inviso:ctp_all(Nodes), % Removes local and global patterns. - ?l true=check_noderesults(Nodes,ok,NodeResults1), - ?l true=check_on_nodes(Nodes,erlang,trace_info,[{code,which,1},traced],{traced,false}), - ?l true=check_on_nodes(Nodes,erlang,trace_info,[{code,get_path,0},traced],{traced,false}), - %% But meta patters shall remain. - ?l true=check_on_nodes(Nodes, - erlang, - trace_info, - [{lists,module_info,0},meta_match_spec], - fun({meta_match_spec,L})when length(L)>0 ->true end), - ?l true=check_on_nodes(Nodes, - erlang, - trace_info, - [{lists,module_info,0},meta], - fun({meta,P})when is_pid(P) -> - P=rpc:call(node(P),erlang,whereis,[inviso_rt_meta]), - true - end), - %% Now kill the meta tracer somewhere and try to activate meta tracing. - ?l [ANode|_]=Nodes, - ?l AMetaPid=rpc:call(ANode,erlang,whereis,[inviso_rt_meta]), - ?l rpc:call(ANode,erlang,exit,[AMetaPid,kill]), - ?l {ok,NodeResults2}=inviso:tpm(Nodes,math,pi,0,[],void), - ?l {value,{ANode,{error,_}}}=lists:keysearch(ANode,1,NodeResults2), - - ?l stop_tracing(Nodes), - ?l stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% ----------------------------------------------------------------------------- -%% Test cases for SUSPEND -%% ----------------------------------------------------------------------------- - -%% TEST CASE: In this test case a trace with ti is started. Trace flags are set, -%% trace patterns are set and meta trace patterns. We then check that the trace -%% flags and the meta patterns are removed when tracing suspended. -%% The suspension is cancelled and we check that it is possible to reactivate -%% tracing by setting the process flags and meta patterns again. -suspend_dist_trace_ti_1(suite) -> []; -suspend_dist_trace_ti_1(doc) -> - [""]; -suspend_dist_trace_ti_1(Config) when is_list(Config) -> - ?l RemoteNodes=get_remotenodes_config(Config), - ?l Nodes=[node()|RemoteNodes], - ?l PrivDir=filename:join(?config(priv_dir,Config),""), - ?l TracerDataFun= - fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf_suspend1_"++atom_to_list(N)])}}, - {ti,{file,filename:join([PrivDir,"tf_suspend1_"++atom_to_list(N)++".ti"])}}]} - end, - ?l TracerDataList=lists:map(TracerDataFun,Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), - activate_local_tracing(Nodes), - activate_meta_tracing(Nodes), - ?l true=(is_pid(whereis(inviso_rt))), - ?l true=(is_pid(whereis(inviso_rt_meta))), - %% Set some trace flags on some newly started test procs. - activate_traceflags(Nodes), - - %% Now suspend the tracing on all nodes. That shall result in the removal - %% of trace flags and meta trace patterns, but not local trace patterns. - ?l {ok,NodeResults1}=inviso:suspend(Nodes,test), - ?l true=check_noderesults(Nodes,ok,NodeResults1), - %% Trace flags gone? - ?l TestProcs=lists:map(fun(N)->rpc:call(N,erlang,whereis,[inviso_test_proc]) end,Nodes), - ?l lists:foreach(fun(P)-> - {flags,[]}= - rpc:call(node(P),erlang,trace_info,[P,flags]) - end, - TestProcs), - %% Meta patterns shall be gone too, but local functions still there. - ?l lists:foreach(fun(N)-> - {meta,false}= - rpc:call(N, - erlang, - trace_info, - [{math,module_info,1},meta]), - {traced,local}= - rpc:call(N, - erlang, - trace_info, - [{code,which,1},traced]) - end, - Nodes), - - %% Try to activate trace flags, trace patterns and meta tracing while - %% suspended. Should not succeed of course! - ?l ThisNode=node(), - ?l {ok,[{ThisNode,{error,suspended}}]}= - inviso:tf([ThisNode],inviso_test_proc,[call]), - ?l {ok,[{ThisNode,{error,suspended}}]}= - inviso:tpl([ThisNode],math,module_info,1,[]), - ?l {ok,[{ThisNode,{error,suspended}}]}= - inviso:init_tpm([ThisNode], - math, - module_info, - 1, - {?MODULE,tpm_init_func2}, % Does not exist on purpose. - {?MODULE,tpm_call_func2}, % Does not exist on purpose. - {?MODULE,tpm_return_func2}, % Does not exist on purpose. - {?MODULE,tpm_remove_func2}), % Does not exist on purpose. - - %% Now we want to cancel suspension and see that we can reactivate tracing. - ?l {ok,NodeResults2}=inviso:cancel_suspension(Nodes), - ?l true=check_noderesults(Nodes,ok,NodeResults2), - - ?l {ok,NodeResults3}= - inviso:init_tpm(math, - module_info, - 1, - {?MODULE,tpm_init_func2}, % Does not exist on purpose. - {?MODULE,tpm_call_func2}, % Does not exist on purpose. - {?MODULE,tpm_return_func2}, % Does not exist on purpose. - {?MODULE,tpm_remove_func2}), % Does not exist on purpose. - ?l true=check_noderesults(Nodes,ok,NodeResults3), - ?l {ok,NodeResults5}= - inviso:tpm_ms(math,module_info,1,ms1,[{'_',[],[{return_trace}]}]), - ?l true=check_noderesults(Nodes,{ok,1},NodeResults5), - ?l true=check_on_nodes(Nodes, - erlang, - trace_info, - [{math,module_info,1},meta_match_spec], - {meta_match_spec,[{'_',[],[{return_trace}]}]}), - ?l {ok,NodeResults6}=inviso:tf(Nodes,inviso_test_proc,[call]), - ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults6), - - %deactivate_meta_tracing(Nodes), - %deactivate_local_tracing(Nodes), - stop_tracing(Nodes), - ?l true=(is_pid(whereis(inviso_rt))), % Shall still be running. - ?l ok=poll(erlang,whereis,[inviso_rt_meta],undefined,3), - stop(Nodes), - ?l timer:sleep(200), % Give it time to terminate. - ?l ok=poll(erlang,whereis,[inviso_rt],undefined,3),% Shall be gone now. - ?l undefined=whereis(inviso_rt_meta), % Still gone. - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: In this test case a trace with ti is started. Trace flags are set, -%% trace patterns are set and meta trace patterns. We then suspend tracing at -%% all nodes, then stop tracing which shall be allowed. We then try to initiate -%% tracing again which shall not be possible. -suspend_dist_trace_ti_2(suite) -> []; -suspend_dist_trace_ti_2(doc) -> - [""]; -suspend_dist_trace_ti_2(Config) when is_list(Config) -> - ?l RemoteNodes=get_remotenodes_config(Config), - ?l Nodes=[node()|RemoteNodes], - ?l PrivDir=filename:join(?config(priv_dir,Config),""), - ?l TracerDataFun= - fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf_suspend2_"++atom_to_list(N)])}}, - {ti,{file,filename:join([PrivDir,"tf_suspend2_"++atom_to_list(N)++".ti"])}}]} - end, - ?l TracerDataList=lists:map(TracerDataFun,Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), - activate_local_tracing(Nodes), - activate_meta_tracing(Nodes), - ?l true=(is_pid(whereis(inviso_rt))), - ?l true=(is_pid(whereis(inviso_rt_meta))), - %% Set some trace flags on some newly started test procs. - activate_traceflags(Nodes), - - %% Now suspend the tracing on all nodes. That shall result in the removal - %% of trace flags and meta trace patterns, but not local trace patterns. - ?l {ok,NodeResults1}=inviso:suspend(Nodes,test), - ?l true=check_noderesults(Nodes,ok,NodeResults1), - - %% Now stop tracing. - ?l {ok,NodeResults3}=inviso:stop_tracing(Nodes), - ?l true=check_noderesults(Nodes,{ok,idle},NodeResults3), - %% Now try to initiate tracing again. - ThisNode=node(), - ?l {ok,[{ThisNode,{error,suspended}}]}= - inviso:init_tracing([ThisNode], - [{trace,{file,filename:join([PrivDir,"tf_suspend3_"++ - atom_to_list(ThisNode)])}}, - {ti,{file,{filename:join([PrivDir,"tf_suspend3_"++ - atom_to_list(ThisNode)])}}}]), - - %% Cancel the suspension and initiate tracing again. - ?l {ok,NodeResults2}=inviso:cancel_suspension(Nodes), - ?l true=check_noderesults(Nodes,ok,NodeResults2), - ?l TracerDataFun2= - fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf_suspend4_"++atom_to_list(N)])}}, - {ti,{file,filename:join([PrivDir,"tf_suspend4_"++atom_to_list(N)++".ti"])}}]} - end, - ?l TracerDataList2=lists:map(TracerDataFun2,Nodes), - ?l {ok,NodeResults4}=inviso:init_tracing(TracerDataList2), - ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok},{ti_log,ok}]},NodeResults4), - stop_tracing(Nodes), - ?l true=(is_pid(whereis(inviso_rt))), % Shall still be running. - stop(Nodes), - ?l timer:sleep(200), % Give it time to terminate. - ?l ok=poll(erlang,whereis,[inviso_rt],undefined,3),% Shall be gone now. - ok. -%% ----------------------------------------------------------------------------- - - - -%% TEST CASE: This test case tests that the clean function removes (prosumed) -%% expired data from the internal public-loopdata structure in the inviso_rt_meta -%% process. -meta_cleanfunc_dist_1(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataFun= - fun(N)->{N,[{trace,{file,filename:join([PrivDir,"mcf1_"++atom_to_list(N)])}}, - {ti,{file,filename:join([PrivDir,"mcf1_"++atom_to_list(N)++".ti"])}}]} - end, - TracerDataList=lists:map(TracerDataFun,Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), - %% Now initialize meta tracing, but the call_func is a bit "fixed". - ?l {ok,NodeResults1}= - inviso:tpm(Nodes,math,module_info,1,[], - {?MODULE,meta_cleanfunc_initfunc_1}, - {?MODULE,meta_cleanfunc_callfunc_1}, - void,void), - ?l true=check_noderesults(Nodes,{ok,1},NodeResults1), - %% Nothing in the "our" part of the public loop data. - ?l true=check_on_nodes(Nodes, - inviso_rt_meta,get_state,[inviso_rt_meta], - fun({ok,_LD,{{_,[]},_}})->true end), - ?l lists:foreach(fun(N)->rpc:call(N,math,module_info,[exports]) end,Nodes), - %% Check that it has been added to the public loopdata structure. - ?l true=check_on_nodes(Nodes, - ?MODULE,poll,[inviso_rt_meta, - get_state, - [inviso_rt_meta], - fun({ok,_LD,{{_,[{meta_cleanfunc_test1,_Now}]},_}})-> - true; - (_)->false - end, - 20], - ok), - %% While we wait for 60 seconds to pass, we test a few other things. - ?l {ok,NodeResults2}= - inviso:tpm(Nodes,?MODULE,slowfunction2,0,[{'_',[],[{return_trace}]}], - {?MODULE,meta_cleanfunc_initfunc_2}, - {?MODULE,meta_cleanfunc_callfunc_2}, - {?MODULE,meta_cleanfunc_returnfunc_2}, - void), - ?l true=check_noderesults(Nodes,{ok,1},NodeResults2), - ?l lists:foreach(fun(N)->rpc:call(N,?MODULE,slowfunction,[]) end,Nodes), - %% Believe it or not but slowfunction is still running, in its own process, - %% we are therefore free now to examine the meta tracer. - ?l true=check_on_nodes(Nodes, - ?MODULE,poll,[inviso_rt_meta, - get_state, - [inviso_rt_meta], - fun({ok,_LD,{{[],Tuples},_}})-> - {value,_}= - lists:keysearch(meta_cleanfunc_test2, - 1, - Tuples), - {value,_}= - lists:keysearch(meta_cleanfunc_test1, - 1, - Tuples), - true; - (_)-> - false - end, - 20], - ok), - %% Now we wait for slowfunction to return and that the meta_cleanfunc_test2 - %% to be removed from public loopdata strucuture. - ?l timer:sleep(10000), - %% The only thing remaining should be the meta_cleanfunc_test1 which will not - %% go away for less than that the clean functionality removes it. - ?l true=check_on_nodes(Nodes, - ?MODULE,poll,[inviso_rt_meta, - get_state, - [inviso_rt_meta], - fun({ok,_LD,{{_,[{meta_cleanfunc_test1,_Now}]},_}})-> - true; - (_)-> - false - end, - 20], - ok), - %% Wait for the clean function to clean meta_cleanfunc_test1 away. - ?l timer:sleep(51000), % Shall be gone after 5 seconds. - ?l true=check_on_nodes(Nodes, - ?MODULE,poll,[inviso_rt_meta, - get_state, - [inviso_rt_meta], - fun({ok,_LD,{{_,[]},_}})->true; - (_)->false - end, - 20], - ok), - stop_tracing(Nodes), - stop(Nodes), - ok. - -%% This function acts as tpm initialization function when we are going to test -%% that the clean function works. Note that we here assume standard public loop -%% datastructure. -meta_cleanfunc_initfunc_1(_M,_F,_Arity,{E1,_E2}) -> - {ok,{E1,[]},void}. -%% Function that is supposed to be called when the meta traced function is -%% called. -meta_cleanfunc_callfunc_1(_Pid,_Args,{{E1,E2},Global}) -> - {ok,{{E1,[{meta_cleanfunc_test1,now()}|E2]},Global},void}. - -meta_cleanfunc_initfunc_2(_M,_F,_Arity,PublLD) -> - {ok,PublLD,void}. -meta_cleanfunc_callfunc_2(_Pid,_Args,{{E1,E2},Global}) -> - {ok,{{E1,[{meta_cleanfunc_test2,now()}|E2]},Global},void}. -meta_cleanfunc_returnfunc_2(_Pid,_,{{E1,E2},Global}) -> - {value,_}=lists:keysearch(meta_cleanfunc_test2,1,E2), - {ok,{{E1,lists:keydelete(meta_cleanfunc_test2,1,E2)},Global},void}. - -slowfunction() -> - spawn(?MODULE,slowfunction1,[]). -slowfunction1() -> - slowfunction2(). % Meta trace on this function call. -slowfunction2() -> - timer:sleep(2000), - true. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Testing that a runtime component can be started instructing it -%% to use a handler fun. Checks that the handler fun is called if a trace -%% message comes in. -basic_handlerfun_dist_1(suite) -> []; -basic_handlerfun_dist_1(doc) -> - [""]; -basic_handlerfun_dist_1(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - ?l lists:foreach(fun(N)->rpc:call(N,ets,insert,[inviso_sideeffect_tab,{bhf1,0}]) end, - Nodes), - TracerDataFun= - fun(N)->{N,{fun basic_handlerfun_dist_1_fun/2,inviso_sideeffect_tab}} end, - TracerDataList=lists:map(TracerDataFun,Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}), - activate_local_tracing(Nodes), - activate_traceflags(Nodes), - ?l lists:foreach(fun(N)->[{bhf1,0}]= - rpc:call(N,ets,lookup,[inviso_sideeffect_tab,bhf1]) - end, - Nodes), - ?l inviso_test_proc ! {apply,code,which,[lists]}, - ok=poll(ets,lookup,[inviso_sideeffect_tab,bhf1],[{bhf1,1}],20), - deactivate_traceflags(Nodes), - deactivate_local_tracing(Nodes), - stop_tracing(Nodes), - timer:sleep(100), - ?l [{bhf1,1}]=ets:lookup(inviso_sideeffect_tab,bhf1), - stop(Nodes), - ok. - -%% Function used as handler fun for testcase above. -basic_handlerfun_dist_1_fun(_Msg,TId) -> - ets:update_counter(TId,bhf1,1), - TId. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Here we test that delete_log removes the files at the involved -%% runtime nodes. In this case we test that we remove logs according to last -%% used tracer data. -delete_log_dist_1(suite) -> []; -delete_log_dist_1(doc) -> [""]; -delete_log_dist_1(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataFun= - fun(N)->{N,[{trace,{file,filename:join([PrivDir,"dl1_"++atom_to_list(N)])}}, - {ti,{file,filename:join([PrivDir,"dl1_"++atom_to_list(N)++".ti"])}}]} - end, - TracerDataList=lists:map(TracerDataFun,Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), - ?l Files=lists:map(fun({N,TD})-> - ?l {value,{_,{_,TraceFile}}}=lists:keysearch(trace,1,TD), - ?l {value,{_,{_,TiFile}}}=lists:keysearch(ti,1,TD), - ?l {N,{TraceFile,TiFile}} - end, - TracerDataList), - io:format("The Files is:~w~n",[Files]), - ?l {ok,NodeResults1}=inviso:delete_log(Nodes), % Should not work! - ?l true=check_noderesults(Nodes,{error,tracing},NodeResults1), - stop_tracing(Nodes), - %% Files still here. - ?l lists:foreach(fun({N,{F1,F2}})-> - ?l {ok,_}=rpc:call(N,file,read_file_info,[F1]), - ?l {ok,_}=rpc:call(N,file,read_file_info,[F2]) - end, - Files), - ?l {ok,NodeResults2}=inviso:delete_log(Nodes), - ?l true=check_noderesults(Nodes, - fun({_N,{ok,LogInfos}})-> - ?l {value,{_,[{ok,_FName1}]}}= - lists:keysearch(trace_log,1,LogInfos), - ?l {value,{_,[{ok,_FName2}]}}= - lists:keysearch(ti_log,1,LogInfos), - true - end, - NodeResults2), - %% The files shall be gone now. - ?l lists:foreach(fun({N,{F1,F2}})-> - ?l {error,enoent}=rpc:call(N,file,read_file_info,[F1]), - ?l {error,enoent}=rpc:call(N,file,read_file_info,[F2]) - end, - Files), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - - -%% TEST CASE: Test of the autostart behaviour of the runtime component. -%% Here we test that a runtime component is started according to the autostart.conf -%% file. Note that the repeat parameter is set to 2. -autostart_dist_1(suite) -> []; -autostart_dist_1(doc) -> - [""]; -autostart_dist_1(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - PrivDir=filename:join(?config(priv_dir,Config),""), - AutoConfFile=filename:join(PrivDir,"autostart1.conf"), - [RNode|_]=RemoteNodes, - ?l ok=rpc:call(RNode,application,stop,[runtime_tools]), - ?l ok=rpc:call(RNode,application,set_env,[runtime_tools, - inviso_autostart_conf, - AutoConfFile]), - ?l {ok,FD}=file:open(AutoConfFile,[write]), - ?l ok=io:format(FD,"~w.~n~w.~n",[{repeat,2},{tag,c_ref}]), - ?l file:close(FD), - ?l ok=rpc:call(RNode,application,start,[runtime_tools]), - timer:sleep(1000), - ?l P1=rpc:call(RNode,erlang,whereis,[inviso_rt]), - ?l true=is_pid(P1), - ?l rpc:call(RNode,erlang,exit,[P1,kill]), - ?l ok=rpc:call(RNode,application,stop,[runtime_tools]), - ?l ok=rpc:call(RNode,application,start,[runtime_tools]), - timer:sleep(1000), - ?l P2=rpc:call(RNode,erlang,whereis,[inviso_rt]), - ?l true=is_pid(P2), - ?l rpc:call(RNode,erlang,exit,[P2,kill]), - ?l ok=rpc:call(RNode,application,stop,[runtime_tools]), - ?l ok=rpc:call(RNode,application,start,[runtime_tools]), - timer:sleep(1000), - ?l undefined=rpc:call(RNode,erlang,whereis,[inviso_rt]), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Test of autostart. Here we focus on that an autostarted -%% runtime component actually follows the trace case command file and -%% initiates tracing. -autostart_dist_2(suite) -> []; -autostart_dist_2(doc) -> - [""]; -autostart_dist_2(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - PrivDir=filename:join(?config(priv_dir,Config),""), - AutoConfFile=filename:join(PrivDir,"autostart2.conf"), - [RNode|_]=RemoteNodes, - ?l ok=rpc:call(RNode,application,stop,[runtime_tools]), - ?l ok=rpc:call(RNode,application,set_env,[runtime_tools, - inviso_autostart_conf, - AutoConfFile]), - ?l CmdFileName=filename:join(PrivDir,"autostart_cmd_as1"), - ?l {ok,FD}=file:open(CmdFileName,[write]), - ?l ok=io:format(FD, - "inviso:tpl(Nodes,M,F,Arity,[]).~n" - "inviso:tf(Nodes,inviso_test_proc,[call]).~n", - []), - ?l file:close(FD), - ?l TraceFileName=filename:join([PrivDir,"as1_"++atom_to_list(RNode)]), - ?l TiFileName=filename:join([PrivDir,"as1_"++atom_to_list(RNode)++".ti"]), - ?l inviso_as_lib:setup_autostart(RNode, - 2, - [], - [{trace,{file,TraceFileName}}, - {ti,{file,TiFileName}}], - [[CmdFileName]], - [{'M',code},{'F',which},{'Arity',1}], - [{{inviso,tpl,5},{inviso_rt,tpl,{erlang,tl}}}, - {{inviso,tf,3},{inviso_rt,tf,{erlang,tl}}}]), - ?l TestP=spawn(RNode,?MODULE,test_proc_init,[]), - ?l ok=rpc:call(RNode,application,start,[runtime_tools]), - ?l timer:sleep(1000), - ?l {ok,_}=file:read_file_info(TraceFileName), - ?l {ok,_}=file:read_file_info(TiFileName), - ?l true=is_pid(P=rpc:call(RNode,erlang,whereis,[inviso_rt])), - ?l ok=poll(rpc,call,[RNode,erlang,trace_info,[{code,which,1},traced]],{traced,local},10), - ?l {flags,[call]}=rpc:call(RNode,erlang,trace_info,[TestP,flags]), - ?l rpc:call(RNode,erlang,exit,[P,kill]), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Here we test that an autostarted runtime component with a dependency -%% to a specific control component tries to connect to that control component -%% during its start-up. -autostart_dist_3(suite) -> []; -autostart_dist_3(doc) -> - [""]; -autostart_dist_3(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - PrivDir=filename:join(?config(priv_dir,Config),""), - AutoConfFile=filename:join(PrivDir,"autostart3.conf"), - [RNode|_]=RemoteNodes, - ?l ok=rpc:call(RNode,application,stop,[runtime_tools]), - ?l ok=rpc:call(RNode,application,set_env,[runtime_tools, - inviso_autostart_conf, - AutoConfFile]), - ?l {ok,FD}=file:open(AutoConfFile,[write]), - ?l ok=io:format(FD,"~w.~n~w.~n~w.~n", - [{options,[{dependency,{infinity,node()}}]},{repeat,2},{tag,c_ref}]), - ?l file:close(FD), - %% Now start inviso at this node here for the runtime to connect. - ?l {ok,_Pid}=inviso:start(), - ?l ok=poll(erlang,whereis,[inviso_c],fun(P) when is_pid(P)->true;(_)->false end,10), - %% Make the runtime component start. - ?l ok=rpc:call(RNode,application,start,[runtime_tools]), - ?l ok=poll(rpc,call,[RNode,erlang,whereis,[inviso_rt]], - fun(P) when is_pid(P)->true;(_)->false end,10), - %% Check that the runtime component started. - ?l ok=poll(inviso,get_status,[[RNode]],{ok,[{RNode,{ok,{new,running}}}]},20), -% ?l {ok,[{RNode,{ok,{new,running}}}]}=inviso:get_status([RNode]), - stop([RNode]), - ok. -%% ----------------------------------------------------------------------------- - - - -%% TEST CASE: Test of the dependency mechanism in the runtime component. -%% Default behaviour is dependency=infinity, i.e the runtime components remains. -%% We also test here that we can reconnect to the runtime. -running_alone_dist_1(suite) -> []; -running_alone_dist_1(doc) -> - [""]; -running_alone_dist_1(Config) when is_list(Config) -> - ?l {ok,_Pid1}=inviso:start(), % Start a control component. - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,[]), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - ?l shutdown=inviso:stop(), % Stop the control component! - ?l undefined=whereis(inviso_c), - timer:sleep(3000), % How long shall we wait? :-) - ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end, - Nodes), - ?l {ok,_Pid2}=inviso:start(), - ?l {ok,NodeResults2}=inviso:add_nodes(Nodes,b_ref,[]), - ?l true=check_noderesults(Nodes,{ok,{adopted,new,running,a_ref}},NodeResults2), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Test of the dependency mechanism in the runtime component. -%% Test that the runtime components terminates after the specified 5000 ms. -running_alone_dist_2(suite) -> []; -running_alone_dist_2(doc) -> - [""]; -running_alone_dist_2(Config) when is_list(Config) -> - ?l {ok,_Pid1}=inviso:start(), % Start a control component. - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,[{dependency,5000}]), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - ?l shutdown=inviso:stop(), % Stop the control component! - ?l undefined=whereis(inviso_c), - timer:sleep(2000), - ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end, - Nodes), - timer:sleep(4000), % Now they shall be dead! - ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt]) end, - Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Test of the dependency mechanism in the runtime component. -%% Test that the runtime components terminates after the specified 5000 ms. -running_alone_dist_3(suite) -> []; -running_alone_dist_3(doc) -> - [""]; -running_alone_dist_3(Config) when is_list(Config) -> - ?l {ok,_Pid1}=inviso:start(), % Start a control component. - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,[{dependency,1000}]), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - ?l {ok,NodeResults2}=inviso:change_options(Nodes,[{dependency,5000}]), - ?l true=check_noderesults(Nodes,ok,NodeResults2), - ?l shutdown=inviso:stop(), % Stop the control component! - ?l undefined=whereis(inviso_c), - timer:sleep(3000), - ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end, - Nodes), - timer:sleep(3000), % Now they shall be dead! - ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt]) end, - Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Test of the dependency mechanism in the runtime component. -%% Test that the runtime components terminates after the specified 5000 ms, -%% like we did in running_alone_dist_2. But now we also start tracing and checks -%% that all inviso processes actually disappears when the time-out is reached. -running_alone_dist_4(suite) -> []; -running_alone_dist_4(doc) -> - [""]; -running_alone_dist_4(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - %% Start some tracing! - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataFun= - fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf_ra4"++atom_to_list(N)])}}, - {ti,{file,filename:join([PrivDir,"tf_ra4_"++atom_to_list(N)++".ti"])}}]} - end, - TracerDataList=lists:map(TracerDataFun,Nodes), - start_and_init_tracing2(Nodes, - [{dependency,5000}], - TracerDataList, - {ok,[{trace_log,ok},{ti_log,ok}]}), - - ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end, - Nodes), - ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt_meta])) end, - Nodes), - %% Stop control component and wait for the runtimes to terminate after - %% running alone timer has expired. - ?l shutdown=inviso:stop(), % Stop the control component! - ?l undefined=whereis(inviso_c), - timer:sleep(2000), - ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end, - Nodes), - ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt_meta])) end, - Nodes), - timer:sleep(4000), % Now they shall be dead! - ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt]) end, - Nodes), - ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt_meta]) end, - Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Test of the dependency mechanism in the runtime component. -%% Test that the runtime components terminates imeediately when the control -%% component is stopped. Check that all processes are gone. -running_alone_dist_5(suite) -> []; -running_alone_dist_5(doc) -> - [""]; -running_alone_dist_5(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - %% Start some tracing! - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataFun= - fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf_ra5"++atom_to_list(N)])}}, - {ti,{file,filename:join([PrivDir,"tf_ra5_"++atom_to_list(N)++".ti"])}}]} - end, - TracerDataList=lists:map(TracerDataFun,Nodes), - start_and_init_tracing2(Nodes, - [{dependency,0}], - TracerDataList, - {ok,[{trace_log,ok},{ti_log,ok}]}), - - ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end, - Nodes), - ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt_meta])) end, - Nodes), - %% Stop control component and check that all runtime component processes have - %% terminate more or less immediately afterwards, since dependency==0. - ?l shutdown=inviso:stop(), % Stop the control component! - timer:sleep(100), - ?l undefined=whereis(inviso_c), - timer:sleep(500), - ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt]) end, - Nodes), - ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt_meta]) end, - Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Test of the overload protection mechanism. The mechanism checks -%% for overload using the callback approximately at the interval specified. -%% Check that it does not start protection until start of tracing. -overload_dist_1(suite) -> []; -overload_dist_1(doc) -> - [""]; -overload_dist_1(Config) when is_list(Config) -> - ?l {ok,_Pid1}=inviso:start(), % Start a control component. - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - ?l lists:foreach(fun(N)->true=rpc:call(N,ets,insert,[inviso_sideeffect_tab,{ovl1,0}]) end, - Nodes), % Initiate the counter. - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes, - a_ref, - [{overload,{{?MODULE,overload1},500}}]), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - timer:sleep(1000), % Give the loadcheck time to perform. - ?l [{_,0}]=ets:lookup(inviso_sideeffect_tab,ovl1), % Nothing should have happened. - - %% Overload check shall not start until we start tracing. - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList=lists:map(fun(N)->{N,[{trace, - {file,filename:join([PrivDir, - "tf_ovl1."++atom_to_list(N) - ])}}]} - end, - Nodes), - ?l {ok,NodeResults2}=inviso:init_tracing(TracerDataList), - ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok}]},NodeResults2), - timer:sleep(1500), % Give the loadcheck time to perform. - ?l [{_,N}]=ets:lookup(inviso_sideeffect_tab,ovl1), - ?l true=(N>=2), % After 1,5 seconds, at least 2 checks. - - %% Now change options and remove overload checking! - ?l {ok,NodeResults3}=inviso:change_options(Nodes,[overload]), - ?l true=check_noderesults(Nodes,ok,NodeResults3), - ?l [{_,N2}]=ets:lookup(inviso_sideeffect_tab,ovl1), - timer:sleep(1000), - ?l [{_,N2}]=ets:lookup(inviso_sideeffect_tab,ovl1), % No more loadchecks! - - stop_tracing(Nodes), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Test of the overload protection mechanism. In this case we focus -%% in that the init and remove functions are carried out at change_options and -%% when starting and stoping the runtime component. -overload_dist_2(suite) -> []; -overload_dist_2(doc) -> - [""]; -overload_dist_2(Config) when is_list(Config) -> - ?l {ok,_Pid1}=inviso:start(), % Start a control component. - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes, - a_ref, - [{overload,{{?MODULE,overload2}, - 500, - {?MODULE,overload2i,[]}, - {?MODULE,overload2r,[]}}}]), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - ?l [{_,0}]=ets:lookup(inviso_sideeffect_tab,ovl2), - - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList=lists:map(fun(N)->{N,[{trace, - {file,filename:join([PrivDir, - "tf_ovl2."++atom_to_list(N) - ])}}]} - end, - Nodes), - ?l {ok,NodeResults2}=inviso:init_tracing(TracerDataList), - ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok}]},NodeResults2), - timer:sleep(1500), % Give the loadcheck time to perform. - ?l [{_,N}]=ets:lookup(inviso_sideeffect_tab,ovl2), - io:format("� is:~p~n",[N]), - ?l true=(N>=2), % After 1,5 seconds, at least 2 checks. - ?l {ok,NodeResults3}=inviso:change_options(Nodes,[{overload,{{?MODULE,overload3}, - 500, - {?MODULE,overload3i,[]}, - {?MODULE,overload3r,[]}}}]), - ?l true=check_noderesults(Nodes,ok,NodeResults3), - ?l []=ets:lookup(inviso_sideeffect_tab,ovl2), - timer:sleep(1500), - ?l [{_,N2}]=ets:lookup(inviso_sideeffect_tab,ovl3), - ?l true=(N2>=2), % After 1,5 seconds, at least 2 checks. - stop_tracing(Nodes), - ?l []=ets:lookup(inviso_sideeffect_tab,ovl3r), % Remove function shall not be called. - ?l [{_,N3}]=ets:lookup(inviso_sideeffect_tab,ovl3), - timer:sleep(1000), % Check that overloadchecking has stopped. - ?l [{_,N3}]=ets:lookup(inviso_sideeffect_tab,ovl3), - stop(Nodes), - ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,ovl3r],[{ovl3r,done}],20), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Test of the overload protections mechanism. Here we focus on testing -%% that if overload is reached tracing is really suspended. -overload_dist_3(suite) -> []; -overload_dist_3(doc) -> - [""]; -overload_dist_3(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList= - lists:map(fun(N)->{N,[{trace,{file,filename:join([PrivDir, - "tf_ovl3."++atom_to_list(N)])}}, - {ti,{file,filename:join([PrivDir, - "tf_ovl3_ti."++atom_to_list(N)])}}]} - end, - Nodes), - ?l lists:foreach(fun(N)-> - true=rpc:call(N,ets,insert,[inviso_sideeffect_tab,{ovl4,0}]) - end, - Nodes), - start_and_init_tracing2(Nodes, - [{overload,{{?MODULE,overload4},500}}], - TracerDataList, - {ok,[{trace_log,ok},{ti_log,ok}]}), - activate_local_tracing(Nodes), - activate_meta_tracing(Nodes), - activate_traceflags(Nodes), - timer:sleep(600), - ?l [{_,N1}]=ets:lookup(inviso_sideeffect_tab,ovl4), - ?l true=(N1>=1), % Overload check has been done! - ?l Node=node(), - ?l {ok,[{Node,{ok,{tracing,running}}}]}=inviso:get_status([node()]), - ?l true=ets:insert(inviso_sideeffect_tab,{ovl4_suspend,true}), - timer:sleep(600), - ?l {ok,[{Node,{ok,{tracing,{suspended,test}}}}]}=inviso:get_status([node()]), - ?l [{_,N2}]=ets:lookup(inviso_sideeffect_tab,ovl4), - ?l {flags,[]}=erlang:trace_info(whereis(inviso_test_proc),flags), - ?l {meta,false}=erlang:trace_info({lists,module_info,0},meta), - ?l {traced,local}=erlang:trace_info({code,which,1},traced), - ?l true=(is_pid(whereis(inviso_rt_meta))), - ?l true=ets:delete(inviso_sideeffect_tab,ovl4_suspend), - timer:sleep(600), - ?l [{_,N2}]=ets:lookup(inviso_sideeffect_tab,ovl4), % No checking while suspended! - ?l {ok,[{Node,ok}]}=inviso:cancel_suspension([node()]), - ?l {ok,NodeResults1}=inviso:get_status(Nodes), - ?l true=check_noderesults(Nodes,{ok,{tracing,running}},NodeResults1), - timer:sleep(600), - ?l [{_,N3}]=ets:lookup(inviso_sideeffect_tab,ovl4), - ?l true=(N3>N2), - ?l deactivate_local_tracing(Nodes), - ?l stop_tracing(Nodes), - ?l stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE. Test that the overload mechanism is triggered by to the runtime -%% component incomming messages, and nothing else. -overload_dist_4(suite) -> []; -overload_dist_4(doc) -> - [""]; -overload_dist_4(Config) when is_list(Config) -> - ?l {ok,_Pid1}=inviso:start(), % Start a control component. - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes, - a_ref, - [{overload,{{?MODULE,overload5}, - infinity, - {?MODULE,overload5i,[]}, - {?MODULE,overload5r,[]}}}]), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - ?l [{_,0}]=ets:lookup(inviso_sideeffect_tab,ovl5), - - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList=lists:map(fun(N)->{N,[{trace, - {file,filename:join([PrivDir, - "tf_ovl4."++atom_to_list(N) - ])}}]} - end, - Nodes), - ?l {ok,NodeResults2}=inviso:init_tracing(TracerDataList), - ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok}]},NodeResults2), - timer:sleep(2000), % Give the loadcheck time to perform. - ?l [{_,N}]=ets:lookup(inviso_sideeffect_tab,ovl5), - ?l true=(N==0), % And nothing shall have happend! - %% Now we send a message to the inviso_rt, then the load check function - %% shall be called. - ?l whereis(inviso_rt) ! test_of_loadcheck, - timer:sleep(200), % Make sure the inviso_rt gets scheduled. - ?l [{_,1}]=ets:lookup(inviso_sideeffect_tab,ovl5), - stop_tracing(Nodes), - ?l []=ets:lookup(inviso_sideeffect_tab,ovl5r), % Remove function shall not be called. - ?l [{_,N3}]=ets:lookup(inviso_sideeffect_tab,ovl5), - ?l whereis(inviso_rt) ! test_of_loadcheck, - timer:sleep(1000), % Check that overloadchecking has stopped. - ?l [{_,N3}]=ets:lookup(inviso_sideeffect_tab,ovl5), - stop(Nodes), - ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,ovl5r],[{ovl5r,done}],20), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE. Test that the overload mechanism correctly calculates remaining time -%% to next load check if a message comes into the runtime component "interupting" -%% the waiting for loadcheck timeout. (Loadcheck timeout is implemented as an after -%% in the receive). -overload_dist_5(suite) -> []; -overload_dist_5(doc) -> - [""]; -overload_dist_5(Config) when is_list(Config) -> - ?l {ok,_Pid1}=inviso:start(), % Start a control component. - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - ?l lists:foreach(fun(N)->true=rpc:call(N,ets,insert,[inviso_sideeffect_tab,{ovl6,0}]) end, - Nodes), % Initiate the counter. - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes, - a_ref, - [{overload,{{?MODULE,overload6},1000}}]), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - %% Overload check shall not start until we start tracing. - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList=lists:map(fun(N)->{N,[{trace, - {file,filename:join([PrivDir, - "tf_ovl5."++atom_to_list(N) - ])}}]} - end, - Nodes), - ?l {ok,NodeResults2}=inviso:init_tracing(TracerDataList), - ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok}]},NodeResults2), - ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,ovl6],[{ovl6,2}],25), - %% Now we know that exactly 2 checks have been made. Try to Distract the runtime :-) - ?l inviso_rt:state(whereis(inviso_rt)), % Make it have to receive a message. - timer:sleep(500), - ?l [{_,2}]=ets:lookup(inviso_sideeffect_tab,ovl6), % Should still be 2. - timer:sleep(600), - ?l [{_,3}]=ets:lookup(inviso_sideeffect_tab,ovl6), % We expect yet one check. - timer:sleep(1100), - ?l [{_,4}]=ets:lookup(inviso_sideeffect_tab,ovl6), - - stop_tracing(Nodes), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - - -%% TEST CASE: Test of the subscription mechanism. -subscribe_dist_1(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - Pid=spawn(?MODULE,inviso_msg_collector,[]), - CtrlPid=whereis(inviso_c), - - ?l {ok,_Pid}=inviso:start(), % Start a control component. - ?l ok=inviso:subscribe(Pid), - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,[]), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - ?l {ok,NodeResults2}=inviso:get_status(Nodes), - ?l true=check_noderesults(Nodes,{ok,{new,running}},NodeResults2), - check_msg_collector(Nodes, - fun({inviso_event,CP,_,{connected,N,{_Tag,{idle,running}}}}) - when CP==CtrlPid -> - {true,N}; - (_) -> - false - end, - 13), - TracerDataList=lists:map(fun(N)->{N,{file, - filename:join([PrivDir, - "tf_sub1"++atom_to_list(N)])}} - end, - Nodes), - ?l {ok,NodeResults3}=inviso:init_tracing(TracerDataList), - ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok}]},NodeResults3), - check_msg_collector(Nodes, - fun({inviso_event,CP,_,{state_change,N,{tracing,running}}}) - when CP==CtrlPid -> - {true,N}; - (_) -> - false - end, - 13), - ?l {ok,NodeResults4}=inviso:suspend(Nodes,test), - ?l true=check_noderesults(Nodes,ok,NodeResults4), - check_msg_collector(Nodes, - fun({inviso_event,CP,_,{state_change,N,{tracing,{suspended,test}}}}) - when CP==CtrlPid -> - {true,N}; - (_) -> - false - end, - 13), - ?l [RNode|_]=RemoteNodes, - ?l RInvisoPid=rpc:call(RNode,erlang,whereis,[inviso_rt]), - ?l rpc:call(RNode,erlang,exit,[RInvisoPid,kill]), - check_msg_collector([RNode], - fun({inviso_event,CP,_,{disconnected,N,_Info}}) - when CP==CtrlPid -> - {true,N}; - (_) -> - false - end, - 11), - - ?l {ok,_NodeResults5}=inviso:stop_tracing(Nodes), - ?l {ok,_NodeResults6}=inviso:stop_nodes(Nodes), - ?l shutdown=inviso:stop(), - ok. -%% ----------------------------------------------------------------------------- - - -%% TEST CASE: fetch_log test of single straight trace_log file in distributed -%% environment. -fetch_log_dist_trace_1(suite) -> []; -fetch_log_dist_trace_1(doc) -> - ["fetch_log test of single straight trace_log file in distributed" - "environment."]; -fetch_log_dist_trace_1(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList=lists:map(fun(N)->{N,[{trace,{file,filename:join([PrivDir, - "testfile1."++ - atom_to_list(N) - ])}}]} end, - Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}), - - %% Put some output in the logs. - ?l inviso:tp(Nodes,math,module_info,0,[]), - ?l inviso:tf(Nodes,all,[call]), - ?l lists:foreach(fun(N)->rpc:call(N,math,module_info,[]) end,Nodes), - - stop_tracing(Nodes), - {H,M,S}=time(), - FetchToDir=filename:join([PrivDir, - "fetch_log_test1_"++integer_to_list(H)++"_"++ - integer_to_list(M)++"_"++integer_to_list(S)]), - ?l ok=file:make_dir(FetchToDir), - ?l {ok,NodeResults}=inviso:fetch_log(RemoteNodes,FetchToDir,"p1"), - io:format("~p~n",[NodeResults]), - ?l true=check_noderesults(RemoteNodes, - fun({N,{complete,[{trace_log,[{ok,File}]},{ti_log,[]}]}}) -> - ?l File="p1testfile1."++atom_to_list(N), - true; - (_)-> - false - end, - NodeResults), - ?l ON=filename:join(PrivDir,"testfile1."), - ?l FN=filename:join(FetchToDir,"p1testfile1."), - ?l lists:foreach(fun(N)-> - {ok,#file_info{size=Size}}= - file:read_file_info(ON++atom_to_list(N)), - {ok,#file_info{size=Size}}= - file:read_file_info(FN++atom_to_list(N)) - end, - RemoteNodes), - %% Now we wish to see that we get an incomplete if we try to fetch to a - %% directory that does not exist. - ?l FetchToErrorDir=filename:join([PrivDir,nonexistingingdir]), - ?l {ok,NodeResults2}=inviso:fetch_log(RemoteNodes,FetchToErrorDir,"p1"), - ?l io:format("NodeResults2:~w~n",[NodeResults2]), - ?l true=check_noderesults(RemoteNodes, - fun({_,{incomplete,_}}) -> - true; - (_)-> - false - end, - NodeResults2), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -fetch_log_dist_trace_2(suite) -> []; -fetch_log_dist_trace_2(doc) -> - [""]; -fetch_log_dist_trace_2(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - - {H,M,S}=time(), - ?l Name="wrap"++integer_to_list(H)++"_"++integer_to_list(M)++"_"++integer_to_list(S), - ?l BaseName=filename:join(PrivDir,Name), - Fun=fun(N)->{N,[{trace,{file,{BaseName++atom_to_list(N),wrap,".log",512,2}}}, - {ti,{file,BaseName++"_ti_"++atom_to_list(N)++".ti"}}]} - end, - ?l TracerDataList=lists:map(Fun,Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), - fill_and_reach_two_wrapfiles(PrivDir,"^"++Name,Nodes), - - stop_tracing(Nodes), - FetchToDir=filename:join([PrivDir, - "fetch_log_test2_"++integer_to_list(H)++"_"++ - integer_to_list(M)++"_"++integer_to_list(S)]), - ?l ok=file:make_dir(FetchToDir), - ?l {ok,NodeResults}=inviso:fetch_log(RemoteNodes,FetchToDir,"p1"), - io:format("~p~n",[NodeResults]), - CheckFun=fun({N,{complete,[{trace_log,FileResults1},{ti_log,[{ok,TiFile}]}]}}) -> - Fun2=fun({ok,File}) -> - match= - re:run(File, - "^"++"p1"++Name++atom_to_list(N), - [{capture,none}]), - true; - (_) -> - false - end, - ?l true=lists:all(Fun2,FileResults1), - ?l TiFile="p1"++Name++"_ti_"++atom_to_list(N)++".ti", - true; - (_)-> - false - end, - ?l true=check_noderesults(RemoteNodes,CheckFun,NodeResults), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -fetch_log_dist_trace_3(suite) -> []; -fetch_log_dist_trace_3(doc) -> - [""]; -fetch_log_dist_trace_3(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - - {H,M,S}=time(), - ?l Name="wrap2_"++integer_to_list(H)++"_"++integer_to_list(M)++"_"++integer_to_list(S), - ?l BaseName=filename:join(PrivDir,Name), - Fun=fun(N)->{N,[{trace,{file,{BaseName++atom_to_list(N),wrap,".log",512,2}}}, - {ti,{file,BaseName++"_ti_"++atom_to_list(N)++".ti"}}]} - end, - ?l TracerDataList=lists:map(Fun,Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), - fill_and_reach_two_wrapfiles(PrivDir,"^"++Name,Nodes), - - stop_tracing(Nodes), - FetchToDir=filename:join([PrivDir, - "fetch_log_test3_"++integer_to_list(H)++"_"++ - integer_to_list(M)++"_"++integer_to_list(S)]), - ?l ok=file:make_dir(FetchToDir), - ?l {ok,NodeResults1}=inviso:list_logs(Nodes), - CheckFun=fun({N,{ok,[{trace_log,PrivDir2,[F1,F2]},{ti_log,PrivDir2,[F3]}]}})-> - PrivDir2=PrivDir, - RegExp="^"++Name++atom_to_list(N)++"[0-9]+"++"\.log", - match=re:run(F1,RegExp,[{capture,none}]), - match=re:run(F2,RegExp,[{capture,none}]), - F3=Name++"_ti_"++atom_to_list(N)++".ti", - true; - (_) -> - false - end, - ?l true=check_noderesults(Nodes,CheckFun,NodeResults1), - ?l NodeFileSpecList=lists:map(fun({N,{ok,L}})->{N,L} end, - lists:keydelete(node(),1,NodeResults1)), - ?l {ok,NodeResults2}=inviso:fetch_log(NodeFileSpecList,FetchToDir,"p1"), -io:format("~p~n",[NodeResults2]), - CheckFun2=fun({N,{complete,[{trace_log,FileResults1},{ti_log,[{ok,TiFile}]}]}}) -> - Fun2=fun({ok,File}) -> - match= - re:run(File, - "^"++"p1"++Name++atom_to_list(N), - [{capture,none}]), - true; - (_) -> - false - end, - ?l true=lists:all(Fun2,FileResults1), - ?l TiFile="p1"++Name++"_ti_"++atom_to_list(N)++".ti", - true; - (_)-> - false - end, - ?l true=check_noderesults(RemoteNodes,CheckFun2,NodeResults2), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -fetch_log_dist_error_1(suite) -> []; -fetch_log_dist_error_1(doc) -> - [""]; -fetch_log_dist_error_1(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - ?l {ok,_Pid}=inviso:start(), % Start a control component. - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - ?l {ok,NodeResults2}=inviso:fetch_log(RemoteNodes,"foo","bar"), -io:format("~p~n",[NodeResults2]), - ?l true=check_noderesults(RemoteNodes, - fun({_N,{error,no_tracerdata}})->true; - (_)->false - end, - NodeResults2), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -fetch_log_dist_error_2(suite) -> []; -fetch_log_dist_error_2(doc) -> - [""]; -fetch_log_dist_error_2(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - ?l {ok,_Pid}=inviso:start(), % Start a control component. - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - ?l NodeLogList=lists:map(fun(N)->{N,[{trace_log, - PrivDir, - ["f1,fil","f2.fil"]}, - {ti_log, - PrivDir, - ["f.ti"]}]} - end, - RemoteNodes), - ?l {ok,NodeResults2}=inviso:fetch_log(NodeLogList,"foo","bar"), - io:format("~p~n",[NodeResults2]), - ?l true=check_noderesults(RemoteNodes, - fun({_N,{incomplete,_}}) -> - true; - (_) -> - false - end, - NodeResults2), - ?l NodeTracerData=lists:map(fun(N)->{N, - [{trace,{file,filename:join(PrivDir,"foo")}}, - {ti,{file,filename:join(PrivDir,"bar.ti")}}]} - end, - RemoteNodes), - {ok,NodeResults3}=inviso:fetch_log(NodeTracerData,"foo","bar"), - io:format("~p~n",[NodeResults3]), -%% This should work this way. Now it says complete [], which is not entirely -%% incorrect. But to follow the sematics of when fetching named files should -%% say incomplete. -%% Must do some rework to make that work. No real danger leaving it this way -%% for now. -% ?l true=check_noderesults(RemoteNodes, -% fun({_N,{incomplete,_}}) -> -% true; -% (_) -> -% false -% end, -% NodeResults3), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: This case tests that the log file merger merges files in the -%% correct order, based on the timestamps. -lfm_trace_dist_1(suite) -> []; -lfm_trace_dist_1(doc) -> - [""]; -lfm_trace_dist_1(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - [RNode1,RNode2|_]=RemoteNodes, - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList= - lists:map(fun(N)->{N,{file,filename:join([PrivDir,"lfm1_"++atom_to_list(N)])}} end, - Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}), - activate_local_tracing(Nodes), - activate_traceflags(Nodes), - - {inviso_test_proc,RNode2} ! {apply,code,which,[lists]}, - timer:sleep(300), - {inviso_test_proc,RNode1} ! {apply,code,which,[lists]}, - timer:sleep(300), - {inviso_test_proc,RNode1} ! {apply,code,which,[lists]}, - timer:sleep(300), - inviso_test_proc ! {apply,code,which,[lists]}, - timer:sleep(300), - {inviso_test_proc,RNode2} ! {apply,code,which,[lists]}, - timer:sleep(300), - inviso_test_proc ! {apply,code,which,[lists]}, - - deactivate_traceflags(Nodes), - deactivate_local_tracing(Nodes), - stop_tracing(Nodes), - stop(Nodes), - - DestFile=filename:join(PrivDir,"lfm1_out.txt"), - ?l {ok,6}= - inviso_lfm:merge([{node(), - [{trace_log, - [filename:join(PrivDir,"lfm1_"++atom_to_list(node()))]}]}, - {RNode1, - [{trace_log, - [filename:join(PrivDir,"lfm1_"++atom_to_list(RNode1))]}]}, - {RNode2, - [{trace_log, - [filename:join(PrivDir,"lfm1_"++atom_to_list(RNode2))]}]}], - DestFile), - ?l {ok,FD}=file:open(DestFile,[read]), - ?l S1=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(RNode2),S1), - ?l S2=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(RNode1),S2), - ?l S3=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(RNode1),S3), - ?l S4=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(node()),S4), - ?l S5=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(RNode2),S5), - ?l S6=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(node()),S6), - ?l file:close(FD), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Testing to the full extent that pid-mappings work with both -%% local and global registration. Also checks that pidmappings can be removed -%% and that consequently the mappings in the resulting merged file stops. -lfm_trace_ti_dist_2(suite) -> []; -lfm_trace_ti_dist_2(doc) -> - [""]; -lfm_trace_ti_dist_2(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - [RNode1,RNode2|_]=RemoteNodes, - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList= - lists:map(fun(N)->{N,[{trace,{file,filename:join(PrivDir,"lfm2_"++atom_to_list(N))}}, - {ti,{file,filename:join(PrivDir,"lfm2_ti_"++atom_to_list(N))}}]} - end, - Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), - activate_local_tracing(Nodes), - activate_meta_tracing(Nodes), - activate_traceflags(Nodes), - - {inviso_test_proc,RNode2} ! {apply,code,which,[lists]}, - timer:sleep(300), - {inviso_test_proc,RNode1} ! {apply,code,which,[lists]}, - timer:sleep(300), - {inviso_test_proc,RNode1} ! {apply,code,which,[lists]}, - timer:sleep(300), - inviso_test_proc ! {apply,code,which,[lists]}, - timer:sleep(300), - - P2=spawn(RNode2,?MODULE,test_proc_loop,[]), - P1=spawn(RNode1,?MODULE,test_proc_loop,[]), - P0=spawn_link(?MODULE,test_proc_loop,[]), - ThisNode=node(), - ?l {ok,[{ThisNode,{ok,[1]}}]}=inviso:tf([node()],P0,[call,timestamp]), - ?l {ok,[{RNode1,{ok,[1]}}]}=inviso:tf([RNode1],P1,[call,timestamp]), - ?l {ok,[{RNode2,{ok,[1]}}]}=inviso:tf([RNode2],P2,[call,timestamp]), - P2 ! {apply,code,which,[lists]}, - timer:sleep(300), - P1 ! {apply,code,which,[lists]}, - timer:sleep(300), - P0 ! {apply,code,which,[lists]}, - timer:sleep(300), - - P3=spawn(RNode2,?MODULE,test_proc_loop,[]), - ?l yes=global:register_name(inviso_test_proc_globalname,P3), - ?l {ok,[{RNode2,{ok,[1]}}]}=inviso:tf([RNode2],P3,[call,timestamp]), - timer:sleep(300), - P3 ! {apply,code,which,[lists]}, - timer:sleep(300), - - P4=rpc:call(RNode1,erlang,whereis,[inviso_test_proc]), - ?l true=rpc:call(RNode1,erlang,unregister,[inviso_test_proc]), - timer:sleep(300), - P4 ! {apply,code,which,[lists]}, - timer:sleep(300), - - ?l true=rpc:call(RNode1,erlang,register,[inviso_test_proc,P4]), - - ?l global:unregister_name(inviso_test_proc_globalname), - timer:sleep(300), - ?l P3 ! {apply,code,which,[lists]}, - timer:sleep(300), - - deactivate_traceflags(Nodes), - deactivate_local_tracing(Nodes), - stop_tracing(Nodes), - stop(Nodes), - - DestFile=filename:join(PrivDir,"lfm2_out.txt"), - ?l {ok,10}= - inviso_lfm:merge([ - {node(), - [{trace_log, - [filename:join(PrivDir,"lfm2_"++atom_to_list(node()))]}, - {ti_log, - [filename:join(PrivDir,"lfm2_ti_"++atom_to_list(node()))]}]}, - {RNode1, - [{trace_log, - [filename:join(PrivDir,"lfm2_"++atom_to_list(RNode1))]}, - {ti_log, - [filename:join(PrivDir,"lfm2_ti_"++atom_to_list(RNode1))]}]}, - {RNode2, - [{trace_log, - [filename:join(PrivDir,"lfm2_"++atom_to_list(RNode2))]}, - {ti_log, - [filename:join(PrivDir,"lfm2_ti_"++atom_to_list(RNode2))]}]} - ], - DestFile), - ?l {ok,FD}=file:open(DestFile,[read]), - ?l S1=io:get_line(FD,""), -io:format("S1 is:~p~n",[S1]), - ?l true=lists:prefix(atom_to_list(RNode2)++" [inviso_test_proc",S1), - ?l S2=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(RNode1)++" [inviso_test_proc",S2), - ?l S3=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(RNode1)++" [inviso_test_proc",S3), - ?l S4=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(node())++" [inviso_test_proc",S4), - ?l S5=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(RNode2)++" []",S5), - ?l S6=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(RNode1)++" []",S6), - ?l S7=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(node())++" []",S7), - ?l S8=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(RNode2)++" [{global,inviso_test_proc_globalname}]",S8), - ?l S9=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(RNode1)++" []",S9), - ?l S10=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(RNode2)++" []",S10), - ?l file:close(FD), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: This tests that the wrapset sorter works. -handle_logfile_sort_wrapset(suite) -> []; -handle_logfile_sort_wrapset(doc) -> - [""]; -handle_logfile_sort_wrapset(Config) when is_list(Config) -> - File0="prefix10.fil", - File1="prefix11.fil", - File2="prefix12.fil", - File3="prefix13.fil", - ?l [File0,File1,File2,File3]= - inviso_lfm_tpfreader:handle_logfile_sort_wrapset([File2,File1,File0,File3]), - File5="prefix15.fil", - ?l [File5,File0,File1,File2,File3]= - inviso_lfm_tpfreader:handle_logfile_sort_wrapset([File2,File5,File1,File0,File3]), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: This case tests that the regexp mechanism in the inviso_rt_lib can -%% find modules using regexps and that its only_loaded mechanism works. -%% This test case can not be run when using cover because cover will make the -%% modules no longer loaded from the path containing "runtime_tools". -expand_regexp_dist_1(suite) -> []; -expand_regexp_dist_1(doc) -> - [""]; -expand_regexp_dist_1(Config) when is_list(Config) -> - case ?t:is_cover() of - true -> - {skip,"Cover is running"}; - false -> - expand_regexp_dist_1_nocover(Config) - end. - -expand_regexp_dist_1_nocover(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - [RNode1|_]=RemoteNodes, - ?l NodeResults1=inviso_rt_lib:expand_regexp(Nodes,"^inviso_rt.*",[]), - ?l L1=length(Nodes), - ?l L1=length(NodeResults1), - ?l true=lists:all(fun({_,Mods})-> - ?l 3=length(Mods), - ?l true=lists:member(inviso_rt,Mods), - ?l true=lists:member(inviso_rt_lib,Mods), - ?l true=lists:member(inviso_rt_meta,Mods), - true; - (_) -> - false - end, - NodeResults1), - %% Check the dir-option. In the following inviso_tool_lib shall not be found. - ?l NodeResults2=inviso_rt_lib:expand_regexp(Nodes,"runtime_tools","invi.*lib.*",[]), -?l io:format("NodeResults2:~w~n",[NodeResults2]), - ?l L1=length(NodeResults2), % Same number of nodes replying. - ?l true=lists:all(fun({_,Mods})-> - 2=length(Mods), - true=lists:member(inviso_as_lib,Mods), - true=lists:member(inviso_rt_lib,Mods), - true; - (_) -> - false - end, - NodeResults2), - ?l [{RNode1,[]}]= - inviso_rt_lib:expand_regexp([RNode1],"^inviso_testmodule1.*",[only_loaded]), - ?l [{RNode1,[inviso_testmodule1_foo]}]= - inviso_rt_lib:expand_regexp([RNode1],"^inviso_testmodule1.*",[]), - ok. -%% ----------------------------------------------------------------------------- - - -only_loaded_dist_1(suite) -> []; -only_loaded_dist_1(doc) -> - [""]; -only_loaded_dist_1(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - [RNode1|_]=RemoteNodes, - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList= - lists:map(fun(N)->{N,[{trace,{file,filename:join(PrivDir,"ol_1_"++atom_to_list(N))}}]} - end, - Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}), - ?l false=rpc:call(RNode1,erlang,module_loaded,[inviso_testmodule1_foo]), - ?l {ok,[{RNode1,{ok,[0]}}]}= - inviso:tpl([RNode1],inviso_testmodule1_foo,'_','_',[],[only_loaded]), - ?l false=rpc:call(RNode1,erlang,module_loaded,[inviso_testmodule1_foo]), - ?l {ok,[{RNode1,{ok,[3]}}]}= - inviso:tpl([RNode1],inviso_testmodule1_foo,'_','_',[],[]), - stop_tracing(Nodes), - stop(Nodes), - ok. - - -%% ============================================================================== -%% Common functions setting up inviso. -%% ============================================================================== - -%% Starts controlcomponent and adds runtime components on the nodes specified. -%% Also initiates tracing on the nodes. -start_and_init_tracing1(Nodes,Options,TracerData,Reply) when is_list(Nodes) -> - ?l {ok,_Pid}=inviso:start(), % Start a control component. - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,Options), - io:format("~p~n",[NodeResults1]), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - ?l {ok,NodeResults2}=inviso:get_status(Nodes), - ?l true=check_noderesults(Nodes,{ok,{new,running}},NodeResults2), - ?l {ok,NodeResults3}=inviso:init_tracing(Nodes,TracerData), - ?l true=check_noderesults(Nodes,Reply,NodeResults3), - ok. -start_and_init_tracing2(Nodes,Options,TracerDataList,Reply) -> - ?l {ok,_Pid}=inviso:start(), % Start a control component. - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,Options), - io:format("~p~n",[NodeResults1]), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - ?l {ok,NodeResults2}=inviso:get_status(Nodes), - ?l true=check_noderesults(Nodes,{ok,{new,running}},NodeResults2), - ?l {ok,NodeResults4}=inviso:get_tracerdata(Nodes), - ?l true=check_noderesults(Nodes,{ok,no_tracerdata},NodeResults4), - ?l {ok,NodeResults3}=inviso:init_tracing(TracerDataList), - io:format("Tracerdatalist:~p~n",[TracerDataList]), - ?l true=check_noderesults(Nodes,Reply,NodeResults3), - - ?l Fun1=fun({N,{ok,TD}}) when is_list(TD)-> - ?l {value,{trace,Trace}}=lists:keysearch(trace,1,TD), - ?l {value,{N,TD2}}=lists:keysearch(N,1,TracerDataList), - ?l true=lists:member({trace,Trace},TD2), - %% Check that the trace file really exists. - ?l case Trace of % Trace={file,FilePortParameters} - {file,FileName1} when is_list(FileName1) -> - ?l {ok,_}=rpc:call(N,file,read_file_info,[FileName1]); - _ -> % This should be extended with more cases. - true - end, - ?l case lists:keysearch(ti,1,TD2) of - {value,{_,Ti}} -> % Ok, we have ti too. - ?l {value,{_,Ti}}=lists:keysearch(ti,1,TD), - ?l FileName2=element(2,Ti), - ?l {ok,_}=rpc:call(N,file,read_file_info,[FileName2]), - true; - false -> % No ti, we are done now. - true - end; - ({N,{ok,{file,FileName}}}) -> - ?l {value,{N,{file,FileName}}}=lists:keysearch(N,1,TracerDataList), - ?l {ok,_}=rpc:call(N,file,read_file_info,[FileName]), - true; - ({N,{ok,LogTD}}) -> % The case using a fun. - ?l {value,{N,LogTD}}=lists:keysearch(N,1,TracerDataList), - true - end, - ?l {ok,NodeResults5}=inviso:get_tracerdata(Nodes), - ?l true=check_noderesults(Nodes,Fun1,NodeResults5), - ok. -%% ------------------------------------------------------------------------------ - -%% Stops tracing on Nodes. -stop_tracing(Nodes) when is_list(Nodes) -> - ?l {ok,NodeResults1}=inviso:stop_tracing(Nodes), - ?l true=check_noderesults(Nodes,{ok,idle},NodeResults1), - ?l {ok,NodeResults2}=inviso:get_status(Nodes), - ?l true=check_noderesults(Nodes,{ok,{idle,running}},NodeResults2), - %% The implementation says that the meta tracer shall be stopped when - %% tracing is stopped. Check that. - ?l lists:foreach(fun(N)-> - ok=poll(erlang,whereis,[inviso_rt_meta],undefined,20) - end, - Nodes). -%% ------------------------------------------------------------------------------ - -%% Stops the runtime components on Nodes and stops the control component at this -%% Erlang node. -stop(Nodes) when is_list(Nodes) -> - ?l true=check_on_nodes(Nodes,erlang,whereis,[inviso_rt],fun(P) when is_pid(P)->true end), - ?l {ok,NodeResults}=inviso:stop_nodes(Nodes), - ?l true=check_noderesults(Nodes,ok,NodeResults), - ?l true=check_on_nodes(Nodes,erlang,whereis,[inviso_rt],fun(undefined)->true end), - ?l true=is_pid(whereis(inviso_c)), - ?l shutdown=inviso:stop(), - ?l ok=poll(erlang,whereis,[inviso_c],undefined,20). -%% ------------------------------------------------------------------------------ - -%% Help function activating local tracing. -activate_local_tracing(Nodes) when is_list(Nodes) -> - ?l true=check_on_nodes(Nodes, - erlang, - trace_info, - [{code,which,1},traced], - {traced,false}), - ?l {ok,NodeResults}=inviso:tpl(Nodes,code,which,1,[]), - ?l true=check_noderesults(Nodes,fun({_,{ok,[1]}})->true end,NodeResults), - ?l true=check_on_nodes(Nodes, - erlang, - trace_info, - [{code,which,1},traced], - {traced,local}). -%% ------------------------------------------------------------------------------ - -%% Help function activating global tracing. -activate_global_tracing(Nodes) when is_list(Nodes) -> - ?l true=check_on_nodes(Nodes, - erlang, - trace_info, - [{code,get_path,0},traced], - {traced,false}), - ?l {ok,NodeResults}=inviso:tp(Nodes,code,get_path,0,[]), - ?l true=check_noderesults(Nodes,fun({_,{ok,[1]}})->true end,NodeResults), - ?l true=check_on_nodes(Nodes, - erlang, - trace_info, - [{code,get_path,0},traced], - {traced,global}). -%% ------------------------------------------------------------------------------ - - -%% Help function activating local tracing and using a regexp to point out modules. -%% Returns the structure of modules and functions that were activated. Must be used -%% when deactivating. -activate_global_tracing_regexp(Nodes) when is_list(Nodes) -> - %% First find out which modules will be effected. - ?l Mods1=inviso_rt_lib:expand_regexp("application.*",[]), - ?l true=(length(Mods1)>1), % Should find more than one module! - ?l Funcs1=lists:foldl(fun(M,Acc)->[{M,M:module_info(exports)}|Acc] end,[],Mods1), - %% Check that these functions are not traced. - io:format("Modules:~w~n",[Mods1]), - ?l {ok,NodeResults}=inviso:tp(Nodes,"application.*",'_','_',[],[]), - io:format("Here 2~w~n",[NodeResults]), - ?l N=lists:foldl(fun({_,L1},A1)->lists:foldl(fun(_,A2)->A2+1 end,A1,L1) end,0,Funcs1), - ?l true=check_noderesults(Nodes,fun({_,{ok,L}})-> N==lists:sum(L) end,NodeResults), - io:format("Here 3~n",[]), - %% Check again! - ?l lists:foreach(fun({M,Funcs})-> - lists:foreach(fun({F,Arity})-> - true=check_on_nodes(Nodes, - erlang, - trace_info, - [{M,F,Arity},traced], - {traced,global}) - end, - Funcs) - end, - Funcs1), - Funcs1. -%% ------------------------------------------------------------------------------ - -%% Help function as above but uses the dir feature as well. -activate_global_tracing_regexp_dir(Nodes) when is_list(Nodes) -> - %% First find out which modules will be effected. - ?l Mods1=inviso_rt_lib:expand_regexp(".*kernel.*","application.*",[]), - ?l true=(length(Mods1)>1), % Should find more than one module! - ?l Funcs1=lists:foldl(fun(M,Acc)->[{M,M:module_info(exports)}|Acc] end,[],Mods1), - %% Check that these functions are not traced. - io:format("Modules:~w~n",[Mods1]), - ?l {ok,NodeResults}=inviso:tp(Nodes,{".*kernel.*","application.*"},'_','_',[],[]), - io:format("Here 2~w~n",[NodeResults]), - ?l N=lists:foldl(fun({_,L1},A1)->lists:foldl(fun(_,A2)->A2+1 end,A1,L1) end,0,Funcs1), - ?l true=check_noderesults(Nodes,fun({_,{ok,L}})-> N==lists:sum(L) end,NodeResults), - io:format("Here 3~n",[]), - %% Check again! - ?l lists:foreach(fun({M,Funcs})-> - lists:foreach(fun({F,Arity})-> - true=check_on_nodes(Nodes, - erlang, - trace_info, - [{M,F,Arity},traced], - {traced,global}) - end, - Funcs) - end, - Funcs1), - Funcs1. -%% ------------------------------------------------------------------------------ - -deactivate_local_tracing(Nodes) when is_list(Nodes) -> - ?l true=check_on_nodes(Nodes, - erlang, - trace_info, - [{code,which,1},traced], - {traced,local}), - ?l {ok,NodeResults}=inviso:ctpl(Nodes,code,'_','_'), - ?l true=check_noderesults(Nodes,fun({_,{ok,[N]}})when is_integer(N)->true end,NodeResults), - ?l true=check_on_nodes(Nodes, - erlang, - trace_info, - [{code,which,1},traced], - {traced,false}). -%% ------------------------------------------------------------------------------ - -deactivate_global_tracing(Nodes) when is_list(Nodes) -> - ?l true=check_on_nodes(Nodes, - erlang, - trace_info, - [{code,get_path,0},traced], - {traced,global}), - ?l {ok,NodeResults}=inviso:ctp(Nodes,code,'_','_'), - ?l true=check_noderesults(Nodes,fun({_,{ok,[N]}})when is_integer(N)->true end,NodeResults), - ?l true=check_on_nodes(Nodes, - erlang, - trace_info, - [{code,get_path,0},traced], - {traced,false}). -%% ------------------------------------------------------------------------------ - - -%% Function deactivating the functions activated by activate_global_tracing_regexp/1. -deactivate_global_tracing_regexp(Nodes,Funcs1) -> - ?l lists:foreach(fun({M,Funcs})-> - lists:foreach(fun({F,Arity})-> - true=check_on_nodes(Nodes, - erlang, - trace_info, - [{M,F,Arity},traced], - {traced,global}) - end, - Funcs) - end, - Funcs1), - ?l {ok,NodeResults}=inviso:ctp(Nodes,"application.*",'_','_'), - ?l N=lists:foldl(fun({_,L1},A1)->lists:foldl(fun(_,A2)->A2+1 end,A1,L1) end,0,Funcs1), - io:format("Noderesult from deactivate;~w~n",[NodeResults]), - ?l true=check_noderesults(Nodes,fun({_,{ok,L}})-> N==lists:sum(L) end,NodeResults), - ?l lists:foreach(fun({M,Funcs})-> - lists:foreach(fun({F,Arity})-> - true=check_on_nodes(Nodes, - erlang, - trace_info, - [{M,F,Arity},traced], - {traced,false}) - end, - Funcs) - end, - Funcs1). -%% ------------------------------------------------------------------------------ - -%% Function deactivating the functions activated by activate_global_tracing_regexp_dir/1. -deactivate_global_tracing_regexp_dir(Nodes,Funcs1) -> - ?l lists:foreach(fun({M,Funcs})-> - lists:foreach(fun({F,Arity})-> - true=check_on_nodes(Nodes, - erlang, - trace_info, - [{M,F,Arity},traced], - {traced,global}) - end, - Funcs) - end, - Funcs1), - ?l {ok,NodeResults}=inviso:ctp(Nodes,{".*kernel.*","application.*"},'_','_'), - ?l N=lists:foldl(fun({_,L1},A1)->lists:foldl(fun(_,A2)->A2+1 end,A1,L1) end,0,Funcs1), - io:format("Noderesult from deactivate;~w~n",[NodeResults]), - ?l true=check_noderesults(Nodes,fun({_,{ok,L}})-> N==lists:sum(L) end,NodeResults), - ?l lists:foreach(fun({M,Funcs})-> - lists:foreach(fun({F,Arity})-> - true=check_on_nodes(Nodes, - erlang, - trace_info, - [{M,F,Arity},traced], - {traced,false}) - end, - Funcs) - end, - Funcs1). -%% ------------------------------------------------------------------------------ - -%% Help function which starts the inviso_test_proc on all nodes and then sets -%% the call flag on that process. -activate_traceflags(Nodes) -> - ?l lists:foreach(fun(N)->spawn(N,?MODULE,test_proc_init,[]) end,Nodes), - ?l lists:foreach(fun(N)-> - P=rpc:call(N,erlang,whereis,[inviso_test_proc]), - {flags,[]}=rpc:call(N,erlang,trace_info,[P,flags]) - end, - Nodes), - ?l {ok,NodeResults}=inviso:tf(Nodes,inviso_test_proc,[call,timestamp]), - ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults), - ?l lists:foreach(fun(N)-> - P=rpc:call(N,erlang,whereis,[inviso_test_proc]), - {flags,Flags}=rpc:call(N,erlang,trace_info,[P,flags]), - true=lists:member(call,Flags), - true=lists:member(timestamp,Flags) - end, - Nodes), - %% Now try a globally registered process. - ?l [ANode|_]=Nodes, - ?l GPid=spawn(ANode,?MODULE,global_test_proc_init,[]), - ?l ok=poll(global,whereis_name,[global_inviso_test_proc], - fun(P) when is_pid(P)->true;(_)->false end, - 10), - ?l {ok,NodeResults2}= - inviso:tf(Nodes,{global,global_inviso_test_proc},[call,timestamp]), - ?l true=check_noderesults(Nodes, - fun({N,{ok,[1]}}) when N==ANode->true; - ({_,{ok,[0]}})->true; - (_)->false - end, - NodeResults2), - ?l {flags,Flags2}=rpc:call(ANode,erlang,trace_info,[GPid,flags]), - ?l 2=length(Flags2), - ?l true=lists:member(call,Flags2), - ?l true=lists:member(timestamp,Flags2), - true. -%% ------------------------------------------------------------------------------ - -deactivate_traceflags(Nodes) -> - ?l lists:foreach(fun(N)-> - P=rpc:call(N,erlang,whereis,[inviso_test_proc]), - {flags,Flags}=rpc:call(N,erlang,trace_info,[P,flags]), - true=lists:member(call,Flags), - true=lists:member(timestamp,Flags) - end, - Nodes), - ?l {ok,NodeResults}=inviso:ctf(Nodes,inviso_test_proc,[call,timestamp]), - ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults), - ?l lists:foreach(fun(N)-> - P=rpc:call(N,erlang,whereis,[inviso_test_proc]), - {flags,[]}=rpc:call(N,erlang,trace_info,[P,flags]) - end, - Nodes), - ?l GPid=global:whereis_name(global_inviso_test_proc), - ?l ANode=node(GPid), - ?l {flags,Flags2}=rpc:call(ANode,erlang,trace_info,[GPid,flags]), - ?l 2=length(Flags2), - ?l {ok,NodeResults2}=inviso:ctf(Nodes,{global,global_inviso_test_proc},[call,timestamp]), - ?l true=check_noderesults(Nodes, - fun({N,{ok,[1]}}) when N==ANode->true; - ({_,{ok,[0]}})->true; - (_)->false - end, - NodeResults2). -%% ------------------------------------------------------------------------------ - - -activate_meta_tracing(Nodes) -> - ?l {ok,NodeResults1}=inviso:tpm_localnames(), - ?l true=check_noderesults(Nodes,{{ok,1},{ok,1}},NodeResults1), - ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), - {meta,P}=rpc:call(N,erlang,trace_info,[{erlang,register,2},meta]) - end, - Nodes), - ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), - {meta,P}=rpc:call(N,erlang,trace_info,[{erlang,unregister,1},meta]) - end, - Nodes), - ?l {ok,NodeResults2}=inviso:tpm_globalnames(), - ?l true=check_noderesults(Nodes,{{ok,1},{ok,1}},NodeResults2), - ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), - {meta,P}=rpc:call(N, - erlang, - trace_info, - [{global,handle_call,3},meta]) - end, - Nodes), - ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), - {meta,P}=rpc:call(N, - erlang, - trace_info, - [{global,delete_global_name,2},meta]) - end, - Nodes), - - ?l lists:foreach(fun(N)->true=rpc:call(N, - ets, - insert, - [inviso_sideeffect_tab,{tpm_init_func1,0}]), - true=rpc:call(N, - ets, - insert, - [inviso_sideeffect_tab,{tpm_call_func1,0}]), - true=rpc:call(N, - ets, - insert, - [inviso_sideeffect_tab,{tpm_return_func1,0}]) - end, - Nodes), - ?l {ok,NodeResults3}= - inviso:init_tpm(lists, - module_info, - 0, - {?MODULE,tpm_init_func1}, - {?MODULE,tpm_call_func1}, - {?MODULE,tpm_return_func1}, - {?MODULE,tpm_remove_func1}), - ?l true=check_noderesults(Nodes,ok,NodeResults3), - ?l [{_,1}]=ets:lookup(inviso_sideeffect_tab,tpm_init_func1), - ?l {ok,NodeResults3a}= - inviso:init_tpm(lists, - module_info, - 0, - {?MODULE,tpm_init_func1}, - {?MODULE,tpm_call_func1}, - {?MODULE,tpm_return_func1}, - {?MODULE,tpm_remove_func1}), - ?l true=check_noderesults(Nodes,{error,already_initiated},NodeResults3a), -% %% Try more forbidden things. Wildcards not allowed in meta tracing! -% ?l {ok,NodeResults3b}=inviso:tpm(Nodes,lists,'_',0,[{'_',[],[{return_trace}]}]), -% io:format("The noderesults3b is:~w~n",[NodeResults3b]), -% ?l true=check_noderesults(Nodes,{error,bad_mfa},NodeResults3b), - ?l {ok,NodeResults3c}=inviso:tpm(Nodes,lists,module_info,0,[{'_',[],[{return_trace}]}]), - ?l true=check_noderesults(Nodes,{ok,1},NodeResults3c), - ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), - {meta,P}=rpc:call(N,erlang,trace_info,[{lists,module_info,0},meta]) - end, - Nodes), - ?l lists:foreach(fun(N)->rpc:call(N,lists,module_info,[]) end,Nodes), - ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_call_func1],[{tpm_call_func1,1}],20), - ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_return_func1],[{tpm_return_func1,1}],20), - ?l lists:foreach(fun(N)->rpc:call(N,lists,module_info,[]) end,Nodes), - ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_call_func1],[{tpm_call_func1,2}],20), - ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_return_func1],[{tpm_return_func1,2}],20), - - ?l {ok,NodeResults4}= - inviso:init_tpm(math, - module_info, - 1, - {?MODULE,tpm_init_func2}, % Does not exist on purpose. - {?MODULE,tpm_call_func2}, % Does not exist on purpose. - {?MODULE,tpm_return_func2}, % Does not exist on purpose. - {?MODULE,tpm_remove_func2}), % Does not exist on purpose. - ?l true=check_noderesults(Nodes,ok,NodeResults4), - ?l {ok,NodeResults5}= - inviso:tpm_ms(math,module_info,1,ms1,[{'_',[],[{return_trace}]}]), - ?l true=check_noderesults(Nodes,{ok,1},NodeResults5), - ?l lists:foreach(fun(N)->{meta_match_spec,[{'_',[],[{return_trace}]}]}= - rpc:call(N,erlang,trace_info,[{math,module_info,1}, - meta_match_spec]) - end, - Nodes), - - ?l {ok,NodeResults6}=inviso:tpm_ms(math,module_info,1,ms2,[{[exports],[],[]}]), - ?l true=check_noderesults(Nodes,{ok,1},NodeResults6), - ?l lists:foreach(fun(N)->{meta_match_spec,[{[exports],[],[]},{'_',[],[{return_trace}]}]}= - rpc:call(N,erlang,trace_info,[{math,module_info,1}, - meta_match_spec]) - end, - Nodes), - ?l {ok,NodeResults7}=inviso:tpm_ms(math,module_info,1,ms3,[{[attributes],[],[]}]), - ?l true=check_noderesults(Nodes,{ok,1},NodeResults7), - ?l lists:foreach(fun(N)->{meta_match_spec,[{[attributes],[],[]}, - {[exports],[],[]}, - {'_',[],[{return_trace}]}]}= - rpc:call(N,erlang,trace_info,[{math,module_info,1}, - meta_match_spec]) - end, - Nodes), - ?l {ok,NodeResults8}=inviso:ctpm_ms(math,module_info,1,ms2), - ?l true=check_noderesults(Nodes,ok,NodeResults8), - ?l lists:foreach(fun(N)->{meta_match_spec,[{[attributes],[],[]}, - {'_',[],[{return_trace}]}]}= - rpc:call(N,erlang,trace_info,[{math,module_info,1}, - meta_match_spec]) - end, - Nodes), - ?l io:format("whereis:~w~n",[lists:map(fun(N)->rpc:call(N,erlang,whereis,[inviso_rt_meta]) end,Nodes)]), - ?l {ok,NodeResults8}=inviso:ctpm_ms(math,module_info,1,ms3), - ?l io:format("whereis:~w~n",[lists:map(fun(N)->rpc:call(N,erlang,whereis,[inviso_rt_meta]) end,Nodes)]), - ?l {ok,NodeResults8}=inviso:ctpm_ms(math,module_info,1,ms1), - ?l lists:foreach(fun(N)->{meta_match_spec,false}= - rpc:call(N,erlang,trace_info,[{math,module_info,1}, - meta_match_spec]) - end, - Nodes), - - %% Now try to do this with exception tracing instead. - %% Reset the side effect tables. - ?l lists:foreach(fun(N)->true=rpc:call(N, - ets, - insert, - [inviso_sideeffect_tab,{tpm_init_func1,0}]), - true=rpc:call(N, - ets, - insert, - [inviso_sideeffect_tab,{tpm_call_func1,0}]), - true=rpc:call(N, - ets, - insert, - [inviso_sideeffect_tab,{tpm_return_func1,0}]) - end, - Nodes), - ?l {ok,NodeResults9}= - inviso:init_tpm(?MODULE, - failing_function, - 1, - {?MODULE,tpm_init_func1}, - {?MODULE,tpm_call_func1}, - {?MODULE,tpm_return_func1}, - {?MODULE,tpm_remove_func1}), - ?l true=check_noderesults(Nodes,ok,NodeResults9), - ?l [{_,1}]=ets:lookup(inviso_sideeffect_tab,tpm_init_func1), - ?l {ok,NodeResults10}=inviso:tpm(Nodes,?MODULE,failing_function,1,[{'_',[],[{exception_trace}]}]), - ?l true=check_noderesults(Nodes,{ok,1},NodeResults10), - ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), - {meta,P}=rpc:call(N,erlang,trace_info,[{?MODULE,failing_function,1},meta]) - end, - Nodes), - ?l lists:foreach(fun(N)->rpc:call(N,?MODULE,failing_function,[nofailure]) end,Nodes), - ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_call_func1],[{tpm_call_func1,1}],20), - ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_return_func1],[{tpm_return_func1,1}],20), - ?l lists:foreach(fun(N)->rpc:call(N,?MODULE,failing_function,[failure]) end,Nodes), - ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_call_func1],[{tpm_call_func1,2}],20), - ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_return_func1],[{tpm_return_func1,3}],20), - - ok. -%% ------------------------------------------------------------------------------ - -%% This function is for testing that appending the tracer to a trace action term -%% works. -activate_deactivate_meta_tracing_tracer(Nodes) -> - ?l {ok,NodeResults}= - inviso:tpm_tracer(Nodes,lists,module_info,0,[{'_',[],[{trace,[all],[call]}]}],void), - ?l true=check_noderesults(Nodes,{ok,1},NodeResults), - ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), - {meta,P}=rpc:call(N,erlang,trace_info,[{lists,module_info,0},meta]), - {meta_match_spec,[{'_',[],[{trace,[all],Enable}]}]}= - rpc:call(N,erlang,trace_info,[{lists,module_info,0}, - meta_match_spec]), - true=list_search(Enable,fun({{tracer,P}}) when is_port(P)->true; - (_) -> false - end) - end, - Nodes), - ?l {ok,NodeResults2}= - inviso:ctpm(Nodes,lists,module_info,0), - ?l true=check_noderesults(Nodes,ok,NodeResults2), - ?l lists:foreach(fun(N)->{meta,false}= - rpc:call(N,erlang,trace_info,[{lists,module_info,0},meta]) - end, - Nodes), - ok. -%% ------------------------------------------------------------------------------ - -deactivate_meta_tracing(Nodes) -> - ?l lists:foreach(fun(N)->{meta,P}= - rpc:call(N,erlang,trace_info,[{erlang,register,2},meta]), - true=is_pid(P) - end, - Nodes), - ?l lists:foreach(fun(N)->{meta,P}= - rpc:call(N,erlang,trace_info,[{erlang,unregister,1},meta]), - true=is_pid(P) - end, - Nodes), - ?l {ok,NodeResults1}=inviso:ctpm_localnames(), - ?l lists:foreach(fun(N)->{meta,false}= - rpc:call(N,erlang,trace_info,[{erlang,register,2},meta]) end, - Nodes), - ?l lists:foreach(fun(N)->{meta,false}= - rpc:call(N,erlang,trace_info,[{erlang,unregister,1},meta]) - end, - Nodes), - ?l true=check_noderesults(Nodes,{ok,ok},NodeResults1), - - ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), - {meta,P}=rpc:call(N, - erlang, - trace_info, - [{global,handle_call,3},meta]) - end, - Nodes), - ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), - {meta,P}=rpc:call(N, - erlang, - trace_info, - [{global,delete_global_name,2},meta]) - end, - Nodes), - ?l {ok,NodeResults1b}=inviso:ctpm_globalnames(), - ?l true=check_noderesults(Nodes,{ok,ok},NodeResults1b), - ?l lists:foreach(fun(N)-> - {meta,false}=rpc:call(N, - erlang, - trace_info, - [{global,handle_call,3},meta]) - end, - Nodes), - ?l lists:foreach(fun(N)-> - {meta,false}=rpc:call(N, - erlang, - trace_info, - [{global,delete_global_name,2},meta]) - end, - Nodes), - - ?l lists:foreach(fun(N)->{meta,P}= - rpc:call(N,erlang,trace_info,[{lists,module_info,0},meta]), - true=is_pid(P) - end, - Nodes), - ?l {ok,NodeResults2}=inviso:ctpm(lists,module_info,0), - ?l true=check_noderesults(Nodes,ok,NodeResults2), - ?l lists:foreach(fun(N)->{meta,false}= - rpc:call(N,erlang,trace_info,[{lists,module_info,0},meta]) end, - Nodes), - ?l [{_,0}]=ets:lookup(inviso_sideeffect_tab,tpm_init_func1), - ?l {ok,NodeResults3}=inviso:ctpm(math,module_info,1), - ?l true=check_noderesults(Nodes,ok,NodeResults3), - ok. -%% ------------------------------------------------------------------------------ - -%% Functions acting as callbacks for testing the meta tracing mechanisms. -tpm_init_func1(_M,_F,_Arity,PublLD) -> - ets:update_counter(inviso_sideeffect_tab,tpm_init_func1,1), - {ok,PublLD,void}. -tpm_call_func1(_Pid,{call,_Args,_TS},PublLD) -> - ets:update_counter(inviso_sideeffect_tab,tpm_call_func1,1), - {ok,PublLD,void}. -tpm_return_func1(_Pid,{return_from,_ReturnVal,_TS},PublLD) -> - ets:update_counter(inviso_sideeffect_tab,tpm_return_func1,1), - {ok,PublLD,void}; -tpm_return_func1(_Pid,{exception_from,_ReturnVal,_TS},PublLD) -> - ets:update_counter(inviso_sideeffect_tab,tpm_return_func1,1), - ets:update_counter(inviso_sideeffect_tab,tpm_return_func1,1), - {ok,PublLD,void}. -tpm_remove_func1(_M,_F,_Arity,PublLD) -> - ets:update_counter(inviso_sideeffect_tab,tpm_init_func1,-1), - {ok,PublLD}. -%% ------------------------------------------------------------------------------ - - -%% Help function which traces on a function and makes function calls until there -%% are two files in the wrap-set. -fill_and_reach_two_wrapfiles(PrivDir,RegExp,Nodes) -> - ?l lists:foreach(fun(N)->spawn(N,?MODULE,test_proc_init,[]) end,Nodes), - ?l {ok,NodeResults1}=inviso:tpl(Nodes,?MODULE,test_function,0,[]), - ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults1), - ?l {ok,NodeResults2}=inviso:tf(Nodes,inviso_test_proc,[call]), - ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults2), - fill_and_reach_two_wrapfiles_2(PrivDir,RegExp,Nodes), - ?l {ok,NodeResults3}=inviso:ctf(Nodes,inviso_test_proc,[call]), - ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults3), - ?l {ok,NodeResults4}=inviso:ctpl(Nodes,?MODULE,test_function,0), - ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults4), - ok. - -fill_and_reach_two_wrapfiles_2(PrivDir,RegExp,[Node|Rest]) -> - ?l ok=rpc:call(Node,?MODULE,fill_and_reach_two_wrapfiles_3,[PrivDir,RegExp]), - fill_and_reach_two_wrapfiles_2(PrivDir,RegExp,Rest); -fill_and_reach_two_wrapfiles_2(_,_,[]) -> - ok. - -fill_and_reach_two_wrapfiles_3(Dir,RegExp) -> - ok=send_to_test_proc({apply,?MODULE,test_function,[]}, - fun reach_two_wraps_stopfun/1, - {Dir,RegExp++atom_to_list(node())}, - 100). - -%% Help function intended to be used as fun in a send_to_test_proc/4 call. -%% The function lists the content of Dir and looks for occurancies of String. -%% If two files containing the string String are found, 'done' is returned. -%% Otherwise 'continue'. -reach_two_wraps_stopfun({Dir,RegExp}) -> - case file:list_dir(Dir) of - {ok,FileNames} -> - case how_many_files_regexp(FileNames,RegExp,0) of - {ok,2} -> - done; - _ -> - continue - end; - {error,_Reason} -> - error - end. -%% ------------------------------------------------------------------------------ - -%% ------------------------------------------------------------------------------ -%% Help function for the overload tests. These functions are used as callbacks. -%% ------------------------------------------------------------------------------ - -overload1(_) -> - ets:update_counter(inviso_sideeffect_tab,ovl1,1), - ok. -%% This function is used when timeout occurs inside the runtime component. -%% That is it is time to check for overload. -overload2({timeout,overload2i_data}) -> - ets:update_counter(inviso_sideeffect_tab,ovl2,1), - ok. -overload2i() -> - ets:insert(inviso_sideeffect_tab,{ovl2,0}), - {ok,overload2i_data}. -overload2r(overload2i_data) -> - ets:delete(inviso_sideeffect_tab,ovl2). - -%% This function is used when timeout occurs inside the runtime component. -%% That is it is time to check for overload. -overload3({timeout,overload3i_data}) -> - ets:update_counter(inviso_sideeffect_tab,ovl3,1), - ok; -overload3(_) -> % Must handle garbage too. - ignore. -overload3i() -> - ets:insert(inviso_sideeffect_tab,{ovl3,0}), - {ok,overload3i_data}. -overload3r(overload3i_data) -> - ets:insert(inviso_sideeffect_tab,{ovl3r,done}), - ets:delete(inviso_sideeffect_tab,ovl3). - -overload4(_) -> - case ets:lookup(inviso_sideeffect_tab,ovl4_suspend) of - [] -> % We are supposed to be running. - ets:update_counter(inviso_sideeffect_tab,ovl4,1), - ok; - [_] -> - {suspend,test} - end. - -%% This function is used when overload check is done by icomming message. -overload5({msg,{test_of_loadcheck,overload5i_data}}) -> - ets:update_counter(inviso_sideeffect_tab,ovl5,1), - ok; -overload5(_) -> - ignore. -overload5i() -> - ets:insert(inviso_sideeffect_tab,{ovl5,0}), - {ok,overload5i_data}. -overload5r(overload5i_data) -> - ets:delete(inviso_sideeffect_tab,ovl5), - ets:insert(inviso_sideeffect_tab,{ovl5r,done}); -overload5r(X) -> - erlang:display({'***',overload5r,X}). - -overload6(_) -> - ets:update_counter(inviso_sideeffect_tab,ovl6,1), - ok. -%% ------------------------------------------------------------------------------ - -%% ------------------------------------------------------------------------------ -%% Help function for the subscription tests. These function implements a collector -%% process which will subscribe to inviso_events from the control component. -%% ------------------------------------------------------------------------------ - -%% Function which can be used to check if an inviso_event has arrived. The function -%% takes a fun which tests the messages. -check_msg_collector([],_,_) -> - true; -check_msg_collector(_,_,0) -> - false; -check_msg_collector(Nodes,Fun,T) -> - Ref=make_ref(), - inviso_collector_proc ! {fetch_message,self(),Ref,Fun}, - receive - {inviso,Ref,{true,Node}} -> - check_msg_collector(lists:delete(Node,Nodes),Fun,T-1); - {inviso,Ref,false} -> - timer:sleep(100), - check_msg_collector(Nodes,Fun,T-1) - end. - -%% Spawn on this function to get a subscriber. -inviso_msg_collector() -> - register(inviso_collector_proc,self()), - inviso_msg_collector_loop([]). - -inviso_msg_collector_loop(Msgs) -> - receive - {fetch_message,From,Ref,Fun} -> - {NewMsgs,Reply}=inviso_msg_collector_selector(Msgs,Fun,[]), - From ! {inviso,Ref,Reply}, - inviso_msg_collector_loop(NewMsgs); - Msg -> - inviso_msg_collector_loop([Msg|Msgs]) - end. - -inviso_msg_collector_selector([M|Rest],Fun,Accum) -> - case Fun(M) of - {true,X} -> - {Rest++Accum,{true,X}}; - _ -> - inviso_msg_collector_selector(Rest,Fun,[M|Accum]) - end; -inviso_msg_collector_selector([],_,Accum) -> - {Accum,false}. -%% ------------------------------------------------------------------------------ - - -%% ============================================================================== -%% Help functions -%% ============================================================================== - -list_search([E|Rest],Fun) -> - case Fun(E) of - true -> - true; - false -> - list_search(Rest,Fun) - end; -list_search([],_Fun) -> - false. -%% ------------------------------------------------------------------------------ - -%% Help function checking that there is a Result for each node in Nodes. -%% Returns 'true' if successful. -check_noderesults(Nodes,Fun,[{Node,Result}|Rest]) when is_function(Fun) -> - case Fun({Node,Result}) of - true -> - case lists:member(Node,Nodes) of - true -> - check_noderesults(lists:delete(Node,Nodes),Fun,Rest); - false -> % Not good. - unknown_node_in_returnvalue - end; - _ -> - illegal_result - end; -check_noderesults(Nodes,Result,[{Node,Result}|Rest]) -> - case lists:member(Node,Nodes) of - true -> - check_noderesults(lists:delete(Node,Nodes),Result,Rest); - false -> % Not good. - unknown_node_in_returnvalue - end; -check_noderesults([],_,[]) -> - true; -check_noderesults(X,Y,Z) -> - io:format("Bad arguments to check noderesults:~w~n~w~n~w~n",[X,Y,Z]), - false. -%% ------------------------------------------------------------------------------ - -%% Help function doing rpc on all nodes in Nodes calling M:F. Returns 'true' if -%% successful. -check_on_nodes([Node|Rest],M,F,Args,Result) when Node==node() -> - if - is_function(Result) -> - ?l true=Result(apply(M,F,Args)); - true -> - ?l Result=apply(M,F,Args) - end, - check_on_nodes(Rest,M,F,Args,Result); -check_on_nodes([Node|Rest],M,F,Args,Result) -> - if - is_function(Result) -> - ?l true=Result(rpc:call(Node,M,F,Args)); - true -> - ?l Result=rpc:call(Node,M,F,Args) - end, - check_on_nodes(Rest,M,F,Args,Result); -check_on_nodes([],_,_,_,_) -> - true. -%% ------------------------------------------------------------------------------ - -%% Help function which given a list of files searches through it and returns -%% how many satisfies the RegExp. -%% Returns {ok,N}. -how_many_files_regexp([],_,N) -> - {ok,N}; -how_many_files_regexp([FName|Rest],RegExp,N) -> - case re:run(FName,RegExp,[{capture,none}]) of - match -> - how_many_files_regexp(Rest,RegExp,N+1); - nomatch -> - how_many_files_regexp(Rest,RegExp,N); - {error,Reason} -> - test_server:fail(Reason) - end. -%% ------------------------------------------------------------------------------ - -%% Help function killing a bunch of registered processes. -process_killer([RegName|Rest]) -> - case whereis(RegName) of - undefined -> - case global:whereis_name(RegName) of - undefined -> - process_killer(Rest); - P when is_pid(P) -> - if - node()==node(P) -> - exit(P,kill); - true -> - true - end, - process_killer(Rest) - end; - P when is_pid(P) -> - exit(P,kill), - process_killer(Rest) - end; -process_killer([]) -> - true. -%% ------------------------------------------------------------------------------ - -%% Help function which waits for a function call to become Result. This is useful -%% if what we are waiting for can happend independantly of indications we have -%% access to. -poll(_,_,_,_,0) -> - error; -poll(M,F,Args,Result,Times) -> - try apply(M,F,Args) of - What when is_function(Result) -> - case Result(What) of - true -> - ok; - _ -> - timer:sleep(100), - poll(M,F,Args,Result,Times-1) - end; - Result -> - ok; - _ -> - timer:sleep(100), - poll(M,F,Args,Result,Times-1) - catch - error:Reason -> - io:format("Apply in suite-function poll/5 failed, ~w~n",[Reason]), - timer:sleep(100), - poll(M,F,Args,Result,Times-1) - end. -%% ------------------------------------------------------------------------------ - -insert_remotenode_config(Name,Node,Config) -> - [{remotenode,{Name,Node}}|Config]. -%% ------------------------------------------------------------------------------ - -insert_timetraphandle_config(Handle,Config) -> - [{timetraphandle,Handle}|Config]. -%% ------------------------------------------------------------------------------ - -get_remotenode_config(Name, [{remotenode, {Name, Node}}| _Cs]) -> - Node; -get_remotenode_config(Name, [_ | Cs]) -> - get_remotenode_config(Name, Cs); -get_remotenode_config(Name, []) -> - exit({no_remotenode, Name}). - -%% ------------------------------------------------------------------------------ - -get_timetraphandle_config(Config) -> - {value,{_,Handle}}=lists:keysearch(timetraphandle,1,Config), - Handle. -%% ------------------------------------------------------------------------------ - -get_remotenodes_config([{remotenode,{_Name,Node}}|Config]) -> - [Node|get_remotenodes_config(Config)]; -get_remotenodes_config([_|Config]) -> - get_remotenodes_config(Config); -get_remotenodes_config([]) -> - []. -%% ------------------------------------------------------------------------------ - -remove_remotenode_config(Name, [{remotenode, {Name, _}} | Cs]) -> - Cs; -remove_remotenode_config(Name, [C | Cs]) -> - [C | remove_remotenode_config(Name, Cs)]; -remove_remotenode_config(_Name, []) -> - []. - -%% ------------------------------------------------------------------------------ - -remove_timetraphandle_config(Config) -> - lists:keydelete(timetraphandle,1,Config). -%% ------------------------------------------------------------------------------ - -%% This function can be meta traced in order to check that exception_trace works. -%% Must be exported. -failing_function(nofailure) -> - true; -failing_function(failure) -> - exit(failure). -%% ------------------------------------------------------------------------------ - -%% ============================================================================== -%% Code for a test process which can be started. -%% ============================================================================== - -test_proc_init() -> - register(inviso_test_proc,self()), - test_proc_loop(). - -test_proc_loop() -> - receive - {apply,M,F,Args} -> - apply(M,F,Args), - test_proc_loop(); - X -> - io:format("Got ~w~n",[X]), - test_proc_loop() - end. - -global_test_proc_init() -> - global:register_name(global_inviso_test_proc,self()), - test_proc_loop(). -%% ------------------------------------------------------------------------------ - -send_to_test_proc(_,_,_,0) -> - error; -send_to_test_proc(Msg,Fun,FunArg,N) -> - inviso_test_proc ! Msg, - case Fun(FunArg) of - done -> - ok; - error -> - test_server:fail(send_to_test_proc); - _ -> - send_to_test_proc(Msg,Fun,FunArg,N-1) - end. -%% ------------------------------------------------------------------------------ - - -%% This function is here to be traced on by the inviso_test_proc. Must be exported. -test_function() -> - 1+1. -%% ------------------------------------------------------------------------------ - - -%% ============================================================================== -%% Code for a test side effect table process. -%% ============================================================================== - -%% The side effect logger is a process owning a public ETS table. The idea is that -%% various callback functions can write in the table when called. In that way -%% correct calling of the call-backs can be verified. -start_side_effect_logger(Node) -> - ?l true=is_pid(spawn(Node,?MODULE,side_effect_logger_proc,[])), - ?l ok=poll(rpc,call,[Node,ets,lookup,[inviso_sideeffect_tab,foo]],[],20). - -%% This one must be exported. -side_effect_logger_proc() -> - register(inviso_tab_proc,self()), % So we can kill it later. - ets:new(inviso_sideeffect_tab,[public,named_table]), - side_effect_logger_proc_2(). - -side_effect_logger_proc_2() -> - receive - _X -> % This process is not expecting anything! - side_effect_logger_proc_2() - end. -%% ------------------------------------------------------------------------------ diff --git a/lib/runtime_tools/test/inviso_testmodule1_foo.erl b/lib/runtime_tools/test/inviso_testmodule1_foo.erl deleted file mode 100644 index a7a22cad39..0000000000 --- a/lib/runtime_tools/test/inviso_testmodule1_foo.erl +++ /dev/null @@ -1,9 +0,0 @@ --module(inviso_testmodule1_foo). - --compile(export_all). - -%% The purpose of this module is simply to have a module that is -%% guaranteed not loaded. - -foo() -> - true. diff --git a/lib/runtime_tools/test/msacc_SUITE.erl b/lib/runtime_tools/test/msacc_SUITE.erl new file mode 100644 index 0000000000..145a6d07fb --- /dev/null +++ b/lib/runtime_tools/test/msacc_SUITE.erl @@ -0,0 +1,132 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2014-2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +-module(msacc_SUITE). + +-include_lib("common_test/include/ct.hrl"). + +%% Test server callbacks +-export([suite/0, all/0]). + +%% Test cases +-export([ + %% API-test + api_file/1, + api_start_stop/1, + api_timer/1, + api_print/1 + ]). + +%%-------------------------------------------------------------------- +%% COMMON TEST CALLBACK FUNCTIONS +%%-------------------------------------------------------------------- +all() -> + [ + api_start_stop, + api_file, + api_timer, + api_print + ]. + +suite() -> [ + {timetrap,{minutes,1}}, + {ct_hooks,[ts_install_cth]} + ]. + +%%-------------------------------------------------------------------- +%% TEST CASES +%%-------------------------------------------------------------------- + +api_timer(_Config) -> + + %% Run msacc for about 100ms + msacc:start(100), + + %% Verify that scheduler 1 executed+slept for about 100ms + [Sched1] = [S || S = #{ type := scheduler, id := 1 } <- msacc:stats()], + + #{ counters := Cnt } = Sched1, + + %% Time should be in us + Time = maps:fold(fun(_,V,Acc) -> V + Acc end, 0, Cnt), + + if Time < 120000 andalso Time > 80000 -> ok; + true -> ct:fail({inaccurate_time, Time, msacc:stats()}) + end. + +%% We just do a basic check that none of the apis crash +api_start_stop(_Config) -> + msacc:start(), + timer:sleep(100), + msacc:stop(), + Runtime = msacc:stats(system_runtime, msacc:stats()), + Realtime = msacc:stats(system_realtime, msacc:stats()), + true = Runtime < Realtime, + + RuntimeCnt = msacc:stats(runtime, msacc:stats()), + RealtimeCnt = msacc:stats(realtime, msacc:stats()), + TypeCnt = msacc:stats(type, msacc:stats()), + + %% These should be very similar + RuntimeTypeCnt = msacc:stats(type, RuntimeCnt), + TypeRuntimeCnt = msacc:stats(runtime, TypeCnt), + lists:map(fun({#{ system := T1 },#{ system := T2}}) -> + if T1-0.5 < T2 orelse T1+0.5 > T2 -> ok; + true -> ct:fail({inaccurate_stats, RuntimeTypeCnt, + TypeRuntimeCnt}) + end + end, lists:zip(RuntimeTypeCnt, TypeRuntimeCnt)), + + %% These should be very similar + RealtimeTypeCnt = msacc:stats(type, RealtimeCnt), + TypeRealtimeCnt = msacc:stats(realtime, TypeCnt), + lists:map(fun({#{ system := T1 },#{ system := T2}}) -> + if T1-0.5 < T2 orelse T1+0.5 > T2 -> ok; + true -> ct:fail({inaccurate_stats, RealtimeTypeCnt, + TypeRealtimeCnt}) + end + end,lists:zip(RealtimeTypeCnt, TypeRealtimeCnt)), + + msacc:reset(). + +api_file(Config) -> + PrivDir = proplists:get_value(priv_dir, Config), + File = filename:join(PrivDir, "msacc.stats"), + Stats = msacc:stats(), + ok = msacc:to_file(File), + Stats = msacc:from_file(File), + + PrintFile = filename:join(PrivDir, "msacc.txt"), + msacc:print(PrintFile, Stats, #{}). + +%% We just check that it is possible to print in a couple of different ways +api_print(_Config) -> + msacc:start(100), + io:format("msacc:print(msacc:stats()).~n"), + msacc:print(msacc:stats()), + io:format("msacc:print(msacc:stats(),#{ system => true }).~n"), + msacc:print(msacc:stats(), #{ system => true }), + io:format("msacc:print(msacc:stats(runtime,msacc:stats())).~n"), + msacc:print(msacc:stats(runtime, msacc:stats())), + io:format("msacc:print(msacc:stats(type,msacc:stats())).~n"), + msacc:print(msacc:stats(type, msacc:stats())), + io:format("msacc:print(msacc:stats(realtime,msacc:stats())).~n"), + msacc:print(msacc:stats(realtime, msacc:stats())), + io:format("msacc:stats(type,msacc:stats(runtime,msacc:stats())).~n"), + msacc:print(msacc:stats(type, msacc:stats(runtime, msacc:stats()))). diff --git a/lib/runtime_tools/test/runtime_tools_SUITE.erl b/lib/runtime_tools/test/runtime_tools_SUITE.erl index b26f3dd881..6877e1a379 100644 --- a/lib/runtime_tools/test/runtime_tools_SUITE.erl +++ b/lib/runtime_tools/test/runtime_tools_SUITE.erl @@ -1,69 +1,52 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2011. All Rights Reserved. +%% Copyright Ericsson AB 2010-2016. All Rights Reserved. %% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at %% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. %% %% %CopyrightEnd% %% -module(runtime_tools_SUITE). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). %% Test server specific exports --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2]). --export([init_per_testcase/2, end_per_testcase/2]). +-export([all/0, suite/0]). %% Test cases --export([app_file/1]). - -%% Default timetrap timeout (set in init_per_testcase) --define(default_timeout, ?t:minutes(1)). - -init_per_testcase(_Case, Config) -> - Dog = test_server:timetrap(?default_timeout), - [{watchdog, Dog} | Config]. - -end_per_testcase(_Case, Config) -> - Dog = ?config(watchdog, Config), - ?t:timetrap_cancel(Dog), - ok. +-export([app_file/1, appup_file/1, start_stop_app/1]). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap, {minutes, 1}}]. all() -> - [app_file]. + [app_file, + appup_file, + start_stop_app]. -groups() -> - []. -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> +app_file(_Config) -> + ok = test_server:app_test(runtime_tools), ok. -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. +appup_file(_Config) -> + ok = test_server:appup_test(runtime_tools). - -app_file(suite) -> - []; -app_file(doc) -> - ["Testing .app file"]; -app_file(Config) when is_list(Config) -> - ?line ok = ?t:app_test(runtime_tools), - ok. +start_stop_app(_Config) -> + ok = application:start(runtime_tools), + Sup = whereis(runtime_tools_sup), + true = is_pid(Sup), + Ref = erlang:monitor(process,Sup), + ok = application:stop(runtime_tools), + receive {'DOWN', Ref, process, Sup, shutdown} -> ok end. diff --git a/lib/runtime_tools/test/system_information_SUITE.erl b/lib/runtime_tools/test/system_information_SUITE.erl new file mode 100644 index 0000000000..a5a025a1cf --- /dev/null +++ b/lib/runtime_tools/test/system_information_SUITE.erl @@ -0,0 +1,307 @@ +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2013. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +%% + +-module(system_information_SUITE). + +-include_lib("common_test/include/ct.hrl"). + +%% Test server callbacks +-export([suite/0, all/0, groups/0, + init_per_suite/1, end_per_suite/1, + init_per_group/2, end_per_group/2, + init_per_testcase/2, end_per_testcase/2]). + +%% Test cases +-export([ + %% API-test + api_report/1, + api_to_file/1, + api_from_file/1, + sanity_check/1, + %% server + api_start_stop/1, + validate_server_interface/1 + ]). + +%%-------------------------------------------------------------------- +%% COMMON TEST CALLBACK FUNCTIONS +%%-------------------------------------------------------------------- +%%-------------------------------------------------------------------- +%% Function: groups() -> [Group] +%% +%% Group = {GroupName,Properties,GroupsAndTestCases} +%% GroupName = atom() +%% The name of the group. +%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}] +%% Group properties that may be combined. +%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase] +%% TestCase = atom() +%% The name of a test case. +%% Shuffle = shuffle | {shuffle,Seed} +%% To get cases executed in random order. +%% Seed = {integer(),integer(),integer()} +%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail | +%% repeat_until_any_ok | repeat_until_any_fail +%% To get execution of cases repeated. +%% N = integer() | forever +%% +%% Description: Returns a list of test case group definitions. +%%-------------------------------------------------------------------- +groups() -> + []. + +%%-------------------------------------------------------------------- +%% Function: all() -> GroupsAndTestCases | {skip,Reason} +%% +%% GroupsAndTestCases = [{group,GroupName} | TestCase] +%% GroupName = atom() +%% Name of a test case group. +%% TestCase = atom() +%% Name of a test case. +%% Reason = term() +%% The reason for skipping all groups and test cases. +%% +%% Description: Returns the list of groups and test cases that +%% are to be executed. +%%-------------------------------------------------------------------- +all() -> [ + api_report, + api_to_file, + api_from_file, + api_start_stop, + validate_server_interface, + sanity_check + ]. + + +%%-------------------------------------------------------------------- +%% Function: suite() -> Info +%% +%% Info = [tuple()] +%% List of key/value pairs. +%% +%% Description: Returns list of tuples to set default properties +%% for the suite. +%% +%% Note: The suite/0 function is only meant to be used to return +%% default data values, not perform any other operations. +%%-------------------------------------------------------------------- +suite() -> [ + {timetrap,{minutes,1}}, + {ct_hooks,[ts_install_cth]} + ]. + +%%-------------------------------------------------------------------- +%% Function: init_per_suite(Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% +%% Config0 = Config1 = [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Reason = term() +%% The reason for skipping the suite. +%% +%% Description: Initialization before the suite. +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_suite(Config0) -> void() | {save_config,Config1} +%% +%% Config0 = Config1 = [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Description: Cleanup after the suite. +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_group(GroupName, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% +%% GroupName = atom() +%% Name of the test case group that is about to run. +%% Config0 = Config1 = [tuple()] +%% A list of key/value pairs, holding configuration data for the group. +%% Reason = term() +%% The reason for skipping all test cases and subgroups in the group. +%% +%% Description: Initialization before each test case group. +%%-------------------------------------------------------------------- +init_per_group(_GroupName, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_group(GroupName, Config0) -> +%% void() | {save_config,Config1} +%% +%% GroupName = atom() +%% Name of the test case group that is finished. +%% Config0 = Config1 = [tuple()] +%% A list of key/value pairs, holding configuration data for the group. +%% +%% Description: Cleanup after each test case group. +%%-------------------------------------------------------------------- +end_per_group(_GroupName, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_testcase(TestCase, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% +%% TestCase = atom() +%% Name of the test case that is about to run. +%% Config0 = Config1 = [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Reason = term() +%% The reason for skipping the test case. +%% +%% Description: Initialization before each test case. +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%%-------------------------------------------------------------------- +init_per_testcase(_TestCase, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_testcase(TestCase, Config0) -> +%% void() | {save_config,Config1} | {fail,Reason} +%% +%% TestCase = atom() +%% Name of the test case that is finished. +%% Config0 = Config1 = [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Reason = term() +%% The reason for failing the test case. +%% +%% Description: Cleanup after each test case. +%%-------------------------------------------------------------------- +end_per_testcase(_TestCase, _Config) -> + ok. + + +%%-------------------------------------------------------------------- +%% TEST CASES +%%-------------------------------------------------------------------- + +%%-------------------------------------------------------------------- +%% Function: TestCase(Config0) -> +%% ok | exit() | {skip,Reason} | {comment,Comment} | +%% {save_config,Config1} | {skip_and_save,Reason,Config1} +%% +%% Config0 = Config1 = [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% Reason = term() +%% The reason for skipping the test case. +%% Comment = term() +%% A comment about the test case that will be printed in the html log. +%% +%% Description: Test case function. (The name of it must be specified in +%% the all/0 list or in a test case group for the test case +%% to be executed). +%%-------------------------------------------------------------------- + + +api_report(_Config) -> + Report = system_information:report(), + ok = validate_report(Report), + ok. + +api_to_file(Config) -> + DataDir = proplists:get_value(data_dir, Config), + Filename = filename:join([DataDir, "system_information_report_1.dat"]), + ok = system_information:to_file(Filename), + {ok, _} = file:consult(Filename), + {save_config, [{report_name, Filename}]}. + +api_from_file(Config) -> + {api_to_file, Saved} = proplists:get_value(saved_config, Config), + DataDir = proplists:get_value(data_dir, Config), + Fname1 = filename:join([DataDir, "information_test_report.dat"]), + Report1 = system_information:from_file(Fname1), + ok = validate_report(Report1), + Fname2 = proplists:get_value(report_name, Saved), + Report2 = system_information:from_file(Fname2), + ok = validate_report(Report2), + ok. + +api_start_stop(_Config) -> + {ok, _} = system_information:start(), + ok = system_information:stop(), + ok. + +validate_server_interface(Config) -> + DataDir = proplists:get_value(data_dir, Config), + Fname1 = filename:join([DataDir, "information_test_report.dat"]), + %% load old report + ok = system_information:load_report(file, Fname1), + ok = validate_loaded_report(), + ok = system_information:stop(), + %% load local + ok = system_information:load_report(), + ok = validate_loaded_report(), + ok = system_information:stop(), + ok. + +sanity_check(Config) when is_list(Config) -> + ok = system_information:sanity_check(). + + +%% aux + +validate_loaded_report() -> + ok = system_information:applications(), + ok = system_information:applications([full]), + ok = system_information:environment(), + ok = system_information:environment([full]), + ok = system_information:application(kernel), + ok = system_information:application(kernel,[full]), + ok = system_information:module(gen_server), + ok = system_information:module(gen_server,[full]), + ok = system_information:modules(native), + ok. + + +validate_report([]) -> {error, no_entries}; +validate_report(Report) -> + ensure_report_keys([ + init_arguments, + code_paths, + code, + system_info, + erts_compile_info, + beam_dynamic_libraries, + environment_erts, + environment, + sanity_check + ], Report). + +ensure_report_keys([], _) -> ok; +ensure_report_keys([K|Ks], Report) -> + case lists:keysearch(K, 1, Report) of + false -> {error, key_not_found, K}; + _ -> ensure_report_keys(Ks, Report) + end. + diff --git a/lib/runtime_tools/test/system_information_SUITE_data/information_test_report.dat b/lib/runtime_tools/test/system_information_SUITE_data/information_test_report.dat new file mode 100644 index 0000000000..bdc510e838 --- /dev/null +++ b/lib/runtime_tools/test/system_information_SUITE_data/information_test_report.dat @@ -0,0 +1,9875 @@ +{system_information_version, "1.0"}. +{system_information, [{init_arguments, + [{root, + ["/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp"]}, + {progname,["erl"]}, + {home,["/home/otptest"]}]}, + {code_paths, + [".", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/kernel-2.16.3/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/stdlib-1.19.3/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/xmerl-1.3.3/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/wx-1.0/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/webtool-0.8.9.2/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/typer-0.9.5/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/tv-2.1.4.10/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/tools-2.6.11/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/toolbar-1.4.2.3/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/test_server-3.6.2/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/syntax_tools-1.6.11/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/ssl-5.3/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/ssh-2.1.7/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/snmp-4.24/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/sasl-2.3.2/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/runtime_tools-1.8.11/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/reltool-0.6.4/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/public_key-0.19/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/pman-2.7.1.4/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/percept-0.8.8.1/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/parsetools-2.0.9/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/otp_mibs-1.0.8/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/os_mon-2.2.12/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/orber-3.6.26.1/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/odbc-2.10.16/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/observer-1.3.1/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/mnesia-4.9/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/megaco-3.17.0.1/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/jinterface-1.5.8", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/inets-5.9.5/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/ic-4.3.2/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/hipe-3.10.2/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/gs-1.5.15.2/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/eunit-2.2.4/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/et-1.4.4.4/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/erts-5.10.3/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/erl_interface-3.7.13", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/erl_docgen-0.3.4/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/eldap-1.0.1/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/edoc-0.7.12/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/diameter-1.4.2/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/dialyzer-2.6.1/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/debugger-3.2.11/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/crypto-3.0/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/cosTransactions-1.2.13/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/cosTime-1.1.13/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/cosProperty-1.1.16/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/cosNotification-1.1.20/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/cosFileTransfer-1.1.15/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/cosEventDomain-1.1.13/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/cosEvent-2.1.14/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/compiler-4.9.2/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/common_test-1.7.2/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/asn1-2.0.2/ebin", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/appmon-2.1.14.2/ebin"]}, + {code, + [{code,[{path,"."},{modules,[]}]}, + {application, + {kernel, + [{description,"ERTS CXC 138 10"}, + {vsn,"2.16.3"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/kernel-2.16.3/ebin"}, + {modules, + [{application, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"69c3102d717e7258701a536ddae1eb89"}]}, + {application_controller, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1bbfd81a8486ac040562ce0fd40c32aa"}]}, + {application_master, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d8eee82bfd661e8f0d862f3aad5b85ca"}]}, + {application_starter, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d505f3189443053e586fdf270446ce2f"}]}, + {auth, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"800c93bf9ba03b6e4951de0d5db28328"}]}, + {code, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"84f37378526c5e82c5d0d967c1ca8f82"}]}, + {code_server, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"09ce0ef7103f3151553c6badc7e96fc1"}]}, + {disk_log, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a5ab0573095f258c87f6166af8f8425c"}]}, + {disk_log_1, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"287f2521436a30a0567d54e2596c1034"}]}, + {disk_log_server, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4c7972e5f3dedce5c87cf8ef88c59bb2"}]}, + {disk_log_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c6012237e70b570585bfb58f60537d9c"}]}, + {dist_ac, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4dfa17c94d63da8f6b9edb1532a3e537"}]}, + {dist_util, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8fa19e7b4bca4b5aac847d138c85c553"}]}, + {erl_boot_server, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"86ecca01e41b2321c01b7181cb826766"}]}, + {erl_ddll, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"90f1c7a6fd3cf6595d95b9f57abd87ce"}]}, + {erl_distribution, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"16a49a506b48567bd32b2021dac425ff"}]}, + {erl_epmd, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"eee4870e061790054c43ff70bbccbe25"}]}, + {erl_reply, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0e0a4f09b0877938b4d79b41122dad38"}]}, + {error_handler, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1af2b51d167b017b3e1fae0beb408181"}]}, + {error_logger, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"941136b080021af90dc32f23774b0def"}]}, + {erts_debug, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e2a7b675323db5946605344ffccca170"}]}, + {file, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5eccb55276e7162ab5bec77b46562332"}]}, + {file_io_server, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"032292fd7d9e2bf08ff23de192710f97"}]}, + {file_server, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"58bd1e532dee0fccff9e1fba1e429a5e"}]}, + {gen_sctp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f1e5e5a8c7708c9a81f26d2a89e3987c"}]}, + {gen_tcp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4cf58918602a7242ca4060bc1d6b5652"}]}, + {gen_udp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"361b9b25604b9053a8a4c98b8df47408"}]}, + {global, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e553137965978f64ffb9ef274c79e9c2"}]}, + {global_group, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8ce6b230fef9340aeb41205a6ef4b4f3"}]}, + {global_search, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0a82f2701d71d2a1576074dd69414e1b"}]}, + {group, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6b3164d5d61625f0651c13107459627c"}]}, + {heart, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b808d9003cf50d73ebf888da50d73e12"}]}, + {hipe_unified_loader, + [{loaded,true}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"879423975936fcf88729034f7d4a93b6"}]}, + {inet, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bd325ceedcab3ca885eeaf4c982561e0"}]}, + {inet6_sctp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d8b6d95ec571f5e669047b5f40455d21"}]}, + {inet6_tcp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"93a9204ef927b17957c61a18f3ba47e2"}]}, + {inet6_tcp_dist, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9a94acd2c5dc0e625d2c2b4292e9a27a"}]}, + {inet6_udp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"17a90b344977dd2c657309507c99b516"}]}, + {inet_config, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"741587fa47d6b66b96ef125b3d5ba61a"}]}, + {inet_db, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f65160805d30ff194618a5ae4038ae9f"}]}, + {inet_dns, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7f0c31b6cecf31d641bf46840f85ebee"}]}, + {inet_gethost_native, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"09867d1d19f3c30b73fb47a48d0d843a"}]}, + {inet_hosts, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a0f48322bd3a1bd0e75f248e39b41f69"}]}, + {inet_parse, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"29aee7378a4d1f814e1fd311d0eaab3a"}]}, + {inet_res, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c1018a662254323cfa45309afb3b3397"}]}, + {inet_sctp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cbce09a1ffa13cb124d87eaecd25dfbf"}]}, + {inet_tcp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0da6499cb44db53be6145a5dc3449d93"}]}, + {inet_tcp_dist, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"797e28cd89efe3a1a9d83244afd0b880"}]}, + {inet_udp, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"70908d7165a2b298a85d9a4c1f8f9fa2"}]}, + {kernel, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cf5c248b778654e664e6d2368ec285df"}]}, + {kernel_config, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"39fbe27956eeb0cca9d7871f7de40a2e"}]}, + {net, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cb8595f084959a2b5e329ab32047dbc4"}]}, + {net_adm, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"628c961d8dbbab4c5b2b180e527530be"}]}, + {net_kernel, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"049f43826000bfefbbc2376bd21c9919"}]}, + {os, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"464c6c09afb87824ecf12bfa6065b3dc"}]}, + {pg2, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"34858fa3619c1dc17d01536593359ed2"}]}, + {ram_file, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"28bf8253c5f8357ab68b4d505e170856"}]}, + {rpc, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"895e080302ac8a39197dfac0cc53adc6"}]}, + {seq_trace, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"845af954b395a80e5cf3d0c2ea0a3b99"}]}, + {standard_error, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c0ac4192fd9f73885581481638c1648a"}]}, + {user, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"93ad1841fa2dee776bff76f8989f5021"}]}, + {user_drv, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"161f1a45735f77129c80bacd778e5632"}]}, + {user_sup, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"baab537a62725bcbe4510c9f0b2d99eb"}]}, + {wrap_log_reader, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5dceb6e671d0c51d181f51ec4e031798"}]}]}]}}, + {application, + {stdlib, + [{description,"ERTS CXC 138 10"}, + {vsn,"1.19.3"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/stdlib-1.19.3/ebin"}, + {modules, + [{array, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c7c98b180715bd79794eef21a2930fff"}]}, + {base64, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e45b571f2414c6131fbf62b1da3560e5"}]}, + {beam_lib, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9e13b050aff529ecac6569f7101237ba"}]}, + {binary, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1e77ffd0688b3f1ace1ac70936969da3"}]}, + {c, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"402465a98ccec8e9314139daacf6203e"}]}, + {calendar, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0c09413575ac7f80ea3d9217b1f7e1bc"}]}, + {dets, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5154c82c2ffefa19096cf87ffb394a6c"}]}, + {dets_server, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c810e731ba4101aba5f6b6c08481ea85"}]}, + {dets_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9b4a9ef0f616b7c5464cf6813384e220"}]}, + {dets_utils, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a64e0220f855e6e97d53a9bc4f0a111b"}]}, + {dets_v8, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ebf2c94f62d180c3159b663ba2094189"}]}, + {dets_v9, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9098391234b6304ff3d106dc56d467b6"}]}, + {dict, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0bc1d74a65bd392960cd7e1b230f07bf"}]}, + {digraph, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ac9049d6d7454a87c40c2f03f4223849"}]}, + {digraph_utils, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"17bbe67d3314e9024825512c1ccc7be8"}]}, + {edlin, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"518247b4963c998e742c0794091c9864"}]}, + {edlin_expand, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"06c4ff7cf326df872bec9feed7f5984d"}]}, + {epp, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"493760bc942ddd16df2a8e55f8b59774"}]}, + {erl_bits, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bba2a00b28557c9678356247c36b0474"}]}, + {erl_compile, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"291c9ddceeb66c7a7c36ab3505799513"}]}, + {erl_eval, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9982f2bca01a352a45932a6db95a1336"}]}, + {erl_expand_records, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"047c93973c9fbf83724cdf688e258cff"}]}, + {erl_internal, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3225aadc9ec4f84cc9451f30833cdefb"}]}, + {erl_lint, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"98ffb79824edc0f2a8ad49ff447e121c"}]}, + {erl_parse, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f9a3d97b028bafa2bba7037bc1987d87"}]}, + {erl_posix_msg, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ecb0903ecde21b7cc58277424d8bac3d"}]}, + {erl_pp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1b7945b193daf989e3f62c4a452f773e"}]}, + {erl_scan, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1dd9fb779b35d1925a0ad68c092af1f0"}]}, + {erl_tar, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0c6161b31a69bd3566a910d369baae00"}]}, + {error_logger_file_h, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"218156df9bdedd04e37eecc76863940c"}]}, + {error_logger_tty_h, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a2cac9386113d6879a4111be3e2d191b"}]}, + {escript, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b77d5172cf00acd06fd6e42f03dc9b06"}]}, + {ets, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"13c77916ba3c85e6e076aa0664f5674f"}]}, + {eval_bits, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7bf8829d056519787fd0f7900bd04b73"}]}, + {file_sorter, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4e31c9ca53e59010980dfc4e46e8aaf1"}]}, + {filelib, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"641651ced98857991b064b22c85cf90f"}]}, + {filename, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9a007021a1e9de6af67e99cc48be13c5"}]}, + {gb_sets, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4891f6d98f4bb81bc64415434d08ff9d"}]}, + {gb_trees, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4e9a8ae86761c41dc0e9d32f57df63c3"}]}, + {gen, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5beaa9b295439aa39187eeef56b8527b"}]}, + {gen_event, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"79bc1c9f72e633331d4518d982221af0"}]}, + {gen_fsm, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fb95e4cf29f5cf640e486c789fe9f1f7"}]}, + {gen_server, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"14f189569fb6420c633a5dab81f7b897"}]}, + {io, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"75fd9a0dc5823e95b4543a09be83c6ce"}]}, + {io_lib, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"34c18dd02ec6458cae20ddc323542eed"}]}, + {io_lib_format, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f1f8f2a4d12d79d82420335d0e84107a"}]}, + {io_lib_fread, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"27699e322a2de2004b057465f549fa3f"}]}, + {io_lib_pretty, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"32d7bae40549bdd60298c0d17efe057b"}]}, + {lib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"394b1b967c909d1830939846963ac4f0"}]}, + {lists, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f840b76db5f9e5d37dcc9dc39a436b90"}]}, + {log_mf_h, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6f972dea76e360d99074b659327db69f"}]}, + {math, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fe02e030a198ec343f3c4a62f60ebf8a"}]}, + {ms_transform, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"dba72a603f0a9382274671842d6aaf55"}]}, + {orddict, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bedb6cdaf10530b2486b46f79853fbea"}]}, + {ordsets, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f5dfe0e73da077c2f86dbbe846e0dab7"}]}, + {otp_internal, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ff3edabfa0633b9553b6fed1e47e41fc"}]}, + {pg, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c3975b993694a2a465d331278b503f81"}]}, + {pool, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3d0398428064137474f5acbb4122a70d"}]}, + {proc_lib, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5542f4add07ef7bb54a76b0cdfa542ba"}]}, + {proplists, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5723876c3ed585a5a4b10dc3aefaf170"}]}, + {qlc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"75df6efc99d9a75bb4c989985125d3da"}]}, + {qlc_pt, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e84b6da8fb84f811f2c58365e59dd47f"}]}, + {queue, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"221ed57d299c2281992706fd6e2c6584"}]}, + {random, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e703cb7ee27e2e23baf924c2f6b29f50"}]}, + {re, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6eef786ed4f4dfec57a568e488e3596d"}]}, + {sets, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c4fbf3b29bf971465a8dc4077fc3e7c8"}]}, + {shell, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c4fdd7e1d18047b5f086b6fe8730c896"}]}, + {shell_default, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5a94fd884c9594ff9056228503cd2731"}]}, + {slave, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f5536e71d137302d699982fc65b9d025"}]}, + {sofs, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"10f13cd4626d429897246538c02c2cb4"}]}, + {string, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d7440fe2e1838223f877286bf7d8f2a4"}]}, + {supervisor, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"29c98bf9e58cc955d4c29d881d98e84f"}]}, + {supervisor_bridge, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f58b58a1fefecc46a476490ef5231d7e"}]}, + {sys, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7afd9c746450e5189048ff3635b37926"}]}, + {timer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fa3e2b017848accc808f92910abf87b8"}]}, + {unicode, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"be45160097c37c9144169f4ba54e0128"}]}, + {win32reg, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9f59ec1a4af1e6381d8770fc2c5915e4"}]}, + {zip, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bc9aab95b5fc9ee7e534e890d8e5516c"}]}]}]}}, + {application, + {xmerl, + [{description,"XML parser"}, + {vsn,"1.3.3"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/xmerl-1.3.3/ebin"}, + {modules, + [{xmerl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1eabeb9846b832059537e2bdf6fed2d2"}]}, + {xmerl_b64Bin, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"62075ae2d95f3188143a41f582542bf9"}]}, + {xmerl_b64Bin_scan, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bd99982371c4db3baf4883c96e146c96"}]}, + {xmerl_eventp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"99aad15d2ad4be80d580fe7e3ba4178f"}]}, + {xmerl_html, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f79915eaadae7d92946f1182110e6f81"}]}, + {xmerl_lib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"91fe55408e50bf92a9f8ef8b402a3e51"}]}, + {xmerl_otpsgml, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f2e027e7204405c168eaa598a6a4d476"}]}, + {xmerl_regexp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"408f3ffbd843e09ed0326f5e6a72356e"}]}, + {xmerl_sax_old_dom, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"66b229f3eec3dce1f8754de256ba8d1d"}]}, + {xmerl_sax_parser, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"66e80c0d03a583d22abc40a54096777c"}]}, + {xmerl_sax_parser_latin1, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e2a462359d6765811f41b1ac1260c81a"}]}, + {xmerl_sax_parser_list, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"db56224dbccdf302e42479027c3f961b"}]}, + {xmerl_sax_parser_utf16be, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"aaa379b8f1008944bd486f29a85ab1c2"}]}, + {xmerl_sax_parser_utf16le, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"027d5c2218de2a7dd6f5db3b1c433a74"}]}, + {xmerl_sax_parser_utf8, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"40f970e9b4eb4122589c0afec6b8907d"}]}, + {xmerl_sax_simple_dom, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2c08dc40f819e4972a58a2fb2fcf6239"}]}, + {xmerl_scan, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0afb5a6c37db1b5dd100297a149d9f8a"}]}, + {xmerl_sgml, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"22933821d58054ab2941678ce2f8a298"}]}, + {xmerl_simple, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8c83463864e0c2117c7659aae4e6ae50"}]}, + {xmerl_text, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"661d77ea6d07fe6281f04e8e553528d4"}]}, + {xmerl_ucs, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8ace187d193a5314fbe329eba939dcf0"}]}, + {xmerl_uri, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1121ced96856184d51daecddbb4b562f"}]}, + {xmerl_validate, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fe1eb20e24d92db08eb03a7a3fbbd73a"}]}, + {xmerl_xlate, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2515e06ee34909465fb4520f199f5a46"}]}, + {xmerl_xml, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e04d0e513bb48336b9e69de89208e97c"}]}, + {xmerl_xpath, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"02a4e2d946ffe93e960c66ce0d391628"}]}, + {xmerl_xpath_lib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d6531ac82f1524946a0a31f40a90546d"}]}, + {xmerl_xpath_parse, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7b3bd078c12f46cf5154d05c49880058"}]}, + {xmerl_xpath_pred, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e2a7d97114507d23ad8cfdf967fd656f"}]}, + {xmerl_xpath_scan, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1d43883f65aa0006900fc053453d1bd2"}]}, + {xmerl_xs, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6963383b4148fd4a7d51bf8e54b79640"}]}, + {xmerl_xsd, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4660a75a540225ba8a88c00914923507"}]}, + {xmerl_xsd_type, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"be422d840d07c53b8ba210889dd5d308"}]}]}]}}, + {application, + {wx, + [{description,"Yet another graphics system"}, + {vsn,"1.0"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/wx-1.0/ebin"}, + {modules, + [{gl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2b2c807a7fbd4012871027dd4292448b"}]}, + {glu, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"28a23cf86e317c54ebd1b609b38f2fe3"}]}, + {wx, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"854481fd306d90c1fe6ad683045a1d98"}]}, + {wxAcceleratorEntry, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3d7572b3e8662e26666964cc64ff7b90"}]}, + {wxAcceleratorTable, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a261f6c3e0d571493a46fcd40b0361f7"}]}, + {wxArtProvider, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"22bc145a24e52e15d6e0f66e3f057df7"}]}, + {wxAuiDockArt, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"22fca5ae251c6592dda5b08c0688138a"}]}, + {wxAuiManager, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6f87b4fc280d820edca4655bfc0388bd"}]}, + {wxAuiManagerEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d08f2847271aae031ed49a0cab96e8f1"}]}, + {wxAuiNotebook, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4b055991aa4efef19c59653db60d611e"}]}, + {wxAuiNotebookEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f9fc2a85bda82dc6406833d3746a1313"}]}, + {wxAuiPaneInfo, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"96dc39e65e2d04e597a76663651cbe45"}]}, + {wxAuiTabArt, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0641080a257e4c0ce7030d7a404ea965"}]}, + {wxBitmap, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"62ddedace917fe7d65ebfdd968e2b442"}]}, + {wxBitmapButton, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"676cbd0f421681f3cdb110b08b89cdf4"}]}, + {wxBitmapDataObject, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9ab868e8a18350bb427d08abd31d805c"}]}, + {wxBoxSizer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8f30f0ad197cd2fe6bb6956ecf55009e"}]}, + {wxBrush, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f41534b5b14c0528729f3faba6d97e1d"}]}, + {wxBufferedDC, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"14bd8d1184f57ca3b71ae50c396b8fb6"}]}, + {wxBufferedPaintDC, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b617bb74c090fd1bedd78a44e87620df"}]}, + {wxButton, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cee0c2cf94d454426067a18f222b5175"}]}, + {wxCalendarCtrl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"684d559165e957aac543b2f75db8821a"}]}, + {wxCalendarDateAttr, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d3406fdefafb1e56b3b4b0c049e8f306"}]}, + {wxCalendarEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"deb02e8741160ee9f1a44853db16a6d3"}]}, + {wxCaret, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"543d4a99c593ac822143cc4c680fbe10"}]}, + {wxCheckBox, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ae5b445190e6d0811bc3bf41c269ad7a"}]}, + {wxCheckListBox, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"094de5ba936cca4c26ffc0b765d371be"}]}, + {wxChildFocusEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d4d29ee311555ab76419724546859432"}]}, + {wxChoice, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b7e31246a035375896498e17c366beaa"}]}, + {wxChoicebook, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"32665c0637a00816a2fff4d4f5f418c1"}]}, + {wxClientDC, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"400fdcc0f51e0e5043be4ca4da99a8a7"}]}, + {wxClipboard, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4ddbb8e1f11321204d48d247e9f7548b"}]}, + {wxCloseEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"815ac954da8b6cb7b694ca4cb28ccd50"}]}, + {wxColourData, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"84cf04d6327af73aabd2f775d16bac5d"}]}, + {wxColourDialog, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d8e90d5109efec91ee6417d01b929951"}]}, + {wxColourPickerCtrl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e7fb673975f4cfa9946c34e30109d036"}]}, + {wxColourPickerEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2cfa29b0fce7f98058c3d5ad016c1f2f"}]}, + {wxComboBox, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b2aa520b9051f42a5e0f1ce1c6408101"}]}, + {wxCommandEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e5fed22a39c6c80dcc029ebe5444b0c0"}]}, + {wxContextMenuEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0a1739b84b365833c87232bfb298f681"}]}, + {wxControl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"aed7a496290caa0b53740c681de998ec"}]}, + {wxControlWithItems, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a14351fadd0f776a4deeaf5ec518a689"}]}, + {wxCursor, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"79eadaef3d9df7bae0a2146634d43e72"}]}, + {wxDC, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3f88cfd62f368172c3ed90684df53ba3"}]}, + {wxDataObject, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"065ea6f1e76ca8b6558ca3dd7ff42077"}]}, + {wxDateEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"56c06074946764fbc74b7070f5759e19"}]}, + {wxDatePickerCtrl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c716525fffbc864c85159fb43b2a8d64"}]}, + {wxDialog, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1a480a0c1690092014cf8198ba52d2a3"}]}, + {wxDirDialog, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"43565cc473a21632555cb3151138b7c0"}]}, + {wxDirPickerCtrl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6463e54c6564a1f7f5d6bec082f9ea63"}]}, + {wxDisplayChangedEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1dbd9061f370f3db0343c4f88f57cfa3"}]}, + {wxEraseEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ff780a85a34cb23667b7e4072db17a2b"}]}, + {wxEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8644675e2fd7bbc6965d4babd0d14d7a"}]}, + {wxEvtHandler, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c0991f5d86247ce757145c326adea516"}]}, + {wxFileDataObject, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cd9b5735e3994492c32ca099a70093d0"}]}, + {wxFileDialog, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b9cb446535683e7a9258953f53cd77de"}]}, + {wxFileDirPickerEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6153d339ac822da8c4a9d766d0af22f9"}]}, + {wxFilePickerCtrl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5c9ff43ff739e3ee37aae637a494d7d3"}]}, + {wxFindReplaceData, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bccc5beebb4aa0bfd424d26f472745a6"}]}, + {wxFindReplaceDialog, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c40b557d35e4bc527a715996daad0e0c"}]}, + {wxFlexGridSizer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ed3da3c3822f59a6b2737f273397367d"}]}, + {wxFocusEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1c04cb018d6c94d24a44ae365dae46c1"}]}, + {wxFont, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"64303b1a35432898649e40e9c3f5bdd2"}]}, + {wxFontData, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0135398ad369de2fd9beda1553f7d309"}]}, + {wxFontDialog, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a872a3b88df4faa051e4b1f8cb0397a0"}]}, + {wxFontPickerCtrl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5e5b363ea487a4284714346d43d6c418"}]}, + {wxFontPickerEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a22e0effda4c521ce1b35bd5b2259758"}]}, + {wxFrame, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"168aac11a6c3835b122ee653ce2e50a0"}]}, + {wxGBSizerItem, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"857c0be340c9c324d39cd525749a7cf7"}]}, + {wxGLCanvas, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"88461209c2234e4e166923d760a42164"}]}, + {wxGauge, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4d998a1ffcf56ccf2ea3a12eabe375d9"}]}, + {wxGenericDirCtrl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c5f8f19f7fdf9545c1a08318a12782b8"}]}, + {wxGraphicsBrush, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9eeb08fd93c17259400e13b1586ef6ee"}]}, + {wxGraphicsContext, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bee681fb85f534a63c2747e704d9001d"}]}, + {wxGraphicsFont, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"be1d636aa381e330db93a1deb9ff4b13"}]}, + {wxGraphicsMatrix, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b452f9e3d87800b00e063b39d71583aa"}]}, + {wxGraphicsObject, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"64dba881c5b70355d45323363715ba69"}]}, + {wxGraphicsPath, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e93e67098fd350e7eb20ccc5f7287b30"}]}, + {wxGraphicsPen, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9c8c8c3cf5277cdc526dca9e591a10b0"}]}, + {wxGraphicsRenderer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4aeb3961b9b1a22263c8abf2473cc53f"}]}, + {wxGrid, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e1195ea11e71c0534fffa76535efefbf"}]}, + {wxGridBagSizer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"60ee2c7022f1feef9c169a191945d637"}]}, + {wxGridCellAttr, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"02222543db113d41d409cd4080764d49"}]}, + {wxGridCellBoolEditor, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"297c5d3648d99bef9bc294d52d28b619"}]}, + {wxGridCellBoolRenderer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5cf8954049f0443ea2f9003deae7960d"}]}, + {wxGridCellChoiceEditor, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b77d6b8cb344c4512cef8adaf23ef93b"}]}, + {wxGridCellEditor, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a5cf6065e8754f96612cff48a1fdcd20"}]}, + {wxGridCellFloatEditor, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"723baea27c999730afcacb3280f611c4"}]}, + {wxGridCellFloatRenderer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ab56332ebccd1245fff7cb86abfd670b"}]}, + {wxGridCellNumberEditor, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f0d86be445b03945610d9154c8905258"}]}, + {wxGridCellNumberRenderer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"28ae774386962927dd552da4e9a28ca1"}]}, + {wxGridCellRenderer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a6da61c7ff2464f3b007626b1f813dcb"}]}, + {wxGridCellStringRenderer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"aefd3b8019cc4321037c8bd8e4faeba2"}]}, + {wxGridCellTextEditor, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"dbce8b54a66e9a9869d84655ef26d908"}]}, + {wxGridEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7b41f04ffe42c4602fe2911b5ca44dbe"}]}, + {wxGridSizer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"37bfde707aa6f2a1f68f8377dcbd7580"}]}, + {wxHelpEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"714f8b000f3d09fe7eae13b1a5daa0c7"}]}, + {wxHtmlEasyPrinting, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"eaa59118b8408b91d16df3b600494e5e"}]}, + {wxHtmlLinkEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6f527856d02011b9f480494b2f3118f0"}]}, + {wxHtmlWindow, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"61e947b44d4ae81b9bb0faf9a443cbd3"}]}, + {wxIcon, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1b4d9209343a029641204f334bd07dc5"}]}, + {wxIconBundle, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3281d9d364552b38009405e79467d5c5"}]}, + {wxIconizeEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d66e4289534961f6868d91e1d1399b53"}]}, + {wxIdleEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fc82957c3a0181ef84ca78ace7a9271e"}]}, + {wxImage, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"25de92b502b3a920e1247d2d1433aa32"}]}, + {wxImageList, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3445492f371fe7d2a6f7534d61ad66a9"}]}, + {wxJoystickEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"15c7352ac168dc5adc0de4a872b9740c"}]}, + {wxKeyEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b2e23f50406c65d5f2269910467a9721"}]}, + {wxLayoutAlgorithm, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2f93e6eac8570144faabaea83388129a"}]}, + {wxListBox, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"87aade14ade89a7021b6908143d339f1"}]}, + {wxListCtrl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1e35643c3218ee7db6bf18dbd72bc470"}]}, + {wxListEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"90354ad1e09b594dd321bca68d8d3f02"}]}, + {wxListItem, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"be95e4c22e265fbcfb14ab7c9c798684"}]}, + {wxListItemAttr, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0137573b7a2b2569b481548c26bb91a9"}]}, + {wxListView, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c0022979dbcc2ac873adb72ea26c16aa"}]}, + {wxListbook, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0e4b01ad81bf68f1784ba30772502e0b"}]}, + {wxLogNull, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"17f8273288c6e880ec0c7a21842b022f"}]}, + {wxMDIChildFrame, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5894b4a01bb643f208995257a0f9a00f"}]}, + {wxMDIClientWindow, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fa7017cfb2e70f0492550a2ecd01d1c7"}]}, + {wxMDIParentFrame, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"251cf2044002bbb5afc2acddf442f14a"}]}, + {wxMask, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8b4ce241e6edd84d32df4b40a2f17a15"}]}, + {wxMaximizeEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e8a766afd7de5050ced825a275c6cdba"}]}, + {wxMemoryDC, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b4c1bb9fed0edf70b44f24ea3fb54f39"}]}, + {wxMenu, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d2e48cd879d0ece5ee24260bc70e2f9b"}]}, + {wxMenuBar, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"562e9979f8ce58c85032ae3e02307d7b"}]}, + {wxMenuEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0571277ab11e756d18d34c6cb4f8f1c0"}]}, + {wxMenuItem, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"900c9de70ac02a326bce22eec1c64d48"}]}, + {wxMessageDialog, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a15267b44d3cbeae16c294c4c0b96324"}]}, + {wxMiniFrame, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2ca0204b8a167fd472a555695e58927b"}]}, + {wxMirrorDC, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d521a1f1e4d37132a7a0de0eccc332f0"}]}, + {wxMouseCaptureChangedEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f85672fbf15ee0b8306de4aaf4eb4719"}]}, + {wxMouseEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"802c21f46105f957d8cd8c84ff36d986"}]}, + {wxMoveEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4231fd181e0b305a82c595f66eb99b96"}]}, + {wxMultiChoiceDialog, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4eb40bfa965a25034ebe4b8fca335863"}]}, + {wxNavigationKeyEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"04b113c9dcf181af633d0eae1f18c36f"}]}, + {wxNotebook, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fef44c082d799a4d86e0cd8db58609df"}]}, + {wxNotebookEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0ccae052bfd1cf87236add4c0b26143d"}]}, + {wxNotifyEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d3d22b2b86ce1a94c57ccd9842211f05"}]}, + {wxPageSetupDialog, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"755792c8d70118493f5147ef26f40d00"}]}, + {wxPageSetupDialogData, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"942f2c8bd296e971ea1d0f74ec700be5"}]}, + {wxPaintDC, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c23afeac816efecc5417b0687437d8cf"}]}, + {wxPaintEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a18ce83af679d334ce979df65607226c"}]}, + {wxPalette, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a5b3e165b8ac3e3cb2d5ba6e149bb0ca"}]}, + {wxPaletteChangedEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"785c765df0a50eac4b2c5c054453c0d9"}]}, + {wxPanel, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"08c772b8c30e7441366bcfcd5005f21d"}]}, + {wxPasswordEntryDialog, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"62b860fd64e74f7d67c51a5d8a0fb157"}]}, + {wxPen, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"51b981a9e2313e58123888c6b67192ed"}]}, + {wxPickerBase, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2ab9e2f2d6c3b5f8184d5b1d806b0dce"}]}, + {wxPostScriptDC, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8a820bdc1354c448a8b442016951a6b2"}]}, + {wxPreviewCanvas, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e7b48321129f0e14c2006272c8926544"}]}, + {wxPreviewControlBar, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"62393081a6ffcb6bf092b47703e31b4d"}]}, + {wxPreviewFrame, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"78f39bbfead1330839955a50281a2329"}]}, + {wxPrintData, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"928a6a97c5c4b664687015c40d660cdf"}]}, + {wxPrintDialog, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"acc4c816bf0a64c8ce31af3c001f1688"}]}, + {wxPrintDialogData, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fc97f97b620110928f4093806b1b8ce4"}]}, + {wxPrintPreview, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"92f04b064e7b041ee27bb202e5a60b80"}]}, + {wxPrinter, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"05626841c780ceaf3c5af0212f53fbaf"}]}, + {wxPrintout, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"feea26109fa63e4d98c2924189762a43"}]}, + {wxProgressDialog, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"eb45280951aef0038b8130c91a333833"}]}, + {wxQueryNewPaletteEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"be6c85603e81f7c90d4a949d42c0b32d"}]}, + {wxRadioBox, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"33684d6ce3f3c5388e6faf4f06d90463"}]}, + {wxRadioButton, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"92bebfd9b33658dcff2e592b5fcaeb7a"}]}, + {wxRegion, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"18cb5a2a1dcb63a646135f2a6cb1b21c"}]}, + {wxSashEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d4c51c14137513da9841890751deafd2"}]}, + {wxSashLayoutWindow, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f6f5167ff888b73c603b2f641e96a49f"}]}, + {wxSashWindow, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"91c5be41fbe95f5ad4504fae2f56f91f"}]}, + {wxScreenDC, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fc9411f49fe7324bcbace2c05d31d39a"}]}, + {wxScrollBar, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e60ffb44799a3684f74d783addbf42c9"}]}, + {wxScrollEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4fbd1eb49f69e56894aa4a7fb26e1b4b"}]}, + {wxScrollWinEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"be44e413061c515cb83a103a46572065"}]}, + {wxScrolledWindow, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ccef65f1430df907d9bd34c27408f9cb"}]}, + {wxSetCursorEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1aad98a9e1d08f792da0d73f23ceb7e5"}]}, + {wxShowEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"89a775b3e6579b8e55e35bc6a46649ef"}]}, + {wxSingleChoiceDialog, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f0df9c7367cbb88a21c8dbfcff668fed"}]}, + {wxSizeEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"78d4dff8fa58b02bd49c31b6de28b935"}]}, + {wxSizer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"581f4ba6c9b3befca1efbcd221455b49"}]}, + {wxSizerFlags, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"54ae0bf1305ef85943158c8f4bc58669"}]}, + {wxSizerItem, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ff2680fb6f057abf757516aa98e26281"}]}, + {wxSlider, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f1e0578ebbde06a5308c00e98e0fbb6b"}]}, + {wxSpinButton, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d27cc12c048bf0b160f53ca416add6ab"}]}, + {wxSpinCtrl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6ce2382ed84ceb1585afea719fcddf73"}]}, + {wxSpinEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"158d1777d9e8d840b6d8fa93982b876a"}]}, + {wxSplashScreen, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2719e687a6f08135c305b0b0692b8f40"}]}, + {wxSplitterEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a71231c8d2c06f12ee862be00ac91fb3"}]}, + {wxSplitterWindow, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d7cf57a832b89c0e8574b09e632c7f1d"}]}, + {wxStaticBitmap, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"709ad1816bd35aa84a5b1eca1a6571f2"}]}, + {wxStaticBox, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"84480d00723cfae07f5c67ad463bec22"}]}, + {wxStaticBoxSizer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b32933189486b806c14a04452a3a5887"}]}, + {wxStaticLine, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"569ff89c23e697fc73de1f13d51b17d3"}]}, + {wxStaticText, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6baa91538f6f4d374f0c8c4a2cb5f25c"}]}, + {wxStatusBar, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1cbef8443710f5270baade15b9312c4e"}]}, + {wxStdDialogButtonSizer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2325bcbc06870de4093489cae45bc2ee"}]}, + {wxStyledTextCtrl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"94cc5d191271e6c87926850e0ea8615d"}]}, + {wxStyledTextEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"451ad9ce6872ea2035c3828713fe09c1"}]}, + {wxSysColourChangedEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c6f80dd65e0c9731e4a6dfcb10c71059"}]}, + {wxSystemOptions, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3f3db4310f5e978392d4c6ec83347dae"}]}, + {wxSystemSettings, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3bb2753eb2dde96fd7f4aac7f944f69e"}]}, + {wxTaskBarIcon, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d221781abd0a15270e591e77e279a840"}]}, + {wxTaskBarIconEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a3d865d9706104b122cab70b07fcc3a1"}]}, + {wxTextAttr, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3a6de5eb0c71625ca14606d4e3919e53"}]}, + {wxTextCtrl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"924adbbbade1b95c226a18484c6bba33"}]}, + {wxTextDataObject, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4a3694d548ae60c8261f55b671ac834a"}]}, + {wxTextEntryDialog, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6c3038c65992b9a6eef33dd1aff7ce1d"}]}, + {wxToggleButton, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4471e21c4fb39eece7418adbcd0f0fd1"}]}, + {wxToolBar, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"163743b59b5ec0b6af08d7a66f1f36a0"}]}, + {wxToolTip, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"71dde961902117baba2d2b70f18ebad5"}]}, + {wxToolbook, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"053b84811ff7ef240d44fa454f966e71"}]}, + {wxTopLevelWindow, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c7dc3f9260823e5ebb2f99855f8d498f"}]}, + {wxTreeCtrl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"72e339bd396c87edd28d5a7cc6954e6d"}]}, + {wxTreeEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"17bf2e16e1f41f451fde53d1b72f8b01"}]}, + {wxTreebook, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b4889ab8905fd0fd8df5d06c900edf44"}]}, + {wxUpdateUIEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b7e61e2de35af5257f49919be1304381"}]}, + {wxWindow, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c5337193a39eb848cbcd1afc79f19c8f"}]}, + {wxWindowCreateEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c898ff077b90017671180089c5b37048"}]}, + {wxWindowDC, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"dcdf0f184f2b85f0915bb8d89ae8be27"}]}, + {wxWindowDestroyEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6c443d15978d3a61549f9817ff75fb48"}]}, + {wxXmlResource, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7240754b5985cf7af7c3ff2a3aba3548"}]}, + {wx_misc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1c24e9903d1b499f26e385d7aae15108"}]}, + {wx_object, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b17d673c7c4f59b27e9625b62077ef41"}]}, + {wxe_master, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cbafeb9aba24bb5e831dede889b317c1"}]}, + {wxe_server, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d6fabc67e68c6a41d8fa0ae642f6b272"}]}, + {wxe_util, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5d6e77598d0db8185bb1cb3bad9c5d14"}]}]}]}}, + {application, + {webtool, + [{description,"Toolbar lookalike for the web"}, + {vsn,"0.8.9.2"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/webtool-0.8.9.2/ebin"}, + {modules, + [{webtool, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"29344486df5f854ae8fd3bd674c80e99"}]}, + {webtool_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0130c653986734ecbcc9eb173c28c60a"}]}]}]}}, + {application, + {typer, + [{description, + "TYPe annotator for ERlang programs, version 0.9.5"}, + {vsn,"0.9.5"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/typer-0.9.5/ebin"}, + {modules, + [{typer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bfd9dd08af18a1e70eacb4048fb641d9"}]}]}]}}, + {application, + {tv, + [{description,"tv Table Visualizer"}, + {vsn,"2.1.4.10"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/tv-2.1.4.10/ebin"}, + {modules, + [{tv, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"be7275d94eee00787500a1a2116f2f42"}]}, + {tv_comm_func, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ac45aad5047bb8c9fd5567c83f513db4"}]}, + {tv_db, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"97de27d10499042aaf10e26289e1e92b"}]}, + {tv_db_search, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"41a489c86d92bc1de3d2b1eba6884c6f"}]}, + {tv_db_sort, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e8f3679aece6310ac4b2d574bb4e7180"}]}, + {tv_ets_rpc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"71f7fcd2da96e0166340d5fecd7b3878"}]}, + {tv_etsread, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"45a731d225555df8f910b7960330f095"}]}, + {tv_info, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1c776d3c4a16bc432fed801d2e3c8d70"}]}, + {tv_io_lib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6c34cbecb007f6b330646a192aac6163"}]}, + {tv_io_lib_format, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"843ef9fc1762e75675f7a27b7ba99eb4"}]}, + {tv_io_lib_pretty, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e749f6a7879008513c7194c145e0faf2"}]}, + {tv_ip, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2d54724ccb30cfd4eaca323d38ef7861"}]}, + {tv_main, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"de096a5d9d31dd3443e6bbbd4207ecd8"}]}, + {tv_mnesia_rpc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"947c40384ab9d95074ee626b399d893d"}]}, + {tv_new_table, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c3105970c5d4e109104492bf286bfb4b"}]}, + {tv_nodewin, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bfd57496a2e56d57558891338db3e79e"}]}, + {tv_pb, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fecb58bfc084d7d6dd979f14ea8c2796"}]}, + {tv_pb_funcs, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bcfb711f62ae07c91da02c5b145f3099"}]}, + {tv_pc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"61f6f61fcc34826ca8bc3b450e94f92f"}]}, + {tv_pc_graph_ctrl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e8c763ad45fac44f4356a4739baa30b0"}]}, + {tv_pc_menu_handling, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fc155c0472d92d089e6d74a1987d2223"}]}, + {tv_pd, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"20b8ec33209b59d6775702be748d2da1"}]}, + {tv_pd_display, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"73d810061bb4e923468e82e414f6c962"}]}, + {tv_pd_frames, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8fd381887281403263da14b070a35ca1"}]}, + {tv_pd_scale, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"daff409824df94f43198e08c00c8aadc"}]}, + {tv_pg, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"de42de073fbf5bd3ae58bef45ee05858"}]}, + {tv_pg_gridfcns, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"663f41dd11d7fbca1f8eb58529e63e53"}]}, + {tv_poll_dialog, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ef887432416a9931b8051963d9a97fdc"}]}, + {tv_pw, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c4443616d58cadb7e473ff9ad95c473c"}]}, + {tv_pw_window, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ef96313278caafa5e4cb0c1f5da9d165"}]}, + {tv_rec_edit, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6cbd579d5ccd73e575e67d00fe9983d2"}]}, + {tv_table_owner, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"af79fe7c2092cd90cd1cd360def69fec"}]}, + {tv_utils, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d6967a2d5f7e03b34c4e26f47355ba43"}]}]}]}}, + {application, + {tools, + [{description,"DEVTOOLS CXC 138 16"}, + {vsn,"2.6.11"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/tools-2.6.11/ebin"}, + {modules, + [{cover, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e7856ff33e1e956b68c9f6527b5700b5"}]}, + {cover_web, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ead2c2bfdef49be858d1caee2d8878a0"}]}, + {cprof, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0d6cd8fb042b31641c7869b4e148e7c5"}]}, + {eprof, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c8fd5ee11ba9f1cdae8af5c8f1b367a1"}]}, + {fprof, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c549341f79f954416e826f591645f676"}]}, + {instrument, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cf9b95c95942f0ca0ca65db707873a74"}]}, + {lcnt, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"04b27f3e814feb4f8d4f95705115ce98"}]}, + {make, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9a69d24258713596763ad87c247cef15"}]}, + {tags, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"450d10b82d488d74ab49eeef1d7277b7"}]}, + {xref, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5f07cbb4541ab47dd30a29a9ad6df8c2"}]}, + {xref_base, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cdb2414576f192e4f5df0f8b0d565598"}]}, + {xref_compiler, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c1bba5a52fff82650e201bd08241277e"}]}, + {xref_parser, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3ee075a14d4a9caf00fd422a5b8a4941"}]}, + {xref_reader, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d257c5126f9d0cc4e9050fbbae796366"}]}, + {xref_scanner, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c7e53f28338fe627ac6fd0821ae6c551"}]}, + {xref_utils, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"66929f66fc0606d320c6e5d216cb3b29"}]}]}]}}, + {application, + {toolbar, + [{description,"Toolbar"}, + {vsn,"1.4.2.3"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/toolbar-1.4.2.3/ebin"}, + {modules, + [{canvasbutton, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2432b0ceaf3b3cd6ab059067bb1b904c"}]}, + {toolbar, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0264f53a2881d926b34401d0583b07fe"}]}, + {toolbar_graphics, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"327c7483e8b5cd55e8478a2cea9f0c1f"}]}, + {toolbar_lib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"64977a22d445c231a98bc12926186e0d"}]}, + {toolbar_toolconfig, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"037bc3e6d48012cb0c18796d7870c33a"}]}]}]}}, + {application, + {test_server, + [{description,"The OTP Test Server application"}, + {vsn,"3.6.2"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/test_server-3.6.2/ebin"}, + {modules, + [{erl2html2, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"28fc702edc8365854f9f66fc2fe01793"}]}, + {test_server, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"09cd3b380d55881b18f4020709ad1ef4"}]}, + {test_server_ctrl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"14f716cc55a7cb00e3db6f747c72bfa7"}]}, + {test_server_gl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"91fa2c7419209a51361800e1a28f3891"}]}, + {test_server_h, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"90c3fbf1bdd3260d8be29c0ab04279bf"}]}, + {test_server_io, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"accd333c058e9b4da064190ef7cf48cc"}]}, + {test_server_node, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"091d5d7aadb062a6e3812afbb130402a"}]}, + {test_server_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9aad63f121b569e197e38735d5f3bf2a"}]}]}]}}, + {application, + {syntax_tools, + [{description,"Syntax tools"}, + {vsn,"1.6.11"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/syntax_tools-1.6.11/ebin"}, + {modules, + [{epp_dodger, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ec04cd4dd5985f232fc3116ba222bfd6"}]}, + {erl_comment_scan, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0b8dce1126af7468c5b30f73044c44db"}]}, + {erl_prettypr, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"020fefd3937417a2029a5278dfe6a6c3"}]}, + {erl_recomment, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f9ef1a5c9ce3c6ce6b88966b1c766452"}]}, + {erl_syntax, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1ee5f2f422313742a2d321fcd901909b"}]}, + {erl_syntax_lib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f27de1f2cf65260fe863025c358c9c86"}]}, + {erl_tidy, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f92471b03263f0cd77f35fd59686258a"}]}, + {igor, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"eabc7b07e7b92b8d34fa8eb20a507cff"}]}, + {prettypr, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c1e07ce1f5edda823216364302796ac1"}]}]}]}}, + {application, + {ssl, + [{description,"Erlang/OTP SSL application"}, + {vsn,"5.3"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/ssl-5.3/ebin"}, + {modules, + [{dtls, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d3942c7ba7ffaf15f739485a0294f256"}]}, + {dtls_connection, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0d3d571363ba45d10d8d772f107cd24f"}]}, + {dtls_handshake, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"92217b2b0b6d3b16913521e333533ca6"}]}, + {dtls_record, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4aa88c3ec82a97c9aef5efb0773c153c"}]}, + {inet_tls_dist, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7c9e1c10262b46fce60dcd0127455cb0"}]}, + {ssl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7c0cf688a767412c4de5ab3be9cb2e55"}]}, + {ssl_alert, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ff069c184808a482f096e6cf5aeda43b"}]}, + {ssl_app, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"08781acbe7e677b43923f943d54e17f5"}]}, + {ssl_certificate, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"292c330ca048353298a264de596e2ee2"}]}, + {ssl_cipher, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c7da7124e32552cf9438259bf544389c"}]}, + {ssl_connection_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b46886f7e29fdc628a965ee9e2314e1f"}]}, + {ssl_dist_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1db0e97b9d77cbb26348e98cf386210b"}]}, + {ssl_manager, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1e170a0ac2f663c4396f5a3b00e36239"}]}, + {ssl_pkix_db, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0c1b5a81345dcd39060c2fb177b29898"}]}, + {ssl_session, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f9103614974d7d39d0f1ccb0a9e5b6f8"}]}, + {ssl_session_cache, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"09b0d541e61e1ed9dbcb169b1d5b945a"}]}, + {ssl_session_cache_api, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ffafcdc2ff0342c4c698df0dec3cdc96"}]}, + {ssl_socket, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4e9d62b4943dddf16fbe39f781699260"}]}, + {ssl_srp_primes, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8c2df3c9a38a3ceb9cb273a030bd423a"}]}, + {ssl_ssl2, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6822bde894695368a294a0e890183b67"}]}, + {ssl_ssl3, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c5cd3fbdb5a3f1fdb4c78a2acf9735fa"}]}, + {ssl_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a69f0e3bb4639f90a310b2b938cb9235"}]}, + {ssl_tls1, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"14b5f8a146f51df359e9c1265e949564"}]}, + {ssl_tls_dist_proxy, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1bbb1df174c32c1f424cfa64547d075f"}]}, + {tls, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7ff734327614ac4d6e4d9acf49998c2d"}]}, + {tls_connection, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ad4d62a6b8101cc5b928498752714ed7"}]}, + {tls_handshake, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c2c5513a959ecbe56166df52dff06e6e"}]}, + {tls_record, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"94501e4bda011f01fba860eebdff5a44"}]}]}]}}, + {application, + {ssh, + [{description,"SSH-2 for Erlang/OTP"}, + {vsn,"2.1.7"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/ssh-2.1.7/ebin"}, + {modules, + [{ssh, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8b91a0a4f8271ff77d0efceb75ba5e8f"}]}, + {ssh_acceptor, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7c39ef119dbfcec7618d1cf223d445d6"}]}, + {ssh_acceptor_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d79d965ce6a8121cfbcc1a57029fa06c"}]}, + {ssh_app, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"11089687f3d5ff2e2ff4527efdb86920"}]}, + {ssh_auth, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0ff2e66febd08d64ffbebed7e7880ca3"}]}, + {ssh_bits, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5ab1a9f964ccce1e001d7484b37c561c"}]}, + {ssh_channel, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e4259284ff9d7671940cfde40b8615fe"}]}, + {ssh_channel_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2594f48f478040f5e861f92c63f78eb3"}]}, + {ssh_cli, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6eb0733483419dc0a920452bb42b7344"}]}, + {ssh_client_key_api, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f1a1ce3edce20525a435533b3f37fcfc"}]}, + {ssh_connection, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b551f86d866df22232a147fca4ac7c04"}]}, + {ssh_connection_handler, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9bec5a32b6f6199b3f52e1fbfbbceba3"}]}, + {ssh_connection_manager, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"399ad1481f99b9d43c874c162742c91c"}]}, + {ssh_connection_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cd1150bc1fe3673d2446811f54dc23de"}]}, + {ssh_daemon_channel, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"17ceee1d84a542cf54dd487808e00a1e"}]}, + {ssh_file, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d014774c5b5dbd368fad2bc809515e48"}]}, + {ssh_io, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c1045e82cd74643c823a1bda96d24b47"}]}, + {ssh_math, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9a4b44ed70c1938a7277f37d56f9de8f"}]}, + {ssh_no_io, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c9bf450746c1bcc1fd90c463299fdaf5"}]}, + {ssh_server_key_api, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"debb7d5dcdf2eb88d30ed95a56652366"}]}, + {ssh_sftp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"74ed0ad4eaf38e4233ea40f4b4769b7d"}]}, + {ssh_sftpd, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"472a422310ca8f6f289334ef64550afd"}]}, + {ssh_sftpd_file, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5269b3e25dd16faeb466f76ba993ba50"}]}, + {ssh_sftpd_file_api, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"627f97d4fb4abd5bee4b509d9225edaa"}]}, + {ssh_shell, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5c7831c144031be28ec9dc12b4da3b94"}]}, + {ssh_subsystem_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"755716a08c990d1f606e90420006a77e"}]}, + {ssh_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"408837d884dc9e1f0a969ef64558d733"}]}, + {ssh_system_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f384bcadd7cdca24ec6e40cbe04d71a0"}]}, + {ssh_transport, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0b1c9ed65701948f63ddb181cfaf2744"}]}, + {ssh_userreg, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a4f27505cb543991360e10ddb88870cc"}]}, + {ssh_xfer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0220668d75e0c89e7823990a0c968eaf"}]}, + {sshc_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"483104e1f9410dfc4e1e29c61d8827ee"}]}, + {sshd_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"aba8a2861b6f773e9016ff2859e8de24"}]}]}]}}, + {application, + {snmp, + [{description,"SNMP CXC 138 13"}, + {vsn,"4.24"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/snmp-4.24/ebin"}, + {modules, + [{snmp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9ab098c46c4c009b5ab8a4a37673cf82"}]}, + {snmp_app, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6a2ab3974db30a5b20ba308e1ef0c1d3"}]}, + {snmp_app_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b81a8361da32fd1da51e85f36b678347"}]}, + {snmp_community_mib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"14e553d78094cb09e2e2a1a3476fa9de"}]}, + {snmp_conf, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5e5c6bc754f1fdf1dfaf7f9815163cc5"}]}, + {snmp_config, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d9ec2fef69fed3fddbb122a5fd31853b"}]}, + {snmp_framework_mib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0886188c6a8c18a6ff8a3b08172a0773"}]}, + {snmp_generic, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b23bcb8a031ccd450999f71b41f1f0dc"}]}, + {snmp_generic_mnesia, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"74806ef6c5e3a1af2cb14a4121f4442a"}]}, + {snmp_index, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8a0358730d6b279e4056b9e78fdabbe2"}]}, + {snmp_log, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f93d36dbfdfef30de3f4807efcec170e"}]}, + {snmp_mini_mib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4bb79af4e373cdc2ec4e6f5fe71d0e01"}]}, + {snmp_misc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2ccd6ba3cc7e504e0c163f8c0f7ff575"}]}, + {snmp_note_store, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a3b5f37d8fc6663a63d177cb72a1c498"}]}, + {snmp_notification_mib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c283ef6cba1ffb08a38c4228f119c1f2"}]}, + {snmp_pdus, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"48138570bb1ff76dabe8f1fa5a6e662c"}]}, + {snmp_shadow_table, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ba004cbc14fe13ad6b29515d6b3b84af"}]}, + {snmp_standard_mib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"75c1099b71f4cde7703c1b651168196a"}]}, + {snmp_target_mib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"52cfb682cf25e4c6ad7c6a31ea71bc41"}]}, + {snmp_user_based_sm_mib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b3b454fe409f6cd24463bfca9369adf5"}]}, + {snmp_usm, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"667650cc1c2f535f771132907bf12342"}]}, + {snmp_verbosity, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c8e3d33775ee83cca4d47f64df1dd5ca"}]}, + {snmp_view_based_acm_mib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1dcc969b6786ab84f450e9f0875eab3e"}]}, + {snmpa, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2057219be785ea520f5a3f1886d51360"}]}, + {snmpa_acm, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f21fee89e88dccc36afbae59e8ccd85f"}]}, + {snmpa_agent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a1fcbbb2b5328095d05622eb5da5b1fa"}]}, + {snmpa_agent_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"668a5398f181b8abce6b0c68716e175e"}]}, + {snmpa_app, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"16cc3053b5568e50b5fa384baca6a40f"}]}, + {snmpa_authentication_service, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fc05c3f08dbdec4878aae7816eb5033e"}]}, + {snmpa_conf, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"826ab227f8829b50aabc3072cf2a8537"}]}, + {snmpa_discovery_handler, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"50040fb1565d5888507dcffe6109cc16"}]}, + {snmpa_discovery_handler_default, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"62413e2497c617d1dabf1ab269610eb3"}]}, + {snmpa_error, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fb436bf4d7bf0615c02c649c0e04541e"}]}, + {snmpa_error_io, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"98147b5cfad093916c0756b37f763e86"}]}, + {snmpa_error_logger, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b0431d9de22543e6608515bc4afc07c2"}]}, + {snmpa_error_report, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"214d6585224898ce39f6eef6554593c4"}]}, + {snmpa_local_db, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"eb82eaa9a8486d087a27e834b58a2f6c"}]}, + {snmpa_mib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e68b813ac1df34912af16ef01738f185"}]}, + {snmpa_mib_data, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ed334445e6e025059b2c9b618109cb9c"}]}, + {snmpa_mib_data_tttn, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2f39357a667d3cb530b431fed0dfa674"}]}, + {snmpa_mib_lib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"79d8aff9ea8d71bce6eac0a6f01f53b8"}]}, + {snmpa_mib_storage, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"22e11676e0303ea2f292534da8ae66f5"}]}, + {snmpa_mib_storage_dets, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f8c4649828d764370112243ccdbd2da3"}]}, + {snmpa_mib_storage_ets, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4410e4e89e46b6e2b818d3b002a98579"}]}, + {snmpa_mib_storage_mnesia, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1e3d387a72c28b5bf76d7a55ac39071a"}]}, + {snmpa_misc_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6c4244cad7870e2ec012bdd05281b182"}]}, + {snmpa_mpd, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8475e9d61092213166efe3667bcf0c06"}]}, + {snmpa_net_if, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"258227a8467ed99df2f9e55cc7b5e9ad"}]}, + {snmpa_net_if_filter, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f57faf094fd82ceadc8527983194b2cd"}]}, + {snmpa_network_interface, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"247221ee7ec97ee189ef5a8b5eb2d18a"}]}, + {snmpa_network_interface_filter, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ec6d7d452145362e9dcc0a8be42b3280"}]}, + {snmpa_notification_delivery_info_receiver, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"de84fce31ef758fbb04722b66e1b22d3"}]}, + {snmpa_notification_filter, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e0b2e493bbbe13f1f17f3fd0be7ce1f7"}]}, + {snmpa_set, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7152d8c4f238062a801fb9b46115b1ee"}]}, + {snmpa_set_lib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c1739e0cf36ad6a9249a8a200409813b"}]}, + {snmpa_set_mechanism, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c3bef6423ec85b3b9a144f17c3e3f6c2"}]}, + {snmpa_supervisor, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"19aa2eef0602df46711bdc98c67d105c"}]}, + {snmpa_svbl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e4079d7e9812ac1c42274316b0f883c0"}]}, + {snmpa_symbolic_store, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e0fe1dda713ed3048f51155e47932e06"}]}, + {snmpa_target_cache, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"02394ee2b706d7c26f027c960c659f39"}]}, + {snmpa_trap, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6ffd78574b7c33a0a96bee64d310531e"}]}, + {snmpa_usm, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b121f7bf87a2d44a14aa42988c2072f3"}]}, + {snmpa_vacm, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d7c7855fb65468a2355c889aa26badb6"}]}, + {snmpc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a474261cc18e1f80f0f742774e3b1417"}]}, + {snmpc_lib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ce88a5b16fdc8fa367c8559a81eabcb8"}]}, + {snmpc_mib_gram, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c8b4a0280a0bd9b0e89fd47361381583"}]}, + {snmpc_mib_to_hrl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"88a2a7964f0b3501263eaf513a72e876"}]}, + {snmpc_misc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"feadc3549879e928bcc4941ff25c1756"}]}, + {snmpc_tok, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"37784c9fb162c53b0fae3cd77566bdb2"}]}, + {snmpm, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cfcde2ccea1b2dbfe7d6f3bead4df7d4"}]}, + {snmpm_conf, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2d6eef427d28f7a96b5be06a0509ed8d"}]}, + {snmpm_config, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5a026c01e17b82bd2fdcb31fb69ae51a"}]}, + {snmpm_misc_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"02dd27ee95e3bbe3aab099b11120b826"}]}, + {snmpm_mpd, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1b593b66256ce780231c57b31298fd29"}]}, + {snmpm_net_if, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"68d325a69b69e7de7106965a049522d2"}]}, + {snmpm_net_if_filter, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a83bf186eec6c82fd6c9b164fc337edb"}]}, + {snmpm_net_if_mt, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e44169e0549ab840243a2e4e0fa3d5fa"}]}, + {snmpm_network_interface, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"47b0e15cd1537e1a3a1b41b8be44998e"}]}, + {snmpm_network_interface_filter, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"93b503aeb95e30d2fcf28c2b7d2e017e"}]}, + {snmpm_server, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fdf5855cd385c8d4589d43f2aaddee8c"}]}, + {snmpm_server_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1fc16c37e8db23a8b3e40d3696488a0d"}]}, + {snmpm_supervisor, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"289642b05307317c1684b5ba76cb81c5"}]}, + {snmpm_user, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9c6e66b34460082bbcb99ccaf1cedbf3"}]}, + {snmpm_user_default, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c8c7e1b66076bcbde4678471ee9066f0"}]}, + {snmpm_user_old, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ae32fe52a746f3be59c94bac2b679fcb"}]}, + {snmpm_usm, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"59bb20fedd0aca2f57ce3b5dad4e50aa"}]}]}]}}, + {application, + {sasl, + [{description,"SASL CXC 138 11"}, + {vsn,"2.3.2"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/sasl-2.3.2/ebin"}, + {modules, + [{alarm_handler, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"250185bf9caa8aafeefc21d2dc85671d"}]}, + {erlsrv, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"656c183c67d6d7556d846752ac2e0168"}]}, + {format_lib_supp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"be7d1b5e03f626bc3a081680842f3c69"}]}, + {misc_supp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"57e2232dbb711535686b684350c6412a"}]}, + {overload, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ce834faf427a10bffb528420385e75fc"}]}, + {rb, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c791582aa44b9701a38bea7b12a737c9"}]}, + {rb_format_supp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f6df90c6b446bfd31471022bae098995"}]}, + {release_handler, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bc289c9b3ed6443f9e88a7a40b1bbd78"}]}, + {release_handler_1, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0b7cbb150cbc1ad629936632bcf8700a"}]}, + {sasl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8a39ff904fad2fb7b62b8745b34e29b9"}]}, + {sasl_report, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"651a20fbd6df5b1c785152aecf691f13"}]}, + {sasl_report_file_h, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6d21420c495fb60e6be13677a923ff7b"}]}, + {sasl_report_tty_h, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"165b304307e62adee19805a95d9b6ccb"}]}, + {si, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ecfe8c3c35aba098dd3530398086bcc1"}]}, + {si_sasl_supp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"77c86cc1c9667be73a48dbcb3c480d36"}]}, + {systools, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5514e0264308050ac1cc5cecaf74c950"}]}, + {systools_lib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f1aa9e6a22dccb94499d5609ce1cf66b"}]}, + {systools_make, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d2c4d3e4b7b322b6629575a64e553f90"}]}, + {systools_rc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4337b68dc98fbbed9e93f2bde9ef4d0d"}]}, + {systools_relup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"dd4bb2c6c8422b979b5a75e6f545baab"}]}]}]}}, + {application, + {runtime_tools, + [{description,"RUNTIME_TOOLS"}, + {vsn,"1.8.11"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/runtime_tools-1.8.11/ebin"}, + {modules, + [{appmon_info, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"62c6dd94499d20f1776df7cd3267c100"}]}, + {dbg, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5a7b449f37506a70985c5b3f69ec579c"}]}, + {dyntrace, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"746609b1554ac41985637b5bba780905"}]}, + {erts_alloc_config, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1a489439d8dded5734eab5eb575ce454"}]}, + {observer_backend, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d9af82e565eecf62c161023fce415c58"}]}, + {percept_profile, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"32909b64d30ade082680e9491a3ddbc8"}]}, + {runtime_tools, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c569a23a42bf744f56abbf4215ca2a9d"}]}, + {runtime_tools_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f52650d88ee6f6754ed9d109accb7eac"}]}, + {system_information, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9ed879d33f6159b48fb25bc472369285"}]}, + {ttb_autostart, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6838c97b9564b06d26e5f599adcee4a6"}]}]}]}}, + {application, + {reltool, + [{description,"Reltool the release management tool"}, + {vsn,"0.6.4"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/reltool-0.6.4/ebin"}, + {modules, + [{reltool, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b15d15af1453d274df701f6c4b39da09"}]}, + {reltool_app_win, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e15041fae657a7abcce63e7e775af842"}]}, + {reltool_fgraph, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0c07b7a13c2ae36b59f5d1f0daf8a567"}]}, + {reltool_fgraph_win, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"230041769919290efa2a3419cf70c8cb"}]}, + {reltool_mod_win, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"752d8f1d674a79955de7afd3ba6b561b"}]}, + {reltool_server, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"135d9bb6ea57344472c185d61c97573c"}]}, + {reltool_sys_win, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f02ff065d17fa8203d711b9cc698ebf4"}]}, + {reltool_target, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"036440a327b1c9cbe5e404ffaf02b9a4"}]}, + {reltool_utils, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c623f90e0c5da5db65d4ca56d9088d7a"}]}]}]}}, + {application, + {public_key, + [{description,"Public key infrastructure"}, + {vsn,"0.19"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/public_key-0.19/ebin"}, + {modules, + [{'OTP-PUB-KEY', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d6f796b3667abf21828ee3daf8df487c"}]}, + {'PKCS-FRAME', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4419b1988012d2d620ac3cc7dec13d65"}]}, + {pubkey_cert, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7a4ac659e84ddfb1dc14f0608460fbfb"}]}, + {pubkey_cert_records, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d5b1f48543bb6b0e62b343c2b965615f"}]}, + {pubkey_crl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"680633b53ae9815138f804c999e78bbd"}]}, + {pubkey_pbe, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"517156230695474828dc4d30af59f656"}]}, + {pubkey_pem, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"eef5632fcf01194dd6c98f116de8f923"}]}, + {pubkey_ssh, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5acc6568d3caea9be2d2b93904f6bda9"}]}, + {public_key, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7b054e72c6e34943c0143ac34edcc37e"}]}]}]}}, + {application, + {pman, + [{description,"pman The Process Manager"}, + {vsn,"2.7.1.4"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/pman-2.7.1.4/ebin"}, + {modules, + [{pman, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3d0ea0aa857d089d112f46bed16fb83c"}]}, + {pman_buf, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"efdccd7cb884a2a9c50cc70719d53575"}]}, + {pman_buf_buffer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bfdd78d8905bd1bb7e07ee22414a0eae"}]}, + {pman_buf_converter, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"afd7e3173377b46ec7374c0e1118a158"}]}, + {pman_buf_printer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7c592081860a9b92b08b557c46b11307"}]}, + {pman_buf_utils, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"77e551e0bc43c59bf5a76f0e32daf822"}]}, + {pman_main, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b4371d24cd7312794afb137de259b8e0"}]}, + {pman_module_info, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0336677781cb813897e9306415f85b38"}]}, + {pman_options, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"016b8cac7c507593a118b25ab3d642d2"}]}, + {pman_process, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"faab007fad0f14fc692df152d60a8abd"}]}, + {pman_relay, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b12bbe3e253211fac5006414f6f6162b"}]}, + {pman_relay_server, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3b7eb65c7c1507892ed8f01a1b5e027d"}]}, + {pman_shell, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3b9e7634fb49f1e84a57ed8cee5e3909"}]}, + {pman_tool, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"58ab631eed4b29ddebd390b4cd30c82f"}]}, + {pman_win, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"697f4a56a374bcacf06e8329356f7b9d"}]}]}]}}, + {application, + {percept, + [{description,"PERCEPT Erlang Concurrency Profiling Tool"}, + {vsn,"0.8.8.1"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/percept-0.8.8.1/ebin"}, + {modules, + [{egd, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"810926c65926827a80dc5de6e9cace80"}]}, + {egd_font, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3f41911d6aa5ada509332aca159c905e"}]}, + {egd_png, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"201db7435f6981d1d5b738c5431d4a39"}]}, + {egd_primitives, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cba1711d459930f92725953bca582106"}]}, + {egd_render, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b86b9269dfad8feb8753abfa8e9be68e"}]}, + {percept, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"af81f6c6164ac09eafdfbe02a985976b"}]}, + {percept_analyzer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"efe67a4369a96144def43df906f2ac94"}]}, + {percept_db, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9bff80fb7515c9c23977cceb2fba5e0f"}]}, + {percept_graph, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1444b51fa93b12bb98f6bf5246e079f9"}]}, + {percept_html, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b84fd915479ddaa158366217f7fb2ff7"}]}, + {percept_image, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ec8d1dae1d54b90ccd7cce76d83573b6"}]}]}]}}, + {application, + {parsetools, + [{description,"XLATETOOLS CXC 138 xx"}, + {vsn,"2.0.9"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/parsetools-2.0.9/ebin"}, + {modules, + [{leex, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c82fd5f503469e40008fb18b393b5421"}]}, + {yecc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e644a07828dcb46e440058ec4e3ea83b"}]}, + {yeccparser, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"43c2c84fbd4caf3c3eacfe0e25874f3a"}]}, + {yeccscan, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cc55537c97f45738825ae56628fd4c71"}]}]}]}}, + {application, + {otp_mibs, + [{description, + "SNMP managment information base for Erlang/OTP nodes."}, + {vsn,"1.0.8"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/otp_mibs-1.0.8/ebin"}, + {modules, + [{otp_mib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b92358a169666b58abe47dc98b1ea1f8"}]}]}]}}, + {application, + {os_mon, + [{description,"CPO CXC 138 46"}, + {vsn,"2.2.12"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/os_mon-2.2.12/ebin"}, + {modules, + [{cpu_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"071d377ab6c706f3c4404dfddf95316c"}]}, + {disksup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"53255f9176fdf57c6d2c62a1e3ca8ce2"}]}, + {memsup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d5aa81b4c0017f97827b13d588e907cc"}]}, + {nteventlog, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d593ff9832f59a682cb9a7217eb1dc55"}]}, + {os_mon, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f8fcf26c77f01a1542d007513e49c214"}]}, + {os_mon_mib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"15ff2fbfd1c88ff31ff9c8e85bf10cb9"}]}, + {os_mon_sysinfo, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2bed5dda663ec63a320198f44c90f388"}]}, + {os_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"52837f657faabaab44288ba2d29ba473"}]}]}]}}, + {application, + {orber, + [{description,"The Erlang ORB application"}, + {vsn,"3.6.26.1"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/orber-3.6.26.1/ebin"}, + {modules, + [{'CosNaming_Binding', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f894f1ca2a53e8c68579c9e786884b64"}]}, + {'CosNaming_BindingIterator', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"938a503dbdbe3f091ce900dbe1efeeaa"}]}, + {'CosNaming_BindingIterator_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"07513574b340d64ec6d50ebf98a772c7"}]}, + {'CosNaming_BindingList', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"37aaba8fc8623355426055d3b9c2e2b8"}]}, + {'CosNaming_Name', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7053bbff4a4dd27357c7ae2b7a1bd158"}]}, + {'CosNaming_NameComponent', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4ef942efe3f30c93b89cbb79f0b0e372"}]}, + {'CosNaming_NamingContext', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9e73232824e400a4b6f9a295922420a5"}]}, + {'CosNaming_NamingContextExt', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fb072ace0d3d1445fa884fbb59d19ff6"}]}, + {'CosNaming_NamingContextExt_InvalidAddress', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ba29a989c4d5c961c62bec9162bedd71"}]}, + {'CosNaming_NamingContextExt_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ece2da1a74559421fd8c5a0fcce5a984"}]}, + {'CosNaming_NamingContext_AlreadyBound', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ba2061d5ba1cd24262351fa0b92b8850"}]}, + {'CosNaming_NamingContext_CannotProceed', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"175c9f998a255ce625568ff7d7258988"}]}, + {'CosNaming_NamingContext_InvalidName', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4b5bb3702b8105f78101d3deeb4c3717"}]}, + {'CosNaming_NamingContext_NotEmpty', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0dbdfc178f40394391977946fdbf331d"}]}, + {'CosNaming_NamingContext_NotFound', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f2f4d6cf9150fcc92bd9568ff89d2774"}]}, + {'OrberApp_IFR', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"67d245498b4abcae1f6acd51c4edc47e"}]}, + {'OrberApp_IFR_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2ab7e63e7a7e47bac6d2cc7e703f2915"}]}, + {any, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1339baf3e573eee6bb558d0097bce4c2"}]}, + {cdr_decode, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"dda23b10f13bec369113cf3ae72b9448"}]}, + {cdr_encode, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4d36c6b8ee3a9fddfdc76246030287ba"}]}, + {cdrlib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d97ec0db3640dda02a25e6ecc9d5fa5e"}]}, + {corba, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3794dffcd3c921332af2b343bb9e8e40"}]}, + {corba_boa, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3dfd1417d677ca18f73c4efe65b37bad"}]}, + {corba_object, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"569d7993c599bd7c2f68bf7a2d11fdbd"}]}, + {erlang_binary, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0ec91157e3e220cc5163b552f3a4050d"}]}, + {erlang_pid, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"49b95cc1773eeed11661fc4cb36b7921"}]}, + {erlang_port, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2b0dd3969488714fc2e2dce30b297b14"}]}, + {erlang_ref, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"98b38f4a590a67a1fa34b2c6d60e8992"}]}, + {fixed, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"469aed745e70550ecb4ee6b382a0c919"}]}, + {iop_ior, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1d3eeb1d5401ad27f97b75926cbf8387"}]}, + {lname, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"945467530d2858f1dfb87b970a3862bc"}]}, + {lname_component, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c2cb0fe6e60c6d07d711cd8c3b28c8f7"}]}, + {oe_CORBA, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"02e20118e9fd5c3f5d2f398851cbdcf1"}]}, + {oe_OrberIFR, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ebc39f59cbd7848e61193c82ab0ee2b9"}]}, + {oe_cos_naming, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"18745eadd8db295fc1e8e656a5c8d4d6"}]}, + {oe_cos_naming_ext, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"56520dda2639eaadae720ac4974080d5"}]}, + {oe_erlang, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"963486a48402a80366275f8dace2a80f"}]}, + {orber, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0b4c2a1e44684d8f314230f21def86f2"}]}, + {orber_acl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"76577170937f03fa23e69e4df6cfc424"}]}, + {orber_cosnaming_utils, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f856cbb99314e9eb7d0d7bfcdb30994e"}]}, + {orber_diagnostics, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"656103538d0ee20b1433c6b2909b26c0"}]}, + {orber_env, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"75b0fa232da40432e3009ead263f3749"}]}, + {orber_exceptions, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2ef09c1b3026ef3aaae5e9c6a5dd2918"}]}, + {orber_ifr, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0fed5973a29d60ab161580bf07f3b185"}]}, + {orber_ifr_aliasdef, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"941404668a378948bbef59da18973eea"}]}, + {orber_ifr_arraydef, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4a1ebba0a7f7a26d5205972ac2bc6fc6"}]}, + {orber_ifr_attributedef, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"141fa0d0127d292e0bfc3f0e654059df"}]}, + {orber_ifr_constantdef, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"337388d13414ab58cdafcbd70a150741"}]}, + {orber_ifr_contained, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a825abb903208287bc2dfb7323342fe6"}]}, + {orber_ifr_container, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3027632d783e5db3440bead382fbc787"}]}, + {orber_ifr_enumdef, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f031b9d117143554a1db00a0f7f9d4af"}]}, + {orber_ifr_exceptiondef, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6e152b750cbb286b90ec49855c9f8115"}]}, + {orber_ifr_fixeddef, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c0f66c8a6999241daec6815a1eaf7112"}]}, + {orber_ifr_idltype, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7f5b0c9c79289e56f5cfe24c5de10c26"}]}, + {orber_ifr_interfacedef, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"985cc443e424939f7f067e9d577c0044"}]}, + {orber_ifr_irobject, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"441a6a89092f9059eddaafb3a19fddac"}]}, + {orber_ifr_moduledef, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"571791fe8c191478f9d99008066db451"}]}, + {orber_ifr_operationdef, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"26ff4727920661a5777fdfeb9542447d"}]}, + {orber_ifr_orb, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9f82245f4568a7ad57b93005504b22f3"}]}, + {orber_ifr_primitivedef, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cad06f8ddc116042d7dd2f54f189dc9e"}]}, + {orber_ifr_repository, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"88fc8f59fe5a883e6a5cc76c9db0a8f0"}]}, + {orber_ifr_sequencedef, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"55db89bec3e336bf1a1087b8b24ec0c9"}]}, + {orber_ifr_stringdef, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7119d2c1827fbfe04397a23e0c9b7bea"}]}, + {orber_ifr_structdef, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2e0643a9e51eb2fe1bb3268623005b9c"}]}, + {orber_ifr_typecode, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"52a2bebb663486dfde545175b24f1db9"}]}, + {orber_ifr_typedef, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1440f73d398af50ec1f1854b68a7ba14"}]}, + {orber_ifr_uniondef, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1a767805d679f87ec96f566ea535b0ae"}]}, + {orber_ifr_utils, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a7a7127b079023e8507c1963bb70c6a8"}]}, + {orber_ifr_wstringdef, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5d9705c3d0a8e75958cfc92c0e065688"}]}, + {orber_iiop, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"08e63cf45c6b87ef390f1ba44908df62"}]}, + {orber_iiop_inproxy, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7d958ccebf1795810daf42c284df0b0e"}]}, + {orber_iiop_inrequest, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"01cf6a0b86d8575aad71a64d1ead078f"}]}, + {orber_iiop_insup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3f3e97ae477f58ab983bbf78c5691a6b"}]}, + {orber_iiop_net, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cf48384275f94de84a88f985e69db8c5"}]}, + {orber_iiop_net_accept, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"311c1717af0f83c768a7904bd4f35d87"}]}, + {orber_iiop_outproxy, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"aadcfde8449aad07dda946c4fe8ae73f"}]}, + {orber_iiop_outsup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4bb6aa4ab42569ea07e6410eec054d96"}]}, + {orber_iiop_pm, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3c23eac6eed61ab8f4b0376bada6a96c"}]}, + {orber_iiop_socketsup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"41cb70052711397c5ff4346c78bad0bc"}]}, + {orber_iiop_tracer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3db9add6a744c5d57f2f88593010189c"}]}, + {orber_iiop_tracer_silent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ddc6f4254d9d55920c182bfc82174cd5"}]}, + {orber_iiop_tracer_stealth, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b5c2faed84597fcc65a1f79f126d38ed"}]}, + {orber_initial_references, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"52d7435fcf9d9b18c41cd15112211641"}]}, + {orber_objectkeys, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"77601464765a034f2157e184b66b27bf"}]}, + {orber_pi, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7772668cb95512b5068384cffb15f5ec"}]}, + {orber_request_number, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ce4912e1c1726a3edd4d2709171895ad"}]}, + {orber_socket, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ea78f1c75c253c070f2b3423b896667a"}]}, + {orber_tb, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3d9b508906d187e6448fd06b88923aea"}]}, + {orber_tc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f43cb767b9c01d13d190a56574aa504c"}]}, + {orber_typedefs, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"82369e4a3e862ef248d19c460b2df8ea"}]}, + {orber_web, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"23cc5e9ac5ffe3b7ac2315ae0759243c"}]}, + {orber_web_server, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c95b45e743c0a1f7a2e88e350075f78c"}]}]}]}}, + {application, + {odbc, + [{description,"Erlang ODBC application"}, + {vsn,"2.10.16"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/odbc-2.10.16/ebin"}, + {modules, + [{odbc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2763e2d38d62e1fbe7c8ed231cce1905"}]}, + {odbc_app, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"83f4d02ba9fd29ff84576abe0fde901e"}]}, + {odbc_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3c39c9a6e602d66a2d12b662bf0a9b20"}]}]}]}}, + {application, + {observer, + [{description,"OBSERVER version 1"}, + {vsn,"1.3.1"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/observer-1.3.1/ebin"}, + {modules, + [{crashdump_viewer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"77bff2805dfd88de4320b9f8c1469fe3"}]}, + {crashdump_viewer_html, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d22f72c96ed77a6e4cabe125db6c8419"}]}, + {etop, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"377b59a76eeb5edb5b8531b5f0267399"}]}, + {etop_gui, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f0421b554807cd47031f0873f649d5e1"}]}, + {etop_tr, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d152946c82611d5f39b1ed3c720cb570"}]}, + {etop_txt, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a02a670a9ee8ea7c3cea6de5bdcfa356"}]}, + {observer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0e7d30dfe8122c8736eeac0582abb076"}]}, + {observer_app_wx, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e6130cbc700be448c7f64c7f8bcefcc6"}]}, + {observer_lib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0973e064b3b2ff3b79f2f1eed47a8539"}]}, + {observer_perf_wx, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b5753467f635c1a98ad5e3f2e50f75f4"}]}, + {observer_pro_wx, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f1e68919849e91012fd156d3ac6228af"}]}, + {observer_procinfo, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"175c07cc3510655fbdfe95a35012a84a"}]}, + {observer_sys_wx, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7637a94c99800b8b1c47467f7411fce6"}]}, + {observer_trace_wx, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a836a58f29e21107efbf7fa3276c0ff6"}]}, + {observer_traceoptions_wx, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e070e083bc809e6bd67284d46876292e"}]}, + {observer_tv_table, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3dfa1b811025f5313ba91c620bdafa62"}]}, + {observer_tv_wx, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0c8661053d6b3b563582c335e6e18bc2"}]}, + {observer_wx, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"72d4b855d618e72367b3b26a9c9fe22e"}]}, + {ttb, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"08eec178cb05729190be64adbfc06fd4"}]}, + {ttb_et, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"18006f41b1483c5378d0d803bb73428f"}]}]}]}}, + {application, + {mnesia, + [{description,"MNESIA CXC 138 12"}, + {vsn,"4.9"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/mnesia-4.9/ebin"}, + {modules, + [{mnesia, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7ef269bdcc2f2ebecc93eed4a7d97e43"}]}, + {mnesia_backup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"50581e2e99465b9ab9adb11193ccbcb8"}]}, + {mnesia_bup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"63c4dc59c47dedf48fb8a67b3aee3a5a"}]}, + {mnesia_checkpoint, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"57fca37f2b0e856bb728f0660f6ad017"}]}, + {mnesia_checkpoint_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"211e3b158a5869145c472cc12080a148"}]}, + {mnesia_controller, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a4d98077e647433bbd4dfe9215bf45c0"}]}, + {mnesia_dumper, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"32b0759359dcf8f05af72e914720ceaf"}]}, + {mnesia_event, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bb423661483d17e8aaa683a22600aee7"}]}, + {mnesia_frag, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"279eb6b4f1f713c9960f1697856030e7"}]}, + {mnesia_frag_hash, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7ca1e314bdfa381005e047965e7fe435"}]}, + {mnesia_frag_old_hash, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"70dd3592f65741eefd724448e56427a3"}]}, + {mnesia_index, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"79261cc27d922d6eeecac20a90920cd0"}]}, + {mnesia_kernel_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8f6da4fd3cf0ce074bf7b04e44e86470"}]}, + {mnesia_late_loader, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"02a44f59cd50a3b6fcb78198781e8e7b"}]}, + {mnesia_lib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"08abcd0826ef6dce6929ca1741c156d7"}]}, + {mnesia_loader, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b316a61b4f5ce23b5c7e4bcfdaf6367f"}]}, + {mnesia_locker, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"847d79bf891a9bcffda9e12458490e7e"}]}, + {mnesia_log, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8ae50e4995027fe6229091521e842b1e"}]}, + {mnesia_monitor, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"105c199cb846668f52e583faee684690"}]}, + {mnesia_recover, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"91044c669bf165c1d9bb72d76da7135c"}]}, + {mnesia_registry, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"aa46aa5634381be997d54dbbf8da99d1"}]}, + {mnesia_schema, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"19676af000bf38b666e545b3c6f22937"}]}, + {mnesia_snmp_hook, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f994954a18270025bf505af1a1dd1244"}]}, + {mnesia_snmp_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bb3f27cfb0a3fa51e062ca6e86973a3f"}]}, + {mnesia_sp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"86565dac38aae327be11f08e8d2e05e8"}]}, + {mnesia_subscr, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a02b0b2458f5900927d72010d097ea94"}]}, + {mnesia_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"309a5b00197c57437131eec4ce49c560"}]}, + {mnesia_text, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3008beca178112720e4dc18ec6325583"}]}, + {mnesia_tm, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7be29c00407f6162375a0d855b36c68d"}]}]}]}}, + {application, + {megaco, + [{description,"Megaco/H.248 protocol"}, + {vsn,"3.17.0.1"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/megaco-3.17.0.1/ebin"}, + {modules, + [{megaco, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1621bcd17d72f8165b568b33e80badff"}]}, + {megaco_ber_encoder, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"12ccb5c139d29b2066d3317a2f6c166f"}]}, + {megaco_ber_media_gateway_control_prev3a, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c13becbea3de6bd37af08cd022c5b5a1"}]}, + {megaco_ber_media_gateway_control_prev3b, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"721176c1221d7ea112757ebe621508fb"}]}, + {megaco_ber_media_gateway_control_prev3c, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c4546f9416ae2b969c41f114c777b994"}]}, + {megaco_ber_media_gateway_control_v1, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0f352af0a5bfe76b5ca6a6393ef0782a"}]}, + {megaco_ber_media_gateway_control_v2, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2321767a4aeeadca11a92a77da4bb488"}]}, + {megaco_ber_media_gateway_control_v3, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"851782cffe570769b46773bc55073bc5"}]}, + {megaco_binary_encoder, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5e378f272d26a606b7d8b99accc472ff"}]}, + {megaco_binary_encoder_lib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1eaa0f4ac077056d2753b4945acac2af"}]}, + {megaco_binary_name_resolver_prev3a, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"afc05954d77f1580e3e3119b28b2ee18"}]}, + {megaco_binary_name_resolver_prev3b, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"64eca1a5ca4891ec6cb56e5b3b747cb1"}]}, + {megaco_binary_name_resolver_prev3c, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7ab8daa26dfc1ecd8593ea03f037e0b1"}]}, + {megaco_binary_name_resolver_v1, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8a28e0729df9ed41a27d38e76d2b1efc"}]}, + {megaco_binary_name_resolver_v2, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6e831098553576721cfa3187f3246577"}]}, + {megaco_binary_name_resolver_v3, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"adc24901b71b89a59191caa575777136"}]}, + {megaco_binary_term_id, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"82f36dc610c932eb0e6ca2e9002d6c5b"}]}, + {megaco_binary_term_id_gen, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0b1f0904c943c78f55b67da76203955d"}]}, + {megaco_binary_transformer_prev3a, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fff3d874f36cfbc32dbbbc5078dcd380"}]}, + {megaco_binary_transformer_prev3b, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"33cc44d1bf46cd3bfb5aea29887bcd57"}]}, + {megaco_binary_transformer_prev3c, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ef3fe41f1f88c54aa4fb1caac2724337"}]}, + {megaco_binary_transformer_v1, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f916e19a7725a6887c4f88395c9af607"}]}, + {megaco_binary_transformer_v2, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d4c8f6b31357bc55c13c7b7881a9a775"}]}, + {megaco_binary_transformer_v3, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ab88024bec5e1fd3c03923d1d0e5119a"}]}, + {megaco_compact_text_encoder, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bf7e1fe374598225fd46f38b81e07d9f"}]}, + {megaco_compact_text_encoder_prev3a, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"23e6620407ec5197028fa798bf01e51a"}]}, + {megaco_compact_text_encoder_prev3b, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a475f5b036fb0aa3dd35f86ff1d3c3fd"}]}, + {megaco_compact_text_encoder_prev3c, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2cbd43381f15e24a25a85797028851d5"}]}, + {megaco_compact_text_encoder_v1, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b193fe2860d7e926e73b71c501412b07"}]}, + {megaco_compact_text_encoder_v2, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"777b3a6ecc8b41b8bbab1ad70c7bf6ae"}]}, + {megaco_compact_text_encoder_v3, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e481d7fc5b319d95e6b6d7301837211c"}]}, + {megaco_config, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"895d349eeee863ee722653edb146eec3"}]}, + {megaco_config_misc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"275e3e57bae4ae030b1e8f2be4a4ece2"}]}, + {megaco_digit_map, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e82b7b9950adc2a9b92418b741056198"}]}, + {megaco_edist_compress, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"de4bb8d979b71e2a77bc6480c755f0e0"}]}, + {megaco_encoder, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"323b5d062600331842c9a23dd847ce29"}]}, + {megaco_erl_dist_encoder, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6523fa00adc2e065d8418983cb9caa83"}]}, + {megaco_erl_dist_encoder_mc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"41066ab829e0f8ebc457c8e087e029db"}]}, + {megaco_filter, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"778b451ec26564a06b01bb6449e62004"}]}, + {megaco_flex_scanner, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"76674c634aab23d50f8746016a4a0be5"}]}, + {megaco_flex_scanner_handler, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"eeafd9d64269893a5e719f9791e846ec"}]}, + {megaco_messenger, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7fc902eabe8adb5b0fe33e79b000ddbd"}]}, + {megaco_messenger_misc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3bee9043dce0a684cdd1cd8134a370a4"}]}, + {megaco_misc_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"441b7ad486bf4eef899e02f97ba14768"}]}, + {megaco_monitor, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6da74b6f55cbbbacdea077af0a845ef1"}]}, + {megaco_per_encoder, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"58c49d0f60e2132cef575414c82a917b"}]}, + {megaco_per_media_gateway_control_prev3a, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b84247f3fbcda78fd09755f5368ade94"}]}, + {megaco_per_media_gateway_control_prev3b, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a981605bd179636baebaef5ff6ebc806"}]}, + {megaco_per_media_gateway_control_prev3c, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f30445cfec10f8cbd55fe17c6724b53c"}]}, + {megaco_per_media_gateway_control_v1, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0fe217237913122558c928dd10ef79f5"}]}, + {megaco_per_media_gateway_control_v2, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d1a9dfc04639677dfb27b24b2829f7ad"}]}, + {megaco_per_media_gateway_control_v3, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e967677da6dc54388db01f5c1545c77e"}]}, + {megaco_pretty_text_encoder, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b9dce15ad90abfcf6a7cc93391dbdc64"}]}, + {megaco_pretty_text_encoder_prev3a, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1b00d8cfa3efaae8d225da7007dada64"}]}, + {megaco_pretty_text_encoder_prev3b, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"aa844b22554dca495b913fc57cfa3013"}]}, + {megaco_pretty_text_encoder_prev3c, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"91b54a6e884a8afa32ffaa8352893baa"}]}, + {megaco_pretty_text_encoder_v1, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0c6db8e013212168a6df39fca101e3aa"}]}, + {megaco_pretty_text_encoder_v2, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"079587bd6b00f80224aaeec199380224"}]}, + {megaco_pretty_text_encoder_v3, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d3a6f2cc1885299f91fb769fd4a1cb01"}]}, + {megaco_sdp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7e2d41d949f9ab2404116f809237301a"}]}, + {megaco_stats, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"03152bbddea7c1e557224711c4b97892"}]}, + {megaco_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cb7802016626e692d5a8519f536cf3d2"}]}, + {megaco_tcp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"15cec9b1865d957412d0945e11bd5630"}]}, + {megaco_tcp_accept, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4999b86506c5da0b256de8fdf1423c20"}]}, + {megaco_tcp_accept_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"91e916f8b5d3aec78b129abb2064f229"}]}, + {megaco_tcp_connection, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"53c5b634698b54c66de0676289c52222"}]}, + {megaco_tcp_connection_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"48ff5ffa59eb95858702320eed91bf59"}]}, + {megaco_tcp_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"597fe1780a9081757e42b57e5ebef1b2"}]}, + {megaco_text_mini_decoder, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4675bc758b6dfade5a21f345c13fd523"}]}, + {megaco_text_mini_parser, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"dbc886fe01447c012941de8bbcb8b1e7"}]}, + {megaco_text_parser_prev3a, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fc946659afb87b8bcd032cd513206016"}]}, + {megaco_text_parser_prev3b, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d0158fa2aa0880bfcfcea1249e90a259"}]}, + {megaco_text_parser_prev3c, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9acb9c582674145c94ada5f3bc58567f"}]}, + {megaco_text_parser_v1, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cfc2972ed82568f1212b10aa5f54a5bf"}]}, + {megaco_text_parser_v2, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"38f90460cdfcaf135be0f96917b2f7fa"}]}, + {megaco_text_parser_v3, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4e9afc2c639e48188d332c8bccf39588"}]}, + {megaco_text_scanner, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3d050061e3c87e8f1964b063624202b3"}]}, + {megaco_timer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1252b5457aeb62266567e5905d4fa76f"}]}, + {megaco_trans_sender, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3be0e627b81fb19dc7a3e27885f0958d"}]}, + {megaco_trans_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c89becbc7e0e3b62c0ee8fac09f5adef"}]}, + {megaco_transport, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8ad32251f0bd50e9289ae09286daf84e"}]}, + {megaco_udp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4274133166af4f35b78505125ca3280a"}]}, + {megaco_udp_server, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"84b71d1f62b9e3958dc6bc55ea87dd5d"}]}, + {megaco_udp_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e05c1a2e530417dee164ad41e4fa8888"}]}, + {megaco_user_default, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"604d252f88e8e7de2e8b2941d6f2fc2f"}]}]}]}}, + {code, + [{path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/jinterface-1.5.8"}, + {modules,[]}]}, + {application, + {inets, + [{description,"INETS CXC 138 49"}, + {vsn,"5.9.5"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/inets-5.9.5/ebin"}, + {modules, + [{ftp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f75e6a1763c0f8ad63c48fee7762bd08"}]}, + {ftp_progress, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a9f1247decddc2091349cc0c561740ba"}]}, + {ftp_response, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8184ca2df27024d938c1745b9b46b21b"}]}, + {ftp_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"23491501dc6175d1a49c2bbb888642a9"}]}, + {http_chunk, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2d127d36200e815d589b358178ae3d98"}]}, + {http_request, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c9d27256b8abc0a4752a98c5fab193d9"}]}, + {http_response, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a327d5e08590cae728288f395b5880ea"}]}, + {http_transport, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fefac9e86284528e5883735ff02f9635"}]}, + {http_uri, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6d8dafbcdb6a18c64161cda56b762aea"}]}, + {http_util, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"948c60f737d5c6d13e9e19b518eb5dcc"}]}, + {httpc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"12f827ea3b4a60e6abe352016df83794"}]}, + {httpc_cookie, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"55dbb04357dcd95196eb831ae6c88924"}]}, + {httpc_handler, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"13538972414b85062867ba8f72b63a6a"}]}, + {httpc_handler_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6d291f5169c3ee61ab92b272e5612628"}]}, + {httpc_manager, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fbc2349ce89229b7aab1397e920c4a23"}]}, + {httpc_profile_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"71f19372131a26ce3fec7fe59cae62a6"}]}, + {httpc_request, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0f9b151b009d24a06987f46db7a7ab32"}]}, + {httpc_response, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"df4086639fe81d9d6b0b0f1c27d783c8"}]}, + {httpc_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cac51bc379bec99f8e2fe737e6701177"}]}, + {httpd, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"965f24797bd0ecb2662f8cccbf5a114f"}]}, + {httpd_acceptor, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"60c4ec255f9d3e71ca247d690fc050e3"}]}, + {httpd_acceptor_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"146196f8aa54e2872ea09789bf43167e"}]}, + {httpd_cgi, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"493bef6896bc09b2a84424756e6aa2d6"}]}, + {httpd_conf, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"122f251eb11290e92a55da1a97647ff7"}]}, + {httpd_esi, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f0a20e7f4efd148111074d6c027a749d"}]}, + {httpd_example, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4e8699c78100cc50e49ac578b154e491"}]}, + {httpd_file, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"30702eec4e62275db10ea6e81cd67866"}]}, + {httpd_instance_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5d7ab2c856e6d5438dd3144b284ee396"}]}, + {httpd_log, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"12fc1dfa3734ae50f2b5912d1245d63d"}]}, + {httpd_manager, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ae9176839ab029c3685eaa1e9b2b90d9"}]}, + {httpd_misc_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4c61eb0828079a16033e6b33e8095104"}]}, + {httpd_request, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a91f7e3de28a17002b2923df84f4b01e"}]}, + {httpd_request_handler, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2b44228586d6ef9df1fb9bbcdf8e395a"}]}, + {httpd_response, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"73a06662a9f1ea7bb68ea6e0487ff3c0"}]}, + {httpd_script_env, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"348c3920cf5e3c2137127c4a1e1345b4"}]}, + {httpd_socket, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2f021c0b5923e108fd344cee27e360a2"}]}, + {httpd_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7814cf6981a80379606be6a64d684e24"}]}, + {httpd_util, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4b6d1e4e24096bf68e395c2105f9ddce"}]}, + {inets, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5dea85fffabe81e273c12c78d57d3ea7"}]}, + {inets_app, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0cc5b16bf76fdd61cc3fcc189509b4cb"}]}, + {inets_regexp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3d90aa0458fda8b4878dc77b59f3a996"}]}, + {inets_service, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fda2c34b97323c1cc7756e681f50073f"}]}, + {inets_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5c8287946a050dad1ffd422678150174"}]}, + {inets_trace, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"38930cb6dedec461e1cb409ee6902dc4"}]}, + {mod_actions, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cd04b142450e4b2a6681a67ff53fe983"}]}, + {mod_alias, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"488cd71dcfc552f96603b8ae70cffbc8"}]}, + {mod_auth, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e4c582f449cb199ea9cc8d5a7004a9da"}]}, + {mod_auth_dets, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"43a467ba929f04d907a1a6ba11bb1893"}]}, + {mod_auth_mnesia, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a3d3fe40e66d1a310a5814ead817db4f"}]}, + {mod_auth_plain, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1692c15dbed5d5a680dbac4354569ec8"}]}, + {mod_auth_server, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ee144579a7fd9a4a761307385f6ef449"}]}, + {mod_browser, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b4187d14f39e293330958d7ed7f61ce5"}]}, + {mod_cgi, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4e72a465306011f4ac2a88f03cd6c9dc"}]}, + {mod_dir, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ec5cbec9126f452057ed437dba2051b2"}]}, + {mod_disk_log, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"702d6f87d24465d11d91f561fd11f7b6"}]}, + {mod_esi, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e83eabd7527ed663b93fd5a58a587be4"}]}, + {mod_get, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8dd5d81c6a7cc426524180332edb7a14"}]}, + {mod_head, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3a62a5beb75a1b60206669499f77130e"}]}, + {mod_htaccess, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1bf3f03a28de0bf786813fc181fdb85f"}]}, + {mod_include, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"145c3dccff68b053b1db14d5f92488a2"}]}, + {mod_log, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5417983275ff4ded18c546c70b8cc7e5"}]}, + {mod_range, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"03a0b6a05ae0fd306c5b3f20bb6e05b8"}]}, + {mod_responsecontrol, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0ebe00aaf53af7508dabc9d09b949a0b"}]}, + {mod_security, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"423eb8f57b9a8bde28e3da13db3de59d"}]}, + {mod_security_server, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cca3960b3899a1a7a4581afc69d7a5cc"}]}, + {mod_trace, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"62fba170a84e8fdb39c8744f64b37a64"}]}, + {tftp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ade4b7390488800507debf97307bd963"}]}, + {tftp_binary, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"67a1747702ba0bff57a6f8aaa883b9d2"}]}, + {tftp_engine, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fb9e0ee93bfa57bd7ef5a038c23edecd"}]}, + {tftp_file, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"48fd419a1467c45c1e7057cdbb59a0a7"}]}, + {tftp_lib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f666dd774c5c60c7ff175b19ade12b2d"}]}, + {tftp_logger, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"151ed197576a35d060b7bbf3c74bdf7f"}]}, + {tftp_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7fc8de866dbc9c30b3d91a8adf8ebf0c"}]}]}]}}, + {application, + {ic, + [{description,"The IDL Compiler"}, + {vsn,"4.3.2"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/ic-4.3.2/ebin"}, + {modules, + [{ic, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fe764abce09fdd454d880128d9ddda2c"}]}, + {ic_array_java, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"227ce84fee6671f9cdf93fb8048f596c"}]}, + {ic_attribute_java, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"975e0b45c8a9ce1cb4551fdfb76cbd11"}]}, + {ic_cbe, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"43ac10b9d3c5142c747d99c3b9dad4d7"}]}, + {ic_cclient, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"73ec31c28859c6c5d6e5dc91b6ce5411"}]}, + {ic_code, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"02d51ffcaef78b26a0bc8c680938fb53"}]}, + {ic_codegen, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"41159947a7c4259a58fec12f96d02d69"}]}, + {ic_constant_java, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ca029a6c4023f792cdd8fb9052241416"}]}, + {ic_cserver, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bf63d17869ccb762e0edab496be39e09"}]}, + {ic_enum_java, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ab555fa7842eec8c99e22d11060e6430"}]}, + {ic_erl_template, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"04c3d10872a5ab6edd781ae24512b6aa"}]}, + {ic_erlbe, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"add3f7151efb782e2437bb626a7d51fd"}]}, + {ic_error, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6379a791ac55b3542b5db5a1e329439d"}]}, + {ic_fetch, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bdc5454c6fe20b3a28d3a10ea4a7b3ed"}]}, + {ic_file, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6597963c839cab5b5591eb1dcaa6a9a1"}]}, + {ic_forms, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9bcfeec18c0f2bc54dd64694b0f6d82e"}]}, + {ic_genobj, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"97c379af6629a74a7b70c60e6338a245"}]}, + {ic_java_type, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"40d0d5d7707b0d63119fdc658f7f3084"}]}, + {ic_jbe, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7e2429e630ce4f7dad22af0d4ab242b7"}]}, + {ic_noc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c8e61ad2dbb06818f812f1a3dcf0f16c"}]}, + {ic_options, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f9f64ecd00b68edfcf38b61e79bd0b80"}]}, + {ic_plainbe, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"44ee00595baf6554efbdb45d3ee28937"}]}, + {ic_pp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"857d2fb9fea30b14657b1c4a86d08386"}]}, + {ic_pragma, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4f69abbe96dd3cbebbff573664fe0997"}]}, + {ic_sequence_java, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fdf12c1c5c020249ba9966ed529e5062"}]}, + {ic_struct_java, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4120b045ef93f4db9bea6c9f14180ca6"}]}, + {ic_symtab, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9c8ba1bfdd061a5e6864f86c957d6408"}]}, + {ic_union_java, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b9b140a193c08210aa09a4484d9a54f3"}]}, + {ic_util, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c6ce2a93793c15e09c8e18ccca534772"}]}, + {icenum, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a53766074b7015a3bae4631d87f017e7"}]}, + {iceval, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d60924eb402c253265ef229824856baa"}]}, + {icparse, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f2a14e584b40aa5b9e79c5f3101dfb3e"}]}, + {icpreproc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"14b63dc40d8160ee25e0f829a0d088c6"}]}, + {icscan, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8c8e2841047e577935f05c0b5cb10b02"}]}, + {icstruct, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3fc6b7d763b490773a0c893a541b3d3a"}]}, + {ictk, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"00ad73c637ec333d51a0905c46381eb0"}]}, + {ictype, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8cfb0ed8d61bdff82302c4b52716ebf0"}]}, + {icunion, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"db222ee3335d7b431061d104f6ecf9b2"}]}]}]}}, + {application, + {hipe, + [{description,"HiPE Native Code Compiler, version 3.10.2"}, + {vsn,"3.10.2"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/hipe-3.10.2/ebin"}, + {modules, + [{cerl_cconv, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"3f8e5afb7f644e20ecc93eff288091d3"}]}, + {cerl_closurean, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"598014277bdc97eb3e42db827964786c"}]}, + {cerl_hipeify, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"c67cb3c827232c389de98edcb669a6f2"}]}, + {cerl_lib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"81c8c4cc2fddba367e557bb8fa3e46b1"}]}, + {cerl_messagean, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"d45d1cf2112a30de90c6e02674b471f5"}]}, + {cerl_pmatch, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"592ae9106c429413eef5bca3404a312a"}]}, + {cerl_prettypr, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"c10b7a51c482eaae5d5bb5156072faed"}]}, + {cerl_to_icode, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"975ca9009d46f139766227e24f00167b"}]}, + {cerl_typean, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"2407a7ab5367d3d2112283c1ddfc53a2"}]}, + {erl_bif_types, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"0a6c9083ace0be207cc54681c6cbf565"}]}, + {erl_types, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"42d756bf4eaf470785a1b81838979af7"}]}, + {hipe, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"32e6ef5c8585a438373c41e5a5d75d91"}]}, + {hipe_adj_list, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"e5bc155da44d7631411dfc1a02fec2ef"}]}, + {hipe_amd64_assemble, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"1647b309190377cb226db1314fcac5cd"}]}, + {hipe_amd64_defuse, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"d3829c95a7eed25abc393e29da9bbf19"}]}, + {hipe_amd64_encode, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"49079178cae281b4645ae6f25ce18838"}]}, + {hipe_amd64_frame, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"4476b9c0703b2a8473aa502dc6bdada8"}]}, + {hipe_amd64_liveness, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"9fab826ab4bd5d716173c1f3b3b4d347"}]}, + {hipe_amd64_main, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"52b41c777e65aeea7e35a9321585d34a"}]}, + {hipe_amd64_pp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"4eb339172dae5c27d67b4410de84f51f"}]}, + {hipe_amd64_ra, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"73bf464fdfd7cf668efdffc3fc78c352"}]}, + {hipe_amd64_ra_finalise, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"7bc4f317d89794f58a1a0bda3b599879"}]}, + {hipe_amd64_ra_ls, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"5c0509cfd228b140247a46214243a415"}]}, + {hipe_amd64_ra_naive, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"6a50f0f7d1c454c50975d6d0b3eb3c4e"}]}, + {hipe_amd64_ra_postconditions, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"1ed593df4c9da2fe96da00274117f1b4"}]}, + {hipe_amd64_ra_sse2_postconditions, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"277417561a1fed88867bfdafe9e1c580"}]}, + {hipe_amd64_ra_x87_ls, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"8684b37d2d952516b2f8e77426decaf2"}]}, + {hipe_amd64_registers, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"02db134b8e57405134b8e68a9f0588d3"}]}, + {hipe_amd64_specific, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"c66c33708abe9f32d36337c358a73530"}]}, + {hipe_amd64_specific_sse2, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"f0e4d5df03612b82d8cffecd5f9d4a84"}]}, + {hipe_amd64_specific_x87, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"3a28b90d577a9db6ef4b70d9defbd863"}]}, + {hipe_amd64_spill_restore, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"81a80af9658effa33fdfe85f6161a35a"}]}, + {hipe_amd64_x87, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"b55ded15ce4283908342b2824226406b"}]}, + {hipe_arm, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"160cf412bbc01adfb4229f8b73a45ba5"}]}, + {hipe_arm_assemble, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"62390a02348b3abffcb4502ff1b2b9f3"}]}, + {hipe_arm_cfg, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"30d169daa65fe2104260b4621d500e17"}]}, + {hipe_arm_defuse, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"c464aa34b089a594edfc1cdb7012f39c"}]}, + {hipe_arm_encode, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"ee3833e47107f465b35e3d9a255d0447"}]}, + {hipe_arm_finalise, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"74ce09dca62bfdfdbe0f667075f78c35"}]}, + {hipe_arm_frame, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"e46614b822aafd6233af080377bc8729"}]}, + {hipe_arm_liveness_gpr, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"19888211ce56a0eb039578ea485a7776"}]}, + {hipe_arm_main, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"b745515f7f9a5b4dc2e3f03f8dba82c3"}]}, + {hipe_arm_pp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"3b5de0ec46bf573c64151697e03dcbeb"}]}, + {hipe_arm_ra, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"d129dfc23327601b4615e91f849c214f"}]}, + {hipe_arm_ra_finalise, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"cdeccd5062db370b87cb350b317c041a"}]}, + {hipe_arm_ra_ls, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"fd59b7eba19bd0985bfc527377e815ea"}]}, + {hipe_arm_ra_naive, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"cbbdef9b7829ce07fc482451a8f7c7a8"}]}, + {hipe_arm_ra_postconditions, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"2a3a8e58a6ba75ca3902348a5b43ec79"}]}, + {hipe_arm_registers, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"7bd890ef97657715f12f031658d4c9c4"}]}, + {hipe_arm_specific, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"611f5b731b1c7fa6f589010db3443a81"}]}, + {hipe_bb, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"66afe906c353f43505649b33dfed45a9"}]}, + {hipe_beam_to_icode, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"826bf8aa6513c06c61e08faa9383b4fc"}]}, + {hipe_coalescing_regalloc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"cf5f22f7e27c8ba6a1e73e29900fb096"}]}, + {hipe_consttab, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"4a430042156f62e55b404d38b82ef6c1"}]}, + {hipe_data_pp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"7843ffb243b1c8d66351c1452fec1cf5"}]}, + {hipe_digraph, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"3caa6181724dc59e70a3c5ee5b886233"}]}, + {hipe_dominators, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"4f7038336d002e637edb3b57cc6b7293"}]}, + {hipe_dot, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"0218e226a92b4a444c90b4c18be48c76"}]}, + {hipe_gen_cfg, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"75a06ae623c2dd5a78903d11ba61cfd6"}]}, + {hipe_gensym, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"1b5a357fb4e6833e55b574343d116217"}]}, + {hipe_graph_coloring_regalloc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"e25c88384aaa7b7a16c5849b31db4fcf"}]}, + {hipe_icode, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"899c47579553070995c5701f16f2c1ca"}]}, + {hipe_icode2rtl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"cba4203ea542c9abfac6eaa92cb269e9"}]}, + {hipe_icode_bincomp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"4e211977eb23242d6a2bf0b099eff090"}]}, + {hipe_icode_callgraph, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"f79f8f10f1aaaf4280abf06cfa40d56d"}]}, + {hipe_icode_cfg, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"ca9529e58b378b731ac6aac84218e2da"}]}, + {hipe_icode_coordinator, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"3a1caa6d31d48a3fb311a2ea97f0c30c"}]}, + {hipe_icode_ebb, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"b6b088a13c02a03e5a28247be6d45b94"}]}, + {hipe_icode_exceptions, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"40dfad7ac3602fece6bb4b5a8c9ab98b"}]}, + {hipe_icode_fp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"f3fcc6b3d555dfa882e7483eb64a6571"}]}, + {hipe_icode_heap_test, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"fed11d612f8f3da9ea1e4cc67389eff5"}]}, + {hipe_icode_inline_bifs, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"3027c916d2ecc9762123585e1d91f467"}]}, + {hipe_icode_instruction_counter, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"cf488cc5eb29636045d2880b33254711"}]}, + {hipe_icode_liveness, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"bb99ee17bd466d1b802a42b0583e26d7"}]}, + {hipe_icode_mulret, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"323e6103d2511e5bd4a87ad2b4dcf3c3"}]}, + {hipe_icode_pp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"56edb2552a5c36757005cebd6196f7ce"}]}, + {hipe_icode_primops, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"3f14ad0079bdc8cf1feb08c6c2da287a"}]}, + {hipe_icode_range, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"0040719dd6effa173e861e4eb0e3cff6"}]}, + {hipe_icode_split_arith, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"5575b7299b149e93d358fdeccc999652"}]}, + {hipe_icode_ssa, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"090ca01ba76f97f346c6fb260751cad3"}]}, + {hipe_icode_ssa_const_prop, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"5944b123b3fcd4b0839b316ee68ee36d"}]}, + {hipe_icode_ssa_copy_prop, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"997be266f8aa90058e1cc47807628ab4"}]}, + {hipe_icode_ssa_struct_reuse, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"8fbe27064d4bb5a27507564d4ace240b"}]}, + {hipe_icode_type, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"cd5755e095fcdc667aa925440a072104"}]}, + {hipe_ig, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"023433ebf566fdd844f091a0d35af764"}]}, + {hipe_ig_moves, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"b1d86094e8232686f4e234cca76178c6"}]}, + {hipe_jit, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"d52c6fa1354f23d6c3234f2ba0adb467"}]}, + {hipe_ls_regalloc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"af8f6022eafbf853ada08fe69e9509ca"}]}, + {hipe_main, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"c5c32cf830833284942651c29d48e796"}]}, + {hipe_moves, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"c4b6be3fb7b1fd8acaa60cf09a34ab92"}]}, + {hipe_node_sets, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"8f506e9e71db4336c1ec699b1335dc17"}]}, + {hipe_optimistic_regalloc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"43cd34d83f3c513ee455a446628c39eb"}]}, + {hipe_pack_constants, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"09e240bfc2522acbaa543f356a28f9af"}]}, + {hipe_ppc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"b4a1ef1f5d56e249be91954a55b35b5c"}]}, + {hipe_ppc_assemble, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"be62cec21a026c5385d2482369ac59a0"}]}, + {hipe_ppc_cfg, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"7d0362cb062e78fb25852d9fcf943371"}]}, + {hipe_ppc_defuse, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"45a4ac6be649d5ebd584abd44704addc"}]}, + {hipe_ppc_encode, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"fb5b41996c46e440e0292565c786d9a2"}]}, + {hipe_ppc_finalise, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"1475ac44aff754105fdd4e85687346ab"}]}, + {hipe_ppc_frame, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"1fd18b642e945b3f6b384549c810f5c6"}]}, + {hipe_ppc_liveness_all, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"5194b99327e725de7a0c94abb4d35974"}]}, + {hipe_ppc_liveness_fpr, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"b3958a1138f1f112f5ff4b357520fa4d"}]}, + {hipe_ppc_liveness_gpr, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"fc4585d446b47d4151671b7bc83f86eb"}]}, + {hipe_ppc_main, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"ec4dd9d536fb6aa5cdb418dded96184b"}]}, + {hipe_ppc_pp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"c37b9de73810ceeaca37bc0520a76884"}]}, + {hipe_ppc_ra, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"db4deb5ea2a237ff1e0984f7979e5d3f"}]}, + {hipe_ppc_ra_finalise, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"c4376f33857d9cb0cea29ff783ea82cf"}]}, + {hipe_ppc_ra_ls, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"6ba2df5f54c48dc90c42547e8bd2ca48"}]}, + {hipe_ppc_ra_naive, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"ba3d03b4267f315b10ed939a37d4597c"}]}, + {hipe_ppc_ra_postconditions, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"a9d4ca393bff97c1931d0eb18d38a811"}]}, + {hipe_ppc_ra_postconditions_fp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"742e3f111a16eb5ca003f1a97804e5a9"}]}, + {hipe_ppc_registers, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"40dd287c6853767e7083a8c5549681ce"}]}, + {hipe_ppc_specific, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"d5e2330aa55edd677ecf3e77bf659781"}]}, + {hipe_ppc_specific_fp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"34a6f358c60c47ebec7956b66205062f"}]}, + {hipe_profile, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"210939fd9ea20991d7fae07b12348d35"}]}, + {hipe_reg_worklists, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"ee79fa6eb3bca9a4f0025d9e4ce02a72"}]}, + {hipe_regalloc_loop, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"19fc9f539fd5abb2ecc5aeaf6c2526db"}]}, + {hipe_rtl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"2ab93246a0c75f83327de3e0234dbe08"}]}, + {hipe_rtl_arch, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"3481cc7240b928da18df9e61214ceb25"}]}, + {hipe_rtl_arith_32, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"328deb7987296b869279c7c0d588f337"}]}, + {hipe_rtl_arith_64, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"64cc932e691e7743d06642103170de55"}]}, + {hipe_rtl_binary, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"198df75c4eefcd2b7a7f769922d4ce60"}]}, + {hipe_rtl_binary_construct, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"7a1b57215669ed36c40b335e6826be2c"}]}, + {hipe_rtl_binary_match, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"1c22996f5b79a3818503a19059bdaf8e"}]}, + {hipe_rtl_cfg, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"60570bb8a1cbde7c72ad1c37e2b8e17d"}]}, + {hipe_rtl_cleanup_const, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"a555a1c325dd9b3ae1775881af8abfad"}]}, + {hipe_rtl_exceptions, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"6c7f64efbed1c8e51f2323fa693d3b89"}]}, + {hipe_rtl_lcm, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"bd3735cbd4bc9eb9254b0c2ee67cd1ad"}]}, + {hipe_rtl_liveness, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"0dcceb8fd82c12480e42399dd2869c41"}]}, + {hipe_rtl_mk_switch, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"8890cf7e39302f57f3adf8987755b34c"}]}, + {hipe_rtl_primops, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"c734e269cbc4be78cb3fe47fa55053a5"}]}, + {hipe_rtl_ssa, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"4d9ce36d8dc1168eecf173bde8a0871a"}]}, + {hipe_rtl_ssa_avail_expr, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"ef5653db422ed4115c734d9676f3b030"}]}, + {hipe_rtl_ssa_const_prop, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"598dee97d9fd44735a534b250bf60e2a"}]}, + {hipe_rtl_ssapre, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"93b3ea7957d2008d763bd4416ef98277"}]}, + {hipe_rtl_symbolic, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"4e6b19de45d978326014a378368a6f8e"}]}, + {hipe_rtl_to_amd64, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"6afb4d232649b0a0ee54e5a4859e85ce"}]}, + {hipe_rtl_to_arm, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"a12eb244baec0e0bcd2d39353ac69b90"}]}, + {hipe_rtl_to_ppc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"521f595296e6c1bf0b7d1caf59bbfb77"}]}, + {hipe_rtl_to_sparc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"66783d3f670bd939159b0abf3548dddc"}]}, + {hipe_rtl_to_x86, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"2b4ebecd4e2fa29e952c650809ec89b6"}]}, + {hipe_rtl_varmap, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"2b1e6ba5714a0764c0897a780fb38c8e"}]}, + {hipe_sdi, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"c305600fbb8905b9b0cf792f2f85ed72"}]}, + {hipe_sparc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"6a5cf680abe539d1dfa669cb52ce1f80"}]}, + {hipe_sparc_assemble, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"330f4c7130dc215c911ecfd48d9dedde"}]}, + {hipe_sparc_cfg, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"d8278464e9d1d65437625517255ae2ab"}]}, + {hipe_sparc_defuse, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"a7f131d52962288326e844f28d13d4cc"}]}, + {hipe_sparc_encode, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"c1b5971e5e6f3304bcc00f1abeb268f7"}]}, + {hipe_sparc_finalise, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"22d88316138d80c3ecf41ced21ec25cf"}]}, + {hipe_sparc_frame, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"623fdaf78bfaff2b07733eb4a211f79b"}]}, + {hipe_sparc_liveness_all, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"2bd5c26371c946fdbf9c1530c1478ca1"}]}, + {hipe_sparc_liveness_fpr, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"7dc401039841503524934a1b97990c2a"}]}, + {hipe_sparc_liveness_gpr, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"4c5e32e6adbbc37b4f793e8bde52ab2f"}]}, + {hipe_sparc_main, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"3c063c4c5b1bd8ec02c6ffe60c561056"}]}, + {hipe_sparc_pp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"f89846e24afb3795d259291e4613c155"}]}, + {hipe_sparc_ra, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"6925c18182b17ee978041e26fbf490b3"}]}, + {hipe_sparc_ra_finalise, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"45cef8c32ae3b2f6f01911592016924b"}]}, + {hipe_sparc_ra_ls, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"2eedc8b13aac2efcd2e3649afd845d02"}]}, + {hipe_sparc_ra_naive, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"81f0a231c4bde04b132bdb6748774c10"}]}, + {hipe_sparc_ra_postconditions, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"549d7dfb54dce00bb7f5317306694308"}]}, + {hipe_sparc_ra_postconditions_fp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"9de491abdbbc1c156a20a692d463965b"}]}, + {hipe_sparc_registers, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"1a4dd5b6dc938d539fead6b1ad9e2ba0"}]}, + {hipe_sparc_specific, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"809b836428fcb194565eeee86ecf138b"}]}, + {hipe_sparc_specific_fp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"4bf2be9b351b82024e81eabfd68806f9"}]}, + {hipe_spillcost, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"b9ef65406aa671e28d1bd8428f102fe9"}]}, + {hipe_spillmin, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"bde0ad7813cb8f86fc4ff110090af2da"}]}, + {hipe_spillmin_color, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"e277f11303f44d6ea07be695c1057d7f"}]}, + {hipe_spillmin_scan, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"b007825bb206e086b9ffc943213aa625"}]}, + {hipe_tagscheme, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"568fc377e498aec5a73e1b2c9cd29432"}]}, + {hipe_temp_map, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"56dff1fb8175d1d7c32f7e8d95e10488"}]}, + {hipe_timing, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"c3238c3b4adc08c290c37ba1ea7d3a31"}]}, + {hipe_tool, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"f93194221b0e3756c9f0f70127b205bd"}]}, + {hipe_vectors, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"c4e6ef55b233f27c27bd2f781baf9c94"}]}, + {hipe_x86, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"051e4ee3dd5298e2cee05b1fca82e64d"}]}, + {hipe_x86_assemble, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"d1829f13a89049280e7cb22cd394af0d"}]}, + {hipe_x86_cfg, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"b9d6a090c32c03e6e91deac9bbb167ae"}]}, + {hipe_x86_defuse, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"c81bb7a0dd72b256c57fb37042de68ff"}]}, + {hipe_x86_encode, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"386d1abc98765c09c6bc6fe44cf2748d"}]}, + {hipe_x86_frame, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"db2a440f5975688c7bf9a88c47aaf627"}]}, + {hipe_x86_liveness, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"8783c19717dda46b566c465ba85b2588"}]}, + {hipe_x86_main, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"236cd462abe386223cefe606b4f48928"}]}, + {hipe_x86_postpass, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"57e5cb6ad12dceef612122c8f759ac15"}]}, + {hipe_x86_pp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"6efd3b5cd8c70edbd326ffe9457a3192"}]}, + {hipe_x86_ra, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"1e8b7f27a05e1e7fac9ea95cdd394909"}]}, + {hipe_x86_ra_finalise, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"4a3c30788866a5e997e0a1687279732e"}]}, + {hipe_x86_ra_ls, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"bb13a4d08391fe3f212fa4eba816029b"}]}, + {hipe_x86_ra_naive, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"e26c0711db5e891c86b64da12fe064ff"}]}, + {hipe_x86_ra_postconditions, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"e3d6ad622a3017744106b653324c0edb"}]}, + {hipe_x86_ra_x87_ls, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"a6092f1853a7a04f8d16228f6183dcc0"}]}, + {hipe_x86_registers, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"ce77b4ffff06c9532943ad5f6907b18e"}]}, + {hipe_x86_specific, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"ad074b1e645c06c2137a46cd19f88b72"}]}, + {hipe_x86_specific_x87, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"a20c2c2b1742aa084dbb7395a92b650d"}]}, + {hipe_x86_spill_restore, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"88e191ef5057ea6a50c75af85c814013"}]}, + {hipe_x86_x87, + [{loaded,false}, + {native,false}, + {compiler,"4.9.2"}, + {md5,"6edcc888c87ffc96414a8dce57d691da"}]}]}]}}, + {application, + {gs, + [{description,"GS The Graphics System"}, + {vsn,"1.5.15.2"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/gs-1.5.15.2/ebin"}, + {modules, + [{gs, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9d416ae60d6cda2ea55a05dbde8a53f7"}]}, + {gs_frontend, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"eb02484f42ac799bdd086f6832b72330"}]}, + {gs_make, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ea7a1edc4bd5b9867ce924130851f295"}]}, + {gs_packer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4c5d911152526836f3487cd3de6b0bf9"}]}, + {gs_widgets, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2efa721783d863bca4ff2e116c9593fd"}]}, + {gse, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9355057cfe2b70da376f208739bd7c06"}]}, + {gstk, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"684b9d8f370368e25ea2ca2ac708c1ee"}]}, + {gstk_arc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1cd1114560c3839fb84380975d61d68b"}]}, + {gstk_button, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"29ce4f10fe8dc2bb85649018aa64d71a"}]}, + {gstk_canvas, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a637d6932415873666ed040817ed2a72"}]}, + {gstk_checkbutton, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3cad265e62fb4cbeda02c089b5b309bb"}]}, + {gstk_db, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"dd236aeb7ff4658fd1a9d1302602a7af"}]}, + {gstk_editor, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"17dd7595545d33bb3143ac3995711b39"}]}, + {gstk_entry, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2740de840e6b8871909dfedd96d4b5b4"}]}, + {gstk_font, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bc2fef06167d48c71cc434fa7411ca95"}]}, + {gstk_frame, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5113cb91ebb88a4cb1a0b4cb7665607d"}]}, + {gstk_generic, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3d392d9f2e6c6220245cff065e99a3f5"}]}, + {gstk_grid, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"61def27e9610041778245948e5f82be1"}]}, + {gstk_gridline, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"40c7173521b57e4c9243ec5258f65d6d"}]}, + {gstk_gs, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9c9ab7ac782c3e36e201d4760f37e478"}]}, + {gstk_image, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"50a6a6b41de78e4f06b0c98cba97992a"}]}, + {gstk_label, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"00b5826ce30fc11e417a7a43f0c7e563"}]}, + {gstk_line, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b7785bc56e2f32b575a4240a60994d62"}]}, + {gstk_listbox, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"053218bec49478a8334df6b0818e981f"}]}, + {gstk_menu, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ccf11b45fdd908fafb781c897d379370"}]}, + {gstk_menubar, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e801f2c6eccc8258d719028b706ec624"}]}, + {gstk_menubutton, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1fc2d88da997bdc39a24f3f0db9963b3"}]}, + {gstk_menuitem, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6a4442a7307d34c544783c9d22433135"}]}, + {gstk_oval, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f4775c1b7522750f395f28a94eefe453"}]}, + {gstk_polygon, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fdc96f316574995486c842b612722e25"}]}, + {gstk_port_handler, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"95ec5d20c905e8cc7fef2df5f99ceb88"}]}, + {gstk_radiobutton, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b67bb9cafd3bf67b210d7b0e0b1bd992"}]}, + {gstk_rectangle, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6bf1f8e7953532468393090fe8d56ba2"}]}, + {gstk_scale, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"848c7ee845d1a59a0a7c4775f64f220e"}]}, + {gstk_text, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"719252f8d069544886ec473e16688530"}]}, + {gstk_widgets, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"29b540f4612eb1f1e65123f08809bee4"}]}, + {gstk_window, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"746a06674df1cd96678689e6ab92a95a"}]}, + {tcl2erl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f67bcc59683d0c578cba1c0062ff6b3e"}]}, + {tool_file_dialog, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3763cc96ed8e2a6136a4c15e54a9adee"}]}, + {tool_utils, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"96edfeab61de9b40618e7808d62225b2"}]}]}]}}, + {application, + {eunit, + [{description,"EUnit"}, + {vsn,"2.2.4"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/eunit-2.2.4/ebin"}, + {modules, + [{eunit, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"800601aeceaf1de519df273ca25741b5"}]}, + {eunit_autoexport, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"48f889ffaa560238fa2269614f93bbce"}]}, + {eunit_data, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ed89782dac4c2b21da64d92bf74f1e22"}]}, + {eunit_lib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"949ed8c5f494a8678c6f29775a7b5154"}]}, + {eunit_listener, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6f107b19b4ecf45031a93afa5ace611f"}]}, + {eunit_proc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cfc2da427b2bf7ba843f6b8d8121e2c9"}]}, + {eunit_serial, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f07a040ebbba4af90fa9668c410befba"}]}, + {eunit_server, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0842dedb36c3b1cd91229a7e4abfe328"}]}, + {eunit_striptests, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"473b48509d28519ba18cfa83a8dea8b4"}]}, + {eunit_surefire, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f1e6a5cebf210cdd8a558cd32b96ac13"}]}, + {eunit_test, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cc3897e05a5146b24c109fbc5da83e86"}]}, + {eunit_tests, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5d2b6b165201e0aad13a8d8f4d542f59"}]}, + {eunit_tty, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a4faaab287e1fa52837cdfd1b58c7faf"}]}]}]}}, + {application, + {et, + [{description,"Event Tracer"}, + {vsn,"1.4.4.4"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/et-1.4.4.4/ebin"}, + {modules, + [{et, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"82db3e8683420a2adb933306c8c822e8"}]}, + {et_collector, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"dd43f7a22b3c3e6a1799a88163c3d441"}]}, + {et_gs_contents_viewer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"44e7ea855be084e48cd364735d79f5f7"}]}, + {et_gs_viewer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d4ef2a5673c20444b198bdc185cc637a"}]}, + {et_selector, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"267f60d2ecdad671eae269cdd2ff30f6"}]}, + {et_viewer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3ae9af3449c17f045d25ca424e9873ae"}]}, + {et_wx_contents_viewer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6d14826378988286a32fc85ca4246325"}]}, + {et_wx_viewer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"87f45e31d50a82d9db2443ddff14ad22"}]}]}]}}, + {application, + {erts, + [{description,"ERTS CXC 138 10"}, + {vsn,"5.10.3"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/erts-5.10.3/ebin"}, + {modules, + [{erl_prim_loader, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"719e5362c7c1f0d1fd96601b7f814981"}]}, + {erlang, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"04b2444affe04bb9287d86e0e0c80578"}]}, + {erts_internal, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a95c0409fe7b4ccf6e2fe509bfd23da8"}]}, + {init, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"55bb9fddcdf820938be2efee15eccd82"}]}, + {otp_ring0, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"47fe4e7e2d2a5f20cd3a9393e0743e57"}]}, + {prim_eval, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"16d4fc3a8e5e2ef7200bd866fe8b1abb"}]}, + {prim_file, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"da0745178ab8aa8fb8d3a373970ebfdd"}]}, + {prim_inet, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4993598825a1083526cbc23cf027f494"}]}, + {prim_zip, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9280fc2398f9eb3bd09f74cfa1d6d267"}]}, + {zlib, + [{loaded,true}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"811834d04ac37676048717e1c51f63ac"}]}]}]}}, + {code, + [{path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/erl_interface-3.7.13"}, + {modules,[]}]}, + {application, + {erl_docgen, + [{description,"Misc tools for building documentation"}, + {vsn,"0.3.4"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/erl_docgen-0.3.4/ebin"}, + {modules, + [{docgen_edoc_xml_cb, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"29c8b94e559528ca0aeacee089f52bcf"}]}, + {docgen_otp_specs, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c6d53404b1059d2da87ce44bee49d2dd"}]}, + {docgen_xmerl_xml_cb, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"274ef03ec5cb146346fea794e77febcf"}]}]}]}}, + {application, + {eldap, + [{description,"Ldap api"}, + {vsn,"1.0.1"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/eldap-1.0.1/ebin"}, + {modules, + [{'ELDAPv3', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"655b60d1b5b0629024e2a78708c64518"}]}, + {eldap, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"df60096d034768188e0fd6eaa0fd571c"}]}]}]}}, + {application, + {edoc, + [{description,"EDoc"}, + {vsn,"0.7.12"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/edoc-0.7.12/ebin"}, + {modules, + [{edoc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f2749685cb80a536ad42426933220065"}]}, + {edoc_data, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3a444b7ae3acc249aac7fe40b38355af"}]}, + {edoc_doclet, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"77b3ccaf177983dab1991425fd3d714b"}]}, + {edoc_extract, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9effef62cfe9939a4c80b43b86041c6c"}]}, + {edoc_layout, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f2b79a133f490b4de09b13f7519d37dd"}]}, + {edoc_lib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4f421fb61a9b2c711d5fc28387b0ffd0"}]}, + {edoc_macros, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ddb1e78cf2ddd20aadc87329067286f3"}]}, + {edoc_parser, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"02fe39575dfda2cffd6031f6c8f470eb"}]}, + {edoc_refs, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5a3ba4e7f5211445d74a4d19bc4c5963"}]}, + {edoc_report, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bfef03c1f2c7de294972d0ad185a3a11"}]}, + {edoc_run, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0db629008caa57ebafde1dda9672306c"}]}, + {edoc_scanner, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"165a8e826f458ac6de7c50c395d012df"}]}, + {edoc_specs, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"21a5746822e2ae01421fb064d9c8ccfd"}]}, + {edoc_tags, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c9ad335a1ce6b99189cfbfaef2ca2038"}]}, + {edoc_types, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"84530d798ce334278df4dea8a69098f4"}]}, + {edoc_wiki, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"eabda8c28daf0cdc040eef58f31cc6a8"}]}, + {otpsgml_layout, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a511240c5864dd31d4df687465e355f6"}]}]}]}}, + {application, + {diameter, + [{description,"Diameter protocol"}, + {vsn,"1.4.2"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/diameter-1.4.2/ebin"}, + {modules, + [{diameter, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b2fdb2feddc71bda9175711150823325"}]}, + {diameter_app, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6dcc769947f323a9ff306c9bcab4dd2c"}]}, + {diameter_callback, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d8c76e1ccf47e3c781cbdf3c8d3e293f"}]}, + {diameter_capx, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"65e483a5f121d99db830329f3dc050cb"}]}, + {diameter_codec, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9bd2e1ef215e88519ca3865601e479dc"}]}, + {diameter_codegen, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"33696e30585762fe29ca103d67ffbb04"}]}, + {diameter_config, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"76e885acd24a697d19b07ce5446f5c2b"}]}, + {diameter_dbg, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0954c1f71a204a0f2c8b3682d520c704"}]}, + {diameter_dict, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1ed21a8d2eea031aa736e95870a7a165"}]}, + {diameter_dict_parser, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c90e506d7eba4f18547238b8f025ce5e"}]}, + {diameter_dict_scanner, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b3fc9ee26b660a97ad67b4c8728a0b75"}]}, + {diameter_dict_util, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"70475203e0968747889eecc533af3f0f"}]}, + {diameter_etcp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"dde08c8d8311e2700c59b741274923fb"}]}, + {diameter_etcp_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"85fc8320ca9eb8daceb03727bdadb6f8"}]}, + {diameter_exprecs, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"728aa8871c778eacc02313d922dde7ae"}]}, + {diameter_gen_acct_rfc6733, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"53fb49bb8c354f36d6e1ad6366fe02a2"}]}, + {diameter_gen_base_accounting, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"845f38b99248c11778453b628ddb4fed"}]}, + {diameter_gen_base_rfc3588, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f6cd02c8318f4ccc198bd08d1ac789fb"}]}, + {diameter_gen_base_rfc6733, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"49edd3b9955c82c872169f769c833482"}]}, + {diameter_gen_relay, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c970d47476d2832f510b6b03699c95c6"}]}, + {diameter_info, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"472b763fc9554c0c92992a3b36177667"}]}, + {diameter_lib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8d49799607d7c7792a79dbc434b4d53e"}]}, + {diameter_make, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"249d7f673e7f192ddff7c66b578e886e"}]}, + {diameter_misc_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3996fa63b0e083301d35fc6d88b75ce4"}]}, + {diameter_peer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"89f28d8d35bdeb8b05995daffb8d868c"}]}, + {diameter_peer_fsm, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"df03404577882e8cfba57087c91fe3ef"}]}, + {diameter_peer_fsm_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b25500795639e63d9a591e33df6e4af7"}]}, + {diameter_reg, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1e7d427dafe432249d3535bc9e6ec538"}]}, + {diameter_sctp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cb7487b2c41e3520b1a46738699a88c8"}]}, + {diameter_sctp_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a02584b6b31789dd38493fd1a8d7d3e3"}]}, + {diameter_service, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e990f54abf1c8706cd7717cba717594c"}]}, + {diameter_service_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a66f4714fa96fd7d289260002851cbf9"}]}, + {diameter_session, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d348e0ca8d3c827d647c3bea8f9c7691"}]}, + {diameter_stats, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f12a18f52de33ca77dacd1bba99680c8"}]}, + {diameter_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c910b68b3d0760f595a81ca58b1337f8"}]}, + {diameter_sync, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ff62cfc82b044d2300345ac7912fe320"}]}, + {diameter_tcp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e4dae7482d9a79d4ead66ef14d1c3a48"}]}, + {diameter_tcp_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c1b03a96691e03eb93144bc50022a007"}]}, + {diameter_traffic, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6d351fdbef0536bba235fe102fe8e697"}]}, + {diameter_transport, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"386e129e240e91794ff79e1da6c6966a"}]}, + {diameter_transport_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c9f8da23c3c870b8a6ed8648d7aac2d5"}]}, + {diameter_types, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d2ecf24e368d30dbef34527e2971caf8"}]}, + {diameter_watchdog, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a0ab7bd910bc959c0d1b64f0a2ae4bda"}]}, + {diameter_watchdog_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e4b16aeb2713fd42bf5e9da7cbe43bcf"}]}]}]}}, + {application, + {dialyzer, + [{description, + "DIscrepancy AnaLYZer of ERlang programs, version 2.6.1"}, + {vsn,"2.6.1"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/dialyzer-2.6.1/ebin"}, + {modules, + [{dialyzer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"929cdc37a18725b9710b9c4345c3aca0"}]}, + {dialyzer_analysis_callgraph, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b679e22bb1edb9f0225b79d995342dc5"}]}, + {dialyzer_behaviours, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5fb71e7e5129b4c2f74cb529d8a745c4"}]}, + {dialyzer_callgraph, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5b03b559fdab4c77a8c955cdfe7a2036"}]}, + {dialyzer_cl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"79a2208b0cc03af530473d2d2f49587f"}]}, + {dialyzer_cl_parse, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b4fcced00882cfef0262398a14319c2a"}]}, + {dialyzer_codeserver, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f5c8a1600210988f627559bc16a49a65"}]}, + {dialyzer_contracts, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c002e8bcddf711ae9feef14b88f28873"}]}, + {dialyzer_coordinator, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"51efdc15e07eaa495060e420585bb74f"}]}, + {dialyzer_dataflow, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ddb43241a51460b67c67780ca6174bef"}]}, + {dialyzer_dep, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ffffdcfd7edb9901be2e92b6d3a5f082"}]}, + {dialyzer_explanation, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"79c9bc71edcc115a03c1bb00a4133627"}]}, + {dialyzer_gui, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ec41553832cb5f49cce3b123ec763448"}]}, + {dialyzer_gui_wx, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"00f5ef9bd8202d5bc303fca27c740b00"}]}, + {dialyzer_options, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"713bf0249b3bb22c7461498b908db812"}]}, + {dialyzer_plt, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e5b1ecae532cb2887c942c6bda2c7dc7"}]}, + {dialyzer_races, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ec1b2f026e1dfd438fbb48dcf16a19de"}]}, + {dialyzer_succ_typings, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"12a59523b727169f2f415b6e57768910"}]}, + {dialyzer_timing, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b170424f433845fb9aab3e554ea61044"}]}, + {dialyzer_typesig, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b6670ae353fa06c5c8a5f301a7079ca6"}]}, + {dialyzer_utils, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cac59b9f59802633948d271fcf8ff92d"}]}, + {dialyzer_worker, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1e9ff1cc342b308c73bab8c607a8437e"}]}]}]}}, + {application, + {debugger, + [{description,"Debugger"}, + {vsn,"3.2.11"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/debugger-3.2.11/ebin"}, + {modules, + [{dbg_debugged, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"78bf1d9b43c718da5e198af36cabb1ce"}]}, + {dbg_icmd, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"615470a6677e03a603c24cf821ba3471"}]}, + {dbg_idb, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0e78e73c63bfe9149a11122857355f29"}]}, + {dbg_ieval, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0e49ed51a1a1e7581334308cd3c9195e"}]}, + {dbg_iload, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f249c44fee09e35262d2cafbfa22ce49"}]}, + {dbg_iserver, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6a2911ffbd531888ac6e1b96a5475436"}]}, + {dbg_istk, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ae44e86b7893633859292861275bdb7f"}]}, + {dbg_ui_break, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e5397708044bd37bac2a6f4e24edbd30"}]}, + {dbg_ui_break_win, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c974a8a9b180cfd4ccbcfd31a7bb88e5"}]}, + {dbg_ui_edit, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7faadd987bb74826e5f5865d725ca177"}]}, + {dbg_ui_edit_win, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0e912e444704ad322b3e25fc6393c068"}]}, + {dbg_ui_filedialog_win, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"06a6b13cd9bcfe7d7d203a981352cfaa"}]}, + {dbg_ui_interpret, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"dcf7a340530f4807d774d4c719a1dbbf"}]}, + {dbg_ui_mon, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5c79f2debfab06b86990ef7e390a61b7"}]}, + {dbg_ui_mon_win, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8c43cdde20d4e66b6f51ef903af75250"}]}, + {dbg_ui_settings, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8deedced7307e14f36cca3d9fe7e367f"}]}, + {dbg_ui_trace, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c817c2cc2f62354d4f59be8b6e6fac96"}]}, + {dbg_ui_trace_win, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"db1abdd3b7a7b45d3c74dbd9c48f07e8"}]}, + {dbg_ui_view, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b10a46e072053a225a894ed76dceebca"}]}, + {dbg_ui_win, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e51ec8a33c335245583f7a9ba8728f66"}]}, + {dbg_ui_winman, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2056472842990c08dfdb81e56df2caa8"}]}, + {dbg_wx_break, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"55c7dc041c4cd1b1da98d49def9c2b15"}]}, + {dbg_wx_break_win, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ad9cde7d28f7de18dda8da80d97a8f00"}]}, + {dbg_wx_code, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"27abac65970e6f7c6bbaca07e9ead6a4"}]}, + {dbg_wx_filedialog_win, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"da924842b25d80b7b258100a4e597810"}]}, + {dbg_wx_interpret, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8549ef4a5bad09472dccd1cb3ab2c764"}]}, + {dbg_wx_mon, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"09140d34a402d7183cf9dfecb0b2b6e8"}]}, + {dbg_wx_mon_win, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1fefe3be53da62cf504daf354579d910"}]}, + {dbg_wx_settings, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"350aed0cb189f0b91979fc38752fd4c4"}]}, + {dbg_wx_src_view, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"644bfb2c2d8fc6e9296722fef5f05b57"}]}, + {dbg_wx_trace, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"024358a893f9b37296fc0c416074a4b1"}]}, + {dbg_wx_trace_win, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b2348218e83d1704bcf894e71c2f3e82"}]}, + {dbg_wx_view, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3d37489d27927cff9f19f76bc0c816c9"}]}, + {dbg_wx_win, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d94add4e9adade091198438a278501a8"}]}, + {dbg_wx_winman, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"caa1febd36494a9088fddbd5557c503f"}]}, + {debugger, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2e242b76bc941785f65d1cf819fd98a5"}]}, + {i, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2bebfb4e91c343a1ad89f1124b06e190"}]}, + {int, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e1d4c0b2e30129359db05d3bc4df646c"}]}]}]}}, + {application, + {crypto, + [{description,"CRYPTO version 2"}, + {vsn,"3.0"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/crypto-3.0/ebin"}, + {modules, + [{crypto, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"858d0e1779f13a6bfde511898916ae94"}]}, + {crypto_app, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6d2de1cd4927d57e8eaa4467404c8c02"}]}, + {crypto_server, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"17e05e4b0d772036706b76ba8f68de2e"}]}, + {crypto_sup, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1342a18fe8d994974e41aa3e351d8500"}]}]}]}}, + {application, + {cosTransactions, + [{description,"The Erlang CosTransactions application"}, + {vsn,"1.2.13"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/cosTransactions-1.2.13/ebin"}, + {modules, + [{'CosTransactions_Control', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9ee94b22194357e2374fe2c026d2a9fb"}]}, + {'CosTransactions_Coordinator', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bca2be777e58bf130a3bf48252c0c0cb"}]}, + {'CosTransactions_HeuristicCommit', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d12c1a0988d03c64a606ba471794e3cc"}]}, + {'CosTransactions_HeuristicHazard', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"79d0dc47e6759987e5b45281bc4c39f2"}]}, + {'CosTransactions_HeuristicMixed', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a77cb11ccf269fa85f2194ab16ec5ebb"}]}, + {'CosTransactions_HeuristicRollback', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"67a56bf7b8084c29dd10db9daa8e08f7"}]}, + {'CosTransactions_Inactive', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8f94debdaa1912d18bbea77492e6fc88"}]}, + {'CosTransactions_InvalidControl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b14b9b82b831e56235c1bca1f6e02e16"}]}, + {'CosTransactions_NoTransaction', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"24252bfbc89f79dac5c90b35e35a66ad"}]}, + {'CosTransactions_NotPrepared', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ddbcd30a479a50fa2fed4b0cb019c0bd"}]}, + {'CosTransactions_NotSubtransaction', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3904cf57a879720704d8b725802cc530"}]}, + {'CosTransactions_PropagationContext', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4d0dd57873deb42ef62f2e9e8620e111"}]}, + {'CosTransactions_RecoveryCoordinator', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2a670d242e21803d3a559b812b3f3bfd"}]}, + {'CosTransactions_Resource', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"78bdc7f9989a5277bde7e066804fa1c0"}]}, + {'CosTransactions_SubtransactionAwareResource', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e1194d19b4db72b1c571aec1847fa65f"}]}, + {'CosTransactions_SubtransactionsUnavailable', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d6ffc90a293248735f58984f7a9f4fa9"}]}, + {'CosTransactions_SynchronizationUnavailable', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9858316a8256791e5fe66729fcd364ef"}]}, + {'CosTransactions_Terminator', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"dbbba1c622d817538fba982cbefd4a15"}]}, + {'CosTransactions_Terminator_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2db2696226a90215edb559cdae7ad928"}]}, + {'CosTransactions_TransIdentity', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d38592cd26cbbbe3a963ca77b5264ea8"}]}, + {'CosTransactions_TransactionFactory', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"04db55c2ba8df7975e98e1c7b7582bb6"}]}, + {'CosTransactions_TransactionFactory_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1d8ff8a2434c10c4716b1b59aebbcb9e"}]}, + {'CosTransactions_Unavailable', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a77c05d98c0c72e2f1d52a1f781a1b98"}]}, + {'CosTransactions_WrongTransaction', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c836d95954f2374d89bfc9ff2bd86793"}]}, + {'CosTransactions_otid_t', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1e903c81e783cb34153bbca99e047870"}]}, + {'ETraP_Common', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ea5d3e59af9cadcb5587cc42fc750470"}]}, + {'ETraP_Server', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8592fd689bdae07056a29bd258293371"}]}, + {'ETraP_Server_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7f192b40f501fd2f5fb3f92b21c5e9d3"}]}, + {cosTransactions, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6d83a1fd7da7dc0b87658efe3039f484"}]}, + {etrap_logmgr, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"91577f644192b682cb8739b9ce7ac7ad"}]}, + {oe_CosTransactions, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6f6c79ffe50eac0c3ced0fba1a8c08a0"}]}]}]}}, + {application, + {cosTime, + [{description,"The Erlang CosTime application"}, + {vsn,"1.1.13"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/cosTime-1.1.13/ebin"}, + {modules, + [{'CosTime_TIO', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"77717ab85418c3c1599b3238c879b770"}]}, + {'CosTime_TIO_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3ce85958b051f2f97925e980f56115e2"}]}, + {'CosTime_TimeService', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a92a3fc07bfeeae58a57075ecddb5ac6"}]}, + {'CosTime_TimeService_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0885fbeef5bd4f72920ae716f0c73d54"}]}, + {'CosTime_TimeUnavailable', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9ee0570f9b91eece7560cc1b6146f784"}]}, + {'CosTime_UTO', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"799ddc99175222b61965c6c8e66e5cb3"}]}, + {'CosTime_UTO_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"552c29f5ece131368c121b5a14c3ae06"}]}, + {'CosTimerEvent_TimerEventHandler', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"76961fc9eaae9e46950b5eb52fe62ae3"}]}, + {'CosTimerEvent_TimerEventHandler_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a69e243a494b80eb34b37456f2b1f855"}]}, + {'CosTimerEvent_TimerEventService', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"62c54aabe64cb28b1245eb80f6b9190d"}]}, + {'CosTimerEvent_TimerEventService_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0c6926dd7faed0366772908c8593691e"}]}, + {'CosTimerEvent_TimerEventT', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"74b7db88a5dd4f17c263683a80bcfe3b"}]}, + {'TimeBase_IntervalT', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5c8f966d02c9520f2d3a4f024892ded3"}]}, + {'TimeBase_UtcT', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"15f72a9538e725e68e375f3d638c1b6d"}]}, + {cosTime, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8c96cfbcafba8c9df1a9b57b7e09c4d8"}]}, + {oe_CosTime, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e607ddba4a35690c39bfcbb1fa3e044e"}]}, + {oe_CosTimerEvent, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"39f960f5b9c079eaecb87e75d9f90f2b"}]}, + {oe_TimeBase, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"764d088e21dd985285d4ccfd723959fe"}]}]}]}}, + {application, + {cosProperty, + [{description,"The Erlang CosProperty application"}, + {vsn,"1.1.16"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/cosProperty-1.1.16/ebin"}, + {modules, + [{'CosPropertyService_ConflictingProperty', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"67353514e217df9f5a5c5e0d3e97d9bd"}]}, + {'CosPropertyService_ConstraintNotSupported', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ce577ca5520194130903c063d8f2211a"}]}, + {'CosPropertyService_FixedProperty', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0ef0b79fd5dbcb18f7b9c94f941678e2"}]}, + {'CosPropertyService_InvalidPropertyName', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bd173257499295fbdc728d60fd14af92"}]}, + {'CosPropertyService_MultipleExceptions', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a3004385ac63dc6aa52bcb2aa46818f0"}]}, + {'CosPropertyService_Properties', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"172b757c8a881b79146f50d9f3da1ea9"}]}, + {'CosPropertyService_PropertiesIterator', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"37fa8c7f1e5ab4798845a1b101835900"}]}, + {'CosPropertyService_PropertiesIterator_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"728fabf6239161186aa9f574ad27fbd6"}]}, + {'CosPropertyService_Property', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a912eb5a31517a6f94ee3f8e3b898ece"}]}, + {'CosPropertyService_PropertyDef', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d8ea474f53418bda870c1f98c522d15b"}]}, + {'CosPropertyService_PropertyDefs', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3c997a6a4db17765d72f52953679fc7d"}]}, + {'CosPropertyService_PropertyException', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3600a7d77fe924d3883a003b68ab8902"}]}, + {'CosPropertyService_PropertyExceptions', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a516b05a720966d4a3568f7f087f22cf"}]}, + {'CosPropertyService_PropertyMode', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b1e1e285b3a2b01a12e328ed94a65225"}]}, + {'CosPropertyService_PropertyModes', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ed697876aa56c111eee5733379303ef3"}]}, + {'CosPropertyService_PropertyNames', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"39684cd186c7d8da459f9d17637606a2"}]}, + {'CosPropertyService_PropertyNamesIterator', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"97b170d84779dcb7b98460588de428e3"}]}, + {'CosPropertyService_PropertyNamesIterator_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e06e012106df3651db1e9d52472bebd3"}]}, + {'CosPropertyService_PropertyNotFound', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"86c83ceacb0b80d4ffa6042cfaec025f"}]}, + {'CosPropertyService_PropertySet', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ffbb0b6b88d4a35cd836322dcc2b4603"}]}, + {'CosPropertyService_PropertySetDef', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"429c3ed48018cc6eef3d28c2407fa42e"}]}, + {'CosPropertyService_PropertySetDefFactory', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"86da518b687db630cd85921ebe96d07a"}]}, + {'CosPropertyService_PropertySetDefFactory_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2f52585d44dd9d6863bd2b0e0359a24e"}]}, + {'CosPropertyService_PropertySetDef_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a02a747cf3856996416253a5cbccfbd7"}]}, + {'CosPropertyService_PropertySetFactory', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"faef66b15f43dc81cbf7dd9bde81c8a2"}]}, + {'CosPropertyService_PropertySetFactory_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b538bc6740ae2b6934e08d831d5b0960"}]}, + {'CosPropertyService_PropertyTypes', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ec088d6b4028f6a9dc2917e6722f1c32"}]}, + {'CosPropertyService_ReadOnlyProperty', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3f4d338a44a7ab32daf202f4d2aa7cbb"}]}, + {'CosPropertyService_UnsupportedMode', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"203ca7e42a209758ceea013cbff109bd"}]}, + {'CosPropertyService_UnsupportedProperty', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"28e9e73be7eb82646e3713135d695a6d"}]}, + {'CosPropertyService_UnsupportedTypeCode', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"da862aea1e36f6fb797bee192a2f3e08"}]}, + {cosProperty, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e5c17adcc4dc9f93a8cf92c91a12c81e"}]}, + {oe_CosProperty, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4c9d35f1b883b805a44e9864136958b1"}]}]}]}}, + {application, + {cosNotification, + [{description,"The Erlang CosNotification application"}, + {vsn,"1.1.20"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/cosNotification-1.1.20/ebin"}, + {modules, + [{'CosNotification', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5a52684ebceaceebe3d7c971fd5e45e6"}]}, + {'CosNotification_AdminPropertiesAdmin', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"aa2af8e932319a2ab715d799c31678b0"}]}, + {'CosNotification_Common', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e908fdcf47fa3d9d234d4061db9760ab"}]}, + {'CosNotification_EventBatch', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8c79e194e19df338bec34cee83d5c999"}]}, + {'CosNotification_EventHeader', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9e08e276e855cfa3dd60bdc9b563b8e9"}]}, + {'CosNotification_EventType', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"be0b154ef34f6279604f04d0be386d64"}]}, + {'CosNotification_EventTypeSeq', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3719ad475d47fd73c1a70891586f0b17"}]}, + {'CosNotification_FixedEventHeader', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e512d2bce68fcb3de1336060be225cad"}]}, + {'CosNotification_NamedPropertyRange', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e42690af83d192433daaadb6cbfc7e02"}]}, + {'CosNotification_NamedPropertyRangeSeq', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5eac2fb6027077046d918d30b36fb45a"}]}, + {'CosNotification_Property', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d89e479fd34c1e6c46447dcb4aaa44e0"}]}, + {'CosNotification_PropertyError', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c2b5a17b0ff2dd997013daf5a4d73a83"}]}, + {'CosNotification_PropertyErrorSeq', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2437aa1bdbeeb5f45213bc7e7922351a"}]}, + {'CosNotification_PropertyRange', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b2392c8040a976dc8db3ba147f7911f2"}]}, + {'CosNotification_PropertySeq', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6950965079eb678d5b2e010c8266cf13"}]}, + {'CosNotification_QoSAdmin', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fafc8842d8f8e11febab4d341a2ce879"}]}, + {'CosNotification_StructuredEvent', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"22a1eae09f5d8cf0d223d06cebf9d85b"}]}, + {'CosNotification_UnsupportedAdmin', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0b1d7ff2796dd090e244cecdbfa4d2ce"}]}, + {'CosNotification_UnsupportedQoS', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d0968f6f188653b1e292c34f3b18c51a"}]}, + {'CosNotifyChannelAdmin_AdminIDSeq', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"42791a7a0d5ca5fef186c441a81cf50b"}]}, + {'CosNotifyChannelAdmin_AdminLimit', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5355d6a703102439e59b070eb6e61b45"}]}, + {'CosNotifyChannelAdmin_AdminLimitExceeded', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"18b11c68d839f9aa90bfe6da07b15cd8"}]}, + {'CosNotifyChannelAdmin_AdminNotFound', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c853cd178ef80d6a46a334d3cb5371d4"}]}, + {'CosNotifyChannelAdmin_ChannelIDSeq', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"992ab8f1ac2f4cc15edd6068c8dc1948"}]}, + {'CosNotifyChannelAdmin_ChannelNotFound', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"475e742fdf1dd2ec932704ccb941f3c1"}]}, + {'CosNotifyChannelAdmin_ConnectionAlreadyActive', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d8b95c202b2ebc28a7208928563b5382"}]}, + {'CosNotifyChannelAdmin_ConnectionAlreadyInactive', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8b106140de30c6cd638b328efe453cb3"}]}, + {'CosNotifyChannelAdmin_ConsumerAdmin', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4c8c31c812099afa148ed0662dc67ea0"}]}, + {'CosNotifyChannelAdmin_ConsumerAdmin_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"172767d1c29ca64e810d8853c61a01e9"}]}, + {'CosNotifyChannelAdmin_EventChannel', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e362f0dc4dc40c98e66b91632554ddb7"}]}, + {'CosNotifyChannelAdmin_EventChannelFactory', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4798a326d18d53e9a7870454fb33ef4c"}]}, + {'CosNotifyChannelAdmin_EventChannelFactory_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4bc146f5b9cc168505d2249e7f04a618"}]}, + {'CosNotifyChannelAdmin_EventChannel_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"db6e5631fc1e5ff158dfc77123c7e752"}]}, + {'CosNotifyChannelAdmin_NotConnected', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b7f5e3229c7849f94b0744a78e38012c"}]}, + {'CosNotifyChannelAdmin_ProxyConsumer', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b1aa19779800f6e97852f5a2e8042641"}]}, + {'CosNotifyChannelAdmin_ProxyIDSeq', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bf0a62dd47773a5a4df90f70644c4e24"}]}, + {'CosNotifyChannelAdmin_ProxyNotFound', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"735c610478319545c1a68c1c8b75609d"}]}, + {'CosNotifyChannelAdmin_ProxyPullConsumer', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6cc803a524bd58d1c33bee3fb8f92ac7"}]}, + {'CosNotifyChannelAdmin_ProxyPullSupplier', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f1683d6e08309fb3fc51d127c407348a"}]}, + {'CosNotifyChannelAdmin_ProxyPushConsumer', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"94416e046b1c566bfa8df9bc1884bea5"}]}, + {'CosNotifyChannelAdmin_ProxyPushSupplier', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"61c57643509be14cbb5e82090fb5bf6d"}]}, + {'CosNotifyChannelAdmin_ProxySupplier', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4c1c83635cd4d1e4a50577e68f084a39"}]}, + {'CosNotifyChannelAdmin_SequenceProxyPullConsumer', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"af562a179799a5ae781278e980912710"}]}, + {'CosNotifyChannelAdmin_SequenceProxyPullSupplier', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"da43e615a23f2485758bec039617792c"}]}, + {'CosNotifyChannelAdmin_SequenceProxyPushConsumer', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6a876b3b2c655fa98e23510ca72be236"}]}, + {'CosNotifyChannelAdmin_SequenceProxyPushSupplier', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"55954cf819fb29c74e8c7fa7dcb17eb8"}]}, + {'CosNotifyChannelAdmin_StructuredProxyPullConsumer', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"aeb95ea3a9deb7c129dccfd77df7976c"}]}, + {'CosNotifyChannelAdmin_StructuredProxyPullSupplier', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e72e1de7fb0ea440aae9ca791fbdd403"}]}, + {'CosNotifyChannelAdmin_StructuredProxyPushConsumer', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d277b85ea15126c7645eccc585325ee2"}]}, + {'CosNotifyChannelAdmin_StructuredProxyPushSupplier', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7339f8c2876066369e6afa27267bfd81"}]}, + {'CosNotifyChannelAdmin_SupplierAdmin', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"043d43346f3ff5c2775bf7030a13e1d9"}]}, + {'CosNotifyChannelAdmin_SupplierAdmin_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"efe73dc58fd1b27c2adc184018e4091a"}]}, + {'CosNotifyComm_InvalidEventType', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"516a9a10d779d7b47a5752d0b4278017"}]}, + {'CosNotifyComm_NotifyPublish', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c50da2c5c4d79c4cd3974c37b6165fbd"}]}, + {'CosNotifyComm_NotifySubscribe', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"180ce40d1660bec349bb7ddf1275c985"}]}, + {'CosNotifyComm_PullConsumer', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"dd7be30cd0685dbb3e0f22b4de8ffb91"}]}, + {'CosNotifyComm_PullSupplier', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e76b3f6be347a5d08350ae25cddc77c1"}]}, + {'CosNotifyComm_PushConsumer', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c2c972f2affe7f936ec38997084045b1"}]}, + {'CosNotifyComm_PushSupplier', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"416e6887077de70bf3aa7cf6c6b35a9c"}]}, + {'CosNotifyComm_SequencePullConsumer', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1322fb2dadb5669a36391f12455c6969"}]}, + {'CosNotifyComm_SequencePullSupplier', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"281779a70fdae7a1de3e569ae707d21a"}]}, + {'CosNotifyComm_SequencePushConsumer', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"701eb7ecaef2fb7f13b5adf2ff8a97aa"}]}, + {'CosNotifyComm_SequencePushSupplier', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ceb164baf53b3df5f90fdbef4c800d8d"}]}, + {'CosNotifyComm_StructuredPullConsumer', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"70d2e255c8613a9d58a4f1f69b1adf51"}]}, + {'CosNotifyComm_StructuredPullSupplier', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fa8164033103e1c40f7721471fa6b8fd"}]}, + {'CosNotifyComm_StructuredPushConsumer', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"684f225a8d760e970a4380c303f82662"}]}, + {'CosNotifyComm_StructuredPushSupplier', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"de1b05e00095ac428839c165db9f92fc"}]}, + {'CosNotifyFilter_CallbackIDSeq', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2ab4cfad0073e21b629ebd16f8973912"}]}, + {'CosNotifyFilter_CallbackNotFound', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5ae7cd265c665a4cd4a969c75388b1fc"}]}, + {'CosNotifyFilter_ConstraintExp', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"421355667259ba4906ed0b0ba89ae1ba"}]}, + {'CosNotifyFilter_ConstraintExpSeq', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2ef901d08223839966e5d67b55731e63"}]}, + {'CosNotifyFilter_ConstraintIDSeq', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"50d0d1e84309217b5a2864eb2df3653b"}]}, + {'CosNotifyFilter_ConstraintInfo', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e988281d1a6d6d2ba412a86cb1b89e0b"}]}, + {'CosNotifyFilter_ConstraintInfoSeq', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ff21820130cfa051a6781e79f53171af"}]}, + {'CosNotifyFilter_ConstraintNotFound', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1611f041bd2826435c850dc36b2a6953"}]}, + {'CosNotifyFilter_DuplicateConstraintID', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"40c6d62f59e44a14649e3de2e78deafd"}]}, + {'CosNotifyFilter_Filter', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"864d9d277d782fca9a15809c5c195c1c"}]}, + {'CosNotifyFilter_FilterAdmin', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ee1e90ea0fbde4a0c53036e0efa4b89a"}]}, + {'CosNotifyFilter_FilterFactory', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b59a3c5c5e24a9a389792ea9ff254312"}]}, + {'CosNotifyFilter_FilterFactory_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"40bc158ddcbb31abff87fe4da270b55a"}]}, + {'CosNotifyFilter_FilterIDSeq', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3dd80855340f372c0682a53a6d3bc216"}]}, + {'CosNotifyFilter_FilterNotFound', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fbdd34c6e28fb4c907410c2f7bc82f92"}]}, + {'CosNotifyFilter_Filter_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a6911bf97e4ebe2333e7e19914d821ea"}]}, + {'CosNotifyFilter_InvalidConstraint', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"beaedbe7bcec40b0d90a0404dde063a9"}]}, + {'CosNotifyFilter_InvalidGrammar', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0055f6477430cf9c38cce84d93393a12"}]}, + {'CosNotifyFilter_InvalidValue', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"041b66a4b7933005a983848254dec48c"}]}, + {'CosNotifyFilter_MappingConstraintInfo', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ab3093c4688953509866f4128d0747d2"}]}, + {'CosNotifyFilter_MappingConstraintInfoSeq', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9f81b4c571998ef9f1cefa77c45be6e5"}]}, + {'CosNotifyFilter_MappingConstraintPair', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"305991c110aca04df1398bd3b640e284"}]}, + {'CosNotifyFilter_MappingConstraintPairSeq', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7bd7692f2d9ad411d3d4323ff4ef9a2d"}]}, + {'CosNotifyFilter_MappingFilter', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fbd3cd1cce0f195048025a19666e4bb8"}]}, + {'CosNotifyFilter_MappingFilter_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5c337925555dac8714bcde4ff0ac3682"}]}, + {'CosNotifyFilter_UnsupportedFilterableData', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"64044f951a82b03309ab90082ed6d354"}]}, + {'PullerConsumer_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a96588beb8db62195c499ba6a61cc53f"}]}, + {'PullerSupplier_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"90058bd6464dc08f79814185696ce1fb"}]}, + {'PusherConsumer_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"72a8f62fb563174cf54b97aa1206b293"}]}, + {'PusherSupplier_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1d03a842669765bf9907b644957fa7cb"}]}, + {cosNotificationApp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0a6dabb21a8926c7f733904336b3375b"}]}, + {cosNotification_Filter, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"63cb134b80f03d8399abe10908055e40"}]}, + {cosNotification_Grammar, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c5636b97c6e449aeafada1b5df5b6e91"}]}, + {cosNotification_Scanner, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9c6334416492eb7be457c13d39b92222"}]}, + {cosNotification_eventDB, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d52b15cf6eaba713bb979684b54fb8df"}]}, + {oe_CosNotification, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"961cde96216694db976f1f714b0f4d6c"}]}, + {oe_CosNotificationComm_Event, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"affa53e3f3dfcb411ff317d98a5ce64a"}]}, + {oe_CosNotifyChannelAdmin, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4ed58499950adf48241f1701c2116857"}]}, + {oe_CosNotifyComm, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a944c5aa4379e8f3b07acc9c5fd56f9a"}]}, + {oe_CosNotifyFilter, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c51f3aaa451621c060bdb0d707324fbd"}]}, + {oe_cosNotificationAppComm, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ed879b4fb4e5e3438e523069a29ce1aa"}]}]}]}}, + {application, + {cosFileTransfer, + [{description,"The Erlang CosFileTransfer application"}, + {vsn,"1.1.15"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/cosFileTransfer-1.1.15/ebin"}, + {modules, + [{'CosFileTransfer', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"537730bb6ac118a9f672ea5c5616502c"}]}, + {'CosFileTransfer_AccessLevel', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"538517d444956f350c54176200fa9c2d"}]}, + {'CosFileTransfer_CommandNotImplementedException', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"06bb7e58f28ad101e4cb2cd2336d3698"}]}, + {'CosFileTransfer_Directory', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a3504d2207476a6439367e5e20b442bc"}]}, + {'CosFileTransfer_Directory_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ca00e96f4f13619cbcaf663edf819405"}]}, + {'CosFileTransfer_File', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"082fb7de49fb7a94ad34873e876fbdd8"}]}, + {'CosFileTransfer_FileIterator', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d7fce306a50dbb7edaea5f9eeec1d5ce"}]}, + {'CosFileTransfer_FileIterator_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bb5946f486a03df082e02ec55308e270"}]}, + {'CosFileTransfer_FileList', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5f508ab863f8cf90e46fda1e2bc6a01b"}]}, + {'CosFileTransfer_FileNameList', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2044a2695019499e1294315eea9f3092"}]}, + {'CosFileTransfer_FileNotFoundException', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b00961e88651b5ab62c9d20b2d60c6e0"}]}, + {'CosFileTransfer_FileTransferSession', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"102d05bd8c1fda9dfa1ba3769ef283fd"}]}, + {'CosFileTransfer_FileTransferSession_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a6774a931a16efaa7bcbf342ef660b49"}]}, + {'CosFileTransfer_FileWrapper', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4d19e7d1eeb8b381847003f8837be28d"}]}, + {'CosFileTransfer_File_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"64eda7b0b054da3e646bba7fbe6be70d"}]}, + {'CosFileTransfer_IllegalOperationException', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"25a05f47c3c2fc5d14d135acb6d72a5f"}]}, + {'CosFileTransfer_ProtocolAddressList', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4587002261d4308181fc93122a15cea9"}]}, + {'CosFileTransfer_ProtocolSupport', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c7937786969ccbba0967581d3c25ad54"}]}, + {'CosFileTransfer_RequestFailureException', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"384095c7be94a7544378f029e966cf2e"}]}, + {'CosFileTransfer_SessionException', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7ef101cef5808b9d7c08037e15ee66fa"}]}, + {'CosFileTransfer_SupportedProtocolAddresses', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d145c64e85be77403b797ad505564018"}]}, + {'CosFileTransfer_TransferException', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a4b8f0ca1710b11ed6d723ee1692c46c"}]}, + {'CosFileTransfer_VirtualFileSystem', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"37e0d0057b23e3e1563b19539bc0a76d"}]}, + {'CosFileTransfer_VirtualFileSystem_ContentList', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"165e5f4d21952fc5eb1f0a289c571fbc"}]}, + {'CosFileTransfer_VirtualFileSystem_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"81b6bf0f44b0eab55cebc3d408671e0a"}]}, + {cosFileTransferApp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ed8d595027fd9c5f7dd1e9398a4351bf"}]}, + {cosFileTransferNATIVE_file, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"91cd6a5ac4ba42b3d2ef0c0cf4c48270"}]}, + {oe_CosFileTransfer, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"683aa469ec95c19f32d0f62f5f7ef6e7"}]}]}]}}, + {application, + {cosEventDomain, + [{description,"The Erlang CosEventDomain application"}, + {vsn,"1.1.13"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/cosEventDomain-1.1.13/ebin"}, + {modules, + [{'CosEventDomainAdmin', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2e2d9e538ddd0f2a2fa74f499e042db1"}]}, + {'CosEventDomainAdmin_AlreadyExists', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a1ce2f0d94e633823bedf296aa1527e5"}]}, + {'CosEventDomainAdmin_Connection', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a3d8e1bead63a2d7644f36edd4a66772"}]}, + {'CosEventDomainAdmin_ConnectionIDSeq', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"56929f00f5dcec6d75408d85921c693f"}]}, + {'CosEventDomainAdmin_ConnectionNotFound', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4de106e024e8f9f45783dd7b45af2cc1"}]}, + {'CosEventDomainAdmin_CycleCreationForbidden', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6a28090bafe2078be88ee5cb996f9d23"}]}, + {'CosEventDomainAdmin_CycleSeq', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3232a8bb21e31c81f7791fdf0359d945"}]}, + {'CosEventDomainAdmin_DiamondCreationForbidden', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8b9e307237ee3408e348d4593c0de997"}]}, + {'CosEventDomainAdmin_DiamondSeq', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"65478f4d3f155d7547b52ea7d04f6628"}]}, + {'CosEventDomainAdmin_DomainIDSeq', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4f44a097ccf00511ed397775b33991a8"}]}, + {'CosEventDomainAdmin_DomainNotFound', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e17639bb3b5f18e80cd8f505191dbc7c"}]}, + {'CosEventDomainAdmin_EventDomain', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b21b34fcceae9698702dadc469ef2cd1"}]}, + {'CosEventDomainAdmin_EventDomainFactory', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bcf4395bcda2d977235b24ec4416ddec"}]}, + {'CosEventDomainAdmin_EventDomainFactory_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a7d21747fe63505e98037202798cca90"}]}, + {'CosEventDomainAdmin_EventDomain_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2801240b7c96984648d565b9b210b8fb"}]}, + {'CosEventDomainAdmin_MemberIDSeq', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"889c0e92b864877d5c2bbbd2ed185575"}]}, + {'CosEventDomainAdmin_RouteSeq', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f77038e040e610031d35f876dfa2925e"}]}, + {cosEventDomainApp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ea692728e2b3d71f1f486a7aece4df48"}]}, + {oe_CosEventDomainAdmin, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"939160a9e6adced7edf36e0a18927785"}]}]}]}}, + {application, + {cosEvent, + [{description,"The Erlang CosEvent application"}, + {vsn,"2.1.14"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/cosEvent-2.1.14/ebin"}, + {modules, + [{'CosEventChannelAdmin_AlreadyConnected', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"64cb912070ade0d3254585904ba4c509"}]}, + {'CosEventChannelAdmin_ConsumerAdmin', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e027fd366965c17a0b51c3cfd80dcd4f"}]}, + {'CosEventChannelAdmin_EventChannel', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f8d2e64b53114282c8c353dd5110ea9e"}]}, + {'CosEventChannelAdmin_ProxyPullConsumer', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9aef474c8cb0c5e9e2cb5d4cc43fe52d"}]}, + {'CosEventChannelAdmin_ProxyPullConsumer_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9057fc161db130ea1ee3bd656b083ad0"}]}, + {'CosEventChannelAdmin_ProxyPullSupplier', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"11cc90a016f1b493838f6f79caa959fa"}]}, + {'CosEventChannelAdmin_ProxyPushConsumer', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"21b14ec7e74c8632349f31cb70324ca6"}]}, + {'CosEventChannelAdmin_ProxyPushConsumer_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"dabc851d850f372affa761150136640d"}]}, + {'CosEventChannelAdmin_ProxyPushSupplier', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d32c6d87385b474519aa936d9bd79256"}]}, + {'CosEventChannelAdmin_SupplierAdmin', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b26b61665649ea2af6fc2b7174d7c4f7"}]}, + {'CosEventChannelAdmin_SupplierAdmin_impl', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8606a32b7269881c1f455edce89344db"}]}, + {'CosEventChannelAdmin_TypeError', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"20bb7e990eb8d6b0e854919c0dff94cc"}]}, + {'CosEventComm_Disconnected', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"c2ec0e6b1fa849a2ab22fdd1ce14ecb7"}]}, + {'CosEventComm_PullConsumer', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"43972738bc29806b38419aaf76d8c393"}]}, + {'CosEventComm_PullSupplier', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5206247fdf5b00621d3732805fe1854a"}]}, + {'CosEventComm_PushConsumer', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"72937626c2c3f3689fb6dafed66bad17"}]}, + {'CosEventComm_PushSupplier', + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"54875107d8748bac2b96a3037669a477"}]}, + {cosEventApp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"dab9a7b6c3106899fe7d2c9e74fcb021"}]}, + {oe_CosEventChannelAdmin, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b192666923744044b3a0e652ec9e9948"}]}, + {oe_CosEventComm, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"884bef0af9742bfe5f3f7e345d24cd18"}]}, + {oe_CosEventComm_CAdmin, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f344012f72ef7bfbdef3d29d525e2896"}]}, + {oe_CosEventComm_CAdmin_impl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"935565447529d9e97da7b98c3631cc92"}]}, + {oe_CosEventComm_Channel, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fe816f373688feb5c63c10543eedd3c2"}]}, + {oe_CosEventComm_Channel_impl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5c3c48bf48ac0b63f62d82064f9ce32f"}]}, + {oe_CosEventComm_Event, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7f5146f9630ff6e60665cf32fc7e6641"}]}, + {oe_CosEventComm_PullerS, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"dbd58f368f06b16fa0a7628594f84c44"}]}, + {oe_CosEventComm_PullerS_impl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2bd0c1df9074f1a792985b4ff1b0ec98"}]}, + {oe_CosEventComm_PusherS, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"36dc7eaaa1b298b7875dd41b3e6b5b85"}]}, + {oe_CosEventComm_PusherS_impl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"63c64664227a2772b5ad3d0c6519f8c4"}]}, + {oe_cosEventApp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cc2ca7e6febb762f39f337c5303390e6"}]}]}]}}, + {application, + {compiler, + [{description,"ERTS CXC 138 10"}, + {vsn,"4.9.2"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/compiler-4.9.2/ebin"}, + {modules, + [{beam_a, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a338f3a7878d0c9a407950fcb5a2e7ed"}]}, + {beam_asm, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cef85f8577595b73910fa77803c58cdb"}]}, + {beam_block, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7e7610e6f816e2c8d869e7ce1c44cba8"}]}, + {beam_bool, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3fcb1cec9f4370800203e1189c01a10c"}]}, + {beam_bsm, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"973abf79efd649a3f0eb1b3351b4fe92"}]}, + {beam_clean, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a0c6b67b764da86372deb11b4c5154f4"}]}, + {beam_dead, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ff4f53d218b932103fcf093dbd366584"}]}, + {beam_dict, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f1e8c36a21a5287a84844e7ffa0a9bbb"}]}, + {beam_disasm, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"63dd1f997343124a900e2fe982fe4cad"}]}, + {beam_except, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"89dd12d9c4781f83554a9d2101d623d8"}]}, + {beam_flatten, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a1e49fa674cc580042459878a27403e9"}]}, + {beam_jump, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1a9f1ce9787205a57d137424b5ab022b"}]}, + {beam_listing, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e9a84340142cd7c90e95851ab1260a0f"}]}, + {beam_opcodes, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3d5d21bc2584bf078639eba76a18d221"}]}, + {beam_peep, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5d81c38cab19af16ff472ce5838c63b1"}]}, + {beam_receive, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"7d22ec74972c53f3f93bd01dbe369370"}]}, + {beam_split, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"03b0416d0fee9081f68cf6468d036170"}]}, + {beam_trim, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9a6a01870ff8f8bda3ea36184da7348a"}]}, + {beam_type, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"cc4a9521730959ffc10d3ccebd20861d"}]}, + {beam_utils, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d7d2b1d7cc0722d47c7fd72fa6487d27"}]}, + {beam_validator, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ed5a82e40ba511c22291f87c1e2b705b"}]}, + {beam_z, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2ffafc7070cf14ec69d569b0f8106f9a"}]}, + {cerl, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"38c2ac91b52a3141d74df2f219b45eb5"}]}, + {cerl_clauses, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"75da88dc5ced060fe52f177dae449ac0"}]}, + {cerl_inline, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"976487fce255a37192ac2a9258cdacf9"}]}, + {cerl_trees, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a240a6560f194a05956f572e436a6861"}]}, + {compile, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"98a40d5fc6bcd14ac5e516a506b6161f"}]}, + {core_lib, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9bdda978e16a885a17587e575cb2b369"}]}, + {core_lint, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"633c18d069ada94f1f1dfec526de2a2a"}]}, + {core_parse, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"21b745083d46bbe9725eb423f0c73c7a"}]}, + {core_pp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9940bb6f480fe3438bf97863ad0a5755"}]}, + {core_scan, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1f3ff89deb03f34714390b93e678989c"}]}, + {erl_bifs, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"74c0a1563ea88b196dc2a18b1a34ffed"}]}, + {rec_env, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9a6fdcf8ffe126bb2838f86949ced210"}]}, + {sys_core_dsetel, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2c45d53e09f1b3f4e92b8f2ff8adf258"}]}, + {sys_core_fold, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ac092bdc7362a76cda76e27ad5610ec7"}]}, + {sys_core_inline, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4f439077cdab9795b782412d556828fa"}]}, + {sys_pre_attributes, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fc95feafdeca105f38589c4ca7b43532"}]}, + {sys_pre_expand, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4b1c1e3bf39af00ca2988295aa2fbdbb"}]}, + {v3_codegen, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"590be66e39ccc3e6260a412ccbc8becd"}]}, + {v3_core, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5997d0774f74e0bad9b8887d24a8bfa3"}]}, + {v3_kernel, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"21a4b3edd53de6b910df1b99219824fc"}]}, + {v3_kernel_pp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1ec5b0e503bcf660d6da8aca9cba9682"}]}, + {v3_life, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"eb4ae7606e9409846d17c5c60751b08f"}]}]}]}}, + {application, + {common_test, + [{description,"The OTP Common Test application"}, + {vsn,"1.7.2"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/common_test-1.7.2/ebin"}, + {modules, + [{ct, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"1f3d139ac677184b601722b92977b971"}]}, + {ct_config, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0257a2b9a5ed7e176df35b2c39a03a5a"}]}, + {ct_config_plain, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8330eca3a0e4401b3a8f9508343df5cc"}]}, + {ct_config_xml, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3502006ebdcc975febe9d750b28fd2b0"}]}, + {ct_conn_log_h, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5f2e020e7c92f8a7c2c148faf855c9b0"}]}, + {ct_cover, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"76b9cecb99d35c0bf38daa0a7107ddeb"}]}, + {ct_event, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2dfbb0a114e64e69b012a83a29312fe8"}]}, + {ct_framework, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d65dc75bd25fe8c45b3e574d18b0be87"}]}, + {ct_ftp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f60d1979bd240e45fb63deb00c6dae6e"}]}, + {ct_gen_conn, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"abb8aa2681d03230890eb5f3fcaffc6b"}]}, + {ct_groups, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0f3c50d44938374c7e364cef4c905079"}]}, + {ct_hooks, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5fbdbe96e81a1abe94ff6ce0c20c9574"}]}, + {ct_hooks_lock, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6e94b9611b2abb9a665606264fb96c2c"}]}, + {ct_logs, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ec22f1709750c55acff646a44502c2db"}]}, + {ct_make, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a2f7f755c88a136bbe56c5415901e217"}]}, + {ct_master, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3d8a8fd7184fd07d8caec68f3653b7f8"}]}, + {ct_master_event, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0c497dbbef03d74f085ee633998aecba"}]}, + {ct_master_logs, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6a2180f96ad17256256d5ef731ac4d04"}]}, + {ct_master_status, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5d63adbf76f9afa47c576284d77d75a9"}]}, + {ct_netconfc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9bff4907efdc764c267f373d12956eca"}]}, + {ct_repeat, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"b18f0f016143922207ef2dd5577d60dc"}]}, + {ct_rpc, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"51957dfa13552f236dad5ad5ab1f83a0"}]}, + {ct_run, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"bcaaaf893ba391b4ce961c33d48b3b5f"}]}, + {ct_slave, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6b03499c65f734a1ad97e2fce458be92"}]}, + {ct_snmp, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"8a6826b2fdf26d9e775f8352ab15b454"}]}, + {ct_ssh, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"657b8f076669c2db4245acd4bc8254d7"}]}, + {ct_telnet, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"47a92efe0ab4b30fe83d83d8d429a8fe"}]}, + {ct_telnet_client, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"53f220488e09886c1933a060c000dddf"}]}, + {ct_testspec, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"fb607ba1ef1abdab4ba76e654cbd1ce1"}]}, + {ct_util, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e6178d700637198b47134c927348b72b"}]}, + {cth_conn_log, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"113d8b745a6d162d678b03dba49ea048"}]}, + {cth_log_redirect, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e7da913515a3b5841c7da153ce0883cb"}]}, + {cth_surefire, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"3c7c9d2147289740b913895898126f1a"}]}, + {unix_telnet, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d38cf476a56523e6222de857b16e89d0"}]}, + {vts, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a31c45897c8d9fe60fbc9115599edcf7"}]}]}]}}, + {application, + {asn1, + [{description,"The Erlang ASN1 compiler version 2.0.2"}, + {vsn,"2.0.2"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/asn1-2.0.2/ebin"}, + {modules, + [{asn1_db, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d9af64def8344330927cefe9a2bf9a8a"}]}, + {asn1ct, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"352b6c8edb6cf7dfc39b3b6b6b0a7b35"}]}, + {asn1ct_check, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"5ef3333d2a492df6b90deff919f28b58"}]}, + {asn1ct_constructed_ber_bin_v2, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"41e917757a2c1195b8f86749a5905d64"}]}, + {asn1ct_constructed_per, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"63d5e7bf85a641a2529c81c7888bfb52"}]}, + {asn1ct_eval_ext, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4f5e38c39875f699ad76e07de7b073b7"}]}, + {asn1ct_func, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"ea7118ee0d45ac6641313e378a1733db"}]}, + {asn1ct_gen, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e5b2688ada58f6ed45c2e7e841088e3e"}]}, + {asn1ct_gen_ber_bin_v2, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"26db838a5c213d6ec1fe2fdf997a06d1"}]}, + {asn1ct_gen_per, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"a67d91fec991b9f08680c35e95f907f0"}]}, + {asn1ct_imm, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"9288c73c656cf6d60fd74bd7946581b2"}]}, + {asn1ct_name, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"2ea14b79e5eb0ae2c3f08f92241f9c4f"}]}, + {asn1ct_parser2, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"6a7951b400104d9f72bcfbb7405e4404"}]}, + {asn1ct_pretty_format, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"dc1240d0e121f12732f8469cbd23051a"}]}, + {asn1ct_rtt, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"f24866e9e2295b4f6c5553ae44d53270"}]}, + {asn1ct_table, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"4d4ec9835f20bc046769547da299363c"}]}, + {asn1ct_tok, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"19908cc77297850954d101491e5eb97d"}]}, + {asn1ct_value, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"388ba3507e46869822607142eef38d70"}]}, + {asn1rt, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0160799421ccb619fc6b08099bfaf37b"}]}, + {asn1rt_nif, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"0c579098c3d97270d004e54a94e42daa"}]}]}]}}, + {application, + {appmon, + [{description,"DEVTOOLS CXC 138 16"}, + {vsn,"2.1.14.2"}, + {path, + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/lib/appmon-2.1.14.2/ebin"}, + {modules, + [{appmon, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"97b8d88aecbd66963563a5aa5df0d0bc"}]}, + {appmon_a, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"adb9049e71eb9e2131b6952974302b4c"}]}, + {appmon_dg, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"438c40af3e96404e73904864597dcca0"}]}, + {appmon_lb, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"d851ee67b54dbf0da46cb21a8c1f7bd9"}]}, + {appmon_place, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"192140bb8bc7e74fd7121d8da2019c56"}]}, + {appmon_txt, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"34c7f9da76880b4f7fcfeb0856fcc097"}]}, + {appmon_web, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"449317a9770ff1aa4cf001604bd2261c"}]}, + {process_info, + [{loaded,false}, + {native,false}, + {compiler,"4.9.1"}, + {md5,"e6d86fad6d0d208318c48af00853ec5b"}]}]}]}}]}, + {system_info, + [{allocator, + {glibc, + [2,4], + [sys_alloc,temp_alloc,sl_alloc,std_alloc,ll_alloc, + eheap_alloc,ets_alloc,fix_alloc,binary_alloc,driver_alloc, + mseg_alloc], + [{sys_alloc,[{e,true},{m,libc},{tt,131072},{tp,0}]}, + {temp_alloc, + [{e,true}, + {t,true}, + {ramv,false}, + {sbct,524288}, + {asbcst,4145152}, + {rsbcst,90}, + {rsbcmt,80}, + {rmbcmt,100}, + {mmbcs,131072}, + {mmmbc,18446744073709551615}, + {mmsbc,256}, + {lmbcs,10485760}, + {smbcs,1048576}, + {mbcgs,10}, + {acul,0}, + {mbsd,3}, + {as,gf}]}, + {sl_alloc, + [{e,true}, + {t,true}, + {ramv,false}, + {sbct,524288}, + {asbcst,4145152}, + {rsbcst,80}, + {rsbcmt,80}, + {rmbcmt,50}, + {mmbcs,32768}, + {mmmbc,18446744073709551615}, + {mmsbc,256}, + {lmbcs,5242880}, + {smbcs,262144}, + {mbcgs,10}, + {acul,0}, + {mbsd,3}, + {as,gf}]}, + {std_alloc, + [{e,true}, + {t,true}, + {ramv,false}, + {sbct,524288}, + {asbcst,4145152}, + {rsbcst,20}, + {rsbcmt,80}, + {rmbcmt,50}, + {mmbcs,32768}, + {mmmbc,18446744073709551615}, + {mmsbc,256}, + {lmbcs,5242880}, + {smbcs,262144}, + {mbcgs,10}, + {acul,0}, + {as,bf}]}, + {ll_alloc, + [{e,true}, + {t,false}, + {ramv,false}, + {sbct,18446744073709551615}, + {asbcst,0}, + {rsbcst,0}, + {rsbcmt,0}, + {rmbcmt,0}, + {mmbcs,2097112}, + {mmmbc,18446744073709551615}, + {mmsbc,0}, + {lmbcs,10485760}, + {smbcs,1048576}, + {mbcgs,10}, + {acul,0}, + {as,aobf}]}, + {eheap_alloc, + [{e,true}, + {t,true}, + {ramv,false}, + {sbct,524288}, + {asbcst,4145152}, + {rsbcst,50}, + {rsbcmt,80}, + {rmbcmt,50}, + {mmbcs,131072}, + {mmmbc,18446744073709551615}, + {mmsbc,256}, + {lmbcs,5242880}, + {smbcs,262144}, + {mbcgs,10}, + {acul,0}, + {mbsd,3}, + {as,gf}]}, + {ets_alloc, + [{e,true}, + {t,true}, + {ramv,false}, + {sbct,524288}, + {asbcst,4145152}, + {rsbcst,20}, + {rsbcmt,80}, + {rmbcmt,50}, + {mmbcs,32768}, + {mmmbc,18446744073709551615}, + {mmsbc,256}, + {lmbcs,5242880}, + {smbcs,262144}, + {mbcgs,10}, + {acul,0}, + {as,bf}]}, + {fix_alloc, + [{e,true}, + {t,true}, + {ramv,false}, + {sbct,524288}, + {asbcst,4145152}, + {rsbcst,20}, + {rsbcmt,80}, + {rmbcmt,50}, + {mmbcs,32768}, + {mmmbc,18446744073709551615}, + {mmsbc,256}, + {lmbcs,5242880}, + {smbcs,262144}, + {mbcgs,10}, + {acul,0}, + {as,aobf}]}, + {binary_alloc, + [{e,true}, + {t,true}, + {ramv,false}, + {sbct,524288}, + {asbcst,4145152}, + {rsbcst,20}, + {rsbcmt,80}, + {rmbcmt,50}, + {mmbcs,32768}, + {mmmbc,18446744073709551615}, + {mmsbc,256}, + {lmbcs,5242880}, + {smbcs,262144}, + {mbcgs,10}, + {acul,0}, + {as,bf}]}, + {driver_alloc, + [{e,true}, + {t,true}, + {ramv,false}, + {sbct,524288}, + {asbcst,4145152}, + {rsbcst,20}, + {rsbcmt,80}, + {rmbcmt,50}, + {mmbcs,32768}, + {mmmbc,18446744073709551615}, + {mmsbc,256}, + {lmbcs,5242880}, + {smbcs,262144}, + {mbcgs,10}, + {acul,0}, + {as,bf}]}, + {mseg_alloc,[{amcbf,4194304},{rmcbf,20},{mcs,10}]}, + {alloc_util,[{mmc,1024},{ycs,1048576}]}, + {instr,[{m,false},{s,false},{t,false}]}]}}, + {check_io, + [{name,erts_poll}, + {primary,poll}, + {fallback,false}, + {kernel_poll,false}, + {memory_size,49808}, + {total_poll_set_size,2}, + {lazy_updates,true}, + {pending_updates,0}, + {batch_updates,false}, + {concurrent_updates,false}, + {max_fds,1024}]}, + {otp_release,"R16B02"}, + {port_limit,65536}, + {process_limit,262144}, + {smp_support,true}, + {system_version, + "Erlang R16B02 (erts-5.10.3) [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]\n"}, + {system_architecture,"x86_64-unknown-linux-gnu"}, + {threads,true}, + {thread_pool_size,10}, + {{wordsize,internal},8}, + {{wordsize,external},8}, + {{cpu_topology,defined},undefined}, + {{cpu_topology,detected}, + [{node, + [{processor,[{core,{logical,0}},{core,{logical,1}}]}]}, + {node, + [{processor,[{core,{logical,2}},{core,{logical,3}}]}]}]}, + {scheduler_bind_type,unbound}, + {scheduler_bindings,{unbound,unbound,unbound,unbound}}, + {compat_rel,16}, + {schedulers_state,{4,4,4}}, + {build_type,opt}, + {logical_processors,4}, + {logical_processors_online,4}, + {logical_processors_available,4}, + {driver_version,"2.1"}, + {nif_version,"1.1"}, + {taints,[]}]}, + {erts_compile_info, + [{ldflags,[]}, + {cflags, + "-g -O2 -I/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp_src_R16B02/erts/x86_64-unknown-linux-gnu -DOTP_RELEASE -D_GNU_SOURCE -DERTS_SMP -DHAVE_CONFIG_H -Wall -Wstrict-prototypes -Wmissing-prototypes -Wdeclaration-after-statement -DUSE_THREADS -D_THREAD_SAFE -D_REENTRANT -DPOSIX_THREADS -D_POSIX_THREAD_SAFE_FUNCTIONS "}, + {config_h, + "/* x86_64-unknown-linux-gnu/config.h. Generated by configure. */\n/* config.h.in. Generated from configure.in by autoheader. */\n\n\n#define GHBN_R_SOLARIS 2\n#define GHBN_R_AIX 3\n#define GHBN_R_GLIBC 4\n\n\n/* Define the brk() argument type. */\n#define BRK_ARG_TYPE void *\n\n/* Define the brk() return type. */\n#define BRK_RET_TYPE int\n\n/* Define if you do not have a high-res. timer & want to use times() instead\n */\n/* #undef CORRECT_USING_TIMES */\n\n/* Modern style mcontext_t in MacOSX */\n/* #undef DARWIN_MODERN_MCONTEXT */\n\n/* Define if you need to include rpc/types.h to get INADDR_LOOPBACK defined */\n/* #undef DEF_INADDR_LOOPBACK_IN_RPC_TYPES_H */\n\n/* Define if you need to include winsock2.h to get INADDR_LOOPBACK defined */\n/* #undef DEF_INADDR_LOOPBACK_IN_WINSOCK2_H */\n\n/* Define if you want to disable child waiter thread */\n/* #undef DISABLE_CHILD_WAITER_THREAD */\n\n/* Define if you want to disable vfork. */\n/* #undef DISABLE_VFORK */\n\n/* Define to 1 if your processor stores the words in a double in middle-endian\n format (like some ARMs). */\n/* #undef DOUBLE_MIDDLE_ENDIAN */\n\n/* Define if you want to enable child waiter thread */\n/* #undef ENABLE_CHILD_WAITER_THREAD */\n\n/* Define if sbrk()/brk() wrappers can track malloc()s core memory use */\n/* #undef ERTS_BRK_WRAPPERS_CAN_TRACK_MALLOC */\n\n/* The only reason ERTS_EMU_CMDLINE_FLAGS exists is to force modification of\n config.h when the emulator command line flags are modified by configure */\n#define ERTS_EMU_CMDLINE_FLAGS \" -g -O2 -I/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp_src_R16B02/erts/x86_64-unknown-linux-gnu -DOTP_RELEASE -D_GNU_SOURCE -g -D_GNU_SOURCE -I/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp_src_R16B02/erts/x86_64-unknown-linux-gnu -DOTP_RELEASE -DUSE_THREADS -D_THREAD_SAFE -D_REENTRANT -DPOSIX_THREADS -D_POSIX_THREAD_SAFE_FUNCTIONS -Wall -Wstrict-prototypes -Wmissing-prototypes -Wdeclaration-after-statement\"\n\n/* Define if you have kernel poll and want to use it */\n#define ERTS_ENABLE_KERNEL_POLL 1\n\n/* Define if the smp emulator is built */\n#define ERTS_HAVE_SMP_EMU 1\n\n/* Define if dlopen() needs to be called before first call to dlerror() */\n/* #undef ERTS_NEED_DLOPEN_BEFORE_DLERROR */\n\n/* Define if poll() should be used instead of select() */\n#define ERTS_USE_POLL 1\n\n/* Define if __after_morecore_hook can track malloc()s core memory use. */\n#define ERTS___AFTER_MORECORE_HOOK_CAN_TRACK_MALLOC 1\n\n/* Define if bigendian */\n/* #undef ETHR_BIGENDIAN */\n\n/* Define if you get a register shortage with cmpxchg8b and position\n independent code */\n/* #undef ETHR_CMPXCHG8B_REGISTER_SHORTAGE */\n\n/* Define if you want to disable native ethread implementations */\n/* #undef ETHR_DISABLE_NATIVE_IMPLS */\n\n/* Define if you want to force usage of pthread rwlocks */\n/* #undef ETHR_FORCE_PTHREAD_RWLOCK */\n\n/* Define if you use a gcc that supports the double word cmpxchg instruction\n */\n#define ETHR_GCC_HAVE_DW_CMPXCHG_ASM_SUPPORT 1\n\n/* Define if you use a gcc that supports -msse2 and understand sse2 specific\n asm statements */\n/* #undef ETHR_GCC_HAVE_SSE2_ASM_SUPPORT */\n\n/* Define if you have all ethread defines */\n#define ETHR_HAVE_ETHREAD_DEFINES 1\n\n/* Define if you have libatomic_ops atomic operations */\n/* #undef ETHR_HAVE_LIBATOMIC_OPS */\n\n/* Define if you have a linux futex implementation. */\n#define ETHR_HAVE_LINUX_FUTEX 1\n\n/* Define if the pthread.h header file is in pthread/mit directory. */\n/* #undef ETHR_HAVE_MIT_PTHREAD_H */\n\n/* Define if you have the pthread_attr_setguardsize function. */\n#define ETHR_HAVE_PTHREAD_ATTR_SETGUARDSIZE 1\n\n/* Define if you have the <pthread.h> header file. */\n#define ETHR_HAVE_PTHREAD_H 1\n\n/* Define if you have the pthread_rwlockattr_setkind_np() function. */\n#define ETHR_HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP 1\n\n/* Define if you have the PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP rwlock\n attribute. */\n#define ETHR_HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP 1\n\n/* Define if you have the pthread_spin_lock function. */\n#define ETHR_HAVE_PTHREAD_SPIN_LOCK 1\n\n/* Define if you have the pthread_yield() function. */\n#define ETHR_HAVE_PTHREAD_YIELD 1\n\n/* Define if you have the <sched.h> header file. */\n#define ETHR_HAVE_SCHED_H 1\n\n/* Define if you have the sched_yield() function. */\n#define ETHR_HAVE_SCHED_YIELD 1\n\n/* Define if you have the <sys/time.h> header file. */\n#define ETHR_HAVE_SYS_TIME_H 1\n\n/* Define if you have _InterlockedAnd() */\n/* #undef ETHR_HAVE__INTERLOCKEDAND */\n\n/* Define if you have _InterlockedAnd64() */\n/* #undef ETHR_HAVE__INTERLOCKEDAND64 */\n\n/* Define if you have _InterlockedCompareExchange() */\n/* #undef ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE */\n\n/* Define if you have _InterlockedCompareExchange128() */\n/* #undef ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE128 */\n\n/* Define if you have _InterlockedCompareExchange64() */\n/* #undef ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64 */\n\n/* Define if you have _InterlockedCompareExchange64_acq() */\n/* #undef ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_ACQ */\n\n/* Define if you have _InterlockedCompareExchange64_rel() */\n/* #undef ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_REL */\n\n/* Define if you have _InterlockedCompareExchange_acq() */\n/* #undef ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_ACQ */\n\n/* Define if you have _InterlockedCompareExchange_rel() */\n/* #undef ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_REL */\n\n/* Define if you have _InterlockedDecrement() */\n/* #undef ETHR_HAVE__INTERLOCKEDDECREMENT */\n\n/* Define if you have _InterlockedDecrement64() */\n/* #undef ETHR_HAVE__INTERLOCKEDDECREMENT64 */\n\n/* Define if you have _InterlockedDecrement64_rel() */\n/* #undef ETHR_HAVE__INTERLOCKEDDECREMENT64_REL */\n\n/* Define if you have _InterlockedDecrement_rel() */\n/* #undef ETHR_HAVE__INTERLOCKEDDECREMENT_REL */\n\n/* Define if you have _InterlockedExchange() */\n/* #undef ETHR_HAVE__INTERLOCKEDEXCHANGE */\n\n/* Define if you have _InterlockedExchange64() */\n/* #undef ETHR_HAVE__INTERLOCKEDEXCHANGE64 */\n\n/* Define if you have _InterlockedExchangeAdd() */\n/* #undef ETHR_HAVE__INTERLOCKEDEXCHANGEADD */\n\n/* Define if you have _InterlockedExchangeAdd64() */\n/* #undef ETHR_HAVE__INTERLOCKEDEXCHANGEADD64 */\n\n/* Define if you have _InterlockedExchangeAdd64_acq() */\n/* #undef ETHR_HAVE__INTERLOCKEDEXCHANGEADD64_ACQ */\n\n/* Define if you have _InterlockedExchangeAdd_acq() */\n/* #undef ETHR_HAVE__INTERLOCKEDEXCHANGEADD_ACQ */\n\n/* Define if you have _InterlockedIncrement() */\n/* #undef ETHR_HAVE__INTERLOCKEDINCREMENT */\n\n/* Define if you have _InterlockedIncrement64() */\n/* #undef ETHR_HAVE__INTERLOCKEDINCREMENT64 */\n\n/* Define if you have _InterlockedIncrement64_acq() */\n/* #undef ETHR_HAVE__INTERLOCKEDINCREMENT64_ACQ */\n\n/* Define if you have _InterlockedIncrement_acq() */\n/* #undef ETHR_HAVE__INTERLOCKEDINCREMENT_ACQ */\n\n/* Define if you have _InterlockedOr() */\n/* #undef ETHR_HAVE__INTERLOCKEDOR */\n\n/* Define if you have _InterlockedOr64() */\n/* #undef ETHR_HAVE__INTERLOCKEDOR64 */\n\n/* Define if you have __sync_add_and_fetch() for 32-bit integers */\n#define ETHR_HAVE___SYNC_ADD_AND_FETCH32 1\n\n/* Define if you have __sync_add_and_fetch() for 64-bit integers */\n#define ETHR_HAVE___SYNC_ADD_AND_FETCH64 1\n\n/* Define if you have __sync_fetch_and_and() for 32-bit integers */\n#define ETHR_HAVE___SYNC_FETCH_AND_AND32 1\n\n/* Define if you have __sync_fetch_and_and() for 64-bit integers */\n#define ETHR_HAVE___SYNC_FETCH_AND_AND64 1\n\n/* Define if you have __sync_fetch_and_or() for 32-bit integers */\n#define ETHR_HAVE___SYNC_FETCH_AND_OR32 1\n\n/* Define if you have __sync_fetch_and_or() for 64-bit integers */\n#define ETHR_HAVE___SYNC_FETCH_AND_OR64 1\n\n/* Define if you have __sync_val_compare_and_swap() for 128-bit integers */\n/* #undef ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP128 */\n\n/* Define if you have __sync_val_compare_and_swap() for 32-bit integers */\n#define ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP32 1\n\n/* Define if you have __sync_val_compare_and_swap() for 64-bit integers */\n#define ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP64 1\n\n/* Define if you want to modify the default stack size */\n/* #undef ETHR_MODIFIED_DEFAULT_STACK_SIZE */\n\n/* Define if you need the <nptl/pthread.h> header file. */\n/* #undef ETHR_NEED_NPTL_PTHREAD_H */\n\n/* Define if you prefer gcc native ethread implementations */\n/* #undef ETHR_PREFER_GCC_NATIVE_IMPLS */\n\n/* Define if you prefer libatomic_ops native ethread implementations */\n/* #undef ETHR_PREFER_LIBATOMIC_OPS_NATIVE_IMPLS */\n\n/* Define if you have pthreads */\n#define ETHR_PTHREADS 1\n\n/* Define if pthread_yield() returns an int. */\n#define ETHR_PTHREAD_YIELD_RET_INT 1\n\n/* Define if sched_yield() returns an int. */\n#define ETHR_SCHED_YIELD_RET_INT 1\n\n/* Define to the size of AO_t if libatomic_ops is used */\n/* #undef ETHR_SIZEOF_AO_T */\n\n/* Define to the size of int */\n#define ETHR_SIZEOF_INT 4\n\n/* Define to the size of long */\n#define ETHR_SIZEOF_LONG 8\n\n/* Define to the size of long long */\n#define ETHR_SIZEOF_LONG_LONG 8\n\n/* Define to the size of pointers */\n#define ETHR_SIZEOF_PTR 8\n\n/* Define to the size of __int128_t */\n#define ETHR_SIZEOF___INT128_T 16\n\n/* Define to the size of __int64 */\n#define ETHR_SIZEOF___INT64 0\n\n/* Define if only run in Sparc PSO, or TSO mode */\n/* #undef ETHR_SPARC_PSO */\n\n/* Define if run in Sparc RMO, PSO, or TSO mode */\n/* #undef ETHR_SPARC_RMO */\n\n/* Define if only run in Sparc TSO mode */\n/* #undef ETHR_SPARC_TSO */\n\n/* Define if you can safely include both <sys/time.h> and <time.h>. */\n#define ETHR_TIME_WITH_SYS_TIME 1\n\n/* Define if you have win32 threads */\n/* #undef ETHR_WIN32_THREADS */\n\n/* Define if x86/x86_64 out of order instructions should be synchronized */\n/* #undef ETHR_X86_OUT_OF_ORDER */\n\n/* Define if you want to use clock_gettime to simulate gethrtime */\n#define GETHRTIME_WITH_CLOCK_GETTIME 1\n\n/* Define if building a halfword-heap 64bit emulator */\n/* #undef HALFWORD_HEAP_EMULATOR */\n\n/* Define to 1 if you have the <arpa/nameser.h> header file. */\n#define HAVE_ARPA_NAMESER_H 1\n\n/* Define to 1 if you have the `brk' function. */\n#define HAVE_BRK 1\n\n/* define if clock_gettime() works for getting process time */\n/* #undef HAVE_CLOCK_GETTIME */\n\n/* Define if you have a decl of fread that conflicts with int fread */\n#define HAVE_CONFLICTING_FREAD_DECLARATION 1\n\n/* Define if you have a putenv() that stores a copy of the key-value pair */\n/* #undef HAVE_COPYING_PUTENV */\n\n/* Define if you have cpuset_getaffinity/cpuset_setaffinity */\n/* #undef HAVE_CPUSET_xETAFFINITY */\n\n/* Define to 1 if you have the declaration of `getrlimit', and to 0 if you\n don't. */\n#define HAVE_DECL_GETRLIMIT 1\n\n/* Define to 1 if you have the declaration of `IN6ADDR_ANY_INIT', and to 0 if\n you don't. */\n#define HAVE_DECL_IN6ADDR_ANY_INIT 1\n\n/* Define to 1 if you have the declaration of `IN6ADDR_LOOPBACK_INIT', and to\n 0 if you don't. */\n#define HAVE_DECL_IN6ADDR_LOOPBACK_INIT 1\n\n/* Define to 1 if you have the declaration of `IPV6_V6ONLY', and to 0 if you\n don't. */\n#define HAVE_DECL_IPV6_V6ONLY 1\n\n/* Define to 1 if you have the declaration of `posix2time', and to 0 if you\n don't. */\n#define HAVE_DECL_POSIX2TIME 0\n\n/* Define to 1 if you have the declaration of `RLIMIT_STACK', and to 0 if you\n don't. */\n#define HAVE_DECL_RLIMIT_STACK 1\n\n/* Define to 1 if you have the declaration of `SCTPS_BOUND', and to 0 if you\n don't. */\n#define HAVE_DECL_SCTPS_BOUND 0\n\n/* Define to 1 if you have the declaration of `SCTPS_COOKIE_ECHOED', and to 0\n if you don't. */\n#define HAVE_DECL_SCTPS_COOKIE_ECHOED 0\n\n/* Define to 1 if you have the declaration of `SCTPS_COOKIE_WAIT', and to 0 if\n you don't. */\n#define HAVE_DECL_SCTPS_COOKIE_WAIT 0\n\n/* Define to 1 if you have the declaration of `SCTPS_ESTABLISHED', and to 0 if\n you don't. */\n#define HAVE_DECL_SCTPS_ESTABLISHED 0\n\n/* Define to 1 if you have the declaration of `SCTPS_IDLE', and to 0 if you\n don't. */\n#define HAVE_DECL_SCTPS_IDLE 0\n\n/* Define to 1 if you have the declaration of `SCTPS_LISTEN', and to 0 if you\n don't. */\n#define HAVE_DECL_SCTPS_LISTEN 0\n\n/* Define to 1 if you have the declaration of `SCTPS_SHUTDOWN_ACK_SENT', and\n to 0 if you don't. */\n#define HAVE_DECL_SCTPS_SHUTDOWN_ACK_SENT 0\n\n/* Define to 1 if you have the declaration of `SCTPS_SHUTDOWN_PENDING', and to\n 0 if you don't. */\n#define HAVE_DECL_SCTPS_SHUTDOWN_PENDING 0\n\n/* Define to 1 if you have the declaration of `SCTPS_SHUTDOWN_RECEIVED', and\n to 0 if you don't. */\n#define HAVE_DECL_SCTPS_SHUTDOWN_RECEIVED 0\n\n/* Define to 1 if you have the declaration of `SCTPS_SHUTDOWN_SENT', and to 0\n if you don't. */\n#define HAVE_DECL_SCTPS_SHUTDOWN_SENT 0\n\n/* Define to 1 if you have the declaration of `SCTP_ABORT', and to 0 if you\n don't. */\n#define HAVE_DECL_SCTP_ABORT 1\n\n/* Define to 1 if you have the declaration of `SCTP_ADDR_CONFIRMED', and to 0\n if you don't. */\n#define HAVE_DECL_SCTP_ADDR_CONFIRMED 0\n\n/* Define to 1 if you have the declaration of `SCTP_ADDR_OVER', and to 0 if\n you don't. */\n#define HAVE_DECL_SCTP_ADDR_OVER 1\n\n/* Define to 1 if you have the declaration of `SCTP_BOUND', and to 0 if you\n don't. */\n#define HAVE_DECL_SCTP_BOUND 0\n\n/* Define to 1 if you have the declaration of `SCTP_CLOSED', and to 0 if you\n don't. */\n#define HAVE_DECL_SCTP_CLOSED 1\n\n/* Define to 1 if you have the declaration of `SCTP_COOKIE_ECHOED', and to 0\n if you don't. */\n#define HAVE_DECL_SCTP_COOKIE_ECHOED 1\n\n/* Define to 1 if you have the declaration of `SCTP_COOKIE_WAIT', and to 0 if\n you don't. */\n#define HAVE_DECL_SCTP_COOKIE_WAIT 1\n\n/* Define to 1 if you have the declaration of `SCTP_DELAYED_ACK_TIME', and to\n 0 if you don't. */\n#define HAVE_DECL_SCTP_DELAYED_ACK_TIME 1\n\n/* Define to 1 if you have the declaration of `SCTP_EMPTY', and to 0 if you\n don't. */\n#define HAVE_DECL_SCTP_EMPTY 1\n\n/* Define to 1 if you have the declaration of `SCTP_EOF', and to 0 if you\n don't. */\n#define HAVE_DECL_SCTP_EOF 1\n\n/* Define to 1 if you have the declaration of `SCTP_ESTABLISHED', and to 0 if\n you don't. */\n#define HAVE_DECL_SCTP_ESTABLISHED 1\n\n/* Define to 1 if you have the declaration of `SCTP_LISTEN', and to 0 if you\n don't. */\n#define HAVE_DECL_SCTP_LISTEN 0\n\n/* Define to 1 if you have the declaration of `SCTP_SENDALL', and to 0 if you\n don't. */\n#define HAVE_DECL_SCTP_SENDALL 0\n\n/* Define to 1 if you have the declaration of `SCTP_SHUTDOWN_ACK_SENT', and to\n 0 if you don't. */\n#define HAVE_DECL_SCTP_SHUTDOWN_ACK_SENT 1\n\n/* Define to 1 if you have the declaration of `SCTP_SHUTDOWN_PENDING', and to\n 0 if you don't. */\n#define HAVE_DECL_SCTP_SHUTDOWN_PENDING 1\n\n/* Define to 1 if you have the declaration of `SCTP_SHUTDOWN_RECEIVED', and to\n 0 if you don't. */\n#define HAVE_DECL_SCTP_SHUTDOWN_RECEIVED 1\n\n/* Define to 1 if you have the declaration of `SCTP_SHUTDOWN_SENT', and to 0\n if you don't. */\n#define HAVE_DECL_SCTP_SHUTDOWN_SENT 1\n\n/* Define to 1 if you have the declaration of `SCTP_UNORDERED', and to 0 if\n you don't. */\n#define HAVE_DECL_SCTP_UNORDERED 1\n\n/* Define to 1 if you have the declaration of `setrlimit', and to 0 if you\n don't. */\n#define HAVE_DECL_SETRLIMIT 1\n\n/* Define to 1 if you have the declaration of `time2posix', and to 0 if you\n don't. */\n#define HAVE_DECL_TIME2POSIX 0\n\n/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.\n */\n#define HAVE_DIRENT_H 1\n\n/* Define to 1 if you have the <dlfcn.h> header file. */\n#define HAVE_DLFCN_H 1\n\n/* Define to 1 if you have the `dlopen' function. */\n#define HAVE_DLOPEN 1\n\n/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */\n/* #undef HAVE_DOPRNT */\n\n/* Define if you have the 'end' symbol */\n#define HAVE_END_SYMBOL 1\n\n/* Define if you have a working fallocate() */\n/* #undef HAVE_FALLOCATE */\n\n/* Define to 1 if you have the <fcntl.h> header file. */\n#define HAVE_FCNTL_H 1\n\n/* Define to 1 if you have the `fdatasync' function. */\n#define HAVE_FDATASYNC 1\n\n/* Define to 1 if you have the `finite' function. */\n#define HAVE_FINITE 1\n\n/* Define to 1 if you have the `flockfile' function. */\n#define HAVE_FLOCKFILE 1\n\n/* Define to 1 if you have the `fork' function. */\n#define HAVE_FORK 1\n\n/* Define to 1 if you have the `fpsetmask' function. */\n/* #undef HAVE_FPSETMASK */\n\n/* Define to 1 if you have the `fstat' function. */\n#define HAVE_FSTAT 1\n\n/* Define if you have fwrite_unlocked */\n#define HAVE_FWRITE_UNLOCKED 1\n\n/* Define to 1 if you have a good `getaddrinfo' function. */\n#define HAVE_GETADDRINFO 1\n\n/* Define to 1 if you have the `gethostbyname2' function. */\n#define HAVE_GETHOSTBYNAME2 1\n\n/* Define to flavour of gethostbyname_r */\n#define HAVE_GETHOSTBYNAME_R GHBN_R_GLIBC\n\n/* Define to 1 if you have the `gethrtime' function. */\n/* #undef HAVE_GETHRTIME */\n\n/* define if gethrvtime() works and uses ioctl() to /proc/self */\n/* #undef HAVE_GETHRVTIME_PROCFS_IOCTL */\n\n/* Define to 1 if you have the `getifaddrs' function. */\n#define HAVE_GETIFADDRS 1\n\n/* Define to 1 if you have the `getipnodebyaddr' function. */\n/* #undef HAVE_GETIPNODEBYADDR */\n\n/* Define to 1 if you have the `getipnodebyname' function. */\n/* #undef HAVE_GETIPNODEBYNAME */\n\n/* Define to 1 if you have a good `getnameinfo' function. */\n#define HAVE_GETNAMEINFO 1\n\n/* Define to 1 if you have the `gmtime_r' function. */\n#define HAVE_GMTIME_R 1\n\n/* Define to 1 if you have the <ieeefp.h> header file. */\n/* #undef HAVE_IEEEFP_H */\n\n/* Define to 1 if you have the `ieee_handler' function. */\n/* #undef HAVE_IEEE_HANDLER */\n\n/* Define to 1 if you have the <ifaddrs.h> header file. */\n#define HAVE_IFADDRS_H 1\n\n/* Define if ipv6 is present */\n#define HAVE_IN6 1\n\n/* Define to 1 if you have the variable in6addr_any declared. */\n#define HAVE_IN6ADDR_ANY 1\n\n/* Define to 1 if you have the variable in6addr_loopback declared. */\n#define HAVE_IN6ADDR_LOOPBACK 1\n\n/* Define to 1 if you have the `inet_pton' function. */\n#define HAVE_INET_PTON 1\n\n/* Define to 1 if you have the <inttypes.h> header file. */\n#define HAVE_INTTYPES_H 1\n\n/* Early linux used in_addr6 instead of in6_addr, define if you have this */\n/* #undef HAVE_IN_ADDR6_STRUCT */\n\n/* Define to 1 if you have the `isinf' function. */\n#define HAVE_ISINF 1\n\n/* Define to 1 if you have the `isnan' function. */\n#define HAVE_ISNAN 1\n\n/* Define if you have kstat */\n/* #undef HAVE_KSTAT */\n\n/* Define to 1 if you have the <langinfo.h> header file. */\n#define HAVE_LANGINFO_H 1\n\n/* Define to 1 if you have the `dl' library (-ldl). */\n#define HAVE_LIBDL 1\n\n/* Define to 1 if you have the `dlpi' library (-ldlpi). */\n/* #undef HAVE_LIBDLPI */\n\n/* Define to 1 if you have the <libdlpi.h> header file. */\n/* #undef HAVE_LIBDLPI_H */\n\n/* Define to 1 if you have the `inet' library (-linet). */\n/* #undef HAVE_LIBINET */\n\n/* Define to 1 if you have the `m' library (-lm). */\n#define HAVE_LIBM 1\n\n/* Define to 1 if you have the `util' library (-lutil). */\n#define HAVE_LIBUTIL 1\n\n/* Define to 1 if you have the `z' library (-lz). */\n/* #undef HAVE_LIBZ */\n\n/* Define to 1 if you have the <limits.h> header file. */\n#define HAVE_LIMITS_H 1\n\n/* Define to 1 if you have the <linux/falloc.h> header file. */\n/* #undef HAVE_LINUX_FALLOC_H */\n\n/* Define to 1 if you have the `localtime_r' function. */\n#define HAVE_LOCALTIME_R 1\n\n/* Define to 1 if you have the <malloc.h> header file. */\n#define HAVE_MALLOC_H 1\n\n/* Define to 1 if you have the `mallopt' function. */\n#define HAVE_MALLOPT 1\n\n/* Define to 1 if you have the `memcpy' function. */\n#define HAVE_MEMCPY 1\n\n/* Define to 1 if you have the `memmove' function. */\n#define HAVE_MEMMOVE 1\n\n/* Define to 1 if you have the <memory.h> header file. */\n#define HAVE_MEMORY_H 1\n\n/* Define if the pthread.h header file is in pthread/mit directory. */\n/* #undef HAVE_MIT_PTHREAD_H */\n\n/* Define to 1 if you have the `mmap' function. */\n#define HAVE_MMAP 1\n\n/* Define to 1 if you have the `mremap' function. */\n#define HAVE_MREMAP 1\n\n/* Define if setsockopt() accepts multicast options */\n#define HAVE_MULTICAST_SUPPORT 1\n\n/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */\n/* #undef HAVE_NDIR_H */\n\n/* Define to 1 if you have the <netpacket/packet.h> header file. */\n#define HAVE_NETPACKET_PACKET_H 1\n\n/* Define to 1 if you have the <net/errno.h> header file. */\n/* #undef HAVE_NET_ERRNO_H */\n\n/* Define to 1 if you have the <net/if_dl.h> header file. */\n/* #undef HAVE_NET_IF_DL_H */\n\n/* Define to 1 if you have the `nl_langinfo' function. */\n#define HAVE_NL_LANGINFO 1\n\n/* Define if you don't have a definition of INADDR_LOOPBACK */\n/* #undef HAVE_NO_INADDR_LOOPBACK */\n\n/* Define to 1 if you have the `openpty' function. */\n#define HAVE_OPENPTY 1\n\n/* Define to 1 if you have the `poll' function. */\n#define HAVE_POLL 1\n\n/* Define to 1 if you have the <poll.h> header file. */\n#define HAVE_POLL_H 1\n\n/* Define to 1 if you have the `posix2time' function. */\n/* #undef HAVE_POSIX2TIME */\n\n/* Define to 1 if you have the `posix_fadvise' function. */\n#define HAVE_POSIX_FADVISE 1\n\n/* Define if you have a working posix_fallocate() */\n/* #undef HAVE_POSIX_FALLOCATE */\n\n/* Define to 1 if you have the `pread' function. */\n#define HAVE_PREAD 1\n\n/* Define if you have processor_bind functionality */\n/* #undef HAVE_PROCESSOR_BIND */\n\n/* Define if you have pset functionality */\n/* #undef HAVE_PSET */\n\n/* Define if you have the <pthread.h> header file. */\n#define HAVE_PTHREAD_H 1\n\n/* Define to 1 if you have the <pty.h> header file. */\n#define HAVE_PTY_H 1\n\n/* Define if you have putc_unlocked */\n#define HAVE_PUTC_UNLOCKED 1\n\n/* Define to 1 if you have the `pwrite' function. */\n#define HAVE_PWRITE 1\n\n/* Define to 1 if you have the `res_gethostbyname' function. */\n/* #undef HAVE_RES_GETHOSTBYNAME */\n\n/* Define to 1 if you have the `sbrk' function. */\n#define HAVE_SBRK 1\n\n/* Define if you have sched_getaffinity/sched_setaffinity */\n#define HAVE_SCHED_xETAFFINITY 1\n\n/* Define to 1 if you have the `sctp_bindx' function. */\n/* #undef HAVE_SCTP_BINDX */\n\n/* Define to 1 if you have the <netinet/sctp.h> header file */\n#define HAVE_SCTP_H 1\n\n/* Define to 1 if you have the `sctp_peeloff' function. */\n/* #undef HAVE_SCTP_PEELOFF */\n\n/* Define to 1 if you have the <sdkddkver.h> header file. */\n/* #undef HAVE_SDKDDKVER_H */\n\n/* Define to 1 if you have the `sendfile' function. */\n#define HAVE_SENDFILE 1\n\n/* Define to 1 if you have the `sendfilev' function. */\n/* #undef HAVE_SENDFILEV */\n\n/* Define to 1 if you have the `setlocale' function. */\n#define HAVE_SETLOCALE 1\n\n/* Define to 1 if you have the `setsid' function. */\n#define HAVE_SETSID 1\n\n/* Define if we have socklen_t */\n#define HAVE_SOCKLEN_T 1\n\n/* define if you have the Solaris/ultrasparc /dev/perfmon interface */\n/* #undef HAVE_SOLARIS_SPARC_PERFMON */\n\n/* Define if you have SO_BSDCOMPAT flag on sockets */\n/* #undef HAVE_SO_BSDCOMPAT */\n\n/* Define to 1 if you have the <stdint.h> header file. */\n#define HAVE_STDINT_H 1\n\n/* Define to 1 if you have the <stdlib.h> header file. */\n#define HAVE_STDLIB_H 1\n\n/* Define to 1 if you have the `strerror' function. */\n#define HAVE_STRERROR 1\n\n/* Define to 1 if you have the `strerror_r' function. */\n#define HAVE_STRERROR_R 1\n\n/* Define to 1 if you have the <strings.h> header file. */\n#define HAVE_STRINGS_H 1\n\n/* Define to 1 if you have the <string.h> header file. */\n#define HAVE_STRING_H 1\n\n/* Define to 1 if you have the `strlcat' function. */\n/* #undef HAVE_STRLCAT */\n\n/* Define to 1 if you have the `strlcpy' function. */\n/* #undef HAVE_STRLCPY */\n\n/* Define to 1 if you have the `strncasecmp' function. */\n#define HAVE_STRNCASECMP 1\n\n/* Define to 1 if `ifr_enaddr' is member of `struct ifreq'. */\n/* #undef HAVE_STRUCT_IFREQ_IFR_ENADDR */\n\n/* Define to 1 if `ifr_hwaddr' is member of `struct ifreq'. */\n#define HAVE_STRUCT_IFREQ_IFR_HWADDR 1\n\n/* Define to 1 if `spp_flags' is member of `struct sctp_paddrparams'. */\n#define HAVE_STRUCT_SCTP_PADDRPARAMS_SPP_FLAGS 1\n\n/* Define to 1 if `spp_pathmtu' is member of `struct sctp_paddrparams'. */\n#define HAVE_STRUCT_SCTP_PADDRPARAMS_SPP_PATHMTU 1\n\n/* Define to 1 if `spp_sackdelay' is member of `struct sctp_paddrparams'. */\n#define HAVE_STRUCT_SCTP_PADDRPARAMS_SPP_SACKDELAY 1\n\n/* Define to 1 if `sre_data' is member of `struct sctp_remote_error'. */\n#define HAVE_STRUCT_SCTP_REMOTE_ERROR_SRE_DATA 1\n\n/* Define to 1 if `ssf_data' is member of `struct sctp_send_failed'. */\n#define HAVE_STRUCT_SCTP_SEND_FAILED_SSF_DATA 1\n\n/* Define to 1 if you have the <syslog.h> header file. */\n#define HAVE_SYSLOG_H 1\n\n/* Define if you have <sys/devpoll.h> header file. */\n/* #undef HAVE_SYS_DEVPOLL_H */\n\n/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.\n */\n/* #undef HAVE_SYS_DIR_H */\n\n/* Define if you have the <sys/epoll.h> header file. */\n#define HAVE_SYS_EPOLL_H 1\n\n/* Define if you have <sys/event.h> header file. */\n/* #undef HAVE_SYS_EVENT_H */\n\n/* Define to 1 if you have the <sys/ioctl.h> header file. */\n#define HAVE_SYS_IOCTL_H 1\n\n/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.\n */\n/* #undef HAVE_SYS_NDIR_H */\n\n/* Define to 1 if you have the <sys/resource.h> header file */\n#define HAVE_SYS_RESOURCE_H 1\n\n/* Define to 1 if you have the <sys/sdt.h> header file. */\n/* #undef HAVE_SYS_SDT_H */\n\n/* Define to 1 if you have the <sys/socketio.h> header file. */\n/* #undef HAVE_SYS_SOCKETIO_H */\n\n/* Define to 1 if you have the <sys/socket.h> header file. */\n#define HAVE_SYS_SOCKET_H 1\n\n/* Define to 1 if you have the <sys/sockio.h> header file. */\n/* #undef HAVE_SYS_SOCKIO_H */\n\n/* Define to 1 if you have the <sys/stat.h> header file. */\n#define HAVE_SYS_STAT_H 1\n\n/* Define to 1 if you have the <sys/stropts.h> header file. */\n#define HAVE_SYS_STROPTS_H 1\n\n/* Define to 1 if you have the <sys/sysctl.h> header file. */\n#define HAVE_SYS_SYSCTL_H 1\n\n/* Define to 1 if you have the <sys/time.h> header file. */\n#define HAVE_SYS_TIME_H 1\n\n/* Define to 1 if you have the <sys/types.h> header file. */\n#define HAVE_SYS_TYPES_H 1\n\n/* Define to 1 if you have the <sys/uio.h> header file. */\n#define HAVE_SYS_UIO_H 1\n\n/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */\n#define HAVE_SYS_WAIT_H 1\n\n/* Define if termcap functions exists */\n#define HAVE_TERMCAP 1\n\n/* Define to 1 if you have the `time2posix' function. */\n/* #undef HAVE_TIME2POSIX */\n\n/* Define to 1 if you have the <unistd.h> header file. */\n#define HAVE_UNISTD_H 1\n\n/* Define to 1 if you have the <util.h> header file. */\n/* #undef HAVE_UTIL_H */\n\n/* Define to 1 if you have the <utmp.h> header file. */\n#define HAVE_UTMP_H 1\n\n/* Define to 1 if you have the `vfork' function. */\n#define HAVE_VFORK 1\n\n/* Define to 1 if you have the <vfork.h> header file. */\n/* #undef HAVE_VFORK_H */\n\n/* Define to 1 if you have the `vprintf' function. */\n#define HAVE_VPRINTF 1\n\n/* Define to 1 if you have a `wcwidth' function. */\n#define HAVE_WCWIDTH 1\n\n/* Define to 1 if you have the <windows.h> header file. */\n/* #undef HAVE_WINDOWS_H */\n\n/* Define to 1 if you have the <winsock2.h> header file. */\n/* #undef HAVE_WINSOCK2_H */\n\n/* Define to 1 if `fork' works. */\n#define HAVE_WORKING_FORK 1\n\n/* Define if you have a working posix_openpt implementation */\n#define HAVE_WORKING_POSIX_OPENPT 1\n\n/* Define to 1 if `vfork' works. */\n#define HAVE_WORKING_VFORK 1\n\n/* Define to 1 if you have the `writev' function. */\n#define HAVE_WRITEV 1\n\n/* Define to 1 if you have the <ws2tcpip.h> header file. */\n/* #undef HAVE_WS2TCPIP_H */\n\n/* Define to 1 if you have the `_brk' function. */\n/* #undef HAVE__BRK */\n\n/* Define if you have the '_end' symbol */\n#define HAVE__END_SYMBOL 1\n\n/* Define to 1 if you have the `_sbrk' function. */\n/* #undef HAVE__SBRK */\n\n/* Define to 1 if you have the `__brk' function. */\n/* #undef HAVE___BRK */\n\n/* Define to 1 if you have the `__sbrk' function. */\n#define HAVE___SBRK 1\n\n/* Define to enable HiPE */\n#define HIPE 1\n\n/* define if h_errno is declared (in some way) in a system header file */\n#define H_ERRNO_DECLARED 1\n\n/* Define if netdb.h needs struct sockaddr_in ans in.h CAN be included before\n */\n#define NETDB_H_NEEDS_IN_H 1\n\n/* Define if floating points exceptions are non-existing/not reliable */\n#define NO_FPE_SIGNALS \n\n/* Defined if no found C compiler can handle jump tables */\n/* #undef NO_JUMP_TABLE */\n\n/* Define if you dont have salen */\n#define NO_SA_LEN 1\n\n/* Define to the address where bug reports for this package should be sent. */\n#define PACKAGE_BUGREPORT \"\"\n\n/* Define to the full name of this package. */\n#define PACKAGE_NAME \"\"\n\n/* Define to the full name and version of this package. */\n#define PACKAGE_STRING \"\"\n\n/* Define to the one symbol short name of this package. */\n#define PACKAGE_TARNAME \"\"\n\n/* Define to the version of this package. */\n#define PACKAGE_VERSION \"\"\n\n/* Define if you wish to redefine FD_SETSIZE to be able to select on more fd\n */\n/* #undef REDEFINE_FD_SETSIZE */\n\n/* Define as the return type of signal handlers (`int' or `void'). */\n#define RETSIGTYPE void\n\n/* Define the sbrk() argument type. */\n#define SBRK_ARG_TYPE intptr_t\n\n/* Define the sbrk() return type. */\n#define SBRK_RET_TYPE void *\n\n/* The size of a `AO_t', as computed by sizeof. */\n/* #undef SIZEOF_AO_T */\n\n/* The size of a `char', as computed by sizeof. */\n#define SIZEOF_CHAR 1\n\n/* The size of a `int', as computed by sizeof. */\n#define SIZEOF_INT 4\n\n/* The size of a `long', as computed by sizeof. */\n#define SIZEOF_LONG 8\n\n/* The size of a `long long', as computed by sizeof. */\n#define SIZEOF_LONG_LONG 8\n\n/* The size of a `off_t', as computed by sizeof. */\n#define SIZEOF_OFF_T 8\n\n/* The size of a `short', as computed by sizeof. */\n#define SIZEOF_SHORT 2\n\n/* The size of a `size_t', as computed by sizeof. */\n#define SIZEOF_SIZE_T 8\n\n/* The size of a `time_t', as computed by sizeof. */\n#define SIZEOF_TIME_T 8\n\n/* The size of a `void *', as computed by sizeof. */\n#define SIZEOF_VOID_P 8\n\n/* The size of a `__int128_t', as computed by sizeof. */\n#define SIZEOF___INT128_T 16\n\n/* The size of a `__int64', as computed by sizeof. */\n#define SIZEOF___INT64 0\n\n/* Define to 1 if you have the ANSI C header files. */\n#define STDC_HEADERS 1\n\n/* define if the variable sys_errlist is declared in a system header file */\n#define SYS_ERRLIST_DECLARED \n\n/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */\n#define TIME_WITH_SYS_TIME 1\n\n/* Define to 1 if your <sys/time.h> declares `struct tm'. */\n/* #undef TM_IN_SYS_TIME */\n\n/* Define if you want to use dtrace for dynamic tracing */\n/* #undef USE_DTRACE */\n\n/* Define if you want to use dynamic tracing */\n/* #undef USE_DYNAMIC_TRACE */\n\n/* Define if you have matherr() function and struct exception type */\n#define USE_MATHERR 1\n\n/* Define to enable hrvtime() on Linux systems with perfctr extension */\n/* #undef USE_PERFCTR */\n\n/* Define if select() should be used instead of poll() */\n/* #undef USE_SELECT */\n\n/* Define if you want to use systemtap for dynamic tracing */\n/* #undef USE_SYSTEMTAP */\n\n/* Define to enable VM dynamic trace probes */\n/* #undef USE_VM_PROBES */\n\n/* Define if windows.h includes winsock2.h */\n/* #undef WINDOWS_H_INCLUDES_WINSOCK2_H */\n\n/* Define to 1 if your processor stores words with the most significant byte\n first (like Motorola and SPARC, unlike Intel and VAX). */\n/* #undef WORDS_BIGENDIAN */\n\n/* Define to empty if `const' does not conform to ANSI C. */\n/* #undef const */\n\n/* Define to `long' if <sys/types.h> does not define. */\n/* #undef off_t */\n\n/* Define to `int' if <sys/types.h> does not define. */\n/* #undef pid_t */\n\n/* Define to `unsigned' if <sys/types.h> does not define. */\n/* #undef size_t */\n\n/* Define as `fork' if `vfork' does not work. */\n/* #undef vfork */\n\n\n/* Redefine in6_addr. XXX this should be moved to the files where it's used? */\n#ifdef HAVE_IN_ADDR6_STRUCT\n#define in6_addr in_addr6\n#endif\n\n/* Define a reasonable default for INADDR_LOOPBACK */\n/* XXX this should be moved to the files where it's used? */\n#ifdef HAVE_NO_INADDR_LOOPBACK\n#define INADDR_LOOPBACK (u_long)0x7F000001\n#endif\n\n#ifdef REDEFINE_FD_SETSIZE\n#define FD_SETSIZE 1024\n#endif\n\n#ifdef HAVE_GETHRVTIME_PROCFS_IOCTL\n#define HAVE_GETHRVTIME\n#endif\n\n#ifndef HAVE_FINITE\n# if defined(HAVE_ISINF) && defined(HAVE_ISNAN)\n# define USE_ISINF_ISNAN\n# endif\n#endif\n\n#if defined(DEBUG) && defined(USE_THREADS) && !defined(ERTS_ENABLE_LOCK_CHECK)\n#define ERTS_ENABLE_LOCK_CHECK 1\n#endif\n\n"}]}, + {beam_dynamic_libraries, + "\tlibutil.so.1 => /lib64/libutil.so.1 (0x00002b3e06a05000)\n\tlibdl.so.2 => /lib64/libdl.so.2 (0x00002b3e06b08000)\n\tlibm.so.6 => /lib64/libm.so.6 (0x00002b3e06c0c000)\n\tlibncurses.so.5 => /lib64/libncurses.so.5 (0x00002b3e06d62000)\n\tlibpthread.so.0 => /lib64/libpthread.so.0 (0x00002b3e06ec5000)\n\tlibrt.so.1 => /lib64/librt.so.1 (0x00002b3e06fdc000)\n\tlibc.so.6 => /lib64/libc.so.6 (0x00002b3e070e6000)\n\t/lib64/ld-linux-x86-64.so.2 (0x00002b3e068e9000)\n"}, + {environment_erts, + [{"BINDIR", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/erts-5.10.3/bin"}, + {"DIALYZER_EMULATOR",false}, + {"CERL_DETACHED_PROG",false}, + {"EMU","beam"}, + {"ERL_CONSOLE_MODE",false}, + {"ERL_CRASH_DUMP",false}, + {"ERL_CRASH_DUMP_NICE",false}, + {"ERL_CRASH_DUMP_SECONDS",false}, + {"ERL_EPMD_PORT",false}, + {"ERL_EMULATOR_DLL",false}, + {"ERL_FULLSWEEP_AFTER",false}, + {"ERL_LIBS",false}, + {"ERL_MALLOC_LIB",false}, + {"ERL_MAX_PORTS",false}, + {"ERL_MAX_ETS_TABLES",false}, + {"ERL_NO_VFORK",false}, + {"ERL_NO_KERNEL_POLL",false}, + {"ERL_THREAD_POOL_SIZE",false}, + {"ERLC_EMULATOR",false}, + {"ESCRIPT_EMULATOR",false}, + {"HOME","/home/otptest"}, + {"HOMEDRIVE",false}, + {"HOMEPATH",false}, + {"LANG","sv_SE.UTF-8"}, + {"LC_ALL",false}, + {"LC_CTYPE",false}, + {"PATH", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/erts-5.10.3/bin:/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/bin:/opt/local/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/otp/patch/bin:/home/otp/obe/bin"}, + {"PROGNAME","erl"}, + {"RELDIR",false}, + {"ROOTDIR", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp"}, + {"TERM","xterm-256color"}, + {"COMSPEC",false}, + {"HEART_COMMAND",false}, + {"RUN_ERL_LOG_ALIVE_MINUTES",false}, + {"RUN_ERL_LOG_ACTIVITY_MINUTES",false}, + {"RUN_ERL_LOG_ALIVE_FORMAT",false}, + {"RUN_ERL_LOG_ALIVE_IN_UTC",false}, + {"RUN_ERL_LOG_GENERATIONS",false}, + {"RUN_ERL_LOG_MAXSIZE",false}, + {"RUN_ERL_DISABLE_FLOWCNTRL",false}, + {"CALLER_DRV_USE_OUTPUTV",false}, + {"ERL_INET_GETHOST_DEBUG",false}, + {"ERL_EFILE_THREAD_SHORT_CIRCUIT",false}, + {"ERL_WINDOW_TITLE",false}, + {"ERL_ABORT_ON_FAILURE",false}, + {"TTYSL_DEBUG_LOG",false}]}, + {environment, + [{"JAVA_ROOT","/usr/lib64/jvm/java"}, + {"COLORTERM","1"}, + {"LC_NAME","sv_SE.UTF-8"}, + {"G_BROKEN_FILENAMES","1"}, + {"LESSCLOSE","lessclose.sh %s %s"}, + {"LC_TIME","sv_SE.UTF-8"}, + {"DISPLAY","localhost:11.0"}, + {"INFOPATH", + "/usr/local/info:/usr/share/info:/usr/info:/opt/gnome/share/info"}, + {"LPDEST","lw5"}, + {"PKG_CONFIG_PATH", + "/usr/local/lib/pkgconfig:/usr/local/share/pkgconfig:/usr/lib64/pkgconfig:/usr/share/pkgconfig:/opt/kde3/lib64/pkgconfig:/opt/gnome/lib64/pkgconfig:/opt/gnome/lib64/pkgconfig:/opt/gnome/share/pkgconfig"}, + {"LESSOPEN","lessopen.sh %s"}, + {"XDG_DATA_DIRS", + "/usr/local/share/:/usr/share/:/etc/opt/kde3/share/:/opt/kde3/share/:/opt/gnome/share/"}, + {"ACLOCAL_FLAGS","-I /opt/gnome/share/aclocal"}, + {"PRINTER","lw5"}, + {"VISUAL","vim"}, + {"GTK_PATH64", + "/usr/local/lib64/gtk-2.0:/opt/gnome/lib64/gtk-2.0:/usr/lib64/gtk-2.0"}, + {"CVS_RSH","ssh"}, + {"LOGIN_PROFILE_RUN","true"}, + {"G_FILENAME_ENCODING","@locale,UTF-8,ISO-8859-15,CP1252"}, + {"LESS","-M -I"}, + {"MACHTYPE","x86_64-suse-linux"}, + {"LOGNAME","otptest"}, + {"GTK_PATH", + "/usr/local/lib/gtk-2.0:/opt/gnome/lib/gtk-2.0:/usr/lib/gtk-2.0"}, + {"WINDOWMANAGER","/usr/X11R6/bin/gnome"}, + {"LS_OPTIONS","-N --color=none -T 0"}, + {"LESS_ADVANCED_PREPROCESSOR","no"}, + {"OSTYPE","linux"}, + {"QT_SYSTEM_DIR","/usr/share/desktop-data"}, + {"JDK_HOME","/usr/lib64/jvm/java"}, + {"SHLVL","1"}, + {"HOME","/home/otptest"}, + {"https_proxy","http://www-proxy.ericsson.se:8080"}, + {"SDK_HOME","/usr/lib64/jvm/java"}, + {"LC_MEASUREMENT","sv_SE.UTF-8"}, + {"PYTHONSTARTUP","/etc/pythonstart"}, + {"PROGNAME","erl"}, + {"LANG","sv_SE.UTF-8"}, + {"EDITOR","vim"}, + {"JAVA_HOME","/usr/lib64/jvm/java"}, + {"INPUTRC","/etc/inputrc"}, + {"PWD", "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20"}, + {"LC_IDENTIFICATION","sv_SE.UTF-8"}, + {"JAVA_BINDIR","/usr/lib64/jvm/java/bin"}, + {"SSH_SENDS_LOCALE","yes"}, + {"CPU","x86_64"}, + {"LC_MESSAGES","POSIX"}, + {"MAIL","/var/mail/otptest"}, + {"PATH", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/erts-5.10.3/bin:/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/bin:/opt/local/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/otp/patch/bin:/home/otp/obe/bin"}, + {"MINICOM","-c on"}, + {"XDG_CONFIG_DIRS", + "/usr/local/etc/xdg/:/etc/xdg/:/etc/opt/gnome/xdg/"}, + {"CSHEDIT","emacs"}, + {"PAGER","less"}, + {"HOSTTYPE","x86_64"}, + {"ENV","/home/otptest/.bashrc"}, + {"ROOTDIR", "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp"}, + {"XNLSPATH","/usr/X11R6/lib/X11/nls"}, + {"LS_COLORS",[]}, + {"LC_TELEPHONE","sv_SE.UTF-8"}, + {"GROFF_NO_SGR","yes"}, + {"JRE_HOME","/usr/lib64/jvm/java/jre"}, + {"USER","otptest"}, + {"SSH_TTY","/dev/pts/3"}, + {"MORE","-sl"}, + {"LC_NUMERIC","sv_SE.UTF-8"}, + {"BINDIR", + "/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/erts-5.10.3/bin"}, + {"PROFILEREAD","true"}, + {"HISTSIZE","1000"}, + {"HOST","duilin"}, + {"TERM","xterm-256color"}, + {"SHELL","/bin/sh"}, + {"GNOME2_PATH","/usr/local:/opt/gnome:/usr"}, + {"XKEYSYMDB","/usr/X11R6/lib/X11/XKeysymDB"}, + {"HOSTNAME","duilin"}, + {"LC_MONETARY","sv_SE.UTF-8"}, + {"EMU","beam"}, + {"LC_ADDRESS","sv_SE.UTF-8"}, + {"LASER","lw5"}, + {"NNTPSERVER","news"}, + {"INFODIR","/usr/local/info:/usr/share/info:/usr/info"}, + {"MANPATH", + "/usr/local/man:/usr/share/man:/usr/X11R6/man:/opt/gnome/share/man"}, + {"LESSKEY","/etc/lesskey.bin"}, + {"LC_PAPER","sv_SE.UTF-8"}]}, + {sanity_check,ok}]}. diff --git a/lib/runtime_tools/vsn.mk b/lib/runtime_tools/vsn.mk index 534c7508d8..53fc51c198 100644 --- a/lib/runtime_tools/vsn.mk +++ b/lib/runtime_tools/vsn.mk @@ -1 +1 @@ -RUNTIME_TOOLS_VSN = 1.8.9 +RUNTIME_TOOLS_VSN = 1.11 |