├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── build.gradle ├── gradle.properties ├── gradle ├── doc.gradle ├── ide.gradle ├── setup.gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src ├── api ├── overview.html └── stylesheet.css ├── docbook ├── css │ ├── highlight.css │ ├── manual-multipage.css │ ├── manual-singlepage.css │ └── manual.css ├── images │ ├── background.png │ ├── caution.png │ ├── important.png │ ├── logo.png │ ├── note.png │ ├── tip.png │ └── warning.png └── xsl │ ├── common.xsl │ ├── epub.xsl │ ├── html-multipage.xsl │ ├── html-singlepage.xsl │ ├── html.xsl │ ├── pdf.xsl │ ├── xslthl-config.xml │ └── xslthl │ ├── asciidoc-hl.xml │ ├── bourne-hl.xml │ ├── c-hl.xml │ ├── cpp-hl.xml │ ├── csharp-hl.xml │ ├── css-hl.xml │ ├── html-hl.xml │ ├── ini-hl.xml │ ├── java-hl.xml │ ├── javascript-hl.xml │ ├── json-hl.xml │ ├── perl-hl.xml │ ├── php-hl.xml │ ├── properties-hl.xml │ ├── python-hl.xml │ ├── ruby-hl.xml │ ├── sql2003-hl.xml │ └── yaml-hl.xml ├── docs └── asciidoc │ ├── 20to21.adoc │ ├── aeron.adoc │ ├── core-bytebuffer.adoc │ ├── gettingstarted.adoc │ ├── images │ ├── RBP.png │ ├── RBWP.png │ ├── broadcast.png │ ├── bus-overview.png │ ├── core-overview.png │ ├── golo │ │ ├── body-bg.png │ │ └── pre-bg.png │ ├── logo-2x.png │ ├── logo.png │ ├── longMaxThreading.png │ ├── maker │ │ └── body-bg.png │ ├── marble │ │ ├── marble-101.png │ │ ├── marble-overflowbuffer.png │ │ ├── marble-overflowdrop.png │ │ ├── marble-requestwhen.png │ │ └── marble-throttle.png │ ├── modules.png │ ├── nThreading.png │ ├── net-latency.png │ ├── net-overview.png │ ├── overview.png │ ├── rbd2.png │ ├── rs.png │ ├── signals.png │ ├── streams-overview.png │ └── wiringup.png │ ├── index-docinfo.html │ ├── index-docinfo.xml │ ├── index.asciidoc │ ├── kafka.adoc │ ├── nav.html │ ├── net-e2e.adoc │ ├── net-http.adoc │ ├── net-tcp.adoc │ ├── net.adoc │ └── stylesheets │ ├── asciidoctor.css │ ├── colony.css │ ├── foundation-lime.css │ ├── foundation-potion.css │ ├── foundation.css │ ├── github.css │ ├── golo.css │ ├── iconic.css │ ├── maker.css │ ├── readthedocs.css │ ├── rocket-panda.css │ └── rubygems.css ├── main └── java │ └── reactor │ └── ipc │ ├── connector │ ├── Connector.java │ ├── Inbound.java │ ├── Outbound.java │ └── OutboundThen.java │ └── stream │ ├── Ipc.java │ ├── IpcDone.java │ ├── IpcInit.java │ ├── IpcServiceMapper.java │ ├── OnStream.java │ ├── SimpleStreamConnector.java │ ├── StreamConnector.java │ ├── StreamContext.java │ ├── StreamContextImpl.java │ ├── StreamOperations.java │ ├── StreamOperationsImpl.java │ ├── StreamOutbound.java │ └── StreamSetup.java └── test ├── java └── reactor │ └── ipc │ ├── BasicPingPongTests.java │ └── socket │ ├── ByteArrayStreamProtocol.java │ ├── SimpleClient.java │ ├── SimpleConnection.java │ ├── SimpleContext.java │ ├── SimplePeer.java │ └── SimpleServer.java └── resources └── logback.xml /.gitignore: -------------------------------------------------------------------------------- 1 | *# 2 | .#* 3 | .DS_Store 4 | bin 5 | build 6 | .classpath 7 | .eclipse 8 | .gradle 9 | .project 10 | .settings 11 | out 12 | *.log 13 | *.i* 14 | *.java.hsp 15 | *.index 16 | *.data 17 | classes 18 | exportToHtml 19 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - oraclejdk8 4 | 5 | sudo: required 6 | 7 | cache: 8 | directories: 9 | - $HOME/.m2 10 | - $HOME/.gradle -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # reactor-ipc is no longer actively maintained by VMware, Inc. 2 | 3 | > :warning: **Note**: This project is has been phased out 4 | in Reactor 3.x and is only used in the non supported reactor-netty versions 0.5 and 0.6. 5 | 6 | If you have questions about Reactor 3, join the 7 | community (see the [reactor README](https://github.com/reactor/reactor/blob/master/README.md)). 8 | 9 | 10 | [![Join the chat at https://gitter.im/reactor/reactor](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/reactor/reactor?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 11 | 12 | # reactor-ipc 13 | 14 | You will find backpressure-ready components to encode, decode, send (unicast, multicast or request/response) and serve connections in dedicated repositories : 15 | - [reactor-netty](https://github.com/reactor/reactor-netty) : Client/Server interactions for UDP/TCP/HTTP 16 | - [reactor-kafka](https://github.com/reactor/reactor-kafka) : Reactive Kafka client 17 | 18 | ## Javadoc 19 | http://projectreactor.io/docs/ipc/release/api/ 20 | 21 | _Licensed under [Apache Software License 2.0](www.apache.org/licenses/LICENSE-2.0)_ 22 | 23 | _Sponsored by [Pivotal](http://pivotal.io)_ 24 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2017 Pivotal Software 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 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | buildscript { 18 | repositories { 19 | maven { url "https://repo.spring.io/plugins-release" } 20 | } 21 | dependencies { 22 | classpath 'org.springframework.build.gradle:propdeps-plugin:0.0.7', 23 | 'io.spring.gradle:spring-io-plugin:0.0.4.RELEASE', 24 | 'com.github.jengelman.gradle.plugins:shadow:1.2.0', 25 | 'org.asciidoctor:asciidoctorj-pdf:1.5.0-alpha.8' 26 | } 27 | } 28 | 29 | plugins { 30 | id 'org.asciidoctor.convert' version '1.5.2' 31 | } 32 | 33 | description = 'IPC contracts for Reactive transport and protocol' 34 | 35 | ext { 36 | gradleVersion = '3.5' 37 | gradleScriptDir = "${rootProject.projectDir}/gradle" 38 | 39 | reactorVersion = '3.1.0.BUILD-SNAPSHOT' 40 | 41 | // Logging 42 | slf4jVersion = '1.7.12' 43 | logbackVersion = '1.1.2' 44 | 45 | javadocLinks = [ 46 | "https://docs.oracle.com/javase/7/docs/api/", 47 | "https://docs.oracle.com/javaee/6/api/", 48 | "https://fasterxml.github.io/jackson-databind/javadoc/2.5/", 49 | "https://www.reactive-streams.org/reactive-streams-1.0.1-javadoc/", 50 | "https://projectreactor.io/docs/core/release/api/", 51 | "https://projectreactor.io/docs/netty/release/api/", 52 | ] as String[] 53 | } 54 | 55 | apply from: "$gradleScriptDir/setup.gradle" 56 | apply from: "$gradleScriptDir/doc.gradle" 57 | 58 | configure(rootProject) { project -> 59 | group = 'io.projectreactor.ipc' 60 | 61 | apply plugin: 'propdeps' 62 | apply plugin: 'java' 63 | apply from: "${gradleScriptDir}/ide.gradle" 64 | 65 | [compileJava, compileTestJava]*.options*.compilerArgs = [ 66 | "-Xlint:varargs", 67 | "-Xlint:cast", 68 | "-Xlint:classfile", 69 | "-Xlint:dep-ann", 70 | "-Xlint:divzero", 71 | "-Xlint:empty", 72 | "-Xlint:finally", 73 | "-Xlint:overrides", 74 | "-Xlint:path", 75 | "-Xlint:processing", 76 | "-Xlint:static", 77 | "-Xlint:try", 78 | "-Xlint:deprecation", 79 | "-Xlint:unchecked", 80 | "-Xlint:-serial", // intentionally disabled 81 | "-Xlint:-options", // intentionally disabled 82 | "-Xlint:-fallthrough", // intentionally disabled 83 | "-Xlint:-rawtypes" // TODO enable and fix warnings 84 | ] 85 | 86 | compileJava { 87 | sourceCompatibility = 1.8 88 | targetCompatibility = 1.8 89 | } 90 | 91 | compileTestJava { 92 | sourceCompatibility = 1.8 93 | targetCompatibility = 1.8 94 | } 95 | 96 | if (JavaVersion.current().isJava8Compatible()) { 97 | compileTestJava.options.compilerArgs += "-parameters" 98 | tasks.withType(Javadoc) { 99 | options.addStringOption('Xdoclint:none', '-quiet') 100 | } 101 | } 102 | 103 | [compileJava, compileTestJava]*.options*.encoding = 'UTF-8' 104 | sourceSets.test.resources.srcDirs = ["src/test/resources", "src/test/java"] 105 | 106 | configurations.all { 107 | exclude group: 'commons-logging', module: 'commons-logging' 108 | } 109 | 110 | project.tasks.withType(Test).all { 111 | systemProperty("java.awt.headless", "true") 112 | systemProperty("reactor.trace.cancel", "true") 113 | systemProperty("reactor.trace.nocapacity", "true") 114 | systemProperty("testGroups", project.properties.get("testGroups")) 115 | scanForTestClasses = false 116 | include '**/*Tests.*' 117 | include '**/*Spec.*' 118 | exclude '**/*Abstract*.*' 119 | } 120 | 121 | repositories { 122 | if (version.endsWith('BUILD-SNAPSHOT') || project.hasProperty('platformVersion')) { 123 | mavenLocal() 124 | maven { url 'https://repo.spring.io/libs-snapshot' } 125 | } 126 | maven { url 'https://repo.spring.io/libs-release' } 127 | maven { url "https://oss.sonatype.org/content/repositories/releases/" } 128 | jcenter() 129 | mavenCentral() 130 | } 131 | 132 | // dependencies that are common across all java projects 133 | dependencies { 134 | // JSR-305 annotations 135 | optional "com.google.code.findbugs:jsr305:3.0.0" 136 | 137 | // Logging 138 | optional "org.slf4j:slf4j-api:$slf4jVersion" 139 | 140 | compile "io.projectreactor:reactor-core:$reactorVersion" 141 | 142 | testRuntime "ch.qos.logback:logback-classic:$logbackVersion" 143 | // Testing 144 | testCompile "org.hamcrest:hamcrest-library:1.3", 145 | "org.testng:testng:6.8.5" 146 | } 147 | 148 | 149 | if (project.hasProperty('platformVersion')) { 150 | apply plugin: 'spring-io' 151 | 152 | repositories { 153 | maven { url 'https://repo.spring.io/libs-snapshot' } 154 | } 155 | 156 | dependencyManagement { 157 | springIoTestRuntime { 158 | imports { 159 | mavenBom "io.spring.platform:platform-bom:$platformVersion" 160 | } 161 | } 162 | } 163 | } 164 | } 165 | 166 | configurations.all { 167 | // check for updates every build 168 | resolutionStrategy.cacheChangingModulesFor 0, 'seconds' 169 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | version=0.7.0.BUILD-SNAPSHOT -------------------------------------------------------------------------------- /gradle/doc.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2016 Pivotal Software 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 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | configure(rootProject) { 18 | apply plugin: "java" 19 | apply plugin: 'org.asciidoctor.convert' 20 | 21 | javadoc { 22 | group = "Reactor IPC Javadoc" 23 | 24 | description = "Generates aggregated Javadoc API documentation." 25 | title = "${rootProject.description} ${version} API" 26 | 27 | if (JavaVersion.current().isJava8Compatible()) { 28 | compileTestJava.options.compilerArgs += "-parameters" 29 | tasks.withType(Javadoc) { 30 | options.addStringOption('Xdoclint:none', '-quiet') 31 | } 32 | } 33 | options.memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PROTECTED 34 | options.author = true 35 | options.header = rootProject.description 36 | options.overview = "src/api/overview.html" 37 | options.stylesheetFile = file("src/api/stylesheet.css") 38 | options.links(rootProject.ext.javadocLinks) 39 | 40 | source rootProject.sourceSets.main.allJava 41 | 42 | maxMemory = "1024m" 43 | destinationDir = new File(buildDir, "docs/javadoc") 44 | } 45 | 46 | asciidoctor { 47 | sources { 48 | include "index.asciidoc" 49 | } 50 | outputDir file("$buildDir/asciidoc") 51 | backends = ['html5', 'pdf'] 52 | logDocuments = true 53 | options = [doctype: 'book'] 54 | attributes docinfo: '', 55 | toc2: '', 56 | 'compat-mode': '', 57 | stylesdir: "stylesheets/", 58 | stylesheet: 'golo.css', 59 | appversion: "$version", 60 | 'source-highlighter': 'coderay' 61 | 62 | doLast { 63 | file("$outputDir/pdf/index.pdf"). 64 | renameTo("$outputDir/pdf/ipc-reference-guide-${version}.pdf") 65 | } 66 | } 67 | 68 | } 69 | 70 | -------------------------------------------------------------------------------- /gradle/ide.gradle: -------------------------------------------------------------------------------- 1 | import org.gradle.plugins.ide.eclipse.model.ProjectDependency 2 | import org.gradle.plugins.ide.eclipse.model.SourceFolder 3 | 4 | apply plugin: 'idea' 5 | apply plugin: 'eclipse' 6 | apply plugin: 'propdeps-eclipse' 7 | apply plugin: 'propdeps-idea' 8 | 9 | // Until eclipse fully supports Java 8 use 1.7 source level 10 | eclipse.jdt { 11 | sourceCompatibility = 1.8 12 | targetCompatibility = 1.8 13 | } 14 | 15 | // Replace classpath entries with project dependencies (GRADLE-1116) 16 | eclipse.classpath.file.whenMerged { classpath -> 17 | def regexp = /.*?\/([^\/]+)\/build\/[^\/]+\/(?:main|test)/ // only match those that end in main or test (avoids removing necessary entries like build/classes/jaxb) 18 | def projectOutputDependencies = classpath.entries.findAll { entry -> entry.path =~ regexp } 19 | projectOutputDependencies.each { entry -> 20 | def matcher = (entry.path =~ regexp) 21 | if (matcher) { 22 | def projectName = matcher[0][1] 23 | def path = "/${projectName}" 24 | if (!classpath.entries.find { e -> e instanceof ProjectDependency && e.path == path }) { 25 | def dependency = new ProjectDependency(path, project(":${projectName}").path) 26 | dependency.exported = true 27 | classpath.entries.add(dependency) 28 | } 29 | classpath.entries.remove(entry) 30 | } 31 | } 32 | classpath.entries.removeAll { entry -> (entry.path =~ /(?!.*?repack.*\.jar).*?\/([^\/]+)\/build\/libs\/[^\/]+\.jar/) } 33 | } 34 | 35 | // Use separate main/test outputs (prevents WTP from packaging test classes) 36 | eclipse.classpath.defaultOutputDir = file(project.name + "/bin/eclipse") 37 | eclipse.classpath.file.beforeMerged { classpath -> 38 | classpath.entries.findAll { it instanceof SourceFolder }.each { 39 | if (it.output?.startsWith("bin/")) { 40 | it.output = null 41 | } 42 | } 43 | } 44 | eclipse.classpath.file.whenMerged { classpath -> 45 | classpath.entries.findAll { it instanceof SourceFolder }.each { 46 | it.output = "bin/" + it.path.split("/")[1] 47 | } 48 | } 49 | 50 | // Allow projects to be used as WPT modules 51 | eclipse.project.natures "org.eclipse.wst.common.project.facet.core.nature" 52 | 53 | // Include project specific settings 54 | task eclipseSettings(type: Copy) { 55 | from rootProject.files( 56 | "src/eclipse/org.eclipse.jdt.ui.prefs", 57 | "src/eclipse/org.eclipse.wst.common.project.facet.core.xml") 58 | into project.file('.settings/') 59 | outputs.upToDateWhen { false } 60 | } 61 | 62 | task eclipseWstComponent(type: Copy) { 63 | from rootProject.files( 64 | "src/eclipse/org.eclipse.wst.common.component") 65 | into project.file('.settings/') 66 | expand(deployname: project.name) 67 | outputs.upToDateWhen { false } 68 | } 69 | 70 | task eclipseJdtPrepare(type: Copy) { 71 | from rootProject.file("src/eclipse/org.eclipse.jdt.core.prefs") 72 | into project.file(".settings/") 73 | outputs.upToDateWhen { false } 74 | } 75 | 76 | task cleanEclipseJdtUi(type: Delete) { 77 | delete project.file(".settings/org.eclipse.jdt.ui.prefs") 78 | delete project.file("org.eclipse.jdt.core.prefs") 79 | delete project.file(".settings/org.eclipse.wst.common.component") 80 | delete project.file(".settings/org.eclipse.wst.common.project.facet.core.xml") 81 | } 82 | 83 | tasks["eclipseJdt"].dependsOn(eclipseJdtPrepare) 84 | tasks["cleanEclipse"].dependsOn(cleanEclipseJdtUi) 85 | tasks["eclipse"].dependsOn(eclipseSettings, eclipseWstComponent) 86 | 87 | // Filter 'build' folder 88 | 89 | eclipse.project.file.withXml { 90 | def node = it.asNode() 91 | 92 | def filteredResources = node.get("filteredResources") 93 | if (filteredResources) { 94 | node.remove(filteredResources) 95 | } 96 | def filterNode = node.appendNode("filteredResources").appendNode("filter") 97 | filterNode.appendNode("id", "1359048889071") 98 | filterNode.appendNode("name", "") 99 | filterNode.appendNode("type", "30") 100 | def matcherNode = filterNode.appendNode("matcher") 101 | matcherNode.appendNode("id", "org.eclipse.ui.ide.multiFilter") 102 | matcherNode.appendNode("arguments", "1.0-projectRelativePath-matches-false-false-build") 103 | } -------------------------------------------------------------------------------- /gradle/setup.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2016 Pivotal Software 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 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | task wrapper(type: Wrapper, description: "Create a Gradle self-download wrapper") { 18 | group = 'Project Setup' 19 | gradleVersion = "$gradleVersion" 20 | } 21 | 22 | configure(rootProject) { subproject -> 23 | if(subproject.name == 'docs') return 24 | 25 | apply plugin: 'propdeps-maven' 26 | apply plugin: 'maven' 27 | 28 | install { 29 | repositories.mavenInstaller { 30 | customizePom(pom, subproject) 31 | } 32 | } 33 | 34 | jar { 35 | manifest.attributes["Created-By"] = "${System.getProperty("java.version")} (${System.getProperty("java.specification.vendor")})" 36 | manifest.attributes["Implementation-Title"] = subproject.name 37 | manifest.attributes["Implementation-Version"] = subproject.version 38 | } 39 | 40 | task sourcesJar(type: Jar) { 41 | classifier = 'sources' 42 | from sourceSets.main.allSource 43 | } 44 | 45 | task javadocJar(type: Jar) { 46 | classifier = 'javadoc' 47 | from javadoc 48 | } 49 | 50 | artifacts { 51 | archives sourcesJar 52 | archives javadocJar 53 | } 54 | } 55 | 56 | def customizePom(def pom, def gradleProject) { 57 | pom.whenConfigured { generatedPom -> 58 | // eliminate test-scoped dependencies (no need in maven central poms) 59 | generatedPom.dependencies.removeAll { dep -> 60 | dep.scope == "test" 61 | } 62 | 63 | // sort to make pom dependencies order consistent to ease comparison of older poms 64 | generatedPom.dependencies = generatedPom.dependencies.sort { dep -> 65 | "$dep.scope:$dep.groupId:$dep.artifactId" 66 | } 67 | 68 | // add all items necessary for maven central publication 69 | generatedPom.project { 70 | name = gradleProject.description 71 | description = gradleProject.description 72 | url = 'https://github.com/reactor/reactor' 73 | organization { 74 | name = 'reactor' 75 | url = 'https://github.com/reactor' 76 | } 77 | licenses { 78 | license { 79 | name 'The Apache Software License, Version 2.0' 80 | url 'https://www.apache.org/licenses/LICENSE-2.0.txt' 81 | distribution 'repo' 82 | } 83 | } 84 | scm { 85 | url = 'https://github.com/reactor/reactor-ipc' 86 | connection = 'scm:git:git://github.com/reactor/reactor-ipc' 87 | developerConnection = 'scm:git:git://github.com/reactor/reactor-ipc' 88 | } 89 | developers { 90 | developer { 91 | id = 'smaldini' 92 | name = 'Stephane Maldini' 93 | email = 'smaldini@pivotal.io' 94 | } 95 | developer { 96 | id = 'kadyana' 97 | name = 'Anatoly Kadyshev' 98 | } 99 | } 100 | issueManagement { 101 | system = "GitHub Issues" 102 | url = "https://github.com/reactor/reactor/issues" 103 | } 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Jul 19 10:36:00 BST 2016 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-bin.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2016 Pivotal Software 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 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | rootProject.name = 'reactor-ipc' -------------------------------------------------------------------------------- /src/api/overview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | This document is the API specification for the Reactor FastData library. 8 |
9 |
10 |

11 | Reactor is a succinct and powerful foundational library for building reactive, FastData applications on the JVM. 12 | More detailed documentation is available on the reference guide. 14 |

15 |
16 | 17 | -------------------------------------------------------------------------------- /src/docbook/css/highlight.css: -------------------------------------------------------------------------------- 1 | /* 2 | code highlight CSS resemblign the Eclipse IDE default color schema 3 | @author Costin Leau 4 | */ 5 | 6 | .hl-keyword { 7 | color: #7F0055; 8 | font-weight: bold; 9 | } 10 | 11 | .hl-comment { 12 | color: #3F5F5F; 13 | font-style: italic; 14 | } 15 | 16 | .hl-multiline-comment { 17 | color: #3F5FBF; 18 | font-style: italic; 19 | } 20 | 21 | .hl-tag { 22 | color: #3F7F7F; 23 | } 24 | 25 | .hl-attribute { 26 | color: #7F007F; 27 | } 28 | 29 | .hl-value { 30 | color: #2A00FF; 31 | } 32 | 33 | .hl-string { 34 | color: #2A00FF; 35 | } -------------------------------------------------------------------------------- /src/docbook/css/manual-multipage.css: -------------------------------------------------------------------------------- 1 | @IMPORT url("manual.css"); 2 | 3 | body.firstpage { 4 | background: url("../images/background.png") no-repeat center top; 5 | } 6 | 7 | div.part h1 { 8 | border-top: none; 9 | } 10 | -------------------------------------------------------------------------------- /src/docbook/css/manual-singlepage.css: -------------------------------------------------------------------------------- 1 | @IMPORT url("manual.css"); 2 | 3 | body { 4 | background: url("../images/background.png") no-repeat center top; 5 | } 6 | 7 | -------------------------------------------------------------------------------- /src/docbook/css/manual.css: -------------------------------------------------------------------------------- 1 | @IMPORT url("highlight.css"); 2 | 3 | html { 4 | padding: 0pt; 5 | margin: 0pt; 6 | } 7 | 8 | body { 9 | color: #333333; 10 | margin: 15px 30px; 11 | font-family: Helvetica, Arial, Freesans, Clean, Sans-serif; 12 | line-height: 1.6; 13 | -webkit-font-smoothing: antialiased; 14 | } 15 | 16 | code { 17 | font-size: 16px; 18 | font-family: Consolas, "Liberation Mono", Courier, monospace; 19 | color: #6D180B; 20 | } 21 | 22 | :not(pre) > code { 23 | background-color: #F2F2F2; 24 | border: 1px solid #CCCCCC; 25 | border-radius: 4px; 26 | padding: 1px 3px 0; 27 | text-shadow: none; 28 | white-space: nowrap; 29 | } 30 | 31 | body > *:first-child { 32 | margin-top: 0 !important; 33 | } 34 | 35 | div { 36 | margin: 0pt; 37 | } 38 | 39 | hr { 40 | border: 1px solid #CCCCCC; 41 | background: #CCCCCC; 42 | } 43 | 44 | h1, h2, h3, h4, h5, h6 { 45 | color: #000000; 46 | cursor: text; 47 | font-weight: bold; 48 | margin: 30px 0 10px; 49 | padding: 0; 50 | } 51 | 52 | h1, h2, h3 { 53 | margin: 40px 0 10px; 54 | } 55 | 56 | h1 { 57 | margin: 70px 0 30px; 58 | padding-top: 20px; 59 | } 60 | 61 | div.part h1 { 62 | border-top: 1px dotted #CCCCCC; 63 | } 64 | 65 | h1, h1 code { 66 | font-size: 32px; 67 | } 68 | 69 | h2, h2 code { 70 | font-size: 24px; 71 | } 72 | 73 | h3, h3 code { 74 | font-size: 20px; 75 | } 76 | 77 | h4, h1 code, h5, h5 code, h6, h6 code { 78 | font-size: 18px; 79 | } 80 | 81 | div.book, div.chapter, div.appendix, div.part, div.preface { 82 | min-width: 300px; 83 | max-width: 1200px; 84 | margin: 0 auto; 85 | } 86 | 87 | p.releaseinfo { 88 | font-weight: bold; 89 | margin-bottom: 40px; 90 | margin-top: 40px; 91 | } 92 | 93 | div.authorgroup { 94 | line-height: 1; 95 | } 96 | 97 | p.copyright { 98 | line-height: 1; 99 | margin-bottom: -5px; 100 | } 101 | 102 | .legalnotice p { 103 | font-style: italic; 104 | font-size: 14px; 105 | line-height: 1; 106 | } 107 | 108 | div.titlepage + p, div.titlepage + p { 109 | margin-top: 0; 110 | } 111 | 112 | pre { 113 | line-height: 1.0; 114 | color: black; 115 | } 116 | 117 | a { 118 | color: #4183C4; 119 | text-decoration: none; 120 | } 121 | 122 | p { 123 | margin: 15px 0; 124 | text-align: left; 125 | } 126 | 127 | ul, ol { 128 | padding-left: 30px; 129 | } 130 | 131 | li p { 132 | margin: 0; 133 | } 134 | 135 | div.table { 136 | margin: 1em; 137 | padding: 0.5em; 138 | text-align: center; 139 | } 140 | 141 | div.table table, div.informaltable table { 142 | display: table; 143 | width: 100%; 144 | } 145 | 146 | div.table td { 147 | padding-left: 7px; 148 | padding-right: 7px; 149 | } 150 | 151 | .sidebar { 152 | line-height: 1.4; 153 | padding: 0 20px; 154 | background-color: #F8F8F8; 155 | border: 1px solid #CCCCCC; 156 | border-radius: 3px 3px 3px 3px; 157 | } 158 | 159 | .sidebar p.title { 160 | color: #6D180B; 161 | } 162 | 163 | pre.programlisting, pre.screen { 164 | font-size: 15px; 165 | padding: 6px 10px; 166 | background-color: #F8F8F8; 167 | border: 1px solid #CCCCCC; 168 | border-radius: 3px 3px 3px 3px; 169 | clear: both; 170 | overflow: auto; 171 | line-height: 1.4; 172 | font-family: Consolas, "Liberation Mono", Courier, monospace; 173 | } 174 | 175 | table { 176 | border-collapse: collapse; 177 | border-spacing: 0; 178 | border: 1px solid #DDDDDD !important; 179 | border-radius: 4px !important; 180 | border-collapse: separate !important; 181 | line-height: 1.6; 182 | } 183 | 184 | table thead { 185 | background: #F5F5F5; 186 | } 187 | 188 | table tr { 189 | border: none; 190 | border-bottom: none; 191 | } 192 | 193 | table th { 194 | font-weight: bold; 195 | } 196 | 197 | table th, table td { 198 | border: none !important; 199 | padding: 6px 13px; 200 | } 201 | 202 | table tr:nth-child(2n) { 203 | background-color: #F8F8F8; 204 | } 205 | 206 | td p { 207 | margin: 0 0 15px 0; 208 | } 209 | 210 | div.table-contents td p { 211 | margin: 0; 212 | } 213 | 214 | div.important *, div.note *, div.tip *, div.warning *, div.navheader *, div.navfooter *, div.calloutlist * { 215 | border: none !important; 216 | background: none !important; 217 | margin: 0; 218 | } 219 | 220 | div.important p, div.note p, div.tip p, div.warning p { 221 | color: #6F6F6F; 222 | line-height: 1.6; 223 | } 224 | 225 | div.important code, div.note code, div.tip code, div.warning code { 226 | background-color: #F2F2F2 !important; 227 | border: 1px solid #CCCCCC !important; 228 | border-radius: 4px !important; 229 | padding: 1px 3px 0 !important; 230 | text-shadow: none !important; 231 | white-space: nowrap !important; 232 | } 233 | 234 | .note th, .tip th, .warning th { 235 | display: none; 236 | } 237 | 238 | .note tr:first-child td, .tip tr:first-child td, .warning tr:first-child td { 239 | border-right: 1px solid #CCCCCC !important; 240 | padding-top: 10px; 241 | } 242 | 243 | div.calloutlist p, div.calloutlist td { 244 | padding: 0; 245 | margin: 0; 246 | } 247 | 248 | div.calloutlist > table > tbody > tr > td:first-child { 249 | padding-left: 10px; 250 | width: 30px !important; 251 | } 252 | 253 | div.important, div.note, div.tip, div.warning { 254 | margin-left: 0px !important; 255 | margin-right: 20px !important; 256 | margin-top: 20px; 257 | margin-bottom: 20px; 258 | padding-top: 10px; 259 | padding-bottom: 10px; 260 | } 261 | 262 | div.toc { 263 | line-height: 1.2; 264 | } 265 | 266 | dl, dt { 267 | margin-top: 1px; 268 | margin-bottom: 0; 269 | } 270 | 271 | div.toc > dl > dt { 272 | font-size: 32px; 273 | font-weight: bold; 274 | margin: 30px 0 10px 0; 275 | display: block; 276 | } 277 | 278 | div.toc > dl > dd > dl > dt { 279 | font-size: 24px; 280 | font-weight: bold; 281 | margin: 20px 0 10px 0; 282 | display: block; 283 | } 284 | 285 | div.toc > dl > dd > dl > dd > dl > dt { 286 | font-weight: bold; 287 | font-size: 20px; 288 | margin: 10px 0 0 0; 289 | } 290 | 291 | tbody.footnotes * { 292 | border: none !important; 293 | } 294 | 295 | div.footnote p { 296 | margin: 0; 297 | line-height: 1; 298 | } 299 | 300 | div.footnote p sup { 301 | margin-right: 6px; 302 | vertical-align: middle; 303 | } 304 | 305 | div.navheader { 306 | border-bottom: 1px solid #CCCCCC; 307 | } 308 | 309 | div.navfooter { 310 | border-top: 1px solid #CCCCCC; 311 | } 312 | 313 | .title { 314 | margin-left: -1em; 315 | padding-left: 1em; 316 | } 317 | 318 | .title > a { 319 | position: absolute; 320 | visibility: hidden; 321 | display: block; 322 | font-size: 0.85em; 323 | margin-top: 0.05em; 324 | margin-left: -1em; 325 | vertical-align: text-top; 326 | color: black; 327 | } 328 | 329 | .title > a:before { 330 | content: "\00A7"; 331 | } 332 | 333 | .title:hover > a, .title > a:hover, .title:hover > a:hover { 334 | visibility: visible; 335 | } 336 | 337 | .title:focus > a, .title > a:focus, .title:focus > a:focus { 338 | outline: 0; 339 | } 340 | -------------------------------------------------------------------------------- /src/docbook/images/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docbook/images/background.png -------------------------------------------------------------------------------- /src/docbook/images/caution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docbook/images/caution.png -------------------------------------------------------------------------------- /src/docbook/images/important.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docbook/images/important.png -------------------------------------------------------------------------------- /src/docbook/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docbook/images/logo.png -------------------------------------------------------------------------------- /src/docbook/images/note.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docbook/images/note.png -------------------------------------------------------------------------------- /src/docbook/images/tip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docbook/images/tip.png -------------------------------------------------------------------------------- /src/docbook/images/warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docbook/images/warning.png -------------------------------------------------------------------------------- /src/docbook/xsl/common.xsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 26 | 27 | 28 | 1 29 | 0 30 | 1 31 | 32 | 33 | 34 | images/ 35 | .png 36 | 37 | 38 | book toc,title 39 | 3 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/docbook/xsl/epub.xsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/docbook/xsl/html-multipage.xsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 24 | 25 | 26 | 27 | 28 | css/manual-multipage.css 29 | 30 | '5' 31 | '1' 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | firstpage 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /src/docbook/xsl/html-singlepage.xsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 24 | 25 | 26 | 27 | 28 | css/manual-singlepage.css 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/docbook/xsl/html.xsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 26 | 27 | 28 | 29 | 30 | 31 | 1 32 | 33 | 34 | 1 35 | 36 | 37 | 38 | 120 39 | images/callouts/ 40 | .png 41 | 42 | 43 | text/css 44 | 45 | text-align: left 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | , 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 |
129 |

Authors

130 | 131 |
132 |
133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | # 150 | 151 | 152 | 153 | 154 | 155 | 156 |
157 | -------------------------------------------------------------------------------- /src/docbook/xsl/xslthl-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/docbook/xsl/xslthl/asciidoc-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | //// 10 | //// 11 | 12 | 13 | // 14 | 15 | 16 | 17 | ^(={1,6} .+)$ 18 | 19 | MULTILINE 20 | 21 | 22 | ^(\.[^\.\s].+)$ 23 | 24 | MULTILINE 25 | 26 | 27 | ^(:!?\w.*?:) 28 | 29 | MULTILINE 30 | 31 | 32 | ^(-|\*{1,5}|\d*\.{1,5})(?= .+$) 33 | 34 | MULTILINE 35 | 36 | 37 | ^(\[.+\])$ 38 | 39 | MULTILINE 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/docbook/xsl/xslthl/bourne-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 27 | 28 | # 29 | 30 | << 31 | ' 32 | " 33 | - 34 | 35 | 36 | 37 | 38 | " 39 | \ 40 | 41 | 42 | ' 43 | \ 44 | 45 | 46 | 47 | 0x 48 | 49 | 50 | 51 | . 52 | 53 | 54 | 55 | 56 | 57 | if 58 | then 59 | else 60 | elif 61 | fi 62 | case 63 | esac 64 | for 65 | while 66 | until 67 | do 68 | done 69 | 70 | exec 71 | shift 72 | exit 73 | times 74 | break 75 | export 76 | trap 77 | continue 78 | readonly 79 | wait 80 | eval 81 | return 82 | 83 | cd 84 | echo 85 | hash 86 | pwd 87 | read 88 | set 89 | test 90 | type 91 | ulimit 92 | umask 93 | unset 94 | 95 | 96 | -------------------------------------------------------------------------------- /src/docbook/xsl/xslthl/c-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 29 | 30 | 31 | /** 32 | */ 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | /* 41 | */ 42 | 43 | // 44 | 45 | 46 | # 47 | \ 48 | 49 | 50 | 51 | 52 | " 53 | \ 54 | 55 | 56 | ' 57 | \ 58 | 59 | 60 | 0x 61 | ul 62 | lu 63 | u 64 | l 65 | 66 | 67 | 68 | . 69 | 70 | e 71 | ul 72 | lu 73 | u 74 | f 75 | l 76 | 77 | 78 | 79 | auto 80 | _Bool 81 | break 82 | case 83 | char 84 | _Complex 85 | const 86 | continue 87 | default 88 | do 89 | double 90 | else 91 | enum 92 | extern 93 | float 94 | for 95 | goto 96 | if 97 | _Imaginary 98 | inline 99 | int 100 | long 101 | register 102 | restrict 103 | return 104 | short 105 | signed 106 | sizeof 107 | static 108 | struct 109 | switch 110 | typedef 111 | union 112 | unsigned 113 | void 114 | volatile 115 | while 116 | 117 | 118 | -------------------------------------------------------------------------------- /src/docbook/xsl/xslthl/cpp-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 31 | 32 | 33 | /** 34 | */ 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | /* 43 | */ 44 | 45 | // 46 | 47 | 48 | # 49 | \ 50 | 51 | 52 | 53 | 54 | " 55 | \ 56 | 57 | 58 | ' 59 | \ 60 | 61 | 62 | 0x 63 | ul 64 | lu 65 | u 66 | l 67 | 68 | 69 | 70 | . 71 | 72 | e 73 | ul 74 | lu 75 | u 76 | f 77 | l 78 | 79 | 80 | 81 | 82 | auto 83 | _Bool 84 | break 85 | case 86 | char 87 | _Complex 88 | const 89 | continue 90 | default 91 | do 92 | double 93 | else 94 | enum 95 | extern 96 | float 97 | for 98 | goto 99 | if 100 | _Imaginary 101 | inline 102 | int 103 | long 104 | register 105 | restrict 106 | return 107 | short 108 | signed 109 | sizeof 110 | static 111 | struct 112 | switch 113 | typedef 114 | union 115 | unsigned 116 | void 117 | volatile 118 | while 119 | 120 | asm 121 | dynamic_cast 122 | namespace 123 | reinterpret_cast 124 | try 125 | bool 126 | explicit 127 | new 128 | static_cast 129 | typeid 130 | catch 131 | false 132 | operator 133 | template 134 | typename 135 | class 136 | friend 137 | private 138 | this 139 | using 140 | const_cast 141 | inline 142 | public 143 | throw 144 | virtual 145 | delete 146 | mutable 147 | protected 148 | true 149 | wchar_t 150 | 151 | 152 | -------------------------------------------------------------------------------- /src/docbook/xsl/xslthl/csharp-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 31 | 32 | 33 | /** 34 | */ 35 | 36 | 37 | 38 | /// 39 | 40 | 41 | 42 | /* 43 | */ 44 | 45 | // 46 | 47 | 48 | [ 49 | ] 50 | ( 51 | ) 52 | 53 | 54 | 55 | # 56 | \ 57 | 58 | 59 | 60 | 61 | 62 | @" 63 | " 64 | \ 65 | 66 | 67 | 68 | " 69 | \ 70 | 71 | 72 | ' 73 | \ 74 | 75 | 76 | 0x 77 | ul 78 | lu 79 | u 80 | l 81 | 82 | 83 | 84 | . 85 | 86 | e 87 | ul 88 | lu 89 | u 90 | f 91 | d 92 | m 93 | l 94 | 95 | 96 | 97 | abstract 98 | as 99 | base 100 | bool 101 | break 102 | byte 103 | case 104 | catch 105 | char 106 | checked 107 | class 108 | const 109 | continue 110 | decimal 111 | default 112 | delegate 113 | do 114 | double 115 | else 116 | enum 117 | event 118 | explicit 119 | extern 120 | false 121 | finally 122 | fixed 123 | float 124 | for 125 | foreach 126 | goto 127 | if 128 | implicit 129 | in 130 | int 131 | interface 132 | internal 133 | is 134 | lock 135 | long 136 | namespace 137 | new 138 | null 139 | object 140 | operator 141 | out 142 | override 143 | params 144 | private 145 | protected 146 | public 147 | readonly 148 | ref 149 | return 150 | sbyte 151 | sealed 152 | short 153 | sizeof 154 | stackalloc 155 | static 156 | string 157 | struct 158 | switch 159 | this 160 | throw 161 | true 162 | try 163 | typeof 164 | uint 165 | ulong 166 | unchecked 167 | unsafe 168 | ushort 169 | using 170 | virtual 171 | void 172 | volatile 173 | while 174 | 175 | 176 | 177 | add 178 | alias 179 | from 180 | get 181 | global 182 | group 183 | into 184 | join 185 | orderby 186 | partial 187 | remove 188 | select 189 | set 190 | value 191 | where 192 | yield 193 | 194 | 195 | -------------------------------------------------------------------------------- /src/docbook/xsl/xslthl/css-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 32 | 33 | 34 | /* 35 | */ 36 | 37 | 38 | " 39 | \ 40 | 41 | 42 | 43 | ' 44 | \ 45 | 46 | 47 | 48 | . 49 | 50 | 51 | 52 | @charset 53 | @import 54 | @media 55 | @page 56 | 57 | 58 | 59 | - 60 | azimuth 61 | background-attachment 62 | background-color 63 | background-image 64 | background-position 65 | background-repeat 66 | background 67 | border-collapse 68 | border-color 69 | border-spacing 70 | border-style 71 | border-top 72 | border-right 73 | border-bottom 74 | border-left 75 | border-top-color 76 | border-right-color 77 | border-bottom-color 78 | border-left-color 79 | border-top-style 80 | border-right-style 81 | border-bottom-style 82 | border-left-style 83 | border-top-width 84 | border-right-width 85 | border-bottom-width 86 | border-left-width 87 | border-width 88 | border 89 | bottom 90 | caption-side 91 | clear 92 | clip 93 | color 94 | content 95 | counter-increment 96 | counter-reset 97 | cue-after 98 | cue-before 99 | cue 100 | cursor 101 | direction 102 | display 103 | elevation 104 | empty-cells 105 | float 106 | font-family 107 | font-size 108 | font-style 109 | font-variant 110 | font-weight 111 | font 112 | height 113 | left 114 | letter-spacing 115 | line-height 116 | list-style-image 117 | list-style-position 118 | list-style-type 119 | list-style 120 | margin-right 121 | margin-left 122 | margin-top 123 | margin-bottom 124 | margin 125 | max-height 126 | max-width 127 | min-height 128 | min-width 129 | orphans 130 | outline-color 131 | outline-style 132 | outline-width 133 | outline 134 | overflow 135 | padding-top 136 | padding-right 137 | padding-bottom 138 | padding-left 139 | padding 140 | page-break-after 141 | page-break-before 142 | page-break-inside 143 | pause-after 144 | pause-before 145 | pause 146 | pitch-range 147 | pitch 148 | play-during 149 | position 150 | quotes 151 | richness 152 | right 153 | speak-header 154 | speak-numeral 155 | speak-punctuation 156 | speak 157 | speech-rate 158 | stress 159 | table-layout 160 | text-align 161 | text-decoration 162 | text-indent 163 | text-transform 164 | top 165 | unicode-bidi 166 | vertical-align 167 | visibility 168 | voice-family 169 | volume 170 | white-space 171 | widows 172 | width 173 | word-spacing 174 | z-index 175 | 176 | 177 | -------------------------------------------------------------------------------- /src/docbook/xsl/xslthl/html-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | 15 | 16 | a 17 | abbr 18 | address 19 | area 20 | article 21 | aside 22 | audio 23 | b 24 | base 25 | bdi 26 | blockquote 27 | body 28 | br 29 | button 30 | caption 31 | canvas 32 | cite 33 | code 34 | command 35 | col 36 | colgroup 37 | dd 38 | del 39 | dialog 40 | div 41 | dl 42 | dt 43 | em 44 | embed 45 | fieldset 46 | figcaption 47 | figure 48 | font 49 | form 50 | footer 51 | h1 52 | h2 53 | h3 54 | h4 55 | h5 56 | h6 57 | head 58 | header 59 | hr 60 | html 61 | i 62 | iframe 63 | img 64 | input 65 | ins 66 | kbd 67 | label 68 | legend 69 | li 70 | link 71 | map 72 | mark 73 | menu 74 | menu 75 | meta 76 | nav 77 | noscript 78 | object 79 | ol 80 | optgroup 81 | option 82 | p 83 | param 84 | pre 85 | q 86 | samp 87 | script 88 | section 89 | select 90 | small 91 | source 92 | span 93 | strong 94 | style 95 | sub 96 | summary 97 | sup 98 | table 99 | tbody 100 | td 101 | textarea 102 | tfoot 103 | th 104 | thead 105 | time 106 | title 107 | tr 108 | track 109 | u 110 | ul 111 | var 112 | video 113 | wbr 114 | xmp 115 | 116 | 117 | 118 | 119 | xsl: 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /src/docbook/xsl/xslthl/ini-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 31 | 32 | ; 33 | 34 | 35 | ^(\[.+\]\s*)$ 36 | 37 | MULTILINE 38 | 39 | 40 | 41 | ^(.+)(?==) 42 | 43 | MULTILINE 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/docbook/xsl/xslthl/java-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 31 | 32 | 33 | /** 34 | */ 35 | 36 | 37 | 38 | /* 39 | */ 40 | 41 | // 42 | 43 | " 44 | \ 45 | 46 | 47 | ' 48 | \ 49 | 50 | 51 | @ 52 | ( 53 | ) 54 | 55 | 56 | 0x 57 | 58 | 59 | 60 | . 61 | e 62 | f 63 | d 64 | l 65 | 66 | 67 | 68 | abstract 69 | boolean 70 | break 71 | byte 72 | case 73 | catch 74 | char 75 | class 76 | const 77 | continue 78 | default 79 | do 80 | double 81 | else 82 | extends 83 | final 84 | finally 85 | float 86 | for 87 | goto 88 | if 89 | implements 90 | import 91 | instanceof 92 | int 93 | interface 94 | long 95 | native 96 | new 97 | package 98 | private 99 | protected 100 | public 101 | return 102 | short 103 | static 104 | strictfp 105 | super 106 | switch 107 | synchronized 108 | this 109 | throw 110 | throws 111 | transient 112 | try 113 | void 114 | volatile 115 | while 116 | 117 | 118 | -------------------------------------------------------------------------------- /src/docbook/xsl/xslthl/javascript-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 31 | 32 | 33 | /* 34 | */ 35 | 36 | // 37 | 38 | " 39 | \ 40 | 41 | 42 | ' 43 | \ 44 | 45 | 46 | 0x 47 | 48 | 49 | 50 | . 51 | e 52 | 53 | 54 | 55 | break 56 | case 57 | catch 58 | continue 59 | default 60 | delete 61 | do 62 | else 63 | finally 64 | for 65 | function 66 | if 67 | in 68 | instanceof 69 | new 70 | return 71 | switch 72 | this 73 | throw 74 | try 75 | typeof 76 | var 77 | void 78 | while 79 | with 80 | 81 | abstract 82 | boolean 83 | byte 84 | char 85 | class 86 | const 87 | debugger 88 | double 89 | enum 90 | export 91 | extends 92 | final 93 | float 94 | goto 95 | implements 96 | import 97 | int 98 | interface 99 | long 100 | native 101 | package 102 | private 103 | protected 104 | public 105 | short 106 | static 107 | super 108 | synchronized 109 | throws 110 | transient 111 | volatile 112 | 113 | 114 | prototype 115 | 116 | Array 117 | Boolean 118 | Date 119 | Error 120 | EvalError 121 | Function 122 | Math 123 | Number 124 | Object 125 | RangeError 126 | ReferenceError 127 | RegExp 128 | String 129 | SyntaxError 130 | TypeError 131 | URIError 132 | 133 | decodeURI 134 | decodeURIComponent 135 | encodeURI 136 | encodeURIComponent 137 | eval 138 | isFinite 139 | isNaN 140 | parseFloat 141 | parseInt 142 | 143 | Infinity 144 | NaN 145 | undefined 146 | 147 | 148 | -------------------------------------------------------------------------------- /src/docbook/xsl/xslthl/json-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 4 | 5 | " 6 | \ 7 | 8 | 9 | ' 10 | \ 11 | 12 | 13 | @ 14 | ( 15 | ) 16 | 17 | 18 | . 19 | e 20 | f 21 | d 22 | l 23 | 24 | 25 | 26 | true 27 | false 28 | 29 | 30 | { 31 | } 32 | , 33 | [ 34 | ] 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/docbook/xsl/xslthl/perl-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 31 | 32 | # 33 | 34 | << 35 | ' 36 | " 37 | 38 | 39 | 40 | " 41 | \ 42 | 43 | 44 | ' 45 | \ 46 | 47 | 48 | 49 | 0x 50 | 51 | 52 | 53 | . 54 | 55 | 56 | 57 | 58 | if 59 | unless 60 | while 61 | until 62 | foreach 63 | else 64 | elsif 65 | for 66 | when 67 | default 68 | given 69 | 70 | caller 71 | continue 72 | die 73 | do 74 | dump 75 | eval 76 | exit 77 | goto 78 | last 79 | next 80 | redo 81 | return 82 | sub 83 | wantarray 84 | 85 | caller 86 | import 87 | local 88 | my 89 | package 90 | use 91 | 92 | do 93 | import 94 | no 95 | package 96 | require 97 | use 98 | 99 | bless 100 | dbmclose 101 | dbmopen 102 | package 103 | ref 104 | tie 105 | tied 106 | untie 107 | use 108 | 109 | and 110 | or 111 | not 112 | eq 113 | ne 114 | lt 115 | gt 116 | le 117 | ge 118 | cmp 119 | 120 | 121 | -------------------------------------------------------------------------------- /src/docbook/xsl/xslthl/php-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 31 | 32 | 33 | /** 34 | */ 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | /* 43 | */ 44 | 45 | // 46 | # 47 | 48 | " 49 | \ 50 | 51 | 52 | 53 | ' 54 | \ 55 | 56 | 57 | 58 | <<< 59 | 60 | 61 | 0x 62 | 63 | 64 | 65 | . 66 | e 67 | 68 | 69 | 70 | and 71 | or 72 | xor 73 | __FILE__ 74 | exception 75 | __LINE__ 76 | array 77 | as 78 | break 79 | case 80 | class 81 | const 82 | continue 83 | declare 84 | default 85 | die 86 | do 87 | echo 88 | else 89 | elseif 90 | empty 91 | enddeclare 92 | endfor 93 | endforeach 94 | endif 95 | endswitch 96 | endwhile 97 | eval 98 | exit 99 | extends 100 | for 101 | foreach 102 | function 103 | global 104 | if 105 | include 106 | include_once 107 | isset 108 | list 109 | new 110 | print 111 | require 112 | require_once 113 | return 114 | static 115 | switch 116 | unset 117 | use 118 | var 119 | while 120 | __FUNCTION__ 121 | __CLASS__ 122 | __METHOD__ 123 | final 124 | php_user_filter 125 | interface 126 | implements 127 | extends 128 | public 129 | private 130 | protected 131 | abstract 132 | clone 133 | try 134 | catch 135 | throw 136 | cfunction 137 | old_function 138 | true 139 | false 140 | 141 | namespace 142 | __NAMESPACE__ 143 | goto 144 | __DIR__ 145 | 146 | 147 | 148 | 149 | ?> 150 | <?php 151 | <?= 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /src/docbook/xsl/xslthl/properties-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 31 | 32 | # 33 | 34 | ^(.+?)(?==|:) 35 | 36 | MULTILINE 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/docbook/xsl/xslthl/python-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 31 | 32 | 33 | 34 | @ 35 | ( 36 | ) 37 | 38 | # 39 | 40 | """ 41 | 42 | 43 | 44 | ''' 45 | 46 | 47 | 48 | " 49 | \ 50 | 51 | 52 | ' 53 | \ 54 | 55 | 56 | 0x 57 | l 58 | 59 | 60 | 61 | . 62 | 63 | e 64 | l 65 | 66 | 67 | 68 | and 69 | del 70 | from 71 | not 72 | while 73 | as 74 | elif 75 | global 76 | or 77 | with 78 | assert 79 | else 80 | if 81 | pass 82 | yield 83 | break 84 | except 85 | import 86 | print 87 | class 88 | exec 89 | in 90 | raise 91 | continue 92 | finally 93 | is 94 | return 95 | def 96 | for 97 | lambda 98 | try 99 | 100 | 101 | -------------------------------------------------------------------------------- /src/docbook/xsl/xslthl/ruby-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 31 | 32 | # 33 | 34 | << 35 | 36 | 37 | 38 | " 39 | \ 40 | 41 | 42 | %Q{ 43 | } 44 | \ 45 | 46 | 47 | %/ 48 | / 49 | \ 50 | 51 | 52 | ' 53 | \ 54 | 55 | 56 | %q{ 57 | } 58 | \ 59 | 60 | 61 | 0x 62 | 63 | 64 | 65 | . 66 | e 67 | 68 | 69 | 70 | alias 71 | and 72 | BEGIN 73 | begin 74 | break 75 | case 76 | class 77 | def 78 | defined 79 | do 80 | else 81 | elsif 82 | END 83 | end 84 | ensure 85 | false 86 | for 87 | if 88 | in 89 | module 90 | next 91 | nil 92 | not 93 | or 94 | redo 95 | rescue 96 | retry 97 | return 98 | self 99 | super 100 | then 101 | true 102 | undef 103 | unless 104 | until 105 | when 106 | while 107 | yield 108 | 109 | 110 | -------------------------------------------------------------------------------- /src/docbook/xsl/xslthl/yaml-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 4 | 5 | " 6 | \ 7 | 8 | 9 | ' 10 | \ 11 | 12 | 13 | @ 14 | ( 15 | ) 16 | 17 | 18 | . 19 | e 20 | f 21 | d 22 | l 23 | 24 | 25 | 26 | true 27 | false 28 | 29 | 30 | { 31 | } 32 | , 33 | [ 34 | ] 35 | 36 | 37 | 38 | ^(---)$ 39 | 40 | MULTILINE 41 | 42 | 43 | ^(.+?)(?==|:) 44 | 45 | MULTILINE 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/docs/asciidoc/20to21.adoc: -------------------------------------------------------------------------------- 1 | [[20to25]] 2 | == Migrating from 2.0 to 2.5 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/docs/asciidoc/core-bytebuffer.adoc: -------------------------------------------------------------------------------- 1 | [[core-bytebuffer]] 2 | ifndef::env-github[] 3 | == Byte Buffer 4 | endif::[] 5 | -------------------------------------------------------------------------------- /src/docs/asciidoc/gettingstarted.adoc: -------------------------------------------------------------------------------- 1 | [[getting-started]] 2 | == *Introducing Reactor IPC* 3 | 4 | [quote, Preface, TL;DR] 5 | Reactor IPC is a foundational library for building demanding, over the wire *Data-Streaming* applications and micro, 6 | nano, or 7 | pico-services that must exhibit *Low-Latency* and be *Fault-Tolerant*. 8 | 9 | [[start]] 10 | === What is Reactor IPC ? 11 | 12 | 13 | === About the Project 14 | 15 | The project started in 2012, with a long internal incubation time. Reactor 1.x appeared in 2013. Reactor 1 has been deployed successfully by various organizations, both Open Source (e.g. Meltdown) and Commercial (e.g. Pivotal RTI). In 2014 we started collaborating on the emerging <> and started a massive re-engineering targeting April 2015 for version 2.0. The Reactive Streams Standard closed the last gap in our _Dispatching_ mechanism: controlling how much in-flight data was hitting Thread boundaries. 16 | 17 | Parallel to that work we also decided to re-align some of our Event-Driven and Task Coordination API to the increasingly popular and documented <>. 18 | 19 | Reactor is sponsored by http://pivotal.io[Pivotal] and is http://www.apache.org/licenses/LICENSE-2.0 20 | .html[Apache 2.0 licensed]. It is available on https://github.com/reactor/reactor-ipc[GitHub]. 21 | 22 | === Requirements 23 | 24 | * Reactor needs at minimum Java 8 to execute. 25 | ** But the full expressive potential of functional composition happens with Java 8 Lambdas. 26 | * Reactor runs at full capacity when the JVM supports *Unsafe* access (e.g., not the case for Android). 27 | * Reactor is packaged as traditional JAR archives in Maven Central and can be pulled into any JVM project as a dependency using your preferred build tool. 28 | 29 | [[architecture]] 30 | === Architecture Overview 31 | .The main modules present in Reactor IPC -------------------------------------------------------------------------------- /src/docs/asciidoc/images/RBP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/RBP.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/RBWP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/RBWP.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/broadcast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/broadcast.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/bus-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/bus-overview.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/core-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/core-overview.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/golo/body-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/golo/body-bg.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/golo/pre-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/golo/pre-bg.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/logo-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/logo-2x.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/logo.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/longMaxThreading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/longMaxThreading.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/maker/body-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/maker/body-bg.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/marble/marble-101.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/marble/marble-101.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/marble/marble-overflowbuffer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/marble/marble-overflowbuffer.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/marble/marble-overflowdrop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/marble/marble-overflowdrop.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/marble/marble-requestwhen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/marble/marble-requestwhen.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/marble/marble-throttle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/marble/marble-throttle.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/modules.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/modules.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/nThreading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/nThreading.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/net-latency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/net-latency.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/net-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/net-overview.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/overview.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/rbd2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/rbd2.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/rs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/rs.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/signals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/signals.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/streams-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/streams-overview.png -------------------------------------------------------------------------------- /src/docs/asciidoc/images/wiringup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/images/wiringup.png -------------------------------------------------------------------------------- /src/docs/asciidoc/index-docinfo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/docs/asciidoc/index-docinfo.xml: -------------------------------------------------------------------------------- 1 | 16 | Reactor 2.0.3.RELEASE 17 | Reactor 18 | {appversion} 19 | 20 | 2013-2015 21 | Pivotal Software Inc. 22 | 23 | -------------------------------------------------------------------------------- /src/docs/asciidoc/index.asciidoc: -------------------------------------------------------------------------------- 1 | = Reactor Guide 2 | Stephane Maldini; 3 | :appversion: 0.6.1.RELEASE (wiki) 4 | ifndef::host-github[:ext-relative: {outfilesuffix}] 5 | {appversion} 6 | :doctype: book 7 | :icons: font 8 | 9 | include::gettingstarted.adoc[] 10 | include::20to25.adoc[] 11 | 12 | [[reactor-ipc]] 13 | = *reactor-ipc* 14 | include::core-bytebuffer.adoc[] 15 | 16 | [[reactor-netty]] 17 | = *reactor-netty* 18 | include::net.adoc[] 19 | include::net-tcp.adoc[] 20 | include::net-http.adoc[] 21 | include::net-e2e.adoc[] 22 | 23 | [[reactor-kafka]] 24 | = *reactor-aeron* 25 | include::kafka.adoc[] 26 | 27 | [[reactor-aeron]] 28 | = *reactor-aeron* 29 | include::aeron.adoc[] 30 | -------------------------------------------------------------------------------- /src/docs/asciidoc/kafka.adoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/reactor-ipc/acccb25e90fe627a521073417adaabfda7376afb/src/docs/asciidoc/kafka.adoc -------------------------------------------------------------------------------- /src/docs/asciidoc/nav.html: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /src/docs/asciidoc/net-e2e.adoc: -------------------------------------------------------------------------------- 1 | [[net-endToEnd]] 2 | == End To End 3 | Combining Reactor Net, Stream and Core to create standalone Ingesters or Data (micro)Services -------------------------------------------------------------------------------- /src/docs/asciidoc/net-http.adoc: -------------------------------------------------------------------------------- 1 | [[net-http101]] 2 | == HTTP 101 3 | Using Reactor's HTTP support to create high-performance HTTP clients and servers. 4 | 5 | === Start and Stop 6 | 7 | === Routing HTTP 8 | 9 | ==== SSE 10 | 11 | === Routing WebSocket 12 | 13 | === Writing Data 14 | 15 | ==== Adding Headers and other Metadata 16 | 17 | ==== From a Server perspective 18 | 19 | ==== From a Client perspective 20 | 21 | === Flushing Strategies 22 | 23 | === Consuming Data 24 | 25 | ==== Reading Headers, URI Params and other Metadata 26 | 27 | ==== From a Server perspective 28 | 29 | ==== From a Client perspective 30 | 31 | === Backpressure Strategies 32 | 33 | === Closing the Channel -------------------------------------------------------------------------------- /src/docs/asciidoc/net-tcp.adoc: -------------------------------------------------------------------------------- 1 | [[net-tcp101]] 2 | == TCP 101 3 | Using Reactor's TCP support to create high-performance TCP clients and servers. 4 | 5 | === Start and Stop 6 | 7 | === Writing Data 8 | 9 | ==== From a Server perspective 10 | 11 | ==== From a Client perspective 12 | 13 | === Flushing Strategies 14 | 15 | === Consuming Data 16 | 17 | ==== From a Server perspective 18 | 19 | ==== From a Client perspective 20 | 21 | === Backpressure Strategies 22 | 23 | === Closing the Channel -------------------------------------------------------------------------------- /src/docs/asciidoc/net.adoc: -------------------------------------------------------------------------------- 1 | == Asynchronous TCP, UDP and HTTP 2 | 3 | "Nothing travels faster than the speed of light, with the possible exception of bad news, which obeys its own special laws." 4 | -- Douglas Noel Adams, Mostly Harmless (1992) 5 | 6 | .Head first with a Java 8 example of some Net work 7 | [source,java] 8 | ---- 9 | import reactor.ipc.netty.tcp.TcpServer; 10 | import reactor.ipc.netty.tcp.TcpClient; 11 | 12 | //... 13 | 14 | CountDownLatch latch = new CountDownLatch(10); 15 | 16 | TcpServer server = TcpServer.create(port); 17 | TcpClient client = TcpClient.create("localhost", port); 18 | 19 | final JsonCodec codec = new JsonCodec(Pojo.class); 20 | 21 | //the client/server are prepared 22 | server.start( input -> 23 | 24 | //for each connection echo any incoming data 25 | 26 | //return the write confirm publisher from send 27 | // >>> close when the write confirm completed 28 | 29 | input.send( 30 | 31 | //read incoming data 32 | input 33 | .decode(codec) //transform Buffer into Pojo 34 | .log("serve") 35 | .map(codec) //transform Pojo into Buffer 36 | 37 | , 5) //auto-flush every 5 elements 38 | ).await(); 39 | 40 | client.start( input -> { 41 | 42 | //read 10 replies and close 43 | input 44 | .take(10) 45 | .decode(codec) 46 | .log("receive") 47 | .subscribe( data -> latch.countDown() ); 48 | 49 | //write data 50 | input.send( 51 | Flux.range(1, 10) 52 | .map( it -> new Pojo("test" + it) ) 53 | .log("send") 54 | .map(codec) 55 | ).subscribe(); 56 | 57 | //keep-alive, until 10 data have been read 58 | return Mono.never(); 59 | 60 | }).await(); 61 | 62 | latch.await(10, TimeUnit.SECONDS); 63 | 64 | client.shutdown().await(); 65 | server.shutdown().await(); 66 | ---- 67 | 68 | [[net-overview]] 69 | === Overview 70 | How is Reactor Net module working ? 71 | 72 | .How Doge can use Reactor-Net 73 | image::images/net-overview.png[Net Overview, width=650, align="center", link="images/net-overview.png"] 74 | 75 | So why should you care about an asynchronous runtime to deal with network operations ? As seen in the <> section, it is preferred to not block for a service reply. Non-Blocking write over network will slightly be more costly than blocking ones in terms of resources, however it might be perceived *more responsive* to the producer. Responsiveness all along the request flow impacts various systems and eventually, 1 or N users waiting their turn to push new requests. 76 | 77 | .Doge trades off CPU for Latency for better responsivity and to leave the service available to his friends 78 | image::images/net-latency.png[Net Latency, width=650, align="center", link="images/net-latency.png"] 79 | 80 | Blocking Read or Write become more like a nightmare for concurrent services use over long-living connections such as TCP or WebSocket. Apart from network routing component which might timeout a too long connection, little can be done with a blocking socket in the application locking the thread on read or write IO methods. 81 | 82 | Of course there is always the choice to provide for a pool of threads or any _Async Facade_ such as a *Core Processor* to mitigate the blocking read/write contention. The problem is there won't be many of these threads available in a *Reactive* world of non blocking dispatching, so blocking behind 4/8/16 async facades is a limited option. Again the thread pool with a large queue or even many threads won't necessarely solve the situation neither. 83 | 84 | .Instead why not invoking callbacks on different IO operations: _connection, read, write, close..._ ? 85 | 86 | *Reactor Net* aims to provide an *Asynchronous IO* runtime that supports *Reactive Streams* backpressure for client or server needs over a range of protocols and drivers. Some drivers will not implement every protocol but at least one, *Netty*, implements all current protocols. At the moment, Reactor Net is *supporting Netty 4.x* and *ZeroMQ* through *jeroMQ 0.3.+* and you must add explicitely one of them in the application classpath. 87 | 88 | 89 | *Reactor Net* has the following artifacts: 90 | 91 | **** 92 | * `ReactorChannel` and its direct implementations `Channel` and `HttpChannel` 93 | ** Represents a direct connection between the application and the remote host 94 | ** Contains non blocking IO write and read operations 95 | ** Reactor drivers will directly expose `Channel` to access the `Stream` functional API for read operations 96 | * `ReactorPeer` and `ReactorChannelHandler` for common network component (client/server) contract 97 | ** Provides for `start` and `shutdown` operations 98 | ** Binds a `ReactorChannelHandler` on `start` to listen to the requesting `Channel` 99 | ** `ReactorChannelHandler` is a function accepting `Channel` requests and returning a `Publisher` for connection close management 100 | * `ReactorClient` for common client contract 101 | ** Extends `ReactorPeer` to provide a _reconnect_ friendly start operation 102 | * `NetStreams` and `Spec` to create any client or server 103 | ** Looks like `Streams`, `BiStreams` and other `Reactor Flux` Factories 104 | ** `NetStreams` factories will accept `Function` called *once* on creation to customize the configuration of the network component. 105 | * *HTTP/WS/UDP/TCP* protocol `ReactorPeer` implementations 106 | ** `HttpServer` & `HttpClient` will provide routing extensions 107 | ** `DatagramServer` will provide multicast extensions 108 | ** `TcpServer` & `TcpClient` will provide additional TCP/IP context informations 109 | * *Netty* and *ZeroMQ* drivers 110 | **** 111 | 112 | [NOTE] 113 | *Reactor Net* implements a model discussed under the https://github.com/reactive-ipc/reactive-ipc-jvm[Reactive IPC] initiative. As we progress we will align more and eventually depend on the specified artefacts likely over 2016. We give you a chance to experiment as of today with some of the principles and make our best to prepare our users to this next-generation standard. 114 | 115 | 116 | === Channels 117 | 118 | === Channel Handlers 119 | 120 | === Specifications 121 | 122 | === Client Specification 123 | 124 | === Server Specification 125 | 126 | [[net-backpressure]] 127 | === Backpressure 128 | Using Reactor and Reactive Stream standard for flow-control with TCP network peers. -------------------------------------------------------------------------------- /src/main/java/reactor/ipc/connector/Connector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2016 Pivotal Software 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 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package reactor.ipc.connector; 18 | 19 | import java.util.function.BiFunction; 20 | 21 | import org.reactivestreams.Publisher; 22 | import reactor.core.Disposable; 23 | import reactor.core.publisher.Mono; 24 | 25 | /** 26 | * An IPC connector is a inbound/outbound factory sharing configuration but usually no 27 | * runtime 28 | * (connection...) state at the exception of shared connection pool setups. Subscribing 29 | * to the returned {@link Mono} will effectively 30 | * create a new stateful "client" or "server" socket depending on the implementation. 31 | * It might also be working on top of a socket pool or connection pool as well, but the 32 | * state should be safely handled by the pool itself. 33 | *

34 | *

Clients or Receivers will onSubscribe when their connection is established. They 35 | * will complete when the unique returned closing {@link Publisher} completes itself or if 36 | * the connection is remotely terminated. Calling the returned {@link 37 | * Disposable#dispose()} from {@link Mono#subscribe()} will terminate the subscription 38 | * and underlying connection from the local peer. 39 | *

40 | *

Servers or Producers will onSubscribe when their socket is bound locally. They will 41 | * never complete as many {@link Publisher} close selectors will be expected. Disposing 42 | * the returned {@link Mono} will safely call shutdown. 43 | * 44 | * @param the input connection data type (bytes, object...) 45 | * @param the output connection data type (bytes, object...) 46 | * @param incoming traffic API such as server request or client response 47 | * @param outgoing traffic API such as server response or client request 48 | */ 49 | @FunctionalInterface 50 | public interface Connector, OUTBOUND extends Outbound> { 51 | 52 | /** 53 | * Prepare a {@link BiFunction} IO handler that will react on a new connected state 54 | * each 55 | * time 56 | * the returned {@link Mono} is subscribed. This {@link Connector} shouldn't assume 57 | * any state related to the individual created/cleaned resources. 58 | *

59 | * The IO handler will return {@link Publisher} to signal when to terminate the 60 | * underlying resource channel. 61 | * 62 | * @param ioHandler the in/out callback returning a closing publisher 63 | * 64 | * @return a {@link Mono} completing with a {@link Disposable} token to dispose 65 | * the active handler (server, client connection...) or failing with the connection 66 | * error. 67 | */ 68 | Mono newHandler(BiFunction> ioHandler); 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/reactor/ipc/connector/Inbound.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2016 Pivotal Software 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 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package reactor.ipc.connector; 18 | 19 | import reactor.core.publisher.Flux; 20 | 21 | /** 22 | * A {@link Inbound} is a reactive gateway for incoming data flows. 23 | * Implementations handle interacting inbound (received data) and errors by subscribing to {@link #receive()}. 24 | *

25 | * 26 | * @author Stephane Maldini 27 | * @since 0.6 28 | */ 29 | @FunctionalInterface 30 | public interface Inbound { 31 | 32 | /** 33 | * Get the inbound publisher (incoming tcp traffic for instance) 34 | * 35 | * @return A {@link Flux} to signal reads and stop reading when un-requested. 36 | */ 37 | Flux receive(); 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/reactor/ipc/connector/Outbound.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2016 Pivotal Software 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 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package reactor.ipc.connector; 18 | 19 | import org.reactivestreams.Publisher; 20 | import org.reactivestreams.Subscriber; 21 | import reactor.core.publisher.Mono; 22 | 23 | /** 24 | * A {@link Outbound} is a reactive gateway for outgoing data flows. Like a Flux or a Mono 25 | * it can be chained via {@link #send} and a subscribe to the tailing outbound will 26 | * schedule all the parent send in the declaration order. 27 | *

28 | * Writing and "flushing" is controlled by sinking 1 or more {@link #send(Publisher)} that 29 | * will forward data to outbound. When a drained Publisher completes or error, the channel 30 | * will automatically "flush" its pending writes. 31 | * 32 | * @author Stephane Maldini 33 | * @since 0.6 34 | */ 35 | @FunctionalInterface 36 | public interface Outbound extends Publisher { 37 | 38 | /** 39 | * Return a never completing {@link Mono} after this {@link Outbound#then()} has 40 | * completed. 41 | * 42 | * @return a never completing {@link Mono} after this {@link Outbound#then()} has 43 | * completed. 44 | */ 45 | default Mono neverComplete() { 46 | return then(Mono.never()).then(); 47 | } 48 | 49 | /** 50 | * Send data to the peer, listen for any error on write and close on terminal signal 51 | * (complete|error).

A new {@link Outbound} type (or the same) for typed send 52 | * sequences. An implementor can therefore specialize the Outbound after a first after 53 | * a prepending data publisher. 54 | * 55 | * @param dataStream the dataStream publishing OUT items to write on this channel 56 | * 57 | * @return A new {@link Outbound} to append further send. It will emit a complete 58 | * signal successful sequence write (e.g. after "flush") or any error during write. 59 | */ 60 | Outbound send(Publisher dataStream); 61 | 62 | /** 63 | * Subscribe a {@code Void} subscriber to this outbound and trigger all eventual 64 | * parent outbound send. 65 | * 66 | * @param s the {@link Subscriber} to listen for send sequence completion/failure 67 | */ 68 | @Override 69 | default void subscribe(Subscriber s) { 70 | then().subscribe(s); 71 | } 72 | 73 | /** 74 | * Obtain a {@link Mono} of pending outbound(s) write completion. 75 | * 76 | * @return a {@link Mono} of pending outbound(s) write completion 77 | */ 78 | default Mono then() { 79 | return Mono.empty(); 80 | } 81 | 82 | /** 83 | * Append a {@link Publisher} task such as a Mono and return a new 84 | * {@link Outbound} to sequence further send. 85 | * 86 | * @param other the {@link Publisher} to subscribe to when this pending outbound 87 | * {@link #then} is complete; 88 | * 89 | * @return a new {@link Outbound} 90 | */ 91 | default Outbound then(Publisher other) { 92 | return new OutboundThen<>(this, other); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/reactor/ipc/connector/OutboundThen.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2016 Pivotal Software 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 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package reactor.ipc.connector; 18 | 19 | import org.reactivestreams.Publisher; 20 | import reactor.core.publisher.Mono; 21 | 22 | /** 23 | * An appending write that delegates to its origin context and append the passed 24 | * publisher after the origin success if any. 25 | * 26 | * @param sending type 27 | */ 28 | final class OutboundThen implements Outbound { 29 | 30 | final Mono thenMono; 31 | final Outbound source; 32 | 33 | OutboundThen(Outbound source, Publisher thenPublisher) { 34 | Mono parentMono = source.then(); 35 | this.source = source; 36 | if (parentMono == Mono.empty()) { 37 | this.thenMono = Mono.from(thenPublisher); 38 | } 39 | else { 40 | this.thenMono = parentMono.thenEmpty(thenPublisher); 41 | } 42 | } 43 | 44 | @Override 45 | public Outbound send(Publisher dataStream) { 46 | return source.send(dataStream); 47 | } 48 | 49 | @Override 50 | public Mono then() { 51 | return thenMono; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/reactor/ipc/stream/Ipc.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2016 Pivotal Software 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 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package reactor.ipc.stream; 18 | 19 | import java.lang.annotation.ElementType; 20 | import java.lang.annotation.Retention; 21 | import java.lang.annotation.RetentionPolicy; 22 | import java.lang.annotation.Target; 23 | 24 | /** 25 | * Indicates a public method is a service with possible function name. 26 | *

Can be applied to incoming and outgoing service interfaces. 27 | */ 28 | @Retention(RetentionPolicy.RUNTIME) 29 | @Target(ElementType.METHOD) 30 | public @interface Ipc { 31 | String name() default ""; 32 | } -------------------------------------------------------------------------------- /src/main/java/reactor/ipc/stream/IpcDone.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2016 Pivotal Software 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 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package reactor.ipc.stream; 17 | 18 | import java.lang.annotation.ElementType; 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | import java.lang.annotation.Target; 22 | 23 | /** 24 | * Indicates the method, which has only an RpcStreamContext parameter and void return 25 | * should be called just after disconnection from the client. 26 | */ 27 | @Retention(RetentionPolicy.RUNTIME) 28 | @Target(ElementType.METHOD) 29 | public @interface IpcDone { 30 | String name() default ""; 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/reactor/ipc/stream/IpcInit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2016 Pivotal Software 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 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package reactor.ipc.stream; 17 | 18 | import java.lang.annotation.ElementType; 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | import java.lang.annotation.Target; 22 | 23 | /** 24 | * Indicates the method, which has only an RpcStreamContext parameter and void return 25 | * should be called just after the connection has been established. 26 | */ 27 | @Retention(RetentionPolicy.RUNTIME) 28 | @Target(ElementType.METHOD) 29 | public @interface IpcInit { 30 | String name() default ""; 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/reactor/ipc/stream/OnStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2016 Pivotal Software 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 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package reactor.ipc.stream; 17 | 18 | @FunctionalInterface 19 | interface OnStream { 20 | 21 | boolean onStream(long streamId, String function, StreamOperationsImpl manager); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/reactor/ipc/stream/SimpleStreamConnector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2016 Pivotal Software 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 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package reactor.ipc.stream; 18 | 19 | import java.util.Objects; 20 | import java.util.function.BiConsumer; 21 | import java.util.function.BiFunction; 22 | import java.util.function.Function; 23 | import java.util.function.Supplier; 24 | 25 | import org.reactivestreams.Publisher; 26 | import reactor.core.Disposable; 27 | import reactor.core.publisher.Mono; 28 | import reactor.ipc.connector.Connector; 29 | import reactor.ipc.connector.Inbound; 30 | import reactor.ipc.connector.Outbound; 31 | 32 | /** 33 | * @author Stephane Maldini 34 | */ 35 | final class SimpleStreamConnector, OUTBOUND extends Outbound> 36 | implements StreamConnector { 37 | 38 | final Connector connector; 39 | final BiConsumer decoder; 40 | final Function encoder; 41 | 42 | SimpleStreamConnector(Connector connector, 43 | BiConsumer decoder, 44 | Function encoder) { 45 | this.connector = Objects.requireNonNull(connector, "connector"); 46 | this.decoder = decoder; 47 | this.encoder = encoder; 48 | } 49 | 50 | @Override 51 | public Mono newBidirectional(Supplier receiverSupplier, 52 | Class api) { 53 | return newStreamSupport(receiverSupplier, api, decoder, encoder); 54 | } 55 | 56 | @Override 57 | public Mono newHandler(BiFunction> ioHandler) { 59 | return connector.newHandler(ioHandler); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/reactor/ipc/stream/StreamConnector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2016 Pivotal Software 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 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package reactor.ipc.stream; 18 | 19 | import java.util.Objects; 20 | import java.util.function.BiConsumer; 21 | import java.util.function.Function; 22 | import java.util.function.Supplier; 23 | 24 | import reactor.core.Disposable; 25 | import reactor.core.publisher.Mono; 26 | import reactor.ipc.connector.Connector; 27 | import reactor.ipc.connector.Inbound; 28 | import reactor.ipc.connector.Outbound; 29 | 30 | /** 31 | * A stream connector is {@link Connector} supporting reactive streams semantics. 32 | * 33 | * @param the input connection data type (bytes, object...) 34 | * @param the output connection data type (bytes, object...) 35 | * @param incoming traffic API such as server request or client response 36 | * @param outgoing traffic API such as server response or client request 37 | */ 38 | public interface StreamConnector, OUTBOUND extends Outbound> 39 | extends Connector { 40 | 41 | /** 42 | * 43 | * @param connector 44 | * @param decoder 45 | * @param encoder 46 | * @param 47 | * @param 48 | * @param 49 | * @param 50 | * @return a {@link StreamConnector} 51 | */ 52 | static , OUTBOUND extends Outbound> StreamConnector from( 53 | Connector connector, 54 | BiConsumer decoder, 55 | Function encoder) { 56 | return new SimpleStreamConnector<>(connector, decoder, encoder); 57 | } 58 | 59 | /** 60 | * @param receiverSupplier 61 | * 62 | * @return 63 | */ 64 | default Mono newReceiver(Supplier receiverSupplier) { 65 | Objects.requireNonNull(receiverSupplier, "receiver"); 66 | return newBidirectional(receiverSupplier, null); 67 | } 68 | 69 | /** 70 | * @param api 71 | * @param 72 | * 73 | * @return 74 | */ 75 | default Mono newProducer(Class api) { 76 | Objects.requireNonNull(api, "api"); 77 | return newBidirectional(null, api); 78 | } 79 | 80 | /** 81 | * @param receiverSupplier 82 | * @param api 83 | * @param 84 | * 85 | * @return 86 | */ 87 | Mono newBidirectional(Supplier receiverSupplier, 88 | Class api); 89 | /** 90 | * @param receiverSupplier 91 | * @param api 92 | * @param decoder 93 | * @param encoder 94 | * @param 95 | * 96 | * @return 97 | */ 98 | default Mono newStreamSupport(Supplier receiverSupplier, 99 | Class api, 100 | BiConsumer decoder, 101 | Function encoder) { 102 | return StreamSetup.connect(this, receiverSupplier, api, decoder, encoder); 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/reactor/ipc/stream/StreamContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2016 Pivotal Software 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 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package reactor.ipc.stream; 18 | 19 | public interface StreamContext { 20 | 21 | void set(CharSequence attribute, Object o); 22 | 23 | U get(CharSequence attribute); 24 | 25 | U get(CharSequence attribute, U defaultValue); 26 | 27 | void remove(CharSequence attribute); 28 | 29 | boolean has(CharSequence attribute); 30 | 31 | T remoteAPI(); 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/reactor/ipc/stream/StreamContextImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2016 Pivotal Software 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 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package reactor.ipc.stream; 18 | 19 | import java.util.concurrent.ConcurrentHashMap; 20 | import java.util.concurrent.ConcurrentMap; 21 | 22 | final class StreamContextImpl implements StreamContext { 23 | 24 | final ConcurrentMap map; 25 | 26 | final T remoteAPI; 27 | 28 | public StreamContextImpl(T remoteAPI) { 29 | this.remoteAPI = remoteAPI; 30 | this.map = new ConcurrentHashMap<>(); 31 | } 32 | 33 | @Override 34 | public void set(CharSequence attribute, Object o) { 35 | map.put(attribute, o); 36 | } 37 | 38 | @SuppressWarnings("unchecked") 39 | @Override 40 | public U get(CharSequence attribute) { 41 | return (U) map.get(attribute); 42 | } 43 | 44 | @SuppressWarnings("unchecked") 45 | @Override 46 | public U get(CharSequence attribute, U defaultValue) { 47 | return (U) map.getOrDefault(attribute, defaultValue); 48 | } 49 | 50 | @Override 51 | public void remove(CharSequence attribute) { 52 | map.remove(attribute); 53 | } 54 | 55 | @Override 56 | public boolean has(CharSequence attribute) { 57 | return map.containsKey(attribute); 58 | } 59 | 60 | @Override 61 | public T remoteAPI() { 62 | return remoteAPI; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/reactor/ipc/stream/StreamOperations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2016 Pivotal Software 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 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package reactor.ipc.stream; 18 | 19 | public interface StreamOperations extends StreamOutbound { 20 | 21 | void onNew(long streamId, String function); 22 | 23 | void onNext(long streamId, Object o); 24 | 25 | void onError(long streamId, String reason); 26 | 27 | void onError(long streamId, Throwable e); 28 | 29 | void onComplete(long streamId); 30 | 31 | void onCancel(long streamId, String reason); 32 | 33 | void onRequested(long streamId, long n); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/reactor/ipc/stream/StreamOperationsImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2017 Pivotal Software 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 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package reactor.ipc.stream; 18 | 19 | import java.io.IOException; 20 | import java.util.concurrent.ConcurrentHashMap; 21 | import java.util.concurrent.ConcurrentMap; 22 | import java.util.concurrent.atomic.AtomicBoolean; 23 | import java.util.concurrent.atomic.AtomicLong; 24 | 25 | import org.reactivestreams.Subscriber; 26 | import org.reactivestreams.Subscription; 27 | import reactor.core.publisher.Operators; 28 | import reactor.ipc.connector.Inbound; 29 | import reactor.util.Logger; 30 | import reactor.util.Loggers; 31 | import reactor.util.context.Context; 32 | 33 | /** 34 | * Allows registering Subscribers and Subscriptions for incoming messages 35 | * and allows sending messages. 36 | */ 37 | 38 | final class StreamOperationsImpl extends AtomicLong 39 | implements StreamOperations { 40 | 41 | static Logger log = Loggers.getLogger(StreamOperationsImpl.class); 42 | 43 | final ConcurrentMap> subscribers; 44 | 45 | final ConcurrentMap subscriptions; 46 | 47 | final StreamOutbound remote; 48 | 49 | final String name; 50 | 51 | final OnStream onNew; 52 | 53 | final Runnable onTerminate; 54 | 55 | final AtomicBoolean terminateOnce; 56 | 57 | final Inbound channel; 58 | 59 | StreamOperationsImpl(String name, 60 | OnStream onNew, 61 | StreamOutbound remote, 62 | Inbound channel, 63 | Runnable onTerminate) { 64 | super(1); 65 | this.name = name; 66 | this.channel = channel; 67 | this.remote = remote; 68 | this.onNew = onNew; 69 | this.onTerminate = onTerminate; 70 | this.terminateOnce = new AtomicBoolean(); 71 | this.subscribers = new ConcurrentHashMap<>(); 72 | this.subscriptions = new ConcurrentHashMap<>(); 73 | } 74 | 75 | long newStreamId() { 76 | return getAndIncrement(); 77 | } 78 | 79 | void registerSubscription(long streamId, Subscription s) { 80 | if (subscriptions.putIfAbsent(streamId, s) != null) { 81 | throw new IllegalStateException("StreamID " + streamId + " already registered"); 82 | } 83 | } 84 | 85 | void registerSubscriber(long streamId, Subscriber s) { 86 | if (subscribers.putIfAbsent(streamId, s) != null) { 87 | throw new IllegalStateException("StreamID " + streamId + " already registered"); 88 | } 89 | } 90 | 91 | boolean deregister(long streamId) { 92 | subscribers.remove(streamId); 93 | return subscriptions.remove(streamId) != null; 94 | } 95 | 96 | @Override 97 | public void onNew(long streamId, String function) { 98 | if (log.isDebugEnabled()) { 99 | log.debug("{}/onStream/{}/{}", name, streamId, function); 100 | } 101 | if (!onNew.onStream(streamId, function, this)) { 102 | if (log.isDebugEnabled()) { 103 | log.debug("{}/onStream/{} {}", 104 | name, 105 | streamId, 106 | "New stream(" + function + ") rejected"); 107 | } 108 | sendCancel(streamId, "New stream(" + function + ") rejected"); 109 | } 110 | } 111 | 112 | @Override 113 | public void onNext(long streamId, Object o) { 114 | 115 | if (log.isDebugEnabled()) { 116 | log.debug("{}/onNext/{}/value={}", name, streamId, o); 117 | } 118 | @SuppressWarnings("unchecked") Subscriber local = 119 | (Subscriber) subscribers.get(streamId); 120 | if (local != null) { 121 | try { 122 | local.onNext(o); 123 | } 124 | catch (Throwable ex) { 125 | if (log.isDebugEnabled()) { 126 | log.debug("{}/onNextError/{}/value={}", name, streamId, o, ex); 127 | } 128 | sendCancel(streamId, ex.toString()); 129 | local.onError(ex); 130 | } 131 | } 132 | } 133 | 134 | @Override 135 | public void onError(long streamId, String reason) { 136 | onError(streamId, new Exception(reason)); 137 | } 138 | 139 | @Override 140 | public void onError(long streamId, Throwable e) { 141 | if (log.isDebugEnabled()) { 142 | log.debug("{}/onError/{}", name, streamId, e); 143 | } 144 | if (streamId > 0) { 145 | Subscriber local = subscribers.get(streamId); 146 | if (local != null) { 147 | local.onError(e); 148 | return; 149 | } 150 | } 151 | else if (streamId < 0) { 152 | if (terminateOnce.compareAndSet(false, true)) { 153 | onTerminate.run(); 154 | } 155 | if (isClosed()) { 156 | return; 157 | } 158 | } 159 | Operators.onErrorDropped(e, Context.empty()); 160 | } 161 | 162 | @Override 163 | public void onComplete(long streamId) { 164 | Subscriber local = subscribers.get(streamId); 165 | if (local != null) { 166 | local.onComplete(); 167 | } 168 | } 169 | 170 | @Override 171 | public void onCancel(long streamId, String reason) { 172 | if (log.isDebugEnabled()) { 173 | log.debug("{}/onCancel/{} {}", name, streamId, reason); 174 | } 175 | Subscription remove = subscriptions.get(streamId); 176 | if (remove != null) { 177 | remove.cancel(); 178 | } 179 | } 180 | 181 | @Override 182 | public void onRequested(long streamId, long n) { 183 | if (log.isDebugEnabled()) { 184 | log.debug("{}/onRequested/{}/{}", name, streamId, n); 185 | } 186 | Subscription remote = subscriptions.get(streamId); 187 | if (remote != null) { 188 | remote.request(n); 189 | } 190 | } 191 | 192 | @Override 193 | public void sendNew(long streamId, String function) { 194 | if (log.isDebugEnabled()) { 195 | log.debug("{}/sendNew/{}/{}", name, streamId, function); 196 | } 197 | remote.sendNew(streamId, function); 198 | } 199 | 200 | @Override 201 | public void sendCancel(long streamId, String reason) { 202 | if (log.isDebugEnabled()) { 203 | log.debug("{}/sendCancel/{} {}", name, streamId, reason); 204 | } 205 | remote.sendCancel(streamId, reason); 206 | } 207 | 208 | @Override 209 | public void sendNext(long streamId, Object o) throws IOException { 210 | if (log.isDebugEnabled()) { 211 | log.debug("{}/sendNext/{}/value={}", name, streamId, o); 212 | } 213 | remote.sendNext(streamId, o); 214 | } 215 | 216 | @Override 217 | public void sendError(long streamId, Throwable e) { 218 | if (log.isDebugEnabled()) { 219 | log.debug("{}/sendError/{}", name, streamId, e); 220 | } 221 | remote.sendError(streamId, e); 222 | } 223 | 224 | @Override 225 | public void sendComplete(long streamId) { 226 | if (log.isDebugEnabled()) { 227 | log.debug("{}/sendComplete/{}", name, streamId); 228 | } 229 | remote.sendComplete(streamId); 230 | } 231 | 232 | @Override 233 | public void sendRequested(long streamId, long n) { 234 | if (log.isDebugEnabled()) { 235 | log.debug("{}/sendRequested/{}/{}", name, streamId, n); 236 | } 237 | remote.sendRequested(streamId, n); 238 | } 239 | 240 | @Override 241 | public boolean isClosed() { 242 | return remote.isClosed(); 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /src/main/java/reactor/ipc/stream/StreamOutbound.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2016 Pivotal Software 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 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package reactor.ipc.stream; 18 | 19 | import java.io.IOException; 20 | 21 | public interface StreamOutbound { 22 | 23 | void sendNew(long streamId, String function); 24 | 25 | void sendCancel(long streamId, String reason); 26 | 27 | void sendNext(long streamId, Object o) throws IOException; 28 | 29 | void sendError(long streamId, Throwable e); 30 | 31 | void sendComplete(long streamId); 32 | 33 | void sendRequested(long streamId, long n); 34 | 35 | boolean isClosed(); 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/reactor/ipc/stream/StreamSetup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2017 Pivotal Software 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 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package reactor.ipc.stream; 18 | 19 | import java.lang.reflect.Proxy; 20 | import java.util.Map; 21 | import java.util.Objects; 22 | import java.util.function.BiConsumer; 23 | import java.util.function.Consumer; 24 | import java.util.function.Function; 25 | import java.util.function.Supplier; 26 | 27 | import reactor.core.Disposable; 28 | import reactor.core.publisher.DirectProcessor; 29 | import reactor.core.publisher.Mono; 30 | import reactor.core.publisher.MonoSink; 31 | import reactor.ipc.connector.Connector; 32 | import reactor.ipc.connector.Inbound; 33 | import reactor.ipc.connector.Outbound; 34 | 35 | abstract class StreamSetup { 36 | 37 | private StreamSetup() { 38 | } 39 | 40 | static , OO extends Outbound, API> Mono connect( 41 | Connector connector, 42 | Supplier receiverSupplier, 43 | Class api, 44 | BiConsumer decoder, 45 | Function encoder) { 46 | 47 | return Mono.create(new OnConnectorSubscribe<>(connector, 48 | receiverSupplier, 49 | api, 50 | decoder, 51 | encoder)); 52 | } 53 | 54 | static final class OnConnectorSubscribe, OO extends Outbound, API> 55 | implements Consumer> { 56 | 57 | final Connector connector; 58 | final Supplier localSupplier; 59 | final Class remoteApi; 60 | final String endpointName; 61 | final BiConsumer ipcReader; 62 | final Function ipcWriter; 63 | 64 | OnConnectorSubscribe(Connector connector, 65 | Supplier localSupplier, 66 | Class remoteApi, 67 | BiConsumer ipcReader, 68 | Function ipcWriter) { 69 | this.connector = Objects.requireNonNull(connector, "connector"); 70 | this.endpointName = connector.getClass() 71 | .getSimpleName() 72 | .toLowerCase(); 73 | this.ipcReader = ipcReader; 74 | this.ipcWriter = ipcWriter; 75 | this.localSupplier = localSupplier; 76 | this.remoteApi = remoteApi; 77 | } 78 | 79 | @Override 80 | @SuppressWarnings("unchecked") 81 | public void accept(MonoSink sink) { 82 | Object localAPI; 83 | 84 | if (localSupplier == null) { 85 | localAPI = null; 86 | } 87 | else { 88 | localAPI = Objects.requireNonNull(localSupplier.get(), "localSupplier"); 89 | } 90 | 91 | Mono connect = connector.newHandler((in, out) -> { 92 | Map clientMap; 93 | Map serverMap; 94 | 95 | StreamOperationsImpl[] am = {null}; 96 | API api; 97 | final DirectProcessor closing; 98 | 99 | if (remoteApi != null) { 100 | clientMap = IpcServiceMapper.clientServiceMap(remoteApi); 101 | if (Disposable.class.isAssignableFrom(remoteApi)) { 102 | closing = DirectProcessor.create(); 103 | } 104 | else { 105 | closing = null; 106 | } 107 | api = 108 | remoteApi.cast(Proxy.newProxyInstance(remoteApi.getClassLoader(), 109 | new Class[]{remoteApi}, 110 | (o, m, args) -> { 111 | String name = m.getName(); 112 | Ipc a = m.getAnnotation(Ipc.class); 113 | if (a == null) { 114 | if (closing != null && m.getDeclaringClass() 115 | .equals(Disposable.class)) { 116 | closing.onComplete(); 117 | return null; 118 | } 119 | throw new IllegalArgumentException( 120 | "The method '" + m.getName() + "' is not annotated with Ipc"); 121 | } 122 | String aname = a.name(); 123 | if (!aname.isEmpty()) { 124 | name = aname; 125 | } 126 | 127 | Object action = clientMap.get(name); 128 | if (action == null) { 129 | throw new IllegalArgumentException( 130 | "The method '" + m.getName() + "' is not a proper Ipc method"); 131 | } 132 | return IpcServiceMapper.dispatchClient(name, 133 | action, 134 | args, 135 | am[0]); 136 | })); 137 | } 138 | else { 139 | api = null; 140 | closing = null; 141 | } 142 | 143 | StreamContextImpl ctx = new StreamContextImpl<>(api); 144 | StreamOutbound streamOutbound = 145 | Objects.requireNonNull(ipcWriter.apply(out), "remote"); 146 | 147 | if (localAPI != null) { 148 | serverMap = IpcServiceMapper.serverServiceMap(localAPI); 149 | 150 | am[0] = new StreamOperationsImpl<>(endpointName, 151 | (streamId, function, iom) -> { 152 | Object action = serverMap.get(function); 153 | if (action == null) { 154 | throw new IllegalStateException("Function " + function + " not found"); 155 | } 156 | return IpcServiceMapper.dispatchServer(streamId, 157 | action, 158 | iom, 159 | ctx); 160 | }, streamOutbound, in, 161 | () -> IpcServiceMapper.invokeDone(localAPI, ctx)); 162 | 163 | IpcServiceMapper.invokeInit(localAPI, ctx); 164 | } 165 | else { 166 | am[0] = new StreamOperationsImpl<>(endpointName, 167 | (streamId, function, iom) -> false, 168 | streamOutbound, 169 | in, 170 | () -> { 171 | }); 172 | } 173 | 174 | if (ipcReader != null) { 175 | ipcReader.accept(in, am[0]); 176 | } 177 | 178 | if (api != null) { 179 | sink.success(api); 180 | } 181 | 182 | return closing != null ? closing : Mono.never(); 183 | }); 184 | 185 | Disposable c; 186 | if (remoteApi != null) { 187 | c = connect.subscribe(null, sink::error); 188 | } 189 | else { 190 | c = 191 | connect.subscribe(connectedState -> sink.success((API) connectedState), 192 | sink::error); 193 | } 194 | sink.onCancel(c); 195 | } 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /src/test/java/reactor/ipc/BasicPingPongTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2016 Pivotal Software 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 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package reactor.ipc; 18 | 19 | import java.util.function.Function; 20 | 21 | import org.junit.Test; 22 | import org.reactivestreams.Publisher; 23 | import reactor.core.Disposable; 24 | import reactor.core.publisher.Flux; 25 | import reactor.core.publisher.Mono; 26 | import reactor.core.scheduler.Schedulers; 27 | import reactor.ipc.socket.SimpleClient; 28 | import reactor.ipc.socket.SimpleContext; 29 | import reactor.ipc.socket.SimpleServer; 30 | import reactor.ipc.stream.Ipc; 31 | import reactor.ipc.stream.StreamContext; 32 | import reactor.util.Logger; 33 | import reactor.util.Loggers; 34 | 35 | public class BasicPingPongTests { 36 | 37 | static final Logger log = Loggers.getLogger(BasicPingPongTests.class); 38 | 39 | public interface PingPongClientAPI extends Disposable { 40 | 41 | @Ipc 42 | Mono pong2(Mono ping); 43 | 44 | @Ipc 45 | Flux pong(Publisher ping); 46 | 47 | @Ipc 48 | void send(Publisher values); 49 | 50 | @Ipc 51 | void send2(Publisher values); 52 | 53 | @Ipc 54 | Flux receive(); 55 | 56 | @Ipc 57 | Mono receive2(); 58 | 59 | @Ipc 60 | void umap(Function, Publisher> mapper); 61 | 62 | @Ipc 63 | void send3(Publisher v); 64 | 65 | @Ipc 66 | Mono receive3(); 67 | 68 | @Ipc 69 | Mono map3(Flux v1); 70 | } 71 | 72 | public static class PingPongServerAPI { 73 | 74 | @Ipc 75 | public void send3(StreamContext ctx, Mono v1) { 76 | v1.log("send3") 77 | .subscribe(); 78 | } 79 | 80 | @Ipc 81 | public Mono receive3(StreamContext ctx) { 82 | log.info("Server: receive3()"); 83 | return Mono.just(33); 84 | } 85 | 86 | @Ipc 87 | public Publisher map3(StreamContext ctx, Flux v1) { 88 | log.info("Server: map3()"); 89 | return v1.scan((p, n) -> p + n); 90 | } 91 | 92 | @Ipc 93 | public Publisher pong2(StreamContext ctx, 94 | Publisher ping) { 95 | log.info("Server: pong2()"); 96 | return Flux.from(ping) 97 | .map(v -> v + 1); 98 | } 99 | 100 | @Ipc 101 | public Publisher pong(StreamContext ctx, Publisher ping) { 102 | log.info("Server: pong()"); 103 | return Flux.from(ping) 104 | .map(v -> v + 1); 105 | } 106 | 107 | @Ipc 108 | public void send(StreamContext ctx, Publisher values) { 109 | log.info("Server: send()"); 110 | Flux.from(values) 111 | .subscribe(v -> { 112 | log.info("Server: " + v); 113 | }, Throwable::printStackTrace); 114 | } 115 | 116 | @Ipc 117 | public void send2(StreamContext ctx, Publisher values) { 118 | send(ctx, values); 119 | } 120 | 121 | @Ipc 122 | public Publisher receive(StreamContext ctx) { 123 | log.info("Server: receive()"); 124 | return Flux.range(1, 1000); 125 | } 126 | 127 | @Ipc 128 | public Publisher receive2(StreamContext ctx) { 129 | return receive(ctx); 130 | } 131 | 132 | @Ipc 133 | public Publisher umap(StreamContext ctx, Flux values) { 134 | log.info("Server: umap()"); 135 | values.subscribe(v -> { 136 | log.info("Server: " + v); 137 | }, Throwable::printStackTrace); 138 | 139 | return Flux.just(50); 140 | } 141 | } 142 | 143 | static void print(Publisher p) { 144 | log.info(Flux.from(p) 145 | .blockLast().toString()); 146 | } 147 | 148 | @Test 149 | public void pingPong() throws Exception { 150 | 151 | SimpleContext c = SimpleServer.create(0) 152 | .newReceiver(PingPongServerAPI::new) 153 | .cast(SimpleContext.class) 154 | .block(); 155 | 156 | PingPongClientAPI api = SimpleClient.create(c.address() 157 | .getAddress(), 158 | c.address() 159 | .getPort()) 160 | .newProducer(PingPongClientAPI.class) 161 | .block(); 162 | 163 | api.send3(Flux.just(1, 2)); 164 | 165 | Thread.sleep(1000); 166 | 167 | log.info(api.receive3() 168 | .block().toString()); 169 | 170 | log.info(api.map3(Flux.just(1, 2)) 171 | .block().toString()); 172 | 173 | log.info("-----------"); 174 | 175 | log.info("Map:"); 176 | print(api.pong(Flux.just(1))); 177 | 178 | log.info("Sync map:"); 179 | log.info(api.pong2(Mono.just(2)) 180 | .block().toString()); 181 | 182 | log.info("Send:"); 183 | api.send(Flux.just(20)); 184 | 185 | Thread.sleep(200); 186 | 187 | log.info("Send:"); 188 | api.send2(Mono.just(25)); 189 | 190 | Thread.sleep(200); 191 | 192 | log.info("Receive:"); 193 | long t = System.currentTimeMillis(); 194 | print(api.receive()); 195 | 196 | log.info("t = " + (System.currentTimeMillis() - t)); 197 | 198 | log.info("Receive sync:"); 199 | log.info(api.receive2() 200 | .block().toString()); 201 | 202 | log.info("Umap:"); 203 | api.umap(o -> o.map(v -> -v)); 204 | 205 | Thread.sleep(5000); 206 | 207 | api.dispose(); 208 | 209 | c.dispose(); 210 | } 211 | 212 | public interface StreamPerfClientAPI extends Disposable { 213 | 214 | @Ipc 215 | Publisher range(Publisher count); 216 | } 217 | 218 | public static final class StreamPerfServerAPI { 219 | 220 | @Ipc 221 | public Publisher range(StreamContext ctx, Publisher count) { 222 | // log.info("Server: range"); 223 | return Flux.from(count) 224 | .concatMap(v -> Flux.range(1, v)); 225 | } 226 | } 227 | 228 | @Test 229 | public void streamPerf() throws Exception { 230 | 231 | SimpleContext c = SimpleServer.create(0) 232 | .newReceiver(StreamPerfServerAPI::new) 233 | .cast(SimpleContext.class) 234 | .block(); 235 | 236 | StreamPerfClientAPI api = SimpleClient.create(c.address() 237 | .getAddress(), 238 | c.address() 239 | .getPort()) 240 | .newProducer(StreamPerfClientAPI.class) 241 | .block(); 242 | 243 | int n = 100_000; 244 | 245 | for (int i = 1; i <= n; i *= 10) { 246 | 247 | System.out.printf("%6d | %n", i); 248 | 249 | for (int j = 0; j < 10; j++) { 250 | long t = System.nanoTime(); 251 | 252 | long count = Flux.from(api.range(Flux.just(i))) 253 | .publishOn(Schedulers.immediate()) 254 | .count() 255 | .block(); 256 | 257 | t = System.nanoTime() - t; 258 | 259 | System.out.printf("-> %6d", count); 260 | System.out.printf(" %.3f ms/op%n", (t / 1024d / 1024d)); 261 | } 262 | } 263 | 264 | api.dispose(); 265 | c.dispose(); 266 | } 267 | } 268 | -------------------------------------------------------------------------------- /src/test/java/reactor/ipc/socket/SimpleClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2017 Pivotal Software 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 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package reactor.ipc.socket; 18 | 19 | import java.io.IOException; 20 | import java.net.InetAddress; 21 | import java.net.Socket; 22 | import java.util.Objects; 23 | import java.util.concurrent.Executors; 24 | import java.util.function.BiFunction; 25 | 26 | import org.reactivestreams.Publisher; 27 | import reactor.core.Disposable; 28 | import reactor.core.publisher.Flux; 29 | import reactor.core.publisher.Mono; 30 | import reactor.core.scheduler.Scheduler; 31 | import reactor.core.scheduler.Schedulers; 32 | import reactor.ipc.connector.Inbound; 33 | import reactor.ipc.connector.Outbound; 34 | 35 | /** 36 | * @author Stephane Maldini 37 | */ 38 | public final class SimpleClient extends SimplePeer { 39 | 40 | static final Scheduler scheduler = 41 | Schedulers.fromExecutorService(Executors.newCachedThreadPool(r -> { 42 | Thread t = new Thread(r, "test-client-pool"); 43 | t.setDaemon(true); 44 | return t; 45 | })); 46 | 47 | static public SimpleClient create(InetAddress bindAddress, int port) { 48 | Objects.requireNonNull(bindAddress, "bindAddress"); 49 | return new SimpleClient(bindAddress, port); 50 | } 51 | 52 | final int port; 53 | final InetAddress address; 54 | 55 | SimpleClient(InetAddress address, int port) { 56 | this.port = port; 57 | this.address = address; 58 | } 59 | 60 | @Override 61 | public Mono newHandler(BiFunction, ? super 62 | Outbound, ? extends Publisher> ioHandler) { 63 | return Mono.create(sink -> { 64 | Socket socket; 65 | 66 | try { 67 | socket = new Socket(address, port); 68 | sink.onCancel(() -> { 69 | try { 70 | socket.close(); 71 | } 72 | catch (IOException ex) { 73 | sink.error(ex); 74 | } 75 | }); 76 | 77 | SimpleConnection connection = new SimpleConnection(socket); 78 | 79 | sink.success(connection); 80 | 81 | Publisher closing = ioHandler.apply(connection, connection); 82 | Flux.from(closing) 83 | .subscribe(null, connection::closeError, connection::close); 84 | } 85 | catch (Throwable e) { 86 | sink.error(e); 87 | } 88 | }).subscribeOn(scheduler); 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/test/java/reactor/ipc/socket/SimpleConnection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2017 Pivotal Software 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 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package reactor.ipc.socket; 18 | 19 | import java.io.ByteArrayInputStream; 20 | import java.io.ByteArrayOutputStream; 21 | import java.io.IOException; 22 | import java.io.InputStream; 23 | import java.io.ObjectInputStream; 24 | import java.io.ObjectOutputStream; 25 | import java.io.OutputStream; 26 | import java.net.InetAddress; 27 | import java.net.InetSocketAddress; 28 | import java.net.Socket; 29 | import java.util.concurrent.atomic.AtomicBoolean; 30 | import java.util.function.IntConsumer; 31 | 32 | import org.reactivestreams.Publisher; 33 | import reactor.core.Exceptions; 34 | import reactor.core.publisher.DirectProcessor; 35 | import reactor.core.publisher.Flux; 36 | import reactor.core.publisher.Mono; 37 | import reactor.core.publisher.Operators; 38 | import reactor.core.scheduler.Scheduler; 39 | import reactor.core.scheduler.Schedulers; 40 | import reactor.ipc.connector.Inbound; 41 | import reactor.ipc.connector.Outbound; 42 | import reactor.ipc.stream.StreamOutbound; 43 | import reactor.util.context.Context; 44 | 45 | /** 46 | * @author Stephane Maldini 47 | */ 48 | final class SimpleConnection implements Inbound, Outbound, 49 | StreamOutbound, SimpleContext { 50 | 51 | final DirectProcessor processor; 52 | 53 | final Mono onClose; 54 | 55 | final Socket socket; 56 | 57 | final AtomicBoolean terminateOnce; 58 | 59 | final Flux receiver; 60 | 61 | final byte[] readBuffer; 62 | 63 | final byte[] writeBuffer; 64 | 65 | final Scheduler readScheduler; 66 | final Scheduler writeScheduler; 67 | final Scheduler dispatcher; 68 | 69 | final InputStream in; 70 | 71 | final OutputStream out; 72 | 73 | SimpleConnection(Socket socket) { 74 | this(socket, false); 75 | } 76 | 77 | SimpleConnection(Socket socket, boolean server) { 78 | this.socket = socket; 79 | this.terminateOnce = new AtomicBoolean(); 80 | this.readBuffer = new byte[16]; 81 | this.writeBuffer = new byte[32]; 82 | this.processor = DirectProcessor.create(); 83 | this.onClose = Mono.from(processor); 84 | this.dispatcher = 85 | Schedulers.newParallel("simple-" + (server ? "server" : "client") + "-io", 86 | 2, 87 | true); 88 | 89 | this.readScheduler = Schedulers.single(dispatcher); 90 | this.writeScheduler = Schedulers.single(dispatcher); 91 | 92 | InputStream in; 93 | OutputStream out; 94 | 95 | try { 96 | in = socket.getInputStream(); 97 | out = socket.getOutputStream(); 98 | } 99 | catch (IOException io) { 100 | throw Exceptions.propagate(io); 101 | } 102 | 103 | this.in = in; 104 | this.out = out; 105 | 106 | this.receiver = Flux.generate(sink -> { 107 | if (readFully(in, readBuffer, 16) < 16) { 108 | sink.complete(); 109 | } 110 | else { 111 | sink.next(readBuffer); 112 | } 113 | }).subscribeOn(readScheduler) 114 | .share(); 115 | 116 | 117 | } 118 | 119 | @Override 120 | public InetSocketAddress address() { 121 | return new InetSocketAddress(socket.getInetAddress(), socket.getPort()); 122 | } 123 | 124 | static void tryClose(Socket socket) { 125 | try { 126 | socket.close(); 127 | } 128 | catch (IOException e) { 129 | //IGNORE 130 | } 131 | } 132 | 133 | void close() { 134 | tryClose(socket); 135 | processor.onComplete(); 136 | } 137 | 138 | void closeError(Throwable throwable) { 139 | tryClose(socket); 140 | processor.onError(throwable); 141 | } 142 | 143 | @Override 144 | public Flux receive() { 145 | return receiver; 146 | } 147 | 148 | 149 | 150 | @Override 151 | public Outbound send(Publisher dataStream) { 152 | throw new UnsupportedOperationException(); 153 | } 154 | 155 | byte[] encode(Object o, IntConsumer flagOut) throws IOException { 156 | 157 | if (o instanceof Integer) { 158 | flagOut.accept(ByteArrayStreamProtocol.PAYLOAD_INT); 159 | byte[] r = new byte[4]; 160 | int v = (Integer) o; 161 | r[0] = (byte) (v & 0xFF); 162 | r[1] = (byte) ((v >> 8) & 0xFF); 163 | r[2] = (byte) ((v >> 16) & 0xFF); 164 | r[3] = (byte) ((v >> 24) & 0xFF); 165 | return r; 166 | } 167 | else if (o instanceof Long) { 168 | flagOut.accept(ByteArrayStreamProtocol.PAYLOAD_LONG); 169 | byte[] r = new byte[8]; 170 | long v = (Long) o; 171 | r[0] = (byte) (v & 0xFF); 172 | r[1] = (byte) ((v >> 8) & 0xFF); 173 | r[2] = (byte) ((v >> 16) & 0xFF); 174 | r[3] = (byte) ((v >> 24) & 0xFF); 175 | r[4] = (byte) ((v >> 32) & 0xFF); 176 | r[5] = (byte) ((v >> 40) & 0xFF); 177 | r[6] = (byte) ((v >> 48) & 0xFF); 178 | r[7] = (byte) ((v >> 56) & 0xFF); 179 | return r; 180 | } 181 | else if (o instanceof String) { 182 | flagOut.accept(ByteArrayStreamProtocol.PAYLOAD_STRING); 183 | return ByteArrayStreamProtocol.utf8((String) o); 184 | } 185 | else if (o instanceof byte[]) { 186 | flagOut.accept(ByteArrayStreamProtocol.PAYLOAD_BYTES); 187 | return ((byte[]) o).clone(); 188 | } 189 | 190 | flagOut.accept(ByteArrayStreamProtocol.PAYLOAD_OBJECT); 191 | 192 | ByteArrayOutputStream bout = new ByteArrayOutputStream(); 193 | 194 | try (ObjectOutputStream oout = new ObjectOutputStream(bout)) { 195 | oout.writeObject(o); 196 | } 197 | 198 | return bout.toByteArray(); 199 | } 200 | 201 | static void flush(OutputStream out) { 202 | try { 203 | out.flush(); 204 | } 205 | catch (IOException ex) { 206 | Operators.onErrorDropped(ex, Context.empty()); 207 | } 208 | } 209 | 210 | @Override 211 | public void sendNew(long streamId, String function) { 212 | writeScheduler.schedule(() -> { 213 | ByteArrayStreamProtocol.open(out, streamId, function, writeBuffer); 214 | flush(out); 215 | }); 216 | } 217 | 218 | @Override 219 | public void sendNext(long streamId, Object o) throws IOException { 220 | 221 | OnNextTask task = new OnNextTask(streamId, out, writeBuffer); 222 | 223 | task.payload = encode(o, task); 224 | 225 | writeScheduler.schedule(task); 226 | } 227 | 228 | static final class OnNextTask implements Runnable, IntConsumer { 229 | 230 | final long streamId; 231 | final OutputStream out; 232 | final byte[] writeBuffer; 233 | byte[] payload; 234 | int flags; 235 | 236 | public OnNextTask(long streamId, OutputStream out, byte[] writeBuffer) { 237 | this.streamId = streamId; 238 | this.out = out; 239 | this.writeBuffer = writeBuffer; 240 | } 241 | 242 | @Override 243 | public void run() { 244 | ByteArrayStreamProtocol.next(out, streamId, flags, payload, writeBuffer); 245 | flush(out); 246 | } 247 | 248 | @Override 249 | public void accept(int value) { 250 | this.flags = value; 251 | } 252 | } 253 | 254 | @Override 255 | public void sendError(long streamId, Throwable e) { 256 | writeScheduler.schedule(() -> { 257 | ByteArrayStreamProtocol.error(out, streamId, e, writeBuffer); 258 | flush(out); 259 | }); 260 | } 261 | 262 | @Override 263 | public void sendComplete(long streamId) { 264 | writeScheduler.schedule(() -> { 265 | ByteArrayStreamProtocol.complete(out, streamId, writeBuffer); 266 | flush(out); 267 | }); 268 | } 269 | 270 | @Override 271 | public void sendCancel(long streamId, String reason) { 272 | writeScheduler.schedule(() -> { 273 | ByteArrayStreamProtocol.cancel(out, streamId, reason, writeBuffer); 274 | flush(out); 275 | }); 276 | } 277 | 278 | @Override 279 | public void sendRequested(long streamId, long requested) { 280 | writeScheduler.schedule(() -> { 281 | ByteArrayStreamProtocol.request(out, streamId, requested, writeBuffer); 282 | flush(out); 283 | }); 284 | } 285 | 286 | @Override 287 | public boolean isClosed() { 288 | return terminateOnce.get(); 289 | } 290 | 291 | static int readFully(InputStream in, byte[] output, int count) { 292 | int offset = 0; 293 | int remaining = count; 294 | 295 | try { 296 | for (; ; ) { 297 | int a = in.read(output, offset, remaining); 298 | if (a < 0) { 299 | break; 300 | } 301 | offset += a; 302 | remaining -= a; 303 | if (remaining == 0) { 304 | break; 305 | } 306 | } 307 | } 308 | catch (IOException io) { 309 | throw Exceptions.propagate(io); 310 | } 311 | return offset; 312 | } 313 | 314 | Object decode(int flags, byte[] payload, int len) 315 | throws IOException, ClassNotFoundException { 316 | if (flags == ByteArrayStreamProtocol.PAYLOAD_INT) { 317 | int v = 318 | (payload[0] & 0xFF) | ((payload[1] & 0xFF) << 8) | ((payload[2] & 0xFF) << 16) | ((payload[3] & 0xFF) << 24); 319 | return v; 320 | } 321 | else if (flags == ByteArrayStreamProtocol.PAYLOAD_LONG) { 322 | long v = 323 | (payload[0] & 0xFFL) | ((payload[1] & 0xFFL) << 8) | ((payload[2] & 0xFFL) << 16) | ((payload[3] & 0xFFL) << 24) | ((payload[4] & 0xFFL) << 32) | ((payload[5] & 0xFFL) << 40) | ((payload[6] & 0xFFL) << 48) | ((payload[7] & 0xFFL) << 56); 324 | return v; 325 | } 326 | else if (flags == ByteArrayStreamProtocol.PAYLOAD_STRING) { 327 | return ByteArrayStreamProtocol.readUtf8(payload, 0, len); 328 | } 329 | else if (flags == ByteArrayStreamProtocol.PAYLOAD_BYTES) { 330 | if (payload == readBuffer) { 331 | byte[] r = new byte[len]; 332 | System.arraycopy(payload, 0, r, 0, len); 333 | return r; 334 | } 335 | return payload; 336 | } 337 | 338 | ByteArrayInputStream bin = new ByteArrayInputStream(payload); 339 | ObjectInputStream oin = new ObjectInputStream(bin); 340 | return oin.readObject(); 341 | } 342 | 343 | @Override 344 | public void dispose() { 345 | try { 346 | readScheduler.dispose(); 347 | writeScheduler.dispose(); 348 | dispatcher.dispose(); 349 | in.close(); 350 | out.close(); 351 | } 352 | catch (IOException io) { 353 | //IGNORE 354 | } 355 | } 356 | } 357 | -------------------------------------------------------------------------------- /src/test/java/reactor/ipc/socket/SimpleContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2017 Pivotal Software 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 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package reactor.ipc.socket; 17 | 18 | import java.net.InetSocketAddress; 19 | 20 | import reactor.core.Disposable; 21 | 22 | /** 23 | * @author Stephane Maldini 24 | */ 25 | public interface SimpleContext extends Disposable { 26 | 27 | InetSocketAddress address(); 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/reactor/ipc/socket/SimplePeer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2016 Pivotal Software 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 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package reactor.ipc.socket; 18 | 19 | import java.util.function.BiConsumer; 20 | import java.util.function.BiFunction; 21 | import java.util.function.Function; 22 | import java.util.function.Supplier; 23 | 24 | import org.reactivestreams.Publisher; 25 | import reactor.core.Disposable; 26 | import reactor.core.publisher.Mono; 27 | import reactor.ipc.connector.Inbound; 28 | import reactor.ipc.connector.Outbound; 29 | import reactor.ipc.stream.StreamConnector; 30 | import reactor.ipc.stream.StreamOperations; 31 | import reactor.ipc.stream.StreamOutbound; 32 | 33 | /** 34 | * @author Stephane Maldini 35 | */ 36 | abstract class SimplePeer 37 | implements StreamConnector, Outbound>, 38 | BiConsumer, StreamOperations>, 39 | Function, StreamOutbound> { 40 | 41 | @Override 42 | @SuppressWarnings("unchecked") 43 | public void accept(Inbound inbound, StreamOperations endpoint) { 44 | inbound.receive() 45 | .subscribe(d -> ByteArrayStreamProtocol.receive(((SimpleConnection) inbound).in, 46 | d, 47 | endpoint)); 48 | } 49 | 50 | @Override 51 | @SuppressWarnings("unchecked") 52 | public StreamOutbound apply(Outbound outbound) { 53 | return (StreamOutbound) outbound; 54 | } 55 | 56 | @Override 57 | public Mono newBidirectional(Supplier receiverSupplier, 58 | Class api) { 59 | return newStreamSupport(receiverSupplier, api, this, this); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/test/java/reactor/ipc/socket/SimpleServer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2017 Pivotal Software 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 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package reactor.ipc.socket; 18 | 19 | import java.io.IOException; 20 | import java.net.InetAddress; 21 | import java.net.InetSocketAddress; 22 | import java.net.ServerSocket; 23 | import java.net.Socket; 24 | import java.util.Objects; 25 | import java.util.concurrent.atomic.AtomicBoolean; 26 | import java.util.function.BiFunction; 27 | 28 | import org.reactivestreams.Publisher; 29 | import reactor.core.Disposable; 30 | import reactor.core.publisher.Flux; 31 | import reactor.core.publisher.Mono; 32 | import reactor.core.publisher.MonoSink; 33 | import reactor.core.scheduler.Scheduler; 34 | import reactor.core.scheduler.Schedulers; 35 | import reactor.ipc.connector.Inbound; 36 | import reactor.ipc.connector.Outbound; 37 | 38 | /** 39 | * @author Stephane Maldini 40 | */ 41 | public final class SimpleServer extends SimplePeer { 42 | 43 | static public SimpleServer create(int port) { 44 | return new SimpleServer(port, null); 45 | } 46 | 47 | static public SimpleServer create(int port, InetAddress bindAddress) { 48 | Objects.requireNonNull(bindAddress, "bindAddress"); 49 | return new SimpleServer(port, bindAddress); 50 | } 51 | 52 | final int port; 53 | final InetAddress address; 54 | 55 | SimpleServer(int port, InetAddress address) { 56 | this.port = port; 57 | this.address = address; 58 | } 59 | 60 | @Override 61 | public Mono newHandler(BiFunction, ? super Outbound, ? extends Publisher> ioHandler) { 62 | 63 | return Mono.create(sink -> { 64 | ServerSocket ssocket; 65 | Scheduler acceptor = 66 | Schedulers.newParallel("simple-server-connection", 1, true); 67 | 68 | try { 69 | if (address == null) { 70 | ssocket = new ServerSocket(port); 71 | } 72 | else { 73 | ssocket = new ServerSocket(port, 50, address); 74 | } 75 | } 76 | catch (IOException e) { 77 | sink.error(e); 78 | return; 79 | } 80 | 81 | AtomicBoolean done = new AtomicBoolean(); 82 | ServerListening connectedState = 83 | new ServerListening(ssocket, done, sink, acceptor); 84 | Disposable c = 85 | acceptor.schedule(() -> socketAccept(ioHandler, connectedState, 86 | acceptor)); 87 | 88 | sink.onCancel(() -> connectedState.close(c)); 89 | }); 90 | } 91 | 92 | static void socketAccept( 93 | BiFunction, ? super Outbound, ? extends Publisher> ioHandler, 94 | ServerListening connectedState, Scheduler acceptor) { 95 | 96 | connectedState.sink.success(connectedState); 97 | 98 | while (!Thread.currentThread() 99 | .isInterrupted() && !acceptor.isDisposed()) { 100 | Socket socket; 101 | 102 | try { 103 | socket = connectedState.ssocket.accept(); 104 | 105 | } 106 | catch (IOException e) { 107 | if (!connectedState.done.get()) { 108 | connectedState.sink.error(e); 109 | } 110 | return; 111 | } 112 | 113 | try { 114 | SimpleConnection connection = new SimpleConnection(socket, true); 115 | Publisher closing = ioHandler.apply(connection, connection); 116 | Flux.from(closing) 117 | .subscribe(null, connection::closeError, connection::close); 118 | } 119 | catch (Throwable ex) { 120 | tryClose(socket); 121 | } 122 | 123 | } 124 | } 125 | 126 | static void tryClose(Socket socket) { 127 | try { 128 | socket.close(); 129 | } 130 | catch (IOException e) { 131 | //IGNORE 132 | } 133 | } 134 | 135 | static final class ServerListening implements SimpleContext { 136 | 137 | final ServerSocket ssocket; 138 | final AtomicBoolean done; 139 | final MonoSink sink; 140 | final Scheduler acceptor; 141 | 142 | ServerListening(ServerSocket ssocket, 143 | AtomicBoolean done, 144 | MonoSink sink, 145 | Scheduler acceptor) { 146 | this.ssocket = ssocket; 147 | this.done = done; 148 | this.sink = sink; 149 | this.acceptor = acceptor; 150 | } 151 | 152 | @Override 153 | public InetSocketAddress address() { 154 | return new InetSocketAddress(ssocket.getInetAddress(), ssocket.getLocalPort()); 155 | } 156 | 157 | @Override 158 | public void dispose() { 159 | close(null); 160 | } 161 | 162 | void close(Disposable disposable) { 163 | if (done.compareAndSet(false, true)) { 164 | acceptor.dispose(); 165 | if (disposable != null) { 166 | disposable.dispose(); 167 | } 168 | try { 169 | ssocket.close(); 170 | } 171 | catch (IOException ex) { 172 | return; 173 | } 174 | } 175 | } 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | --------------------------------------------------------------------------------