├── .gitignore
├── LICENSE.txt
├── NOTICE.txt
├── README.md
├── assembly.xml
├── index.html
├── lib
├── kryo-1.01.jar
├── minlog-1.2.jar
├── reflectasm-0.8.jar
└── zookeeper-3.1.1.jar
├── pom.xml
├── scripts
├── generate_load.sh
├── run_adapter.sh
├── run_client_adapter.sh
└── s4_start.sh
└── src
├── main
├── java
│ └── io
│ │ └── s4
│ │ ├── MainApp.java
│ │ ├── adapter
│ │ └── Adapter.java
│ │ ├── client
│ │ ├── Adapter.java
│ │ ├── ClientConnection.java
│ │ ├── ClientReadMode.java
│ │ ├── ClientStub.java
│ │ ├── ClientWriteMode.java
│ │ ├── GenericJsonClientStub.java
│ │ ├── Handshake.java
│ │ ├── IOChannel.java
│ │ ├── InputStub.java
│ │ ├── OutputStub.java
│ │ └── util
│ │ │ └── ObjectBuilder.java
│ │ ├── collector
│ │ ├── Event.java
│ │ ├── EventListener.java
│ │ ├── EventRecord.java
│ │ └── EventWrapper.java
│ │ ├── dispatcher
│ │ ├── Dispatcher.java
│ │ ├── EventDispatcher.java
│ │ ├── MultiDispatcher.java
│ │ ├── StreamExcludingDispatcher.java
│ │ ├── StreamSelectingDispatcher.java
│ │ ├── partitioner
│ │ │ ├── BroadcastPartitioner.java
│ │ │ ├── CompoundKeyInfo.java
│ │ │ ├── DefaultHasher.java
│ │ │ ├── DefaultPartitioner.java
│ │ │ ├── DummyPartitioner.java
│ │ │ ├── HashAlgorithm.java
│ │ │ ├── Hasher.java
│ │ │ ├── KeyInfo.java
│ │ │ ├── Partitioner.java
│ │ │ ├── RoundRobinPartitioner.java
│ │ │ ├── TestDefaultPartitioner.java
│ │ │ └── VariableKeyPartitioner.java
│ │ └── transformer
│ │ │ └── Transformer.java
│ │ ├── emitter
│ │ ├── CommLayerEmitter.java
│ │ └── EventEmitter.java
│ │ ├── listener
│ │ ├── CommLayerListener.java
│ │ ├── EventHandler.java
│ │ ├── EventListener.java
│ │ └── EventProducer.java
│ │ ├── logger
│ │ ├── Log4jMonitor.java
│ │ ├── Monitor.java
│ │ └── TraceMessage.java
│ │ ├── message
│ │ ├── PrototypeRequest.java
│ │ ├── Request.java
│ │ ├── Response.java
│ │ └── SinglePERequest.java
│ │ ├── persist
│ │ ├── ConMapPersister.java
│ │ ├── DumpingPersister.java
│ │ ├── HashMapPersister.java
│ │ └── Persister.java
│ │ ├── processor
│ │ ├── AbstractPE.java
│ │ ├── AbstractWindowingPE.java
│ │ ├── AsynchronousEventProcessor.java
│ │ ├── ControlEventProcessor.java
│ │ ├── EventAdvice.java
│ │ ├── JoinPE.java
│ │ ├── OutputFormatter.java
│ │ ├── OverloadDispatcher.java
│ │ ├── OverloadDispatcherGenerator.java
│ │ ├── OverloadDispatcherSlot.java
│ │ ├── PEContainer.java
│ │ ├── PrintEventPE.java
│ │ ├── ProcessingElement.java
│ │ ├── PrototypeWrapper.java
│ │ ├── ReroutePE.java
│ │ └── SimpleCountingPE.java
│ │ ├── schema
│ │ ├── AvroSchemaManager.java
│ │ ├── Schema.java
│ │ ├── SchemaContainer.java
│ │ └── SchemaManager.java
│ │ ├── serialize
│ │ ├── AvroSerDeser.java
│ │ ├── AvroUtils.java
│ │ ├── KryoSerDeser.java
│ │ └── SerializerDeserializer.java
│ │ ├── test
│ │ ├── TestPersisterEventClock.java
│ │ └── TestPersisterWallClock.java
│ │ └── util
│ │ ├── AvroSchemaSupplementer.java
│ │ ├── ByteArrayIOChannel.java
│ │ ├── Cloner.java
│ │ ├── ClonerGenerator.java
│ │ ├── DoubleOutputFormatter.java
│ │ ├── GsonUtil.java
│ │ ├── KeyUtil.java
│ │ ├── LoadGenerator.java
│ │ ├── MethodInvoker.java
│ │ ├── MetricsName.java
│ │ ├── MiscConstants.java
│ │ ├── NumberUtils.java
│ │ ├── PreprodLogger.java
│ │ ├── ReverseDoubleOutputFormatter.java
│ │ ├── ReverseIntegerOutputFormatter.java
│ │ ├── S4Util.java
│ │ ├── SlotUtils.java
│ │ ├── ToStringOutputFormatter.java
│ │ ├── Watcher.java
│ │ └── clock
│ │ ├── Clock.java
│ │ ├── ClockStreamsLoader.java
│ │ ├── DrivenClock.java
│ │ ├── EventClock.java
│ │ ├── TimerRequest.java
│ │ └── WallClock.java
└── resources
│ ├── adapter_conf.xml
│ ├── client_adapter_conf.xml
│ ├── client_stub_conf.xml
│ ├── clusters_example.xml
│ ├── event_clock.xml
│ ├── log4j.xml
│ ├── s4_core.properties_header_redbutton
│ ├── s4_core.properties_header_typical
│ ├── s4_core_conf_typical.xml
│ └── wall_clock.xml
└── test
├── java
└── io
│ └── s4
│ └── processor
│ ├── MockPE.java
│ └── TestPrototypeWrapper.java
└── resources
└── log4j.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | # Eclipse meta-information
2 | /.project
3 | /.classpath
4 | /.settings
5 |
6 | # Build directory
7 | /target/
8 | !/target/site/apidocs/
9 | !/target/s4_core*.tar.gz
10 |
11 | # SVN
12 | .svn
13 |
--------------------------------------------------------------------------------
/NOTICE.txt:
--------------------------------------------------------------------------------
1 | =======================================================================
2 | NOTICE file for use with, and corresponding to Section 4 of,
3 | the Apache License, Version 2.0, in this case for the S4 project.
4 | =========================================================================
5 |
6 | This product includes software developed by
7 | Yahoo! Inc. (www.yahoo.com)
8 | Copyright (c) 2010 Yahoo! Inc. All rights reserved.
9 |
10 | This product includes software developed by
11 | The Apache Software Foundation (http://www.apache.org/).
12 |
13 | This product includes software (Jackson) developed by
14 | The Codehaus Foundation (http://www.codehaus.org/).
15 |
16 | Kryo binaries, distributed in lib/kryo-1.01.jar, developed by
17 | Nathan Sweet
18 | Copyright (c) 2008, Nathan Sweet.
19 | All rights reserved.
20 |
21 | json.org binaries
22 | Copyright (c) 2002 JSON.org
23 | Permission is hereby granted, free of charge, to any person
24 | obtaining a copy of this software and associated documentation
25 | files (the "Software"), to deal in the Software without
26 | restriction, including without limitation the rights to use,
27 | copy, modify, merge, publish, distribute, sublicense, and/or
28 | sell copies of the Software, and to permit persons to whom the
29 | Software is furnished to do so, subject to the following conditions:
30 | - The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
31 | - The Software shall be used for Good, not Evil.
32 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | S4 Core Classes
2 | ===============
3 |
4 | Introduction
5 | ------------
6 | This is a component of the S4 streaming system. For more information, see [s4.io](http://s4.io)
7 |
8 | Requirements
9 | ------------
10 |
11 | * Linux
12 | * Java 1.6
13 | * Maven
14 | * S4 Communication Layer
15 |
16 | Build Instructions
17 | ------------------
18 |
19 | 1. First build and install the comm package in your Maven repository.
20 |
21 | 2. Kryo, Reflectasm, and minlog must be installed to your local Maven repository manually.
22 | The jars are present in lib/ within this project. To install, run the following commands:
23 |
24 | mvn install:install-file -DgroupId=com.esotericsoftware -DartifactId=kryo -Dversion=1.01 -Dpackaging=jar -Dfile=lib/kryo-1.01.jar
25 | mvn install:install-file -DgroupId=com.esotericsoftware -DartifactId=reflectasm -Dversion=0.8 -Dpackaging=jar -Dfile=lib/reflectasm-0.8.jar
26 | mvn install:install-file -DgroupId=com.esotericsoftware -DartifactId=minlog -Dversion=1.2 -Dpackaging=jar -Dfile=lib/minlog-1.2.jar
27 |
28 | 3. Build and install using Maven
29 |
30 | mvn assembly:assembly install
31 |
32 |
--------------------------------------------------------------------------------
/assembly.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | tar.gz
6 |
7 | false
8 |
9 |
10 | false
11 | s4_core/lib
12 | runtime
13 | false
14 |
15 |
16 |
17 |
18 | ${project.basedir}/NOTICE.txt
19 |
20 | NOTICE.txt
21 |
22 |
23 | ${project.basedir}/src/main/resources/s4_core_conf_typical.xml
24 | s4_core/conf/typical
25 | s4_core_conf.xml
26 |
27 |
28 | ${project.basedir}/src/main/resources/wall_clock.xml
29 | s4_core/conf/typical
30 | wall_clock.xml
31 |
32 |
33 | ${project.basedir}/src/main/resources/event_clock.xml
34 | s4_core/conf/typical
35 | event_clock.xml
36 |
37 |
38 | ${project.basedir}/src/main/resources/s4_core.properties_header_typical
39 | s4_core/conf/typical
40 | s4_core.properties_header
41 |
42 |
43 | ${project.basedir}/src/main/resources/s4_core_conf_typical.xml
44 | s4_core/conf/redbutton
45 | s4_core_conf.xml
46 |
47 |
48 | ${project.basedir}/src/main/resources/wall_clock.xml
49 | s4_core/conf/redbutton
50 | wall_clock.xml
51 |
52 |
53 | ${project.basedir}/src/main/resources/event_clock.xml
54 | s4_core/conf/redbutton
55 | event_clock.xml
56 |
57 |
58 | ${project.basedir}/src/main/resources/s4_core.properties_header_redbutton
59 | s4_core/conf/redbutton
60 | s4_core.properties_header
61 |
62 |
63 | ${project.basedir}/src/main/resources/clusters_example.xml
64 | s4_core/conf/redbutton
65 | clusters.xml
66 |
67 |
68 |
69 |
70 | ${project.basedir}/target
71 | s4_core/lib
72 |
73 | *.jar
74 |
75 |
76 |
77 | ${project.basedir}/src/main/resources
78 | s4_core/conf/typical
79 |
80 | adapter_conf.xml
81 | log4j.xml
82 |
83 |
84 |
85 | ${project.basedir}/src/main/resources
86 | s4_core/conf/redbutton
87 |
88 | adapter_conf.xml
89 | client_adapter_conf.xml
90 | client_stub_conf.xml
91 | log4j.xml
92 |
93 |
94 |
95 | ${project.basedir}/scripts
96 | 0755
97 | bin
98 |
99 | s4_start.sh
100 | generate_load.sh
101 | run_adapter.sh
102 | run_client_adapter.sh
103 |
104 |
105 |
106 | ${project.basedir}
107 | s4_core/lock
108 |
109 | **/*
110 |
111 |
112 |
113 | ${project.basedir}
114 | s4_core/log
115 |
116 | **/*
117 |
118 |
119 |
120 | ${project.basedir}/
121 | s4_apps
122 |
123 | **/*
124 |
125 |
126 |
127 | ${project.basedir}
128 | s4_exts
129 |
130 | **/*
131 |
132 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | S4 Core Classes
4 |
5 |
6 | Javadocs
7 |
8 |
9 |
--------------------------------------------------------------------------------
/lib/kryo-1.01.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/s4/core/be285416364777531034950794ed545eb223d1ac/lib/kryo-1.01.jar
--------------------------------------------------------------------------------
/lib/minlog-1.2.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/s4/core/be285416364777531034950794ed545eb223d1ac/lib/minlog-1.2.jar
--------------------------------------------------------------------------------
/lib/reflectasm-0.8.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/s4/core/be285416364777531034950794ed545eb223d1ac/lib/reflectasm-0.8.jar
--------------------------------------------------------------------------------
/lib/zookeeper-3.1.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/s4/core/be285416364777531034950794ed545eb223d1ac/lib/zookeeper-3.1.1.jar
--------------------------------------------------------------------------------
/scripts/generate_load.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | osx=false
4 | case "`uname`" in
5 | Darwin*) osx=true;;
6 | esac
7 |
8 | if $osx; then
9 | READLINK="stat"
10 | else
11 | READLINK="readlink"
12 | fi
13 |
14 | #---------------------------------------------
15 | # USAGE and read arguments
16 | #---------------------------------------------
17 |
18 | if [ "$1" == "-h" ]; then
19 | echo "Usage: $0" >&2
20 | echo " -c s4 core home" >&2
21 | echo " -a sender cluster name" >&2
22 | echo " -g listener cluster name (same as -a if not specified)" >&2
23 | echo " -z cluster manager address (hostname:port)" >&2
24 | echo " -r emit rate" >&2
25 | echo " -d rate display interval" >&2
26 | echo " -s comma delimited list of schema files" >&2
27 | echo " -u path to user defined event classes" >&2
28 | echo " -x redbutton mode (explicit cluster management)" >&2
29 | echo " -h help" >&2
30 | exit 1
31 | fi
32 |
33 | BASE_DIR=`dirname $($READLINK -f $0)`
34 | CORE_HOME=`$READLINK -f ${BASE_DIR}/../s4_core`
35 | CP_SEP=":"
36 | REDBUTTON_MODE="false"
37 |
38 | while getopts ":c:z:a:g:r:d:l:u:x" opt;
39 | do case "$opt" in
40 | c) CORE_HOME=$OPTARG;;
41 | z) CLUSTER_MANAGER=$OPTARG;;
42 | a) SENDER_CLUSTER_NAME=$OPTARG;;
43 | g) LISTENER_CLUSTER_NAME=$OPTARG;;
44 | r) RATE=$OPTARG;;
45 | d) DISPLAY_INTERVAL=$OPTARG;;
46 | l) LOCK_DIR=$OPTARG;;
47 | u) USER_CLASS_PATH=$OPTARG;;
48 | x) REDBUTTON_MODE="true";;
49 | \?)
50 | echo "Invalid option: -$OPTARG" >&2
51 | exit 1
52 | ;;
53 | :)
54 | echo "Option -$OPTARG requires an argument." >&2
55 | exit 1
56 | ;;
57 | esac
58 | done
59 | shift $(($OPTIND-1))
60 |
61 | INPUT_FILE=$1
62 |
63 | if [ "x$CLUSTER_MANAGER" == "x" ] ; then
64 | CLUSTER_MANAGER="localhost:2181"
65 | fi
66 |
67 | if [ "x$SENDER_CLUSTER_NAME" == "x" ] ; then
68 | SENDER_CLUSTER_NAME="s4"
69 | fi
70 |
71 | if [ "x$LISTENER_CLUSTER_NAME" == "x" ] ; then
72 | LISTENER_CLUSTER_NAME=$SENDER_CLUSTER_NAME
73 | fi
74 |
75 | if [ "x$RATE" == "x" ] ; then
76 | RATE=80
77 | fi
78 |
79 | if [ "x$DISPLAY_INTERVAL" == "x" ] ; then
80 | DISPLAY_INTERVAL=15
81 | fi
82 |
83 | if [ "x$SCHEMA_FILE_LIST" != "x" ] ; then
84 | SCHEMA_FILE_LIST="${SCHEMA_FILE_LIST},"
85 | fi
86 | SCHEMA_FILE_LIST="${SCHEMA_FILE_LIST}${CORE_HOME}/conf/typical/schemas/EventWrapper_schema.js"
87 |
88 | if [ "x$LOCK_DIR" == "x" ] ; then
89 | LOCK_DIR="${CORE_HOME}/lock"
90 | fi
91 |
92 | echo "Cluster manager ${CLUSTER_MANAGER}"
93 | echo "Sender cluster name ${SENDER_CLUSTER_NAME}"
94 | echo "Listener cluster name ${LISTENER_CLUSTER_NAME}"
95 | echo "Rate ${RATE}"
96 | echo "Display interval ${DISPLAY_INTERVAL}"
97 | echo "Schema list ${SCHEMA_FILE_LIST}"
98 |
99 | JAVA_LOC=""
100 | if [ "x$JAVA_HOME" != "x" ] ; then
101 | JAVA_LOC=${JAVA_HOME}"/bin/"
102 | fi
103 |
104 | JAVA_OPTS=""
105 | if [ "x$LOCK_DIR" != "x" ] ; then
106 | JAVA_OPTS="$JAVA_OPTS -Dlock_dir=$LOCK_DIR "
107 | fi
108 |
109 | echo "java location is ${JAVA_LOC}"
110 | echo -n "JAVA VERSION="
111 | echo `${JAVA_LOC}java -version`
112 | #---------------------------------------------
113 | #ADDING CORE JARS TO CLASSPATH
114 | #---------------------------------------------
115 |
116 | CLASSPATH=`find $CORE_HOME -name "*.jar" | awk '{p=$0"'$CP_SEP'"p;} END {print p}'`
117 | if [ $REDBUTTON_MODE == "true" ] ; then
118 | CLASSPATH=${CLASSPATH}${CP_SEP}${CORE_HOME}/conf/redbutton
119 | JAVA_OPTS="$JAVA_OPTS -Dcommlayer.mode=static"
120 | fi
121 |
122 | if [ "x$USER_CLASS_PATH" != "x" ] ; then
123 | CLASSPATH=${CLASSPATH}${CP_SEP}${USER_CLASS_PATH}
124 | fi
125 |
126 |
127 | CMD="${JAVA_LOC}java $JAVA_OPTS -classpath $CLASSPATH io.s4.util.LoadGenerator -a ${SENDER_CLUSTER_NAME} -g ${LISTENER_CLUSTER_NAME} -z ${CLUSTER_MANAGER} -r${RATE} -d ${DISPLAY_INTERVAL} $INPUT_FILE"
128 | echo "Running ${CMD}"
129 | $CMD
130 |
--------------------------------------------------------------------------------
/scripts/run_adapter.sh:
--------------------------------------------------------------------------------
1 | #/bin/bash
2 |
3 | get_property()
4 | {
5 | val=`sed '/^\#/d' ${CONF_LOC}/s4_core.properties_header | grep $1 | tail -n 1 | sed 's/^[^=]*=//;s/^[[:space:]]*//;s/[[:space:]]*$//'`
6 | echo "$val"
7 | }
8 |
9 | osx=false
10 | case "`uname`" in
11 | Darwin*) osx=true;;
12 | esac
13 |
14 | if $osx; then
15 | READLINK="stat"
16 | else
17 | READLINK="readlink"
18 | fi
19 |
20 | #---------------------------------------------
21 | # USAGE and read arguments
22 | #---------------------------------------------
23 |
24 | if [ "$1" == "-h" ]; then
25 | echo "Usage: $0" >&2
26 | echo " -c s4 core home" >&2
27 | echo " -a sender cluster name" >&2
28 | echo " -g listener cluster name (same as -a if not specified)" >&2
29 | echo " -z cluster manager address (hostname:port)" >&2
30 | echo " -u path to user defined data adapter classes" >&2
31 | echo " -x redbutton mode (explicit cluster management)" >&2
32 | echo " -d legacy data adapter conf file" >&2
33 | echo " -h help" >&2
34 | exit 1
35 | fi
36 |
37 | BASE_DIR=`dirname $($READLINK -f $0)`
38 | CORE_HOME=`$READLINK -f ${BASE_DIR}/../s4_core`
39 | APPS_HOME=`$READLINK -f ${BASE_DIR}/../s4_apps`
40 | CP_SEP=":"
41 | REDBUTTON_MODE="false"
42 |
43 | while getopts ":c:z:a:l:u:d:x" opt;
44 | do case "$opt" in
45 | c) CORE_HOME=$OPTARG;;
46 | a) APPS_HOME=$OPTARG;;
47 | z) CLUSTER_MANAGER=$OPTARG;;
48 | a) SENDER_CLUSTER_NAME=$OPTARG;;
49 | g) LISTENER_CLUSTER_NAME=$OPTARG;;
50 | l) LOCK_DIR=$OPTARG;;
51 | u) USER_CLASS_PATH=$OPTARG;;
52 | d) DATA_ADAPTER_CONF=$OPTARG;;
53 | x) REDBUTTON_MODE="true";;
54 | \?)
55 | echo "Invalid option: -$OPTARG" >&2
56 | exit 1
57 | ;;
58 | :)
59 | echo "Option -$OPTARG requires an argument." >&2
60 | exit 1
61 | ;;
62 | esac
63 | done
64 | shift $(($OPTIND-1))
65 |
66 | CONF_TYPE=$1
67 | if [ "x$CONF_TYPE" == "x" ] ; then
68 | CONF_TYPE="redbutton"
69 | fi
70 |
71 | CONF_FILE=${CORE_HOME}"/conf/"${CONF_TYPE}"/adapter_conf.xml"
72 | CONF_LOC=`dirname $CONF_FILE`
73 | LOG_LOC="${CORE_HOME}/logs"
74 | COMMLAYER_MODE=$(get_property "commlayer_mode")
75 |
76 | if [ "x$CLUSTER_MANAGER" == "x" ] ; then
77 | CLUSTER_MANAGER="localhost:2181"
78 | fi
79 |
80 | if [ "x$SENDER_CLUSTER_NAME" == "x" ] ; then
81 | SENDER_CLUSTER_NAME="s4"
82 | fi
83 |
84 | if [ "x$LISTENER_CLUSTER_NAME" == "x" ] ; then
85 | LISTENER_CLUSTER_NAME=$SENDER_CLUSTER_NAME
86 | fi
87 |
88 | if [ "x$LOCK_DIR" == "x" ] ; then
89 | LOCK_DIR="${CORE_HOME}/lock"
90 | fi
91 |
92 | if [ "x$DATA_ADAPTER_CONF" == "x" ] ; then
93 | echo "No data adapter configuration specified"
94 | exit 1
95 | fi
96 |
97 | echo "Cluster manager ${CLUSTER_MANAGER}"
98 | echo "Sender cluster name ${SENDER_CLUSTER_NAME}"
99 | echo "Listener cluster name ${LISTENER_CLUSTER_NAME}"
100 |
101 | JAVA_LOC=""
102 | if [ "x$JAVA_HOME" != "x" ] ; then
103 | JAVA_LOC=${JAVA_HOME}"/bin/"
104 | fi
105 |
106 | JAVA_OPTS=""
107 | if [ "x$LOCK_DIR" != "x" ] ; then
108 | JAVA_OPTS="$JAVA_OPTS -Dlock_dir=$LOCK_DIR "
109 | fi
110 |
111 | JAVA_OPTS="$JAVA_OPTS -Dlog_loc=${LOG_LOC} "
112 |
113 | echo "java location is ${JAVA_LOC}"
114 | echo -n "JAVA VERSION="
115 | echo `${JAVA_LOC}java -version`
116 | #---------------------------------------------
117 | #ADDING CORE JARS TO CLASSPATH
118 | #---------------------------------------------
119 |
120 | CLASSPATH=`find $CORE_HOME -name "*.jar" | awk '{p=$0"'$CP_SEP'"p;} END {print p}'`
121 | CLASSPATH=$CLASSPATH$CP_SEP`find $APPS_HOME -name "*.jar" | awk '{p=$0"'$CP_SEP'"p;} END {print p}'`
122 | JAVA_OPTS="$JAVA_OPTS -Dzk_session_timeout=5000"
123 |
124 | CLASSPATH=${CLASSPATH}${CP_SEP}${CONF_LOC}
125 | if [ $REDBUTTON_MODE == "true" ] ; then
126 | JAVA_OPTS="$JAVA_OPTS -Dcommlayer.mode=static"
127 | else
128 | JAVA_OPTS="$JAVA_OPTS -Dcommlayer.mode=${COMMLAYER_MODE}"
129 | fi
130 |
131 | if [ "x$USER_CLASS_PATH" != "x" ] ; then
132 | CLASSPATH=${CLASSPATH}${CP_SEP}${USER_CLASS_PATH}
133 | fi
134 |
135 | MKTEMP_ARGS=""
136 |
137 | if $osx ; then
138 | MKTEMP_ARGS="tmpXXXX"
139 | fi
140 |
141 | TMP1=`mktemp -d $MKTEMP_ARGS`
142 | echo "Temp is $TMP1"
143 | echo "appName=${SENDER_CLUSTER_NAME}" > $TMP1/adapter.properties
144 | echo "listenerAppName=${LISTENER_CLUSTER_NAME}" >> $TMP1/adapter.properties
145 | cat $TMP1/adapter.properties
146 |
147 | CLASSPATH=${CLASSPATH}${CP_SEP}${TMP1}
148 |
149 | CMD="${JAVA_LOC}java $JAVA_OPTS -Dlog4j.configuration=file:${CONF_LOC}/log4j.xml -classpath $CLASSPATH io.s4.adapter.Adapter -t ${CONF_TYPE} -c ${CORE_HOME} -d ${DATA_ADAPTER_CONF}"
150 | echo "Running ${CMD}"
151 | $CMD
152 |
--------------------------------------------------------------------------------
/scripts/run_client_adapter.sh:
--------------------------------------------------------------------------------
1 | #/bin/bash
2 |
3 | get_property()
4 | {
5 | val=`sed '/^\#/d' ${CONF_LOC}/s4_core.properties_header | grep $1 | tail -n 1 | sed 's/^[^=]*=//;s/^[[:space:]]*//;s/[[:space:]]*$//'`
6 | echo "$val"
7 | }
8 |
9 | osx=false
10 | case "`uname`" in
11 | Darwin*) osx=true;;
12 | esac
13 |
14 | if $osx; then
15 | READLINK="stat"
16 | else
17 | READLINK="readlink"
18 | fi
19 |
20 | #---------------------------------------------
21 | # USAGE and read arguments
22 | #---------------------------------------------
23 |
24 | if [ "$1" == "-h" ]; then
25 | echo "Usage: $0" >&2
26 | echo " -c s4 core home" >&2
27 | echo " -a s4 apps home" >&2
28 | echo " -s sender cluster name" >&2
29 | echo " -g listener cluster name (same as -s if not specified)" >&2
30 | echo " -z cluster manager address (hostname:port)" >&2
31 | echo " -u path to user defined data adapter classes" >&2
32 | echo " -x redbutton mode (explicit cluster management)" >&2
33 | echo " -d client stub conf file" >&2
34 | echo " -h help" >&2
35 | exit 1
36 | fi
37 |
38 | BASE_DIR=`dirname $($READLINK -f $0)`
39 | CORE_HOME=`$READLINK -f ${BASE_DIR}/../s4_core`
40 | APPS_HOME=`$READLINK -f ${BASE_DIR}/../s4_apps`
41 | CP_SEP=":"
42 | REDBUTTON_MODE="false"
43 |
44 | while getopts ":c:z:a:s:g:l:u:d:x" opt;
45 | do case "$opt" in
46 | c) CORE_HOME=$OPTARG;;
47 | a) APPS_HOME=$OPTARG;;
48 | z) CLUSTER_MANAGER=$OPTARG;;
49 | s) SENDER_CLUSTER_NAME=$OPTARG;;
50 | g) LISTENER_CLUSTER_NAME=$OPTARG;;
51 | l) LOCK_DIR=$OPTARG;;
52 | u) USER_CLASS_PATH=$OPTARG;;
53 | d) DATA_ADAPTER_CONF=$OPTARG;;
54 | x) REDBUTTON_MODE="true";;
55 | \?)
56 | echo "Invalid option: -$OPTARG" >&2
57 | exit 1
58 | ;;
59 | :)
60 | echo "Option -$OPTARG requires an argument." >&2
61 | exit 1
62 | ;;
63 | esac
64 | done
65 | shift $(($OPTIND-1))
66 |
67 | CONF_TYPE=$1
68 | if [ "x$CONF_TYPE" == "x" ] ; then
69 | CONF_TYPE="redbutton"
70 | fi
71 |
72 | CONF_FILE=${CORE_HOME}"/conf/"${CONF_TYPE}"/adapter_conf.xml"
73 | CONF_LOC=`dirname $CONF_FILE`
74 | LOG_LOC="${CORE_HOME}/logs"
75 | COMMLAYER_MODE=$(get_property "commlayer_mode")
76 |
77 | if [ "x$CLUSTER_MANAGER" == "x" ] ; then
78 | CLUSTER_MANAGER="localhost:2181"
79 | fi
80 |
81 | if [ "x$SENDER_CLUSTER_NAME" == "x" ] ; then
82 | SENDER_CLUSTER_NAME="s4"
83 | fi
84 |
85 | if [ "x$LISTENER_CLUSTER_NAME" == "x" ] ; then
86 | LISTENER_CLUSTER_NAME=$SENDER_CLUSTER_NAME
87 | fi
88 |
89 | if [ "x$LOCK_DIR" == "x" ] ; then
90 | LOCK_DIR="${CORE_HOME}/lock"
91 | fi
92 |
93 | if [ "x$DATA_ADAPTER_CONF" == "x" ] ; then
94 | echo "No data adapter configuration specified"
95 | exit 1
96 | fi
97 |
98 | echo "Cluster manager ${CLUSTER_MANAGER}"
99 | echo "Sender cluster name ${SENDER_CLUSTER_NAME}"
100 | echo "Listener cluster name ${LISTENER_CLUSTER_NAME}"
101 |
102 | JAVA_LOC=""
103 | if [ "x$JAVA_HOME" != "x" ] ; then
104 | JAVA_LOC=${JAVA_HOME}"/bin/"
105 | fi
106 |
107 | JAVA_OPTS=""
108 | if [ "x$LOCK_DIR" != "x" ] ; then
109 | JAVA_OPTS="$JAVA_OPTS -Dlock_dir=$LOCK_DIR "
110 | fi
111 |
112 | JAVA_OPTS="$JAVA_OPTS -Dlog_loc=${LOG_LOC} "
113 |
114 | echo "java location is ${JAVA_LOC}"
115 | echo -n "JAVA VERSION="
116 | echo `${JAVA_LOC}java -version`
117 | #---------------------------------------------
118 | #ADDING CORE JARS TO CLASSPATH
119 | #---------------------------------------------
120 |
121 | CLASSPATH=`find $CORE_HOME -name "*.jar" | awk '{p=$0"'$CP_SEP'"p;} END {print p}'`
122 | CLASSPATH=$CLASSPATH$CP_SEP`find $APPS_HOME -name "*.jar" | awk '{p=$0"'$CP_SEP'"p;} END {print p}'`
123 | JAVA_OPTS="$JAVA_OPTS -Dzk_session_timeout=5000"
124 |
125 | CLASSPATH=${CLASSPATH}${CP_SEP}${CONF_LOC}
126 | if [ $REDBUTTON_MODE == "true" ] ; then
127 | JAVA_OPTS="$JAVA_OPTS -Dcommlayer.mode=static"
128 | else
129 | JAVA_OPTS="$JAVA_OPTS -Dcommlayer.mode=${COMMLAYER_MODE}"
130 | fi
131 |
132 | if [ "x$USER_CLASS_PATH" != "x" ] ; then
133 | CLASSPATH=${CLASSPATH}${CP_SEP}${USER_CLASS_PATH}
134 | fi
135 |
136 | MKTEMP_ARGS=""
137 |
138 | if $osx ; then
139 | MKTEMP_ARGS="tmpXXXX"
140 | fi
141 |
142 | TMP1=`mktemp -d $MKTEMP_ARGS`
143 | echo "Temp is $TMP1"
144 | echo "appName=${SENDER_CLUSTER_NAME}" > $TMP1/adapter.properties
145 | echo "listenerAppName=${LISTENER_CLUSTER_NAME}" >> $TMP1/adapter.properties
146 | echo "listener_max_queue_size=8000" >> $TMP1/adapter.properties
147 | cat $TMP1/adapter.properties
148 |
149 | CLASSPATH=${CLASSPATH}${CP_SEP}${TMP1}
150 |
151 | CMD="${JAVA_LOC}java $JAVA_OPTS -Dlog4j.configuration=file:${CONF_LOC}/log4j.xml -classpath $CLASSPATH io.s4.client.Adapter -t ${CONF_TYPE} -c ${CORE_HOME} -d ${DATA_ADAPTER_CONF}"
152 | echo "Running ${CMD}"
153 | $CMD
154 |
--------------------------------------------------------------------------------
/src/main/java/io/s4/client/ClientConnection.java:
--------------------------------------------------------------------------------
1 | package io.s4.client;
2 |
3 | import io.s4.collector.EventWrapper;
4 | import io.s4.message.Request;
5 |
6 | import java.io.IOException;
7 | import java.net.Socket;
8 | import java.util.HashSet;
9 | import java.util.List;
10 | import java.util.UUID;
11 |
12 | /**
13 | * Connection to a client. A Stub has a collection of connections.
14 | */
15 | public class ClientConnection {
16 | /**
17 | *
18 | */
19 | private final ClientStub clientStub;
20 |
21 | /**
22 | * TCP/IP socket used to communicate with client.
23 | */
24 | private final Socket socket;
25 |
26 | public final IOChannel io;
27 |
28 | public final ClientReadMode clientReadMode;
29 | public final ClientWriteMode clientWriteMode;
30 |
31 | /**
32 | * GUID of client.
33 | */
34 | public final UUID uuid;
35 |
36 | public ClientConnection(ClientStub clientStub, Socket socket, UUID uuid,
37 | ClientReadMode clientReadMode, ClientWriteMode clientWriteMode)
38 | throws IOException {
39 | this.clientStub = clientStub;
40 | this.uuid = uuid;
41 | this.socket = socket;
42 | this.io = this.clientStub.createIOChannel(socket);
43 | this.clientReadMode = clientReadMode;
44 | this.clientWriteMode = clientWriteMode;
45 | }
46 |
47 | public boolean good() {
48 | return socket.isConnected();
49 | }
50 |
51 | public void close() {
52 | synchronized (this.clientStub.clients) {
53 | ClientStub.logger.info("closing connection to client " + uuid);
54 | this.clientStub.clients.remove(this.uuid);
55 | }
56 |
57 | try {
58 | socket.close();
59 | } catch (IOException e) {
60 | ClientStub.logger.error("problem closing client connection to client "
61 | + uuid,
62 | e);
63 | }
64 | }
65 |
66 | private HashSet includeStreams = new HashSet();
67 | private HashSet excludeStreams = new HashSet();
68 |
69 | public void includeStreams(List streams) {
70 | includeStreams.addAll(streams);
71 | }
72 |
73 | public void excludeStreams(List streams) {
74 | excludeStreams.addAll(streams);
75 | }
76 |
77 | /**
78 | * Stream is accepted if and only if:
79 | *
80 | * (A) readMode is Select and: 1. indifferent to stream inclusion OR stream
81 | * is included AND 2. indifferent to stream exclusion OR stream is not
82 | * excluded.
83 | *
84 | * OR (B) readMode is All
85 | *
86 | * @return true if and only if stream is accepted
87 | */
88 | public boolean streamAccepted(String s) {
89 | switch (clientReadMode) {
90 | case None:
91 | case Private:
92 | return false;
93 |
94 | case Select:
95 | return (includeStreams.isEmpty() || includeStreams.contains(s))
96 | && (excludeStreams.isEmpty() || !excludeStreams.contains(s));
97 |
98 | case All:
99 | return true;
100 |
101 | default:
102 | return false;
103 | }
104 | }
105 |
106 | private Thread receiverThread = null;
107 |
108 | public void start() {
109 | if (clientWriteMode == ClientWriteMode.Enabled)
110 | (receiverThread = new Thread(receiver)).start();
111 | }
112 |
113 | public void stop() {
114 | if (receiverThread != null) {
115 | receiverThread.interrupt();
116 | receiverThread = null;
117 | }
118 | }
119 |
120 | public final Runnable receiver = new Runnable() {
121 | public void run() {
122 | try {
123 | while (good()) {
124 | byte[] b = io.recv();
125 |
126 | // null, empty => goodbye
127 | if (b == null || b.length == 0) {
128 | ClientStub.logger.info("client session ended " + uuid);
129 | break;
130 | }
131 |
132 | EventWrapper ew = ClientConnection.this.clientStub.eventWrapperFromBytes(b);
133 | if (ew == null)
134 | continue;
135 |
136 | Object event = ew.getEvent();
137 | if (event instanceof Request) {
138 | decorateRequest((Request) event);
139 | ClientStub.logger.info("Decorated client request: "
140 | + ew.toString());
141 | }
142 |
143 | ClientConnection.this.clientStub.injectEvent(ew);
144 | }
145 | } catch (IOException e) {
146 | ClientStub.logger.info("error while reading from client "
147 | + uuid, e);
148 |
149 | } finally {
150 | close();
151 | }
152 | }
153 |
154 | private void decorateRequest(Request r) {
155 | // add UUID of client into request.
156 | Request.RInfo info = r.getRInfo();
157 |
158 | if (info != null && info instanceof Request.ClientRInfo)
159 | ((Request.ClientRInfo) info).setRequesterUUID(ClientConnection.this.uuid);
160 | }
161 | };
162 |
163 | }
--------------------------------------------------------------------------------
/src/main/java/io/s4/client/ClientReadMode.java:
--------------------------------------------------------------------------------
1 | package io.s4.client;
2 |
3 | /**
4 | * Client mode.
5 | */
6 | public enum ClientReadMode {
7 | None(false, false), Private(true, false), Select(true, true), All(true, true);
8 |
9 | private final boolean priv;
10 | private final boolean pub;
11 |
12 | ClientReadMode(boolean priv, boolean pub) {
13 | this.priv = priv;
14 | this.pub = pub;
15 | }
16 |
17 | public boolean takePublic() {
18 | return pub;
19 | }
20 |
21 | public boolean takePrivate() {
22 | return priv;
23 | }
24 |
25 | public static ClientReadMode fromString(String s) {
26 | if (s.equalsIgnoreCase("none"))
27 | return None;
28 | else if (s.equalsIgnoreCase("private"))
29 | return Private;
30 | else if (s.equalsIgnoreCase("select"))
31 | return Select;
32 | else if (s.equalsIgnoreCase("all"))
33 | return All;
34 | else
35 | return null;
36 | }
37 | }
--------------------------------------------------------------------------------
/src/main/java/io/s4/client/ClientWriteMode.java:
--------------------------------------------------------------------------------
1 | package io.s4.client;
2 |
3 | /**
4 | * Client's write mode.
5 | */
6 | public enum ClientWriteMode {
7 | Enabled, Disabled;
8 |
9 | public static ClientWriteMode fromString(String s) {
10 | if (s.equalsIgnoreCase("enabled"))
11 | return Enabled;
12 | else if (s.equalsIgnoreCase("disabled"))
13 | return Disabled;
14 | else
15 | return null;
16 | }
17 | }
--------------------------------------------------------------------------------
/src/main/java/io/s4/client/GenericJsonClientStub.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2010 Yahoo! Inc. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing,
10 | * software distributed under the License is distributed on an
11 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
12 | * either express or implied. See the License for the specific
13 | * language governing permissions and limitations under the
14 | * License. See accompanying LICENSE file.
15 | */
16 | package io.s4.client;
17 |
18 | import io.s4.client.util.ObjectBuilder;
19 | import io.s4.collector.EventWrapper;
20 | import io.s4.util.GsonUtil;
21 |
22 | import java.nio.charset.Charset;
23 |
24 | import org.json.JSONArray;
25 | import org.json.JSONException;
26 | import org.json.JSONObject;
27 |
28 | public class GenericJsonClientStub extends ClientStub {
29 |
30 | // private static final ObjectBuilder builder = new ObjectBuilder();
31 | // private static final Gson builder = new Gson();
32 |
33 | private static final Info protocolInfo = new Info("generic-json", 1, 0);
34 |
35 | @Override
36 | public Info getProtocolInfo() {
37 | return protocolInfo;
38 | }
39 |
40 | @Override
41 | public EventWrapper eventWrapperFromBytes(byte[] v) {
42 | try {
43 | // interpret v as a JSON string
44 | String s = new String(v, Charset.forName("UTF8"));
45 | JSONObject json = new JSONObject(s);
46 |
47 | String streamName = json.getString("stream");
48 | String className = json.getString("class");
49 |
50 | Class> clazz;
51 | try {
52 | clazz = Class.forName(className);
53 | } catch (ClassNotFoundException e) {
54 | throw new ObjectBuilder.Exception("bad class name for json-encoded object: "
55 | + className,
56 | e);
57 | }
58 |
59 | String[] keyNames = null;
60 | JSONArray keyArray = json.optJSONArray("keys");
61 | if (keyArray != null) {
62 | keyNames = new String[keyArray.length()];
63 | for (int i = 0; i < keyNames.length; ++i) {
64 | keyNames[i] = keyArray.optString(i);
65 | }
66 | }
67 |
68 | String jevent = json.getString("object");
69 |
70 | Object obj = GsonUtil.get().fromJson(jevent, clazz);
71 |
72 | return new EventWrapper(streamName, keyNames, obj);
73 |
74 | } catch (JSONException e) {
75 | logger.error("problem with event JSON", e);
76 | } catch (ObjectBuilder.Exception e) {
77 | logger.error("failed to build object from JSON", e);
78 | }
79 |
80 | return null;
81 | }
82 |
83 | @Override
84 | public byte[] bytesFromEventWrapper(EventWrapper ew) {
85 | JSONObject jevent = new JSONObject();
86 |
87 | Object obj = ew.getEvent();
88 |
89 | try {
90 | jevent.put("stream", ew.getStreamName());
91 | jevent.put("class", obj.getClass().getName());
92 | jevent.put("object", GsonUtil.get().toJson(obj));
93 |
94 | return jevent.toString().getBytes(Charset.forName("UTF8"));
95 |
96 | } catch (JSONException e) {
97 | logger.error("exception while converting event wrapper to bytes.",
98 | e);
99 | return null;
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/main/java/io/s4/client/IOChannel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2010 Yahoo! Inc. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing,
10 | * software distributed under the License is distributed on an
11 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
12 | * either express or implied. See the License for the specific
13 | * language governing permissions and limitations under the
14 | * License. See accompanying LICENSE file.
15 | */
16 | package io.s4.client;
17 |
18 | import java.io.IOException;
19 |
20 | public interface IOChannel {
21 | byte[] recv() throws IOException;
22 |
23 | void send(byte[] v) throws IOException;
24 | }
--------------------------------------------------------------------------------
/src/main/java/io/s4/client/InputStub.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2010 Yahoo! Inc. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing,
10 | * software distributed under the License is distributed on an
11 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
12 | * either express or implied. See the License for the specific
13 | * language governing permissions and limitations under the
14 | * License. See accompanying LICENSE file.
15 | */
16 | package io.s4.client;
17 |
18 | import io.s4.listener.EventProducer;
19 |
20 | public interface InputStub extends EventProducer {
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/io/s4/client/OutputStub.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2010 Yahoo! Inc. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing,
10 | * software distributed under the License is distributed on an
11 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
12 | * either express or implied. See the License for the specific
13 | * language governing permissions and limitations under the
14 | * License. See accompanying LICENSE file.
15 | */
16 | package io.s4.client;
17 |
18 | import io.s4.processor.AsynchronousEventProcessor;
19 |
20 | import java.util.List;
21 |
22 | public interface OutputStub extends AsynchronousEventProcessor {
23 |
24 | List getAcceptedStreams();
25 |
26 | }
--------------------------------------------------------------------------------
/src/main/java/io/s4/collector/Event.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2010 Yahoo! Inc. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing,
10 | * software distributed under the License is distributed on an
11 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
12 | * either express or implied. See the License for the specific
13 | * language governing permissions and limitations under the
14 | * License. See accompanying LICENSE file.
15 | */
16 | package io.s4.collector;
17 |
18 | import io.s4.dispatcher.Dispatcher;
19 | import io.s4.dispatcher.partitioner.CompoundKeyInfo;
20 | import io.s4.dispatcher.partitioner.KeyInfo;
21 | import io.s4.dispatcher.partitioner.KeyInfo.KeyPathElement;
22 | import io.s4.dispatcher.partitioner.KeyInfo.KeyPathElementIndex;
23 | import io.s4.dispatcher.partitioner.KeyInfo.KeyPathElementName;
24 |
25 | import java.util.ArrayList;
26 | import java.util.List;
27 | import java.util.Map;
28 |
29 | public class Event extends EventRecord {
30 | private String eventName;
31 | private long timestamp;
32 | private List compoundKeys = new ArrayList();
33 | private boolean debug = false;
34 | public static final String EVENT_NAME_KEY = "S4__eventName";
35 | public static final String TIMESTAMP_KEY = "S4__timestamp";
36 |
37 | public void setDebug(boolean debug) {
38 | this.debug = debug;
39 | }
40 |
41 | public Event(Map passedEventData) {
42 | super(passedEventData);
43 |
44 | eventName = this.get(EVENT_NAME_KEY, "unknown");
45 | timestamp = this.get(TIMESTAMP_KEY, -1L);
46 |
47 | List plainCompoundKeyList = null;
48 | if ((plainCompoundKeyList = get(Dispatcher.PARTITION_INFO_KEY,
49 | EMPTY_LIST)) != EMPTY_LIST) {
50 | for (EventRecord plainCompoundKeyInfo : plainCompoundKeyList) {
51 | CompoundKeyInfo compoundKeyInfo = new CompoundKeyInfo();
52 | compoundKeyInfo.setCompoundValue(plainCompoundKeyInfo.get("compoundValue",
53 | (String) null));
54 | compoundKeyInfo.setCompoundKey(plainCompoundKeyInfo.get("compoundKey",
55 | (String) null));
56 | compoundKeys.add(compoundKeyInfo);
57 | for (EventRecord plainKeyInfo : plainCompoundKeyInfo.get("keyInfoList",
58 | EMPTY_LIST)) {
59 | KeyInfo keyInfo = new KeyInfo();
60 | for (EventRecord plainKeyPathElement : plainKeyInfo.get("keyPathElementList",
61 | EMPTY_LIST)) {
62 | String keyName = plainKeyPathElement.get("keyName",
63 | (String) null);
64 | Integer index = plainKeyPathElement.get("index",
65 | (Integer) null);
66 |
67 | if (keyName != null) {
68 | keyInfo.addElementToPath(keyName);
69 | } else if (index != null) {
70 | keyInfo.addElementToPath(index);
71 | }
72 | }
73 | compoundKeyInfo.addKeyInfo(keyInfo);
74 | }
75 | }
76 | }
77 | if (debug) {
78 | for (CompoundKeyInfo compoundKeyInfo : compoundKeys) {
79 | System.out.println("CompoundKey: "
80 | + compoundKeyInfo.getCompoundValue());
81 | for (KeyInfo keyInfo : compoundKeyInfo.getKeyInfoList()) {
82 | String keyPath = "";
83 | for (KeyPathElement keyPathElement : keyInfo.getKeyPath()) {
84 | if (keyPathElement instanceof KeyPathElementIndex) {
85 | keyPath += "["
86 | + ((KeyPathElementIndex) keyPathElement).getIndex()
87 | + "]";
88 | } else {
89 | if (keyPath.length() > 0) {
90 | keyPath += "/";
91 | }
92 | keyPath += ((KeyPathElementName) keyPathElement).getKeyName();
93 | }
94 | }
95 | System.out.println(" " + keyPath);
96 | }
97 | }
98 | }
99 | }
100 |
101 | public List getCompoundKeys() {
102 | return compoundKeys;
103 | }
104 |
105 | public String getEventName() {
106 | return eventName;
107 | }
108 |
109 | public long getTimeStamp() {
110 | return timestamp;
111 | }
112 |
113 | public List