├── .gitignore ├── README.md ├── doozerd-0.8 ├── linux-386 │ ├── doozer │ └── doozerd └── osx-386 │ ├── doozer │ └── doozerd ├── project ├── build.properties └── build │ └── FlangeProject.scala ├── src ├── main │ ├── java │ │ └── doozer │ │ │ └── DoozerMsg.java │ ├── protobuf │ │ └── doozer-msg.proto │ ├── resources │ │ └── akka.conf │ └── scala │ │ └── com │ │ └── force │ │ └── doozer │ │ └── flange │ │ ├── DoozerClient.scala │ │ └── Messages.scala └── test │ └── scala │ └── com │ └── force │ └── doozer │ └── flange │ ├── ClientSpec.scala │ ├── ConnectionSpec.scala │ ├── FailoverSpec.scala │ ├── URISpec.scala │ └── Waiting.scala ├── startDoozer.sh └── stopDoozer.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *# 3 | src_managed 4 | activemq-data 5 | project/plugins/project 6 | project/boot/* 7 | */project/build/target 8 | */project/boot 9 | lib_managed 10 | etags 11 | tags 12 | TAGS 13 | akka.tmproj 14 | reports 15 | dist 16 | build 17 | target 18 | deploy/*.jar 19 | data 20 | out 21 | logs 22 | .#* 23 | .codefellow 24 | storage 25 | .codefellow 26 | .ensime 27 | _dump 28 | .manager 29 | manifest.mf 30 | semantic.cache 31 | tm*.log 32 | tm*.lck 33 | tm.out 34 | *.tm.epoch 35 | .DS_Store 36 | *.iws 37 | *.ipr 38 | *.iml 39 | run-codefellow 40 | .project 41 | .settings 42 | .classpath 43 | .idea 44 | .scala_dependencies 45 | multiverse.log 46 | .eprj 47 | .*.swp 48 | akka-tutorials/akka-tutorial-pi-sbt/project/boot/ 49 | doozer-*/dooz.log 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Flange: Scala client For Doozer 2 | 3 | ## Build and test 4 | 5 | ./startDoozer.sh 6 | sbt test 7 | ./stopDoozer.sh 8 | 9 | ## Basic Usage (explicit types for clarity) 10 | ./startDoozer.sh 11 | sbt console 12 | 13 | import com.force.doozer.flange.Flange 14 | import com.force.doozer.flange.{GetResponse,SetResponse,ErrorResponse,WatchNotification,WatchResponse} 15 | 16 | val client = new Flange("doozer:?ca=localhost:8046&ca=localhost:8047&ca=localhost:8048") 17 | 18 | //Set returns an Left(ErrorResponse(_,_)) if there is a failure 19 | val set:Either[ErrorResponse,SetResponse] = client.set("/foo", "bar".getBytes(), 0L) 20 | 21 | //Set succeeds or throws an exception 22 | val set2:SetResponse = client.set_!("/foofoo", "bar".getBytes(), 0L) 23 | 24 | //Get returns an Left(ErrorResponse(_,_)) if there is a failure 25 | val get:Either[ErrorResponse,GetResponse] = client.get("/foo") 26 | //Get succeeds or exception is thrown 27 | val get2:GetResponse = client.get_!("/foofoo") 28 | //Watch succeeds or exception is thrown 29 | val watch:WatchResponse = client.watch_!("/foofoo", get2.cas){ 30 | notification:WatchNotification => System.out.println("/foofoo changed to "+new String(notification.value)) 31 | } 32 | client.set_!("/foofoo", "newbar".getBytes(), get2.cas) 33 | //Should print notification of change 34 | 35 | 36 | ##Failover 37 | 38 | The Flange client will by default will failover to each of the doozer servers specified in the doozerURI when an operation fails. The failing operation 39 | is transparently retried. Once all of the doozer servers have failed the client is dead. 40 | 41 | This behavior is pluggable. You simply need to supply a function of List[String] => Iterable[String] when constructing a Flange instance 42 | that will be passed the list of doozerd hosts parsed from the doozer URI. 43 | 44 | The Flange companion object defines 2 of these functions, eachDoozerOnceStrategy and retryForeverStrategy. The default is eachDoozerOnceStrategy 45 | 46 | To use the retryForeverStrategy 47 | 48 | import com.force.doozer.flange.Flange 49 | import com.force.doozer.flange.Flange._ 50 | 51 | val doozerUri = ... 52 | val flange = new Flange(doozerUri, retryForeverStrategy) 53 | 54 | 55 | To use your own 56 | 57 | import com.force.doozer.flange.Flange 58 | 59 | val funk: List[String]=>Iterable[String] = {doozerds:List[String]=>...} 60 | val doozerUri = ... 61 | val flange = new Flange(doozerUri, funk) 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /doozerd-0.8/linux-386/doozer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclasen/flange/a49aeebdc59554a82f5bf53471fe480958f782fe/doozerd-0.8/linux-386/doozer -------------------------------------------------------------------------------- /doozerd-0.8/linux-386/doozerd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclasen/flange/a49aeebdc59554a82f5bf53471fe480958f782fe/doozerd-0.8/linux-386/doozerd -------------------------------------------------------------------------------- /doozerd-0.8/osx-386/doozer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclasen/flange/a49aeebdc59554a82f5bf53471fe480958f782fe/doozerd-0.8/osx-386/doozer -------------------------------------------------------------------------------- /doozerd-0.8/osx-386/doozerd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sclasen/flange/a49aeebdc59554a82f5bf53471fe480958f782fe/doozerd-0.8/osx-386/doozerd -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | #Project properties 2 | #Thu Apr 21 15:10:58 PDT 2011 3 | project.organization=com.force.doozer 4 | project.name=flange 5 | sbt.version=0.7.7 6 | project.version=1.0 7 | build.scala.versions=2.9.0 8 | project.initialize=false 9 | -------------------------------------------------------------------------------- /project/build/FlangeProject.scala: -------------------------------------------------------------------------------- 1 | import sbt._ 2 | 3 | class FlangeProject(info: ProjectInfo) extends DefaultProject(info) { 4 | 5 | 6 | object Repositories { 7 | lazy val AkkaRepo = MavenRepository("Akka Repository", "http://akka.io/repository") 8 | lazy val ScalaToolsRepo = MavenRepository("Scala-Tools Repo", "http://scala-tools.org/repo-releases") 9 | lazy val ScalaToolsSnapshotRepo = MavenRepository("Scala-Tools Snapshot Repo", "http://scala-tools.org/repo-snapshots") 10 | lazy val CodehausRepo = MavenRepository("Codehaus Repo", "http://repository.codehaus.org") 11 | lazy val LocalMavenRepo = MavenRepository("Local Maven Repo", (Path.userHome / ".m2" / "repository").asURL.toString) 12 | lazy val GuiceyFruitRepo = MavenRepository("GuiceyFruit Repo", "http://guiceyfruit.googlecode.com/svn/repo/releases/") 13 | lazy val JBossRepo = MavenRepository("JBoss Repo", "http://repository.jboss.org/nexus/content/groups/public/") 14 | lazy val JavaNetRepo = MavenRepository("java.net Repo", "http://download.java.net/maven/2") 15 | lazy val SonatypeSnapshotRepo = MavenRepository("Sonatype OSS Repo", "http://oss.sonatype.org/content/repositories/releases") 16 | lazy val SunJDMKRepo = MavenRepository("Sun JDMK Repo", "http://wp5.e-taxonomy.eu/cdmlib/mavenrepo") 17 | lazy val ClojarsRepo = MavenRepository("Clojars Repo", "http://clojars.org/repo") 18 | lazy val ScalaToolsRelRepo = MavenRepository("Scala Tools Releases Repo", "http://scala-tools.org/repo-releases") 19 | lazy val ForceRelRepo = MavenRepository("Force releases", "http://repo.t.salesforce.com/archiva/repository/releases") 20 | lazy val ForceSnaplRepo = MavenRepository("Force snapshots", "http://repo.t.salesforce.com/archiva/repository/snapshots") 21 | lazy val javanetRepo = MavenRepository("javanetrepo", "http://download.java.net/maven/2/") 22 | } 23 | 24 | import Repositories._ 25 | 26 | lazy val nettyModuleConfig = ModuleConfiguration("org.jboss.netty", JBossRepo) 27 | lazy val akkaoduleConfig = ModuleConfiguration("se.scalablesolutions.akka", AkkaRepo) 28 | lazy val scalaTestModuleConfig = ModuleConfiguration("org.scalatest", ScalaToolsSnapshots) 29 | val localMavenRepo = LocalMavenRepo 30 | 31 | // Second exception, also fast! ;-) 32 | 33 | // ------------------------------------------------------------------------------------------------------------------- 34 | // Versions 35 | // ------------------------------------------------------------------------------------------------------------------- 36 | 37 | lazy val AKKA_VERSION = "1.1" 38 | lazy val CAMEL_VERSION = "2.7.0" 39 | lazy val SCALATEST_VERSION = "1.4-SNAPSHOT" 40 | lazy val SLF4J_VERSION = "1.6.0" 41 | 42 | // ------------------------------------------------------------------------------------------------------------------- 43 | // Dependencies 44 | // ------------------------------------------------------------------------------------------------------------------- 45 | 46 | object Dependencies { 47 | 48 | // Compile 49 | lazy val akka_actor = "se.scalablesolutions.akka" % "akka-actor" % AKKA_VERSION % "compile" withSources () 50 | //ApacheV2 51 | lazy val akka_slf4j = "se.scalablesolutions.akka" % "akka-slf4j" % AKKA_VERSION % "compile" 52 | //ApacheV2 53 | lazy val camel_netty = "org.apache.camel" % "camel-netty" % CAMEL_VERSION % "compile" withSources () 54 | //ApacheV2 55 | lazy val netty = "org.jboss.netty" % "netty" % "3.2.3.Final" % "compile" withSources () 56 | //ApacheV2 57 | lazy val protobuf = "com.google.protobuf" % "protobuf-java" % "2.4.0a" withSources () 58 | //New BSD 59 | lazy val slf4_api = "org.slf4j" % "slf4j-api" % SLF4J_VERSION % "compile" 60 | lazy val slf4_jcl = "org.slf4j" % "jcl-over-slf4j" % SLF4J_VERSION % "compile" 61 | lazy val slf4_jul = "org.slf4j" % "jul-to-slf4j" % SLF4J_VERSION % "compile" 62 | lazy val slf4_log4j = "org.slf4j" % "log4j-over-slf4j" % SLF4J_VERSION % "compile" 63 | // MIT 64 | // Test 65 | lazy val scalatest = "org.scalatest" % "scalatest" % SCALATEST_VERSION % "test" 66 | //ApacheV2 67 | lazy val logback = "ch.qos.logback" % "logback-classic" % "0.9.28" % "compile" 68 | 69 | } 70 | 71 | 72 | override def ivyXML = 73 | 74 | 75 | 76 | 77 | val protobuf = Dependencies.protobuf 78 | val akka_actor = Dependencies.akka_actor 79 | val netty = Dependencies.netty 80 | val akka_slf4j = Dependencies.akka_slf4j 81 | val slf4j_api = Dependencies.slf4_api 82 | val logback = Dependencies.logback 83 | val scalatest = Dependencies.scalatest 84 | 85 | 86 | } -------------------------------------------------------------------------------- /src/main/java/doozer/DoozerMsg.java: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: doozer-msg.proto 3 | 4 | package doozer; 5 | 6 | public final class DoozerMsg { 7 | private DoozerMsg() {} 8 | public static void registerAllExtensions( 9 | com.google.protobuf.ExtensionRegistry registry) { 10 | } 11 | public interface RequestOrBuilder 12 | extends com.google.protobuf.MessageOrBuilder { 13 | 14 | // optional int32 tag = 1; 15 | boolean hasTag(); 16 | int getTag(); 17 | 18 | // optional .doozer.Request.Verb verb = 2; 19 | boolean hasVerb(); 20 | doozer.DoozerMsg.Request.Verb getVerb(); 21 | 22 | // optional string path = 4; 23 | boolean hasPath(); 24 | String getPath(); 25 | 26 | // optional bytes value = 5; 27 | boolean hasValue(); 28 | com.google.protobuf.ByteString getValue(); 29 | 30 | // optional int32 other_tag = 6; 31 | boolean hasOtherTag(); 32 | int getOtherTag(); 33 | 34 | // optional int32 offset = 7; 35 | boolean hasOffset(); 36 | int getOffset(); 37 | 38 | // optional int64 rev = 9; 39 | boolean hasRev(); 40 | long getRev(); 41 | } 42 | public static final class Request extends 43 | com.google.protobuf.GeneratedMessage 44 | implements RequestOrBuilder { 45 | // Use Request.newBuilder() to construct. 46 | private Request(Builder builder) { 47 | super(builder); 48 | } 49 | private Request(boolean noInit) {} 50 | 51 | private static final Request defaultInstance; 52 | public static Request getDefaultInstance() { 53 | return defaultInstance; 54 | } 55 | 56 | public Request getDefaultInstanceForType() { 57 | return defaultInstance; 58 | } 59 | 60 | public static final com.google.protobuf.Descriptors.Descriptor 61 | getDescriptor() { 62 | return doozer.DoozerMsg.internal_static_doozer_Request_descriptor; 63 | } 64 | 65 | protected com.google.protobuf.GeneratedMessage.FieldAccessorTable 66 | internalGetFieldAccessorTable() { 67 | return doozer.DoozerMsg.internal_static_doozer_Request_fieldAccessorTable; 68 | } 69 | 70 | public enum Verb 71 | implements com.google.protobuf.ProtocolMessageEnum { 72 | GET(0, 1), 73 | SET(1, 2), 74 | DEL(2, 3), 75 | REV(3, 5), 76 | WAIT(4, 6), 77 | NOP(5, 7), 78 | WALK(6, 9), 79 | GETDIR(7, 14), 80 | STAT(8, 16), 81 | ACCESS(9, 99), 82 | ; 83 | 84 | public static final int GET_VALUE = 1; 85 | public static final int SET_VALUE = 2; 86 | public static final int DEL_VALUE = 3; 87 | public static final int REV_VALUE = 5; 88 | public static final int WAIT_VALUE = 6; 89 | public static final int NOP_VALUE = 7; 90 | public static final int WALK_VALUE = 9; 91 | public static final int GETDIR_VALUE = 14; 92 | public static final int STAT_VALUE = 16; 93 | public static final int ACCESS_VALUE = 99; 94 | 95 | 96 | public final int getNumber() { return value; } 97 | 98 | public static Verb valueOf(int value) { 99 | switch (value) { 100 | case 1: return GET; 101 | case 2: return SET; 102 | case 3: return DEL; 103 | case 5: return REV; 104 | case 6: return WAIT; 105 | case 7: return NOP; 106 | case 9: return WALK; 107 | case 14: return GETDIR; 108 | case 16: return STAT; 109 | case 99: return ACCESS; 110 | default: return null; 111 | } 112 | } 113 | 114 | public static com.google.protobuf.Internal.EnumLiteMap 115 | internalGetValueMap() { 116 | return internalValueMap; 117 | } 118 | private static com.google.protobuf.Internal.EnumLiteMap 119 | internalValueMap = 120 | new com.google.protobuf.Internal.EnumLiteMap() { 121 | public Verb findValueByNumber(int number) { 122 | return Verb.valueOf(number); 123 | } 124 | }; 125 | 126 | public final com.google.protobuf.Descriptors.EnumValueDescriptor 127 | getValueDescriptor() { 128 | return getDescriptor().getValues().get(index); 129 | } 130 | public final com.google.protobuf.Descriptors.EnumDescriptor 131 | getDescriptorForType() { 132 | return getDescriptor(); 133 | } 134 | public static final com.google.protobuf.Descriptors.EnumDescriptor 135 | getDescriptor() { 136 | return doozer.DoozerMsg.Request.getDescriptor().getEnumTypes().get(0); 137 | } 138 | 139 | private static final Verb[] VALUES = { 140 | GET, SET, DEL, REV, WAIT, NOP, WALK, GETDIR, STAT, ACCESS, 141 | }; 142 | 143 | public static Verb valueOf( 144 | com.google.protobuf.Descriptors.EnumValueDescriptor desc) { 145 | if (desc.getType() != getDescriptor()) { 146 | throw new java.lang.IllegalArgumentException( 147 | "EnumValueDescriptor is not for this type."); 148 | } 149 | return VALUES[desc.getIndex()]; 150 | } 151 | 152 | private final int index; 153 | private final int value; 154 | 155 | private Verb(int index, int value) { 156 | this.index = index; 157 | this.value = value; 158 | } 159 | 160 | // @@protoc_insertion_point(enum_scope:doozer.Request.Verb) 161 | } 162 | 163 | private int bitField0_; 164 | // optional int32 tag = 1; 165 | public static final int TAG_FIELD_NUMBER = 1; 166 | private int tag_; 167 | public boolean hasTag() { 168 | return ((bitField0_ & 0x00000001) == 0x00000001); 169 | } 170 | public int getTag() { 171 | return tag_; 172 | } 173 | 174 | // optional .doozer.Request.Verb verb = 2; 175 | public static final int VERB_FIELD_NUMBER = 2; 176 | private doozer.DoozerMsg.Request.Verb verb_; 177 | public boolean hasVerb() { 178 | return ((bitField0_ & 0x00000002) == 0x00000002); 179 | } 180 | public doozer.DoozerMsg.Request.Verb getVerb() { 181 | return verb_; 182 | } 183 | 184 | // optional string path = 4; 185 | public static final int PATH_FIELD_NUMBER = 4; 186 | private Object path_; 187 | public boolean hasPath() { 188 | return ((bitField0_ & 0x00000004) == 0x00000004); 189 | } 190 | public String getPath() { 191 | Object ref = path_; 192 | if (ref instanceof String) { 193 | return (String) ref; 194 | } else { 195 | com.google.protobuf.ByteString bs = 196 | (com.google.protobuf.ByteString) ref; 197 | String s = bs.toStringUtf8(); 198 | if (com.google.protobuf.Internal.isValidUtf8(bs)) { 199 | path_ = s; 200 | } 201 | return s; 202 | } 203 | } 204 | private com.google.protobuf.ByteString getPathBytes() { 205 | Object ref = path_; 206 | if (ref instanceof String) { 207 | com.google.protobuf.ByteString b = 208 | com.google.protobuf.ByteString.copyFromUtf8((String) ref); 209 | path_ = b; 210 | return b; 211 | } else { 212 | return (com.google.protobuf.ByteString) ref; 213 | } 214 | } 215 | 216 | // optional bytes value = 5; 217 | public static final int VALUE_FIELD_NUMBER = 5; 218 | private com.google.protobuf.ByteString value_; 219 | public boolean hasValue() { 220 | return ((bitField0_ & 0x00000008) == 0x00000008); 221 | } 222 | public com.google.protobuf.ByteString getValue() { 223 | return value_; 224 | } 225 | 226 | // optional int32 other_tag = 6; 227 | public static final int OTHER_TAG_FIELD_NUMBER = 6; 228 | private int otherTag_; 229 | public boolean hasOtherTag() { 230 | return ((bitField0_ & 0x00000010) == 0x00000010); 231 | } 232 | public int getOtherTag() { 233 | return otherTag_; 234 | } 235 | 236 | // optional int32 offset = 7; 237 | public static final int OFFSET_FIELD_NUMBER = 7; 238 | private int offset_; 239 | public boolean hasOffset() { 240 | return ((bitField0_ & 0x00000020) == 0x00000020); 241 | } 242 | public int getOffset() { 243 | return offset_; 244 | } 245 | 246 | // optional int64 rev = 9; 247 | public static final int REV_FIELD_NUMBER = 9; 248 | private long rev_; 249 | public boolean hasRev() { 250 | return ((bitField0_ & 0x00000040) == 0x00000040); 251 | } 252 | public long getRev() { 253 | return rev_; 254 | } 255 | 256 | private void initFields() { 257 | tag_ = 0; 258 | verb_ = doozer.DoozerMsg.Request.Verb.GET; 259 | path_ = ""; 260 | value_ = com.google.protobuf.ByteString.EMPTY; 261 | otherTag_ = 0; 262 | offset_ = 0; 263 | rev_ = 0L; 264 | } 265 | private byte memoizedIsInitialized = -1; 266 | public final boolean isInitialized() { 267 | byte isInitialized = memoizedIsInitialized; 268 | if (isInitialized != -1) return isInitialized == 1; 269 | 270 | memoizedIsInitialized = 1; 271 | return true; 272 | } 273 | 274 | public void writeTo(com.google.protobuf.CodedOutputStream output) 275 | throws java.io.IOException { 276 | getSerializedSize(); 277 | if (((bitField0_ & 0x00000001) == 0x00000001)) { 278 | output.writeInt32(1, tag_); 279 | } 280 | if (((bitField0_ & 0x00000002) == 0x00000002)) { 281 | output.writeEnum(2, verb_.getNumber()); 282 | } 283 | if (((bitField0_ & 0x00000004) == 0x00000004)) { 284 | output.writeBytes(4, getPathBytes()); 285 | } 286 | if (((bitField0_ & 0x00000008) == 0x00000008)) { 287 | output.writeBytes(5, value_); 288 | } 289 | if (((bitField0_ & 0x00000010) == 0x00000010)) { 290 | output.writeInt32(6, otherTag_); 291 | } 292 | if (((bitField0_ & 0x00000020) == 0x00000020)) { 293 | output.writeInt32(7, offset_); 294 | } 295 | if (((bitField0_ & 0x00000040) == 0x00000040)) { 296 | output.writeInt64(9, rev_); 297 | } 298 | getUnknownFields().writeTo(output); 299 | } 300 | 301 | private int memoizedSerializedSize = -1; 302 | public int getSerializedSize() { 303 | int size = memoizedSerializedSize; 304 | if (size != -1) return size; 305 | 306 | size = 0; 307 | if (((bitField0_ & 0x00000001) == 0x00000001)) { 308 | size += com.google.protobuf.CodedOutputStream 309 | .computeInt32Size(1, tag_); 310 | } 311 | if (((bitField0_ & 0x00000002) == 0x00000002)) { 312 | size += com.google.protobuf.CodedOutputStream 313 | .computeEnumSize(2, verb_.getNumber()); 314 | } 315 | if (((bitField0_ & 0x00000004) == 0x00000004)) { 316 | size += com.google.protobuf.CodedOutputStream 317 | .computeBytesSize(4, getPathBytes()); 318 | } 319 | if (((bitField0_ & 0x00000008) == 0x00000008)) { 320 | size += com.google.protobuf.CodedOutputStream 321 | .computeBytesSize(5, value_); 322 | } 323 | if (((bitField0_ & 0x00000010) == 0x00000010)) { 324 | size += com.google.protobuf.CodedOutputStream 325 | .computeInt32Size(6, otherTag_); 326 | } 327 | if (((bitField0_ & 0x00000020) == 0x00000020)) { 328 | size += com.google.protobuf.CodedOutputStream 329 | .computeInt32Size(7, offset_); 330 | } 331 | if (((bitField0_ & 0x00000040) == 0x00000040)) { 332 | size += com.google.protobuf.CodedOutputStream 333 | .computeInt64Size(9, rev_); 334 | } 335 | size += getUnknownFields().getSerializedSize(); 336 | memoizedSerializedSize = size; 337 | return size; 338 | } 339 | 340 | @java.lang.Override 341 | protected Object writeReplace() throws java.io.ObjectStreamException { 342 | return super.writeReplace(); 343 | } 344 | 345 | public static doozer.DoozerMsg.Request parseFrom( 346 | com.google.protobuf.ByteString data) 347 | throws com.google.protobuf.InvalidProtocolBufferException { 348 | return newBuilder().mergeFrom(data).buildParsed(); 349 | } 350 | public static doozer.DoozerMsg.Request parseFrom( 351 | com.google.protobuf.ByteString data, 352 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 353 | throws com.google.protobuf.InvalidProtocolBufferException { 354 | return newBuilder().mergeFrom(data, extensionRegistry) 355 | .buildParsed(); 356 | } 357 | public static doozer.DoozerMsg.Request parseFrom(byte[] data) 358 | throws com.google.protobuf.InvalidProtocolBufferException { 359 | return newBuilder().mergeFrom(data).buildParsed(); 360 | } 361 | public static doozer.DoozerMsg.Request parseFrom( 362 | byte[] data, 363 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 364 | throws com.google.protobuf.InvalidProtocolBufferException { 365 | return newBuilder().mergeFrom(data, extensionRegistry) 366 | .buildParsed(); 367 | } 368 | public static doozer.DoozerMsg.Request parseFrom(java.io.InputStream input) 369 | throws java.io.IOException { 370 | return newBuilder().mergeFrom(input).buildParsed(); 371 | } 372 | public static doozer.DoozerMsg.Request parseFrom( 373 | java.io.InputStream input, 374 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 375 | throws java.io.IOException { 376 | return newBuilder().mergeFrom(input, extensionRegistry) 377 | .buildParsed(); 378 | } 379 | public static doozer.DoozerMsg.Request parseDelimitedFrom(java.io.InputStream input) 380 | throws java.io.IOException { 381 | Builder builder = newBuilder(); 382 | if (builder.mergeDelimitedFrom(input)) { 383 | return builder.buildParsed(); 384 | } else { 385 | return null; 386 | } 387 | } 388 | public static doozer.DoozerMsg.Request parseDelimitedFrom( 389 | java.io.InputStream input, 390 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 391 | throws java.io.IOException { 392 | Builder builder = newBuilder(); 393 | if (builder.mergeDelimitedFrom(input, extensionRegistry)) { 394 | return builder.buildParsed(); 395 | } else { 396 | return null; 397 | } 398 | } 399 | public static doozer.DoozerMsg.Request parseFrom( 400 | com.google.protobuf.CodedInputStream input) 401 | throws java.io.IOException { 402 | return newBuilder().mergeFrom(input).buildParsed(); 403 | } 404 | public static doozer.DoozerMsg.Request parseFrom( 405 | com.google.protobuf.CodedInputStream input, 406 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 407 | throws java.io.IOException { 408 | return newBuilder().mergeFrom(input, extensionRegistry) 409 | .buildParsed(); 410 | } 411 | 412 | public static Builder newBuilder() { return Builder.create(); } 413 | public Builder newBuilderForType() { return newBuilder(); } 414 | public static Builder newBuilder(doozer.DoozerMsg.Request prototype) { 415 | return newBuilder().mergeFrom(prototype); 416 | } 417 | public Builder toBuilder() { return newBuilder(this); } 418 | 419 | @java.lang.Override 420 | protected Builder newBuilderForType( 421 | com.google.protobuf.GeneratedMessage.BuilderParent parent) { 422 | Builder builder = new Builder(parent); 423 | return builder; 424 | } 425 | public static final class Builder extends 426 | com.google.protobuf.GeneratedMessage.Builder 427 | implements doozer.DoozerMsg.RequestOrBuilder { 428 | public static final com.google.protobuf.Descriptors.Descriptor 429 | getDescriptor() { 430 | return doozer.DoozerMsg.internal_static_doozer_Request_descriptor; 431 | } 432 | 433 | protected com.google.protobuf.GeneratedMessage.FieldAccessorTable 434 | internalGetFieldAccessorTable() { 435 | return doozer.DoozerMsg.internal_static_doozer_Request_fieldAccessorTable; 436 | } 437 | 438 | // Construct using doozer.DoozerMsg.Request.newBuilder() 439 | private Builder() { 440 | maybeForceBuilderInitialization(); 441 | } 442 | 443 | private Builder(BuilderParent parent) { 444 | super(parent); 445 | maybeForceBuilderInitialization(); 446 | } 447 | private void maybeForceBuilderInitialization() { 448 | if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { 449 | } 450 | } 451 | private static Builder create() { 452 | return new Builder(); 453 | } 454 | 455 | public Builder clear() { 456 | super.clear(); 457 | tag_ = 0; 458 | bitField0_ = (bitField0_ & ~0x00000001); 459 | verb_ = doozer.DoozerMsg.Request.Verb.GET; 460 | bitField0_ = (bitField0_ & ~0x00000002); 461 | path_ = ""; 462 | bitField0_ = (bitField0_ & ~0x00000004); 463 | value_ = com.google.protobuf.ByteString.EMPTY; 464 | bitField0_ = (bitField0_ & ~0x00000008); 465 | otherTag_ = 0; 466 | bitField0_ = (bitField0_ & ~0x00000010); 467 | offset_ = 0; 468 | bitField0_ = (bitField0_ & ~0x00000020); 469 | rev_ = 0L; 470 | bitField0_ = (bitField0_ & ~0x00000040); 471 | return this; 472 | } 473 | 474 | public Builder clone() { 475 | return create().mergeFrom(buildPartial()); 476 | } 477 | 478 | public com.google.protobuf.Descriptors.Descriptor 479 | getDescriptorForType() { 480 | return doozer.DoozerMsg.Request.getDescriptor(); 481 | } 482 | 483 | public doozer.DoozerMsg.Request getDefaultInstanceForType() { 484 | return doozer.DoozerMsg.Request.getDefaultInstance(); 485 | } 486 | 487 | public doozer.DoozerMsg.Request build() { 488 | doozer.DoozerMsg.Request result = buildPartial(); 489 | if (!result.isInitialized()) { 490 | throw newUninitializedMessageException(result); 491 | } 492 | return result; 493 | } 494 | 495 | private doozer.DoozerMsg.Request buildParsed() 496 | throws com.google.protobuf.InvalidProtocolBufferException { 497 | doozer.DoozerMsg.Request result = buildPartial(); 498 | if (!result.isInitialized()) { 499 | throw newUninitializedMessageException( 500 | result).asInvalidProtocolBufferException(); 501 | } 502 | return result; 503 | } 504 | 505 | public doozer.DoozerMsg.Request buildPartial() { 506 | doozer.DoozerMsg.Request result = new doozer.DoozerMsg.Request(this); 507 | int from_bitField0_ = bitField0_; 508 | int to_bitField0_ = 0; 509 | if (((from_bitField0_ & 0x00000001) == 0x00000001)) { 510 | to_bitField0_ |= 0x00000001; 511 | } 512 | result.tag_ = tag_; 513 | if (((from_bitField0_ & 0x00000002) == 0x00000002)) { 514 | to_bitField0_ |= 0x00000002; 515 | } 516 | result.verb_ = verb_; 517 | if (((from_bitField0_ & 0x00000004) == 0x00000004)) { 518 | to_bitField0_ |= 0x00000004; 519 | } 520 | result.path_ = path_; 521 | if (((from_bitField0_ & 0x00000008) == 0x00000008)) { 522 | to_bitField0_ |= 0x00000008; 523 | } 524 | result.value_ = value_; 525 | if (((from_bitField0_ & 0x00000010) == 0x00000010)) { 526 | to_bitField0_ |= 0x00000010; 527 | } 528 | result.otherTag_ = otherTag_; 529 | if (((from_bitField0_ & 0x00000020) == 0x00000020)) { 530 | to_bitField0_ |= 0x00000020; 531 | } 532 | result.offset_ = offset_; 533 | if (((from_bitField0_ & 0x00000040) == 0x00000040)) { 534 | to_bitField0_ |= 0x00000040; 535 | } 536 | result.rev_ = rev_; 537 | result.bitField0_ = to_bitField0_; 538 | onBuilt(); 539 | return result; 540 | } 541 | 542 | public Builder mergeFrom(com.google.protobuf.Message other) { 543 | if (other instanceof doozer.DoozerMsg.Request) { 544 | return mergeFrom((doozer.DoozerMsg.Request)other); 545 | } else { 546 | super.mergeFrom(other); 547 | return this; 548 | } 549 | } 550 | 551 | public Builder mergeFrom(doozer.DoozerMsg.Request other) { 552 | if (other == doozer.DoozerMsg.Request.getDefaultInstance()) return this; 553 | if (other.hasTag()) { 554 | setTag(other.getTag()); 555 | } 556 | if (other.hasVerb()) { 557 | setVerb(other.getVerb()); 558 | } 559 | if (other.hasPath()) { 560 | setPath(other.getPath()); 561 | } 562 | if (other.hasValue()) { 563 | setValue(other.getValue()); 564 | } 565 | if (other.hasOtherTag()) { 566 | setOtherTag(other.getOtherTag()); 567 | } 568 | if (other.hasOffset()) { 569 | setOffset(other.getOffset()); 570 | } 571 | if (other.hasRev()) { 572 | setRev(other.getRev()); 573 | } 574 | this.mergeUnknownFields(other.getUnknownFields()); 575 | return this; 576 | } 577 | 578 | public final boolean isInitialized() { 579 | return true; 580 | } 581 | 582 | public Builder mergeFrom( 583 | com.google.protobuf.CodedInputStream input, 584 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 585 | throws java.io.IOException { 586 | com.google.protobuf.UnknownFieldSet.Builder unknownFields = 587 | com.google.protobuf.UnknownFieldSet.newBuilder( 588 | this.getUnknownFields()); 589 | while (true) { 590 | int tag = input.readTag(); 591 | switch (tag) { 592 | case 0: 593 | this.setUnknownFields(unknownFields.build()); 594 | onChanged(); 595 | return this; 596 | default: { 597 | if (!parseUnknownField(input, unknownFields, 598 | extensionRegistry, tag)) { 599 | this.setUnknownFields(unknownFields.build()); 600 | onChanged(); 601 | return this; 602 | } 603 | break; 604 | } 605 | case 8: { 606 | bitField0_ |= 0x00000001; 607 | tag_ = input.readInt32(); 608 | break; 609 | } 610 | case 16: { 611 | int rawValue = input.readEnum(); 612 | doozer.DoozerMsg.Request.Verb value = doozer.DoozerMsg.Request.Verb.valueOf(rawValue); 613 | if (value == null) { 614 | unknownFields.mergeVarintField(2, rawValue); 615 | } else { 616 | bitField0_ |= 0x00000002; 617 | verb_ = value; 618 | } 619 | break; 620 | } 621 | case 34: { 622 | bitField0_ |= 0x00000004; 623 | path_ = input.readBytes(); 624 | break; 625 | } 626 | case 42: { 627 | bitField0_ |= 0x00000008; 628 | value_ = input.readBytes(); 629 | break; 630 | } 631 | case 48: { 632 | bitField0_ |= 0x00000010; 633 | otherTag_ = input.readInt32(); 634 | break; 635 | } 636 | case 56: { 637 | bitField0_ |= 0x00000020; 638 | offset_ = input.readInt32(); 639 | break; 640 | } 641 | case 72: { 642 | bitField0_ |= 0x00000040; 643 | rev_ = input.readInt64(); 644 | break; 645 | } 646 | } 647 | } 648 | } 649 | 650 | private int bitField0_; 651 | 652 | // optional int32 tag = 1; 653 | private int tag_ ; 654 | public boolean hasTag() { 655 | return ((bitField0_ & 0x00000001) == 0x00000001); 656 | } 657 | public int getTag() { 658 | return tag_; 659 | } 660 | public Builder setTag(int value) { 661 | bitField0_ |= 0x00000001; 662 | tag_ = value; 663 | onChanged(); 664 | return this; 665 | } 666 | public Builder clearTag() { 667 | bitField0_ = (bitField0_ & ~0x00000001); 668 | tag_ = 0; 669 | onChanged(); 670 | return this; 671 | } 672 | 673 | // optional .doozer.Request.Verb verb = 2; 674 | private doozer.DoozerMsg.Request.Verb verb_ = doozer.DoozerMsg.Request.Verb.GET; 675 | public boolean hasVerb() { 676 | return ((bitField0_ & 0x00000002) == 0x00000002); 677 | } 678 | public doozer.DoozerMsg.Request.Verb getVerb() { 679 | return verb_; 680 | } 681 | public Builder setVerb(doozer.DoozerMsg.Request.Verb value) { 682 | if (value == null) { 683 | throw new NullPointerException(); 684 | } 685 | bitField0_ |= 0x00000002; 686 | verb_ = value; 687 | onChanged(); 688 | return this; 689 | } 690 | public Builder clearVerb() { 691 | bitField0_ = (bitField0_ & ~0x00000002); 692 | verb_ = doozer.DoozerMsg.Request.Verb.GET; 693 | onChanged(); 694 | return this; 695 | } 696 | 697 | // optional string path = 4; 698 | private Object path_ = ""; 699 | public boolean hasPath() { 700 | return ((bitField0_ & 0x00000004) == 0x00000004); 701 | } 702 | public String getPath() { 703 | Object ref = path_; 704 | if (!(ref instanceof String)) { 705 | String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); 706 | path_ = s; 707 | return s; 708 | } else { 709 | return (String) ref; 710 | } 711 | } 712 | public Builder setPath(String value) { 713 | if (value == null) { 714 | throw new NullPointerException(); 715 | } 716 | bitField0_ |= 0x00000004; 717 | path_ = value; 718 | onChanged(); 719 | return this; 720 | } 721 | public Builder clearPath() { 722 | bitField0_ = (bitField0_ & ~0x00000004); 723 | path_ = getDefaultInstance().getPath(); 724 | onChanged(); 725 | return this; 726 | } 727 | void setPath(com.google.protobuf.ByteString value) { 728 | bitField0_ |= 0x00000004; 729 | path_ = value; 730 | onChanged(); 731 | } 732 | 733 | // optional bytes value = 5; 734 | private com.google.protobuf.ByteString value_ = com.google.protobuf.ByteString.EMPTY; 735 | public boolean hasValue() { 736 | return ((bitField0_ & 0x00000008) == 0x00000008); 737 | } 738 | public com.google.protobuf.ByteString getValue() { 739 | return value_; 740 | } 741 | public Builder setValue(com.google.protobuf.ByteString value) { 742 | if (value == null) { 743 | throw new NullPointerException(); 744 | } 745 | bitField0_ |= 0x00000008; 746 | value_ = value; 747 | onChanged(); 748 | return this; 749 | } 750 | public Builder clearValue() { 751 | bitField0_ = (bitField0_ & ~0x00000008); 752 | value_ = getDefaultInstance().getValue(); 753 | onChanged(); 754 | return this; 755 | } 756 | 757 | // optional int32 other_tag = 6; 758 | private int otherTag_ ; 759 | public boolean hasOtherTag() { 760 | return ((bitField0_ & 0x00000010) == 0x00000010); 761 | } 762 | public int getOtherTag() { 763 | return otherTag_; 764 | } 765 | public Builder setOtherTag(int value) { 766 | bitField0_ |= 0x00000010; 767 | otherTag_ = value; 768 | onChanged(); 769 | return this; 770 | } 771 | public Builder clearOtherTag() { 772 | bitField0_ = (bitField0_ & ~0x00000010); 773 | otherTag_ = 0; 774 | onChanged(); 775 | return this; 776 | } 777 | 778 | // optional int32 offset = 7; 779 | private int offset_ ; 780 | public boolean hasOffset() { 781 | return ((bitField0_ & 0x00000020) == 0x00000020); 782 | } 783 | public int getOffset() { 784 | return offset_; 785 | } 786 | public Builder setOffset(int value) { 787 | bitField0_ |= 0x00000020; 788 | offset_ = value; 789 | onChanged(); 790 | return this; 791 | } 792 | public Builder clearOffset() { 793 | bitField0_ = (bitField0_ & ~0x00000020); 794 | offset_ = 0; 795 | onChanged(); 796 | return this; 797 | } 798 | 799 | // optional int64 rev = 9; 800 | private long rev_ ; 801 | public boolean hasRev() { 802 | return ((bitField0_ & 0x00000040) == 0x00000040); 803 | } 804 | public long getRev() { 805 | return rev_; 806 | } 807 | public Builder setRev(long value) { 808 | bitField0_ |= 0x00000040; 809 | rev_ = value; 810 | onChanged(); 811 | return this; 812 | } 813 | public Builder clearRev() { 814 | bitField0_ = (bitField0_ & ~0x00000040); 815 | rev_ = 0L; 816 | onChanged(); 817 | return this; 818 | } 819 | 820 | // @@protoc_insertion_point(builder_scope:doozer.Request) 821 | } 822 | 823 | static { 824 | defaultInstance = new Request(true); 825 | defaultInstance.initFields(); 826 | } 827 | 828 | // @@protoc_insertion_point(class_scope:doozer.Request) 829 | } 830 | 831 | public interface ResponseOrBuilder 832 | extends com.google.protobuf.MessageOrBuilder { 833 | 834 | // optional int32 tag = 1; 835 | boolean hasTag(); 836 | int getTag(); 837 | 838 | // optional int32 flags = 2; 839 | boolean hasFlags(); 840 | int getFlags(); 841 | 842 | // optional int64 rev = 3; 843 | boolean hasRev(); 844 | long getRev(); 845 | 846 | // optional string path = 5; 847 | boolean hasPath(); 848 | String getPath(); 849 | 850 | // optional bytes value = 6; 851 | boolean hasValue(); 852 | com.google.protobuf.ByteString getValue(); 853 | 854 | // optional int32 len = 8; 855 | boolean hasLen(); 856 | int getLen(); 857 | 858 | // optional .doozer.Response.Err err_code = 100; 859 | boolean hasErrCode(); 860 | doozer.DoozerMsg.Response.Err getErrCode(); 861 | 862 | // optional string err_detail = 101; 863 | boolean hasErrDetail(); 864 | String getErrDetail(); 865 | } 866 | public static final class Response extends 867 | com.google.protobuf.GeneratedMessage 868 | implements ResponseOrBuilder { 869 | // Use Response.newBuilder() to construct. 870 | private Response(Builder builder) { 871 | super(builder); 872 | } 873 | private Response(boolean noInit) {} 874 | 875 | private static final Response defaultInstance; 876 | public static Response getDefaultInstance() { 877 | return defaultInstance; 878 | } 879 | 880 | public Response getDefaultInstanceForType() { 881 | return defaultInstance; 882 | } 883 | 884 | public static final com.google.protobuf.Descriptors.Descriptor 885 | getDescriptor() { 886 | return doozer.DoozerMsg.internal_static_doozer_Response_descriptor; 887 | } 888 | 889 | protected com.google.protobuf.GeneratedMessage.FieldAccessorTable 890 | internalGetFieldAccessorTable() { 891 | return doozer.DoozerMsg.internal_static_doozer_Response_fieldAccessorTable; 892 | } 893 | 894 | public enum Err 895 | implements com.google.protobuf.ProtocolMessageEnum { 896 | OTHER(0, 127), 897 | TAG_IN_USE(1, 1), 898 | UNKNOWN_VERB(2, 2), 899 | READONLY(3, 3), 900 | TOO_LATE(4, 4), 901 | REV_MISMATCH(5, 5), 902 | BAD_PATH(6, 6), 903 | MISSING_ARG(7, 7), 904 | RANGE(8, 8), 905 | NOTDIR(9, 20), 906 | ISDIR(10, 21), 907 | NOENT(11, 22), 908 | ; 909 | 910 | public static final int OTHER_VALUE = 127; 911 | public static final int TAG_IN_USE_VALUE = 1; 912 | public static final int UNKNOWN_VERB_VALUE = 2; 913 | public static final int READONLY_VALUE = 3; 914 | public static final int TOO_LATE_VALUE = 4; 915 | public static final int REV_MISMATCH_VALUE = 5; 916 | public static final int BAD_PATH_VALUE = 6; 917 | public static final int MISSING_ARG_VALUE = 7; 918 | public static final int RANGE_VALUE = 8; 919 | public static final int NOTDIR_VALUE = 20; 920 | public static final int ISDIR_VALUE = 21; 921 | public static final int NOENT_VALUE = 22; 922 | 923 | 924 | public final int getNumber() { return value; } 925 | 926 | public static Err valueOf(int value) { 927 | switch (value) { 928 | case 127: return OTHER; 929 | case 1: return TAG_IN_USE; 930 | case 2: return UNKNOWN_VERB; 931 | case 3: return READONLY; 932 | case 4: return TOO_LATE; 933 | case 5: return REV_MISMATCH; 934 | case 6: return BAD_PATH; 935 | case 7: return MISSING_ARG; 936 | case 8: return RANGE; 937 | case 20: return NOTDIR; 938 | case 21: return ISDIR; 939 | case 22: return NOENT; 940 | default: return null; 941 | } 942 | } 943 | 944 | public static com.google.protobuf.Internal.EnumLiteMap 945 | internalGetValueMap() { 946 | return internalValueMap; 947 | } 948 | private static com.google.protobuf.Internal.EnumLiteMap 949 | internalValueMap = 950 | new com.google.protobuf.Internal.EnumLiteMap() { 951 | public Err findValueByNumber(int number) { 952 | return Err.valueOf(number); 953 | } 954 | }; 955 | 956 | public final com.google.protobuf.Descriptors.EnumValueDescriptor 957 | getValueDescriptor() { 958 | return getDescriptor().getValues().get(index); 959 | } 960 | public final com.google.protobuf.Descriptors.EnumDescriptor 961 | getDescriptorForType() { 962 | return getDescriptor(); 963 | } 964 | public static final com.google.protobuf.Descriptors.EnumDescriptor 965 | getDescriptor() { 966 | return doozer.DoozerMsg.Response.getDescriptor().getEnumTypes().get(0); 967 | } 968 | 969 | private static final Err[] VALUES = { 970 | OTHER, TAG_IN_USE, UNKNOWN_VERB, READONLY, TOO_LATE, REV_MISMATCH, BAD_PATH, MISSING_ARG, RANGE, NOTDIR, ISDIR, NOENT, 971 | }; 972 | 973 | public static Err valueOf( 974 | com.google.protobuf.Descriptors.EnumValueDescriptor desc) { 975 | if (desc.getType() != getDescriptor()) { 976 | throw new java.lang.IllegalArgumentException( 977 | "EnumValueDescriptor is not for this type."); 978 | } 979 | return VALUES[desc.getIndex()]; 980 | } 981 | 982 | private final int index; 983 | private final int value; 984 | 985 | private Err(int index, int value) { 986 | this.index = index; 987 | this.value = value; 988 | } 989 | 990 | // @@protoc_insertion_point(enum_scope:doozer.Response.Err) 991 | } 992 | 993 | private int bitField0_; 994 | // optional int32 tag = 1; 995 | public static final int TAG_FIELD_NUMBER = 1; 996 | private int tag_; 997 | public boolean hasTag() { 998 | return ((bitField0_ & 0x00000001) == 0x00000001); 999 | } 1000 | public int getTag() { 1001 | return tag_; 1002 | } 1003 | 1004 | // optional int32 flags = 2; 1005 | public static final int FLAGS_FIELD_NUMBER = 2; 1006 | private int flags_; 1007 | public boolean hasFlags() { 1008 | return ((bitField0_ & 0x00000002) == 0x00000002); 1009 | } 1010 | public int getFlags() { 1011 | return flags_; 1012 | } 1013 | 1014 | // optional int64 rev = 3; 1015 | public static final int REV_FIELD_NUMBER = 3; 1016 | private long rev_; 1017 | public boolean hasRev() { 1018 | return ((bitField0_ & 0x00000004) == 0x00000004); 1019 | } 1020 | public long getRev() { 1021 | return rev_; 1022 | } 1023 | 1024 | // optional string path = 5; 1025 | public static final int PATH_FIELD_NUMBER = 5; 1026 | private Object path_; 1027 | public boolean hasPath() { 1028 | return ((bitField0_ & 0x00000008) == 0x00000008); 1029 | } 1030 | public String getPath() { 1031 | Object ref = path_; 1032 | if (ref instanceof String) { 1033 | return (String) ref; 1034 | } else { 1035 | com.google.protobuf.ByteString bs = 1036 | (com.google.protobuf.ByteString) ref; 1037 | String s = bs.toStringUtf8(); 1038 | if (com.google.protobuf.Internal.isValidUtf8(bs)) { 1039 | path_ = s; 1040 | } 1041 | return s; 1042 | } 1043 | } 1044 | private com.google.protobuf.ByteString getPathBytes() { 1045 | Object ref = path_; 1046 | if (ref instanceof String) { 1047 | com.google.protobuf.ByteString b = 1048 | com.google.protobuf.ByteString.copyFromUtf8((String) ref); 1049 | path_ = b; 1050 | return b; 1051 | } else { 1052 | return (com.google.protobuf.ByteString) ref; 1053 | } 1054 | } 1055 | 1056 | // optional bytes value = 6; 1057 | public static final int VALUE_FIELD_NUMBER = 6; 1058 | private com.google.protobuf.ByteString value_; 1059 | public boolean hasValue() { 1060 | return ((bitField0_ & 0x00000010) == 0x00000010); 1061 | } 1062 | public com.google.protobuf.ByteString getValue() { 1063 | return value_; 1064 | } 1065 | 1066 | // optional int32 len = 8; 1067 | public static final int LEN_FIELD_NUMBER = 8; 1068 | private int len_; 1069 | public boolean hasLen() { 1070 | return ((bitField0_ & 0x00000020) == 0x00000020); 1071 | } 1072 | public int getLen() { 1073 | return len_; 1074 | } 1075 | 1076 | // optional .doozer.Response.Err err_code = 100; 1077 | public static final int ERR_CODE_FIELD_NUMBER = 100; 1078 | private doozer.DoozerMsg.Response.Err errCode_; 1079 | public boolean hasErrCode() { 1080 | return ((bitField0_ & 0x00000040) == 0x00000040); 1081 | } 1082 | public doozer.DoozerMsg.Response.Err getErrCode() { 1083 | return errCode_; 1084 | } 1085 | 1086 | // optional string err_detail = 101; 1087 | public static final int ERR_DETAIL_FIELD_NUMBER = 101; 1088 | private Object errDetail_; 1089 | public boolean hasErrDetail() { 1090 | return ((bitField0_ & 0x00000080) == 0x00000080); 1091 | } 1092 | public String getErrDetail() { 1093 | Object ref = errDetail_; 1094 | if (ref instanceof String) { 1095 | return (String) ref; 1096 | } else { 1097 | com.google.protobuf.ByteString bs = 1098 | (com.google.protobuf.ByteString) ref; 1099 | String s = bs.toStringUtf8(); 1100 | if (com.google.protobuf.Internal.isValidUtf8(bs)) { 1101 | errDetail_ = s; 1102 | } 1103 | return s; 1104 | } 1105 | } 1106 | private com.google.protobuf.ByteString getErrDetailBytes() { 1107 | Object ref = errDetail_; 1108 | if (ref instanceof String) { 1109 | com.google.protobuf.ByteString b = 1110 | com.google.protobuf.ByteString.copyFromUtf8((String) ref); 1111 | errDetail_ = b; 1112 | return b; 1113 | } else { 1114 | return (com.google.protobuf.ByteString) ref; 1115 | } 1116 | } 1117 | 1118 | private void initFields() { 1119 | tag_ = 0; 1120 | flags_ = 0; 1121 | rev_ = 0L; 1122 | path_ = ""; 1123 | value_ = com.google.protobuf.ByteString.EMPTY; 1124 | len_ = 0; 1125 | errCode_ = doozer.DoozerMsg.Response.Err.OTHER; 1126 | errDetail_ = ""; 1127 | } 1128 | private byte memoizedIsInitialized = -1; 1129 | public final boolean isInitialized() { 1130 | byte isInitialized = memoizedIsInitialized; 1131 | if (isInitialized != -1) return isInitialized == 1; 1132 | 1133 | memoizedIsInitialized = 1; 1134 | return true; 1135 | } 1136 | 1137 | public void writeTo(com.google.protobuf.CodedOutputStream output) 1138 | throws java.io.IOException { 1139 | getSerializedSize(); 1140 | if (((bitField0_ & 0x00000001) == 0x00000001)) { 1141 | output.writeInt32(1, tag_); 1142 | } 1143 | if (((bitField0_ & 0x00000002) == 0x00000002)) { 1144 | output.writeInt32(2, flags_); 1145 | } 1146 | if (((bitField0_ & 0x00000004) == 0x00000004)) { 1147 | output.writeInt64(3, rev_); 1148 | } 1149 | if (((bitField0_ & 0x00000008) == 0x00000008)) { 1150 | output.writeBytes(5, getPathBytes()); 1151 | } 1152 | if (((bitField0_ & 0x00000010) == 0x00000010)) { 1153 | output.writeBytes(6, value_); 1154 | } 1155 | if (((bitField0_ & 0x00000020) == 0x00000020)) { 1156 | output.writeInt32(8, len_); 1157 | } 1158 | if (((bitField0_ & 0x00000040) == 0x00000040)) { 1159 | output.writeEnum(100, errCode_.getNumber()); 1160 | } 1161 | if (((bitField0_ & 0x00000080) == 0x00000080)) { 1162 | output.writeBytes(101, getErrDetailBytes()); 1163 | } 1164 | getUnknownFields().writeTo(output); 1165 | } 1166 | 1167 | private int memoizedSerializedSize = -1; 1168 | public int getSerializedSize() { 1169 | int size = memoizedSerializedSize; 1170 | if (size != -1) return size; 1171 | 1172 | size = 0; 1173 | if (((bitField0_ & 0x00000001) == 0x00000001)) { 1174 | size += com.google.protobuf.CodedOutputStream 1175 | .computeInt32Size(1, tag_); 1176 | } 1177 | if (((bitField0_ & 0x00000002) == 0x00000002)) { 1178 | size += com.google.protobuf.CodedOutputStream 1179 | .computeInt32Size(2, flags_); 1180 | } 1181 | if (((bitField0_ & 0x00000004) == 0x00000004)) { 1182 | size += com.google.protobuf.CodedOutputStream 1183 | .computeInt64Size(3, rev_); 1184 | } 1185 | if (((bitField0_ & 0x00000008) == 0x00000008)) { 1186 | size += com.google.protobuf.CodedOutputStream 1187 | .computeBytesSize(5, getPathBytes()); 1188 | } 1189 | if (((bitField0_ & 0x00000010) == 0x00000010)) { 1190 | size += com.google.protobuf.CodedOutputStream 1191 | .computeBytesSize(6, value_); 1192 | } 1193 | if (((bitField0_ & 0x00000020) == 0x00000020)) { 1194 | size += com.google.protobuf.CodedOutputStream 1195 | .computeInt32Size(8, len_); 1196 | } 1197 | if (((bitField0_ & 0x00000040) == 0x00000040)) { 1198 | size += com.google.protobuf.CodedOutputStream 1199 | .computeEnumSize(100, errCode_.getNumber()); 1200 | } 1201 | if (((bitField0_ & 0x00000080) == 0x00000080)) { 1202 | size += com.google.protobuf.CodedOutputStream 1203 | .computeBytesSize(101, getErrDetailBytes()); 1204 | } 1205 | size += getUnknownFields().getSerializedSize(); 1206 | memoizedSerializedSize = size; 1207 | return size; 1208 | } 1209 | 1210 | @java.lang.Override 1211 | protected Object writeReplace() throws java.io.ObjectStreamException { 1212 | return super.writeReplace(); 1213 | } 1214 | 1215 | public static doozer.DoozerMsg.Response parseFrom( 1216 | com.google.protobuf.ByteString data) 1217 | throws com.google.protobuf.InvalidProtocolBufferException { 1218 | return newBuilder().mergeFrom(data).buildParsed(); 1219 | } 1220 | public static doozer.DoozerMsg.Response parseFrom( 1221 | com.google.protobuf.ByteString data, 1222 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 1223 | throws com.google.protobuf.InvalidProtocolBufferException { 1224 | return newBuilder().mergeFrom(data, extensionRegistry) 1225 | .buildParsed(); 1226 | } 1227 | public static doozer.DoozerMsg.Response parseFrom(byte[] data) 1228 | throws com.google.protobuf.InvalidProtocolBufferException { 1229 | return newBuilder().mergeFrom(data).buildParsed(); 1230 | } 1231 | public static doozer.DoozerMsg.Response parseFrom( 1232 | byte[] data, 1233 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 1234 | throws com.google.protobuf.InvalidProtocolBufferException { 1235 | return newBuilder().mergeFrom(data, extensionRegistry) 1236 | .buildParsed(); 1237 | } 1238 | public static doozer.DoozerMsg.Response parseFrom(java.io.InputStream input) 1239 | throws java.io.IOException { 1240 | return newBuilder().mergeFrom(input).buildParsed(); 1241 | } 1242 | public static doozer.DoozerMsg.Response parseFrom( 1243 | java.io.InputStream input, 1244 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 1245 | throws java.io.IOException { 1246 | return newBuilder().mergeFrom(input, extensionRegistry) 1247 | .buildParsed(); 1248 | } 1249 | public static doozer.DoozerMsg.Response parseDelimitedFrom(java.io.InputStream input) 1250 | throws java.io.IOException { 1251 | Builder builder = newBuilder(); 1252 | if (builder.mergeDelimitedFrom(input)) { 1253 | return builder.buildParsed(); 1254 | } else { 1255 | return null; 1256 | } 1257 | } 1258 | public static doozer.DoozerMsg.Response parseDelimitedFrom( 1259 | java.io.InputStream input, 1260 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 1261 | throws java.io.IOException { 1262 | Builder builder = newBuilder(); 1263 | if (builder.mergeDelimitedFrom(input, extensionRegistry)) { 1264 | return builder.buildParsed(); 1265 | } else { 1266 | return null; 1267 | } 1268 | } 1269 | public static doozer.DoozerMsg.Response parseFrom( 1270 | com.google.protobuf.CodedInputStream input) 1271 | throws java.io.IOException { 1272 | return newBuilder().mergeFrom(input).buildParsed(); 1273 | } 1274 | public static doozer.DoozerMsg.Response parseFrom( 1275 | com.google.protobuf.CodedInputStream input, 1276 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 1277 | throws java.io.IOException { 1278 | return newBuilder().mergeFrom(input, extensionRegistry) 1279 | .buildParsed(); 1280 | } 1281 | 1282 | public static Builder newBuilder() { return Builder.create(); } 1283 | public Builder newBuilderForType() { return newBuilder(); } 1284 | public static Builder newBuilder(doozer.DoozerMsg.Response prototype) { 1285 | return newBuilder().mergeFrom(prototype); 1286 | } 1287 | public Builder toBuilder() { return newBuilder(this); } 1288 | 1289 | @java.lang.Override 1290 | protected Builder newBuilderForType( 1291 | com.google.protobuf.GeneratedMessage.BuilderParent parent) { 1292 | Builder builder = new Builder(parent); 1293 | return builder; 1294 | } 1295 | public static final class Builder extends 1296 | com.google.protobuf.GeneratedMessage.Builder 1297 | implements doozer.DoozerMsg.ResponseOrBuilder { 1298 | public static final com.google.protobuf.Descriptors.Descriptor 1299 | getDescriptor() { 1300 | return doozer.DoozerMsg.internal_static_doozer_Response_descriptor; 1301 | } 1302 | 1303 | protected com.google.protobuf.GeneratedMessage.FieldAccessorTable 1304 | internalGetFieldAccessorTable() { 1305 | return doozer.DoozerMsg.internal_static_doozer_Response_fieldAccessorTable; 1306 | } 1307 | 1308 | // Construct using doozer.DoozerMsg.Response.newBuilder() 1309 | private Builder() { 1310 | maybeForceBuilderInitialization(); 1311 | } 1312 | 1313 | private Builder(BuilderParent parent) { 1314 | super(parent); 1315 | maybeForceBuilderInitialization(); 1316 | } 1317 | private void maybeForceBuilderInitialization() { 1318 | if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { 1319 | } 1320 | } 1321 | private static Builder create() { 1322 | return new Builder(); 1323 | } 1324 | 1325 | public Builder clear() { 1326 | super.clear(); 1327 | tag_ = 0; 1328 | bitField0_ = (bitField0_ & ~0x00000001); 1329 | flags_ = 0; 1330 | bitField0_ = (bitField0_ & ~0x00000002); 1331 | rev_ = 0L; 1332 | bitField0_ = (bitField0_ & ~0x00000004); 1333 | path_ = ""; 1334 | bitField0_ = (bitField0_ & ~0x00000008); 1335 | value_ = com.google.protobuf.ByteString.EMPTY; 1336 | bitField0_ = (bitField0_ & ~0x00000010); 1337 | len_ = 0; 1338 | bitField0_ = (bitField0_ & ~0x00000020); 1339 | errCode_ = doozer.DoozerMsg.Response.Err.OTHER; 1340 | bitField0_ = (bitField0_ & ~0x00000040); 1341 | errDetail_ = ""; 1342 | bitField0_ = (bitField0_ & ~0x00000080); 1343 | return this; 1344 | } 1345 | 1346 | public Builder clone() { 1347 | return create().mergeFrom(buildPartial()); 1348 | } 1349 | 1350 | public com.google.protobuf.Descriptors.Descriptor 1351 | getDescriptorForType() { 1352 | return doozer.DoozerMsg.Response.getDescriptor(); 1353 | } 1354 | 1355 | public doozer.DoozerMsg.Response getDefaultInstanceForType() { 1356 | return doozer.DoozerMsg.Response.getDefaultInstance(); 1357 | } 1358 | 1359 | public doozer.DoozerMsg.Response build() { 1360 | doozer.DoozerMsg.Response result = buildPartial(); 1361 | if (!result.isInitialized()) { 1362 | throw newUninitializedMessageException(result); 1363 | } 1364 | return result; 1365 | } 1366 | 1367 | private doozer.DoozerMsg.Response buildParsed() 1368 | throws com.google.protobuf.InvalidProtocolBufferException { 1369 | doozer.DoozerMsg.Response result = buildPartial(); 1370 | if (!result.isInitialized()) { 1371 | throw newUninitializedMessageException( 1372 | result).asInvalidProtocolBufferException(); 1373 | } 1374 | return result; 1375 | } 1376 | 1377 | public doozer.DoozerMsg.Response buildPartial() { 1378 | doozer.DoozerMsg.Response result = new doozer.DoozerMsg.Response(this); 1379 | int from_bitField0_ = bitField0_; 1380 | int to_bitField0_ = 0; 1381 | if (((from_bitField0_ & 0x00000001) == 0x00000001)) { 1382 | to_bitField0_ |= 0x00000001; 1383 | } 1384 | result.tag_ = tag_; 1385 | if (((from_bitField0_ & 0x00000002) == 0x00000002)) { 1386 | to_bitField0_ |= 0x00000002; 1387 | } 1388 | result.flags_ = flags_; 1389 | if (((from_bitField0_ & 0x00000004) == 0x00000004)) { 1390 | to_bitField0_ |= 0x00000004; 1391 | } 1392 | result.rev_ = rev_; 1393 | if (((from_bitField0_ & 0x00000008) == 0x00000008)) { 1394 | to_bitField0_ |= 0x00000008; 1395 | } 1396 | result.path_ = path_; 1397 | if (((from_bitField0_ & 0x00000010) == 0x00000010)) { 1398 | to_bitField0_ |= 0x00000010; 1399 | } 1400 | result.value_ = value_; 1401 | if (((from_bitField0_ & 0x00000020) == 0x00000020)) { 1402 | to_bitField0_ |= 0x00000020; 1403 | } 1404 | result.len_ = len_; 1405 | if (((from_bitField0_ & 0x00000040) == 0x00000040)) { 1406 | to_bitField0_ |= 0x00000040; 1407 | } 1408 | result.errCode_ = errCode_; 1409 | if (((from_bitField0_ & 0x00000080) == 0x00000080)) { 1410 | to_bitField0_ |= 0x00000080; 1411 | } 1412 | result.errDetail_ = errDetail_; 1413 | result.bitField0_ = to_bitField0_; 1414 | onBuilt(); 1415 | return result; 1416 | } 1417 | 1418 | public Builder mergeFrom(com.google.protobuf.Message other) { 1419 | if (other instanceof doozer.DoozerMsg.Response) { 1420 | return mergeFrom((doozer.DoozerMsg.Response)other); 1421 | } else { 1422 | super.mergeFrom(other); 1423 | return this; 1424 | } 1425 | } 1426 | 1427 | public Builder mergeFrom(doozer.DoozerMsg.Response other) { 1428 | if (other == doozer.DoozerMsg.Response.getDefaultInstance()) return this; 1429 | if (other.hasTag()) { 1430 | setTag(other.getTag()); 1431 | } 1432 | if (other.hasFlags()) { 1433 | setFlags(other.getFlags()); 1434 | } 1435 | if (other.hasRev()) { 1436 | setRev(other.getRev()); 1437 | } 1438 | if (other.hasPath()) { 1439 | setPath(other.getPath()); 1440 | } 1441 | if (other.hasValue()) { 1442 | setValue(other.getValue()); 1443 | } 1444 | if (other.hasLen()) { 1445 | setLen(other.getLen()); 1446 | } 1447 | if (other.hasErrCode()) { 1448 | setErrCode(other.getErrCode()); 1449 | } 1450 | if (other.hasErrDetail()) { 1451 | setErrDetail(other.getErrDetail()); 1452 | } 1453 | this.mergeUnknownFields(other.getUnknownFields()); 1454 | return this; 1455 | } 1456 | 1457 | public final boolean isInitialized() { 1458 | return true; 1459 | } 1460 | 1461 | public Builder mergeFrom( 1462 | com.google.protobuf.CodedInputStream input, 1463 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 1464 | throws java.io.IOException { 1465 | com.google.protobuf.UnknownFieldSet.Builder unknownFields = 1466 | com.google.protobuf.UnknownFieldSet.newBuilder( 1467 | this.getUnknownFields()); 1468 | while (true) { 1469 | int tag = input.readTag(); 1470 | switch (tag) { 1471 | case 0: 1472 | this.setUnknownFields(unknownFields.build()); 1473 | onChanged(); 1474 | return this; 1475 | default: { 1476 | if (!parseUnknownField(input, unknownFields, 1477 | extensionRegistry, tag)) { 1478 | this.setUnknownFields(unknownFields.build()); 1479 | onChanged(); 1480 | return this; 1481 | } 1482 | break; 1483 | } 1484 | case 8: { 1485 | bitField0_ |= 0x00000001; 1486 | tag_ = input.readInt32(); 1487 | break; 1488 | } 1489 | case 16: { 1490 | bitField0_ |= 0x00000002; 1491 | flags_ = input.readInt32(); 1492 | break; 1493 | } 1494 | case 24: { 1495 | bitField0_ |= 0x00000004; 1496 | rev_ = input.readInt64(); 1497 | break; 1498 | } 1499 | case 42: { 1500 | bitField0_ |= 0x00000008; 1501 | path_ = input.readBytes(); 1502 | break; 1503 | } 1504 | case 50: { 1505 | bitField0_ |= 0x00000010; 1506 | value_ = input.readBytes(); 1507 | break; 1508 | } 1509 | case 64: { 1510 | bitField0_ |= 0x00000020; 1511 | len_ = input.readInt32(); 1512 | break; 1513 | } 1514 | case 800: { 1515 | int rawValue = input.readEnum(); 1516 | doozer.DoozerMsg.Response.Err value = doozer.DoozerMsg.Response.Err.valueOf(rawValue); 1517 | if (value == null) { 1518 | unknownFields.mergeVarintField(100, rawValue); 1519 | } else { 1520 | bitField0_ |= 0x00000040; 1521 | errCode_ = value; 1522 | } 1523 | break; 1524 | } 1525 | case 810: { 1526 | bitField0_ |= 0x00000080; 1527 | errDetail_ = input.readBytes(); 1528 | break; 1529 | } 1530 | } 1531 | } 1532 | } 1533 | 1534 | private int bitField0_; 1535 | 1536 | // optional int32 tag = 1; 1537 | private int tag_ ; 1538 | public boolean hasTag() { 1539 | return ((bitField0_ & 0x00000001) == 0x00000001); 1540 | } 1541 | public int getTag() { 1542 | return tag_; 1543 | } 1544 | public Builder setTag(int value) { 1545 | bitField0_ |= 0x00000001; 1546 | tag_ = value; 1547 | onChanged(); 1548 | return this; 1549 | } 1550 | public Builder clearTag() { 1551 | bitField0_ = (bitField0_ & ~0x00000001); 1552 | tag_ = 0; 1553 | onChanged(); 1554 | return this; 1555 | } 1556 | 1557 | // optional int32 flags = 2; 1558 | private int flags_ ; 1559 | public boolean hasFlags() { 1560 | return ((bitField0_ & 0x00000002) == 0x00000002); 1561 | } 1562 | public int getFlags() { 1563 | return flags_; 1564 | } 1565 | public Builder setFlags(int value) { 1566 | bitField0_ |= 0x00000002; 1567 | flags_ = value; 1568 | onChanged(); 1569 | return this; 1570 | } 1571 | public Builder clearFlags() { 1572 | bitField0_ = (bitField0_ & ~0x00000002); 1573 | flags_ = 0; 1574 | onChanged(); 1575 | return this; 1576 | } 1577 | 1578 | // optional int64 rev = 3; 1579 | private long rev_ ; 1580 | public boolean hasRev() { 1581 | return ((bitField0_ & 0x00000004) == 0x00000004); 1582 | } 1583 | public long getRev() { 1584 | return rev_; 1585 | } 1586 | public Builder setRev(long value) { 1587 | bitField0_ |= 0x00000004; 1588 | rev_ = value; 1589 | onChanged(); 1590 | return this; 1591 | } 1592 | public Builder clearRev() { 1593 | bitField0_ = (bitField0_ & ~0x00000004); 1594 | rev_ = 0L; 1595 | onChanged(); 1596 | return this; 1597 | } 1598 | 1599 | // optional string path = 5; 1600 | private Object path_ = ""; 1601 | public boolean hasPath() { 1602 | return ((bitField0_ & 0x00000008) == 0x00000008); 1603 | } 1604 | public String getPath() { 1605 | Object ref = path_; 1606 | if (!(ref instanceof String)) { 1607 | String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); 1608 | path_ = s; 1609 | return s; 1610 | } else { 1611 | return (String) ref; 1612 | } 1613 | } 1614 | public Builder setPath(String value) { 1615 | if (value == null) { 1616 | throw new NullPointerException(); 1617 | } 1618 | bitField0_ |= 0x00000008; 1619 | path_ = value; 1620 | onChanged(); 1621 | return this; 1622 | } 1623 | public Builder clearPath() { 1624 | bitField0_ = (bitField0_ & ~0x00000008); 1625 | path_ = getDefaultInstance().getPath(); 1626 | onChanged(); 1627 | return this; 1628 | } 1629 | void setPath(com.google.protobuf.ByteString value) { 1630 | bitField0_ |= 0x00000008; 1631 | path_ = value; 1632 | onChanged(); 1633 | } 1634 | 1635 | // optional bytes value = 6; 1636 | private com.google.protobuf.ByteString value_ = com.google.protobuf.ByteString.EMPTY; 1637 | public boolean hasValue() { 1638 | return ((bitField0_ & 0x00000010) == 0x00000010); 1639 | } 1640 | public com.google.protobuf.ByteString getValue() { 1641 | return value_; 1642 | } 1643 | public Builder setValue(com.google.protobuf.ByteString value) { 1644 | if (value == null) { 1645 | throw new NullPointerException(); 1646 | } 1647 | bitField0_ |= 0x00000010; 1648 | value_ = value; 1649 | onChanged(); 1650 | return this; 1651 | } 1652 | public Builder clearValue() { 1653 | bitField0_ = (bitField0_ & ~0x00000010); 1654 | value_ = getDefaultInstance().getValue(); 1655 | onChanged(); 1656 | return this; 1657 | } 1658 | 1659 | // optional int32 len = 8; 1660 | private int len_ ; 1661 | public boolean hasLen() { 1662 | return ((bitField0_ & 0x00000020) == 0x00000020); 1663 | } 1664 | public int getLen() { 1665 | return len_; 1666 | } 1667 | public Builder setLen(int value) { 1668 | bitField0_ |= 0x00000020; 1669 | len_ = value; 1670 | onChanged(); 1671 | return this; 1672 | } 1673 | public Builder clearLen() { 1674 | bitField0_ = (bitField0_ & ~0x00000020); 1675 | len_ = 0; 1676 | onChanged(); 1677 | return this; 1678 | } 1679 | 1680 | // optional .doozer.Response.Err err_code = 100; 1681 | private doozer.DoozerMsg.Response.Err errCode_ = doozer.DoozerMsg.Response.Err.OTHER; 1682 | public boolean hasErrCode() { 1683 | return ((bitField0_ & 0x00000040) == 0x00000040); 1684 | } 1685 | public doozer.DoozerMsg.Response.Err getErrCode() { 1686 | return errCode_; 1687 | } 1688 | public Builder setErrCode(doozer.DoozerMsg.Response.Err value) { 1689 | if (value == null) { 1690 | throw new NullPointerException(); 1691 | } 1692 | bitField0_ |= 0x00000040; 1693 | errCode_ = value; 1694 | onChanged(); 1695 | return this; 1696 | } 1697 | public Builder clearErrCode() { 1698 | bitField0_ = (bitField0_ & ~0x00000040); 1699 | errCode_ = doozer.DoozerMsg.Response.Err.OTHER; 1700 | onChanged(); 1701 | return this; 1702 | } 1703 | 1704 | // optional string err_detail = 101; 1705 | private Object errDetail_ = ""; 1706 | public boolean hasErrDetail() { 1707 | return ((bitField0_ & 0x00000080) == 0x00000080); 1708 | } 1709 | public String getErrDetail() { 1710 | Object ref = errDetail_; 1711 | if (!(ref instanceof String)) { 1712 | String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); 1713 | errDetail_ = s; 1714 | return s; 1715 | } else { 1716 | return (String) ref; 1717 | } 1718 | } 1719 | public Builder setErrDetail(String value) { 1720 | if (value == null) { 1721 | throw new NullPointerException(); 1722 | } 1723 | bitField0_ |= 0x00000080; 1724 | errDetail_ = value; 1725 | onChanged(); 1726 | return this; 1727 | } 1728 | public Builder clearErrDetail() { 1729 | bitField0_ = (bitField0_ & ~0x00000080); 1730 | errDetail_ = getDefaultInstance().getErrDetail(); 1731 | onChanged(); 1732 | return this; 1733 | } 1734 | void setErrDetail(com.google.protobuf.ByteString value) { 1735 | bitField0_ |= 0x00000080; 1736 | errDetail_ = value; 1737 | onChanged(); 1738 | } 1739 | 1740 | // @@protoc_insertion_point(builder_scope:doozer.Response) 1741 | } 1742 | 1743 | static { 1744 | defaultInstance = new Response(true); 1745 | defaultInstance.initFields(); 1746 | } 1747 | 1748 | // @@protoc_insertion_point(class_scope:doozer.Response) 1749 | } 1750 | 1751 | private static com.google.protobuf.Descriptors.Descriptor 1752 | internal_static_doozer_Request_descriptor; 1753 | private static 1754 | com.google.protobuf.GeneratedMessage.FieldAccessorTable 1755 | internal_static_doozer_Request_fieldAccessorTable; 1756 | private static com.google.protobuf.Descriptors.Descriptor 1757 | internal_static_doozer_Response_descriptor; 1758 | private static 1759 | com.google.protobuf.GeneratedMessage.FieldAccessorTable 1760 | internal_static_doozer_Response_fieldAccessorTable; 1761 | 1762 | public static com.google.protobuf.Descriptors.FileDescriptor 1763 | getDescriptor() { 1764 | return descriptor; 1765 | } 1766 | private static com.google.protobuf.Descriptors.FileDescriptor 1767 | descriptor; 1768 | static { 1769 | java.lang.String[] descriptorData = { 1770 | "\n\020doozer-msg.proto\022\006doozer\"\362\001\n\007Request\022\013" + 1771 | "\n\003tag\030\001 \001(\005\022\"\n\004verb\030\002 \001(\0162\024.doozer.Reque" + 1772 | "st.Verb\022\014\n\004path\030\004 \001(\t\022\r\n\005value\030\005 \001(\014\022\021\n\t" + 1773 | "other_tag\030\006 \001(\005\022\016\n\006offset\030\007 \001(\005\022\013\n\003rev\030\t" + 1774 | " \001(\003\"i\n\004Verb\022\007\n\003GET\020\001\022\007\n\003SET\020\002\022\007\n\003DEL\020\003\022" + 1775 | "\007\n\003REV\020\005\022\010\n\004WAIT\020\006\022\007\n\003NOP\020\007\022\010\n\004WALK\020\t\022\n\n" + 1776 | "\006GETDIR\020\016\022\010\n\004STAT\020\020\022\n\n\006ACCESS\020c\"\310\002\n\010Resp" + 1777 | "onse\022\013\n\003tag\030\001 \001(\005\022\r\n\005flags\030\002 \001(\005\022\013\n\003rev\030" + 1778 | "\003 \001(\003\022\014\n\004path\030\005 \001(\t\022\r\n\005value\030\006 \001(\014\022\013\n\003le" + 1779 | "n\030\010 \001(\005\022&\n\010err_code\030d \001(\0162\024.doozer.Respo", 1780 | "nse.Err\022\022\n\nerr_detail\030e \001(\t\"\254\001\n\003Err\022\t\n\005O" + 1781 | "THER\020\177\022\016\n\nTAG_IN_USE\020\001\022\020\n\014UNKNOWN_VERB\020\002" + 1782 | "\022\014\n\010READONLY\020\003\022\014\n\010TOO_LATE\020\004\022\020\n\014REV_MISM" + 1783 | "ATCH\020\005\022\014\n\010BAD_PATH\020\006\022\017\n\013MISSING_ARG\020\007\022\t\n" + 1784 | "\005RANGE\020\010\022\n\n\006NOTDIR\020\024\022\t\n\005ISDIR\020\025\022\t\n\005NOENT" + 1785 | "\020\026" 1786 | }; 1787 | com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = 1788 | new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { 1789 | public com.google.protobuf.ExtensionRegistry assignDescriptors( 1790 | com.google.protobuf.Descriptors.FileDescriptor root) { 1791 | descriptor = root; 1792 | internal_static_doozer_Request_descriptor = 1793 | getDescriptor().getMessageTypes().get(0); 1794 | internal_static_doozer_Request_fieldAccessorTable = new 1795 | com.google.protobuf.GeneratedMessage.FieldAccessorTable( 1796 | internal_static_doozer_Request_descriptor, 1797 | new java.lang.String[] { "Tag", "Verb", "Path", "Value", "OtherTag", "Offset", "Rev", }, 1798 | doozer.DoozerMsg.Request.class, 1799 | doozer.DoozerMsg.Request.Builder.class); 1800 | internal_static_doozer_Response_descriptor = 1801 | getDescriptor().getMessageTypes().get(1); 1802 | internal_static_doozer_Response_fieldAccessorTable = new 1803 | com.google.protobuf.GeneratedMessage.FieldAccessorTable( 1804 | internal_static_doozer_Response_descriptor, 1805 | new java.lang.String[] { "Tag", "Flags", "Rev", "Path", "Value", "Len", "ErrCode", "ErrDetail", }, 1806 | doozer.DoozerMsg.Response.class, 1807 | doozer.DoozerMsg.Response.Builder.class); 1808 | return null; 1809 | } 1810 | }; 1811 | com.google.protobuf.Descriptors.FileDescriptor 1812 | .internalBuildGeneratedFileFrom(descriptorData, 1813 | new com.google.protobuf.Descriptors.FileDescriptor[] { 1814 | }, assigner); 1815 | } 1816 | 1817 | // @@protoc_insertion_point(outer_class_scope) 1818 | } 1819 | -------------------------------------------------------------------------------- /src/main/protobuf/doozer-msg.proto: -------------------------------------------------------------------------------- 1 | package doozer; 2 | 3 | // see doc/proto.md 4 | message Request { 5 | optional int32 tag = 1; 6 | 7 | enum Verb { 8 | GET = 1; 9 | SET = 2; 10 | DEL = 3; 11 | REV = 5; 12 | WAIT = 6; 13 | NOP = 7; 14 | WALK = 9; 15 | GETDIR = 14; 16 | STAT = 16; 17 | ACCESS = 99; 18 | } 19 | optional Verb verb = 2; 20 | 21 | optional string path = 4; 22 | optional bytes value = 5; 23 | optional int32 other_tag = 6; 24 | 25 | optional int32 offset = 7; 26 | 27 | optional int64 rev = 9; 28 | } 29 | 30 | // see doc/proto.md 31 | message Response { 32 | optional int32 tag = 1; 33 | optional int32 flags = 2; 34 | 35 | optional int64 rev = 3; 36 | optional string path = 5; 37 | optional bytes value = 6; 38 | optional int32 len = 8; 39 | 40 | enum Err { 41 | // don't use value 0 42 | OTHER = 127; 43 | TAG_IN_USE = 1; 44 | UNKNOWN_VERB = 2; 45 | READONLY = 3; 46 | TOO_LATE = 4; 47 | REV_MISMATCH = 5; 48 | BAD_PATH = 6; 49 | MISSING_ARG = 7; 50 | RANGE = 8; 51 | NOTDIR = 20; 52 | ISDIR = 21; 53 | NOENT = 22; 54 | } 55 | optional Err err_code = 100; 56 | optional string err_detail = 101; 57 | } 58 | -------------------------------------------------------------------------------- /src/main/resources/akka.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | version = "1.1" 3 | time-unit = "seconds" 4 | event-handlers = ["akka.event.slf4j.Slf4jEventHandler"] 5 | event-handler-level = "INFO" 6 | } -------------------------------------------------------------------------------- /src/main/scala/com/force/doozer/flange/DoozerClient.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Created by IntelliJ IDEA. 3 | * User: sclasen 4 | * Date: 4/21/11 5 | * Time: 4:12 PM 6 | */ 7 | 8 | package com.force.doozer.flange 9 | 10 | import doozer.DoozerMsg 11 | import doozer.DoozerMsg.Response.Err 12 | import akka.actor.Actor._ 13 | import akka.dispatch.Future 14 | import org.jboss.netty.handler.codec.frame.{LengthFieldBasedFrameDecoder, LengthFieldPrepender} 15 | import collection.mutable.HashMap 16 | import akka.dispatch.CompletableFuture 17 | import akka.config.Supervision._ 18 | import annotation.tailrec 19 | import util.matching.Regex 20 | 21 | import akka.event.EventHandler 22 | import akka.actor.{MaximumNumberOfRestartsWithinTimeRangeReached, Actor} 23 | import java.util.concurrent.ThreadFactory 24 | import java.util.concurrent.atomic.AtomicInteger 25 | import java.lang.{RuntimeException, Thread} 26 | 27 | 28 | object DoozerClient { 29 | implicit def stringToByteArray(value: String): Array[Byte] = value.getBytes("UTF-8") 30 | 31 | implicit def byteArrayToString(value: Array[Byte]): String = new String(value, "UTF-8") 32 | } 33 | 34 | trait DoozerClient { 35 | 36 | def get_!(path: String, rev: Long = 0L): GetResponse 37 | 38 | def get(path: String, rev: Long = 0L): Either[ErrorResponse, GetResponse] 39 | 40 | def getAsync(path: String, rev: Long = 0L)(callback: (Either[ErrorResponse, GetResponse] => Unit)): Unit 41 | 42 | def set_!(path: String, value: Array[Byte], rev: Long): SetResponse 43 | 44 | def set(path: String, value: Array[Byte], rev: Long): Either[ErrorResponse, SetResponse] 45 | 46 | def setAsync(path: String, value: Array[Byte], rev: Long)(callback: (Either[ErrorResponse, SetResponse] => Unit)): Unit 47 | 48 | def delete_!(path: String, rev: Long): DeleteResponse 49 | 50 | def delete(path: String, rev: Long): Either[ErrorResponse, DeleteResponse] 51 | 52 | def deleteAsync(path: String, rev: Long)(callback: (Either[ErrorResponse, DeleteResponse] => Unit)): Unit 53 | 54 | def rev_! : RevResponse 55 | 56 | def rev: Either[ErrorResponse, RevResponse] 57 | 58 | def revAsync(callback: (Either[ErrorResponse, RevResponse] => Unit)) 59 | 60 | def wait_!(glob: String, rev: Long, waitFor: Long = Long.MaxValue): WaitResponse 61 | 62 | def wait(glob: String, rev: Long, waitFor: Long = Long.MaxValue): Either[ErrorResponse, WaitResponse] 63 | 64 | def waitAsync(glob: String, rev: Long, waitFor: Long = Long.MaxValue)(callback: (Either[ErrorResponse, WaitResponse]) => Unit) 65 | 66 | def stat_!(path: String, rev: Long): StatResponse 67 | 68 | def stat(path: String, rev: Long): Either[ErrorResponse, StatResponse] 69 | 70 | def statAsync(path: String, rev: Long)(callback: (Either[ErrorResponse, StatResponse]) => Unit) 71 | 72 | def getdir(dir: String, rev: Long, offset: Int): Either[ErrorResponse, GetdirResponse] 73 | 74 | def getdir_!(dir: String, rev: Long, offset: Int): GetdirResponse 75 | 76 | def getdirAsync(dir: String, rev: Long, offset: Int)(callback: (Either[ErrorResponse, GetdirResponse]) => Unit) 77 | 78 | def walk(glob: String, rev: Long, offset: Int): Either[ErrorResponse, WalkResponse] 79 | 80 | def walk_!(glob: String, rev: Long, offset: Int): WalkResponse 81 | 82 | def walkAsync(glob: String, rev: Long, offset: Int)(callback: (Either[ErrorResponse, WalkResponse]) => Unit) 83 | 84 | def walk_all(glob: String, rev: Long): Either[ErrorResponse, List[WalkResponse]] 85 | 86 | def getdir_all(dir: String, rev: Long): Either[ErrorResponse, List[GetdirResponse]] 87 | 88 | def walk_all_!(glob: String, rev: Long): List[WalkResponse] 89 | 90 | def getdir_all_!(dir: String, rev: Long): List[GetdirResponse] 91 | 92 | def watch(glob: String, rev: Long, watchFor: Long = Long.MaxValue)(callback: (Either[ErrorResponse, WaitResponse]) => Boolean) 93 | 94 | 95 | } 96 | 97 | object Flange { 98 | 99 | lazy val daemonThreadFactory = new ThreadFactory { 100 | val count = new AtomicInteger(0) 101 | 102 | def newThread(r: Runnable) = { 103 | val t = new Thread(r, "FlangeConnector:" + count.incrementAndGet()) 104 | t.setDaemon(true) 105 | t 106 | } 107 | } 108 | 109 | def parseDoozerUri(doozerUri: String): (List[String], String) = { 110 | """^doozer:\?(.*)$""".r.findFirstMatchIn(doozerUri) match { 111 | case Some(m@Regex.Match(_)) => { 112 | val doozerds = for { 113 | caServer <- m.group(1).split("&").toList 114 | k <- caServer.split("=").headOption if k == "ca" 115 | v <- caServer.split("=").tail.headOption 116 | } yield v 117 | val sk = for { 118 | sks <- m.group(1).split("&").toList 119 | k <- sks.split("=").headOption if k == "sk" 120 | v <- sks.split("=").tail.headOption 121 | } yield v 122 | 123 | (doozerds, sk.headOption.getOrElse(throw new IllegalArgumentException("Missing sk param"))) 124 | } 125 | case _ => throw new IllegalArgumentException("cant parse doozerUri:" + doozerUri) 126 | } 127 | } 128 | 129 | def eachDoozerOnceStrategy(doozerds: List[String]): Iterable[String] = { 130 | doozerds.toIterable 131 | } 132 | 133 | def retryForeverStrategy(doozerds: List[String]): Iterable[String] = { 134 | var cur = doozerds 135 | Stream.continually { 136 | cur.headOption match { 137 | case Some(doozer) => { 138 | cur = cur.tail 139 | doozer 140 | } 141 | case None => { 142 | cur = doozerds.tail 143 | doozerds.head 144 | } 145 | } 146 | } 147 | } 148 | 149 | val allConnectionsFailed = "ALL_CONNECTIONS_FAILED" 150 | } 151 | 152 | 153 | import Flange._ 154 | 155 | 156 | class Flange(doozerUri: String, failoverStrategy: List[String] => Iterable[String] = eachDoozerOnceStrategy) extends DoozerClient { 157 | 158 | private val (doozerds, sk) = parseDoozerUri(doozerUri) 159 | private val supervisor = actorOf(new ConnectionSupervisor(doozerds.size)).start() 160 | private val connection = { 161 | val state = new ClientState(sk, failoverStrategy(doozerds)) 162 | val conn = actorOf(new ConnectionActor(state)) 163 | supervisor.startLink(conn) 164 | conn 165 | } 166 | 167 | def stop() { 168 | connection.stop() 169 | supervisor.stop() 170 | } 171 | 172 | private def timeout = Left(ErrorResponse("CLIENT_TIMEOUT", "The operation timed out")) 173 | 174 | private def noConnections = Left(ErrorResponse(allConnectionsFailed, "Attempts to retry the operation at all configured servers failed")) 175 | 176 | private def exception(t: Throwable) = Left(ErrorResponse("DoozerClient Exception", t.getStackTraceString)) 177 | 178 | private def retry[T](req: DoozerRequest)(success: PartialFunction[Any, Either[ErrorResponse, T]]): Either[ConnectionFailed, Either[ErrorResponse, T]] = { 179 | try { 180 | val resp = connection !! (req, req.timeout) 181 | if (resp.isDefined && success.isDefinedAt(resp.get)) Right(success(resp.get)) 182 | else resp match { 183 | case Some(e@ErrorResponse(_, desc)) if desc equals "permission denied" => { 184 | connection !! AccessRequest(sk) match { 185 | case Some(r: AccessResponse) => retry(req)(success) 186 | case er@_ => { 187 | EventHandler.error(er, "cant auth") 188 | Left(ConnectionFailed()) 189 | } 190 | } 191 | } 192 | case Some(e@ErrorResponse(_, _)) => Right(Left(e)) 193 | case Some(NoConnectionsLeft) => Right(noConnections) 194 | case None => Left(ConnectionFailed()) 195 | } 196 | } catch { 197 | case e => 198 | EventHandler.error(e, this, "error") 199 | Left(ConnectionFailed()) 200 | } 201 | } 202 | 203 | @tailrec 204 | private def complete[T](req: DoozerRequest)(success: PartialFunction[Any, Either[ErrorResponse, T]]): Either[ErrorResponse, T] = { 205 | val res = retry[T](req)(success) 206 | res match { 207 | case Right(ok) => ok 208 | case Left(fail) => complete[T](req)(success) 209 | } 210 | } 211 | 212 | 213 | private def completeFuture[T](req: DoozerRequest, responseCallback: (Either[ErrorResponse, T] => Unit))(success: PartialFunction[Any, Either[ErrorResponse, T]]) { 214 | val future: Future[_] = connection !!! (req, req.timeout) 215 | future.asInstanceOf[Future[T]].onComplete { 216 | f: Future[T] => 217 | if (success.isDefinedAt(f.value)) responseCallback(success(f.value)) 218 | else { 219 | f.value match { 220 | case Some(Right(e@ErrorResponse(_, desc))) if desc equals "permission denied" => { 221 | connection !! AccessRequest(sk) match { 222 | case Some(r: AccessResponse) => retry(req)(success) 223 | case er@_ => { 224 | EventHandler.error(er, "cant auth") 225 | responseCallback(Left(e)) 226 | } 227 | } 228 | } 229 | case Some(Right(e@ErrorResponse(_, _))) => responseCallback(Left(e)) 230 | case Some(Right(NoConnectionsLeft)) => responseCallback(noConnections) 231 | case _ => completeFuture(req, responseCallback)(success) 232 | } 233 | } 234 | } 235 | } 236 | 237 | 238 | def deleteAsync(path: String, rev: Long)(callback: (Either[ErrorResponse, DeleteResponse]) => Unit) { 239 | completeFuture[DeleteResponse](DeleteRequest(path, rev), callback) { 240 | case Some(Right(d@DeleteResponse(_))) => Right(d) 241 | } 242 | } 243 | 244 | 245 | def delete_!(path: String, rev: Long) = delete(path, rev) match { 246 | case Right(d@DeleteResponse(_)) => d 247 | case Left(e@ErrorResponse(_, _)) => throw new ErrorResponseException(e) 248 | } 249 | 250 | def delete(path: String, rev: Long) = complete[DeleteResponse](DeleteRequest(path, rev)) { 251 | case d@DeleteResponse(_) => Right(d) 252 | } 253 | 254 | def setAsync(path: String, value: Array[Byte], rev: Long)(callback: (Either[ErrorResponse, SetResponse]) => Unit) { 255 | completeFuture[SetResponse](SetRequest(path, value, rev), callback) { 256 | case Some(Right(s@SetResponse(_))) => Right(s) 257 | } 258 | } 259 | 260 | def set_!(path: String, value: Array[Byte], rev: Long) = set(path, value, rev) match { 261 | case Right(s@SetResponse(_)) => s 262 | case Left(e@ErrorResponse(_, _)) => throw new ErrorResponseException(e) 263 | } 264 | 265 | def set(path: String, value: Array[Byte], rev: Long) = complete[SetResponse](SetRequest(path, value, rev)) { 266 | case s@SetResponse(_) => Right(s) 267 | } 268 | 269 | def getAsync(path: String, rev: Long = 0L)(callback: (Either[ErrorResponse, GetResponse]) => Unit) { 270 | completeFuture[GetResponse](GetRequest(path, rev), callback) { 271 | case Some(Right(g@GetResponse(_, _))) => Right(g) 272 | } 273 | } 274 | 275 | def get(path: String, rev: Long = 0L): Either[ErrorResponse, GetResponse] = complete[GetResponse](GetRequest(path, rev)) { 276 | case g@GetResponse(_, _) => Right(g) 277 | } 278 | 279 | def get_!(path: String, rev: Long = 0L) = get(path, rev) match { 280 | case Right(g@GetResponse(_, _)) => g 281 | case Left(e@ErrorResponse(_, _)) => throw new ErrorResponseException(e) 282 | } 283 | 284 | def revAsync(callback: (Either[ErrorResponse, RevResponse]) => Unit) { 285 | completeFuture[RevResponse](RevRequest, callback) { 286 | case Some(Right(r@RevResponse(_))) => Right(r) 287 | } 288 | } 289 | 290 | def rev = complete[RevResponse](RevRequest) { 291 | case r@RevResponse(_) => Right(r) 292 | } 293 | 294 | def rev_! = rev match { 295 | case Right(r@RevResponse(_)) => r 296 | case Left(e@ErrorResponse(_, _)) => throw new ErrorResponseException(e) 297 | } 298 | 299 | def waitAsync(glob: String, rev: Long, waitFor: Long = Long.MaxValue)(callback: (Either[ErrorResponse, WaitResponse]) => Unit) = { 300 | completeFuture[WaitResponse](WaitRequest(glob, rev, waitFor), callback) { 301 | case Some(Right(w@WaitResponse(_, _, _))) => Right(w) 302 | } 303 | } 304 | 305 | def wait(glob: String, rev: Long, waitFor: Long = Long.MaxValue) = complete[WaitResponse](WaitRequest(glob, rev, waitFor)) { 306 | case w@WaitResponse(_, _, _) => Right(w) 307 | } 308 | 309 | def wait_!(glob: String, rev: Long, waitFor: Long = Long.MaxValue) = wait(glob, rev, waitFor) match { 310 | case Right(w@WaitResponse(_, _, _)) => w 311 | case Left(e@ErrorResponse(_, _)) => throw new ErrorResponseException(e) 312 | } 313 | 314 | def statAsync(path: String, rev: Long)(callback: (Either[ErrorResponse, StatResponse]) => Unit) = { 315 | completeFuture[StatResponse](StatRequest(path, rev), callback) { 316 | case Some(Right(s@StatResponse(_, _, _))) => Right(s) 317 | } 318 | } 319 | 320 | def stat(path: String, rev: Long) = complete[StatResponse](StatRequest(path, rev)) { 321 | case s@StatResponse(_, _, _) => Right(s) 322 | } 323 | 324 | 325 | def stat_!(path: String, rev: Long) = stat(path, rev) match { 326 | case Right(s@StatResponse(_, _, _)) => s 327 | case Left(e@ErrorResponse(_, _)) => throw new ErrorResponseException(e) 328 | } 329 | 330 | def getdir(dir: String, rev: Long, offset: Int) = complete[GetdirResponse](GetdirRequest(dir, rev, offset)) { 331 | case g@GetdirResponse(_, _) => Right(g) 332 | } 333 | 334 | def getdir_!(dir: String, rev: Long, offset: Int) = getdir(dir, rev, offset) match { 335 | case Right(g@GetdirResponse(_, _)) => g 336 | case Left(e@ErrorResponse(_, _)) => throw new ErrorResponseException(e) 337 | } 338 | 339 | def getdirAsync(dir: String, rev: Long, offset: Int)(callback: (Either[ErrorResponse, GetdirResponse]) => Unit) = { 340 | completeFuture[GetdirResponse](GetdirRequest(dir, rev, offset), callback) { 341 | case Some(Right(g@GetdirResponse(_, _))) => Right(g) 342 | } 343 | } 344 | 345 | def walk(glob: String, rev: Long, offset: Int) = complete[WalkResponse](WalkRequest(glob, rev, offset)) { 346 | case w@WalkResponse(_, _, _) => Right(w) 347 | } 348 | 349 | def walk_!(glob: String, rev: Long, offset: Int) = walk(glob, rev, offset) match { 350 | case Right(w@WalkResponse(_, _, _)) => w 351 | case Left(e@ErrorResponse(_, _)) => throw new ErrorResponseException(e) 352 | } 353 | 354 | def walkAsync(glob: String, rev: Long, offset: Int)(callback: (Either[ErrorResponse, WalkResponse]) => Unit) = { 355 | completeFuture[WalkResponse](WalkRequest(glob, rev, offset), callback) { 356 | case Some(Right(w@WalkResponse(_, _, _))) => Right(w) 357 | } 358 | } 359 | 360 | def watch(glob: String, rev: Long, waitFor: Long = Long.MaxValue)(callback: (Either[ErrorResponse, WaitResponse]) => Boolean) = { 361 | def inner(r: Long, either: Either[ErrorResponse, WaitResponse]) { 362 | if (callback.apply(either)) { 363 | either match { 364 | case Left(_) => waitAsync(glob, r , waitFor)(inner(r , _)) 365 | case Right(WaitResponse(_,_,newRev)) => waitAsync(glob, newRev+1 , waitFor)(inner(newRev+1 , _)) 366 | } 367 | } 368 | } 369 | waitAsync(glob, rev, waitFor)(inner(rev, _)) 370 | } 371 | 372 | def getdir_all(dir: String, rev: Long) = { 373 | all_internal[GetdirResponse](getdir(dir, rev, _), 0, Nil) 374 | } 375 | 376 | @tailrec 377 | private def all_internal[T](func: Int => Either[ErrorResponse, T], offset: Int, responses: List[T]): Either[ErrorResponse, List[T]] = { 378 | func.apply(offset) match { 379 | case Left(ErrorResponse(code, msg)) if code eq Err.RANGE.name() => Right(responses) 380 | case Left(e@ErrorResponse(_, _)) => Left(e) 381 | case Right(t: T) => all_internal(func, offset + 1, responses :+ t) 382 | } 383 | } 384 | 385 | def walk_all(glob: String, rev: Long) = { 386 | all_internal[WalkResponse](walk(glob, rev, _), 0, Nil) 387 | } 388 | 389 | def getdir_all_!(dir: String, rev: Long) = getdir_all(dir, rev) match { 390 | case Right(responses) => responses 391 | case Left(e@ErrorResponse(_, _)) => throw new ErrorResponseException(e) 392 | } 393 | 394 | def walk_all_!(glob: String, rev: Long) = walk_all(glob, rev) match { 395 | case Right(responses) => responses 396 | case Left(e@ErrorResponse(_, _)) => throw new ErrorResponseException(e) 397 | } 398 | } 399 | 400 | class ConnectionSupervisor(numHosts: Int) extends Actor { 401 | self.faultHandler = OneForOneStrategy(List(classOf[Exception]), numHosts, numHosts * 1000) 402 | 403 | protected def receive = { 404 | case MaximumNumberOfRestartsWithinTimeRangeReached(_, _, _, ex) => EventHandler.error(ex, this, "Too Many Restarts") 405 | } 406 | } 407 | 408 | class ClientState(val secret: String, var hosts: Iterable[String], var tag: Int = 0) 409 | 410 | class ConnectionFailedException(val host: String, cause: Throwable) extends RuntimeException(cause) 411 | 412 | class ErrorResponseException(val resp: ErrorResponse) extends RuntimeException() 413 | 414 | import org.jboss.netty.bootstrap.ClientBootstrap 415 | import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory 416 | import org.jboss.netty.channel.Channel 417 | import java.util.concurrent.Executors 418 | import java.net.InetSocketAddress 419 | import com.force.doozer.flange.Flange._ 420 | 421 | 422 | class ConnectionActor(state: ClientState) extends Actor { 423 | self.lifeCycle = Permanent 424 | 425 | private var host: String = null 426 | private var port: Int = 0 427 | private var requests = new HashMap[Int, DoozerRequest] 428 | private var responses = new HashMap[Int, Option[CompletableFuture[_]]] 429 | private var connected = false 430 | private var bootstrap: ClientBootstrap = null 431 | private var handler: Handler = null 432 | private var channel: Channel = null 433 | 434 | 435 | state.hosts.headOption match { 436 | case Some(h) => { 437 | host = h.split(":").apply(0) 438 | port = h.split(":").apply(1).toInt 439 | state.hosts = state.hosts.tail 440 | } 441 | case None => { 442 | become(noConn(), false) 443 | } 444 | } 445 | 446 | private def notifyWaiters(ex: Throwable) { 447 | for { 448 | futureOpt <- responses.values 449 | future <- futureOpt 450 | } future.completeWithException(ex) 451 | } 452 | 453 | override def postStop() { 454 | notifyWaiters(new RuntimeException("Connection actor was stopped")) 455 | } 456 | 457 | override def preRestart(reason: Throwable) { 458 | EventHandler.warning(this, "failed:" + host + ":" + port) 459 | try { 460 | if (channel != null) channel.close() 461 | } 462 | catch { 463 | case _ => 464 | } 465 | try { 466 | if (bootstrap != null) bootstrap.releaseExternalResources() 467 | } 468 | catch { 469 | case _ => 470 | } 471 | notifyWaiters(reason) 472 | } 473 | 474 | 475 | override def postRestart(reason: Throwable) { 476 | EventHandler.warning(this, "failTo:" + host + ":" + port) 477 | } 478 | 479 | private def noConn(): Receive = { 480 | case _ => self.reply(NoConnectionsLeft) 481 | } 482 | 483 | private def connect() { 484 | bootstrap = new ClientBootstrap(new NioClientSocketChannelFactory( 485 | Executors.newCachedThreadPool(daemonThreadFactory), 486 | Executors.newCachedThreadPool(daemonThreadFactory))); 487 | bootstrap.setPipelineFactory(new PipelineFactory()); 488 | bootstrap.setOption("tcpNoDelay", true) 489 | bootstrap.setOption("keepAlive", true) 490 | // Make a new connection. 491 | val connectFuture = 492 | bootstrap.connect(new InetSocketAddress(host, port)); 493 | // Wait until the connection is made successfully 494 | connectFuture.awaitUninterruptibly() 495 | if (connectFuture.isSuccess) channel = connectFuture.getChannel 496 | else throw new IllegalStateException("Channel didnt connect") 497 | // Get the handler instance to initiate the request. 498 | handler = 499 | channel.getPipeline().get(classOf[Handler]) 500 | handler.ref = self 501 | } 502 | 503 | private def doSend(req: DoozerRequest): Unit = { 504 | val currentTag = state.tag 505 | state.tag += 1 506 | requests += currentTag -> req 507 | responses += currentTag -> self.senderFuture 508 | if (!connected) { 509 | connect() 510 | connected = true 511 | } 512 | handler.send(req.toBuilder.setTag(currentTag).build) 513 | } 514 | 515 | 516 | override protected def receive = { 517 | case req: DoozerRequest => doSend(req) 518 | case response: DoozerMsg.Response => { 519 | requests.remove(response.getTag) match { 520 | case Some(req) => { 521 | val msg = DoozerResponse.isOk(response) match { 522 | case true => req.toResponse(response) 523 | case false => req.toError(response) 524 | } 525 | responses.remove(response.getTag) match { 526 | case Some(future) => future.get.asInstanceOf[CompletableFuture[Any]].completeWithResult(msg) 527 | case None => EventHandler.warning(this, "Received a response with tag %d but there was no futute to complete".format(response.getTag)) 528 | } 529 | } 530 | case None => EventHandler.warning(this, "Revieved a response with tag %d but there was no request to correlate with".format(response.getTag)) 531 | } 532 | } 533 | } 534 | 535 | 536 | } 537 | 538 | import org.jboss.netty.channel._ 539 | import akka.actor.ActorRef 540 | 541 | class Handler extends SimpleChannelUpstreamHandler { 542 | 543 | @volatile var ref: ActorRef = null 544 | @volatile var channel: Channel = null 545 | 546 | def send(msg: DoozerMsg.Request) { 547 | EventHandler.debug(this, "====>sent:" + msg.toString) 548 | val future = channel.write(msg) 549 | future.awaitUninterruptibly 550 | } 551 | 552 | 553 | override def exceptionCaught(ctx: ChannelHandlerContext, e: ExceptionEvent) { 554 | EventHandler.error(e.getCause, this, "exceptionCaught") 555 | } 556 | 557 | override def messageReceived(ctx: ChannelHandlerContext, e: MessageEvent) { 558 | EventHandler.debug(this, "===>recieved:" + e.getMessage) 559 | ref ! e.getMessage 560 | } 561 | 562 | override def channelOpen(ctx: ChannelHandlerContext, e: ChannelStateEvent) { 563 | channel = ctx.getChannel 564 | super.channelOpen(ctx, e) 565 | } 566 | } 567 | 568 | import org.jboss.netty.channel.ChannelPipelineFactory 569 | import org.jboss.netty.handler.codec.protobuf._ 570 | 571 | class PipelineFactory extends ChannelPipelineFactory { 572 | def getPipeline = { 573 | val p = Channels.pipeline 574 | p.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4)) 575 | p.addLast("protobufDecoder", new ProtobufDecoder(DoozerMsg.Response.getDefaultInstance())) 576 | p.addLast("frameEncoder", new LengthFieldPrepender(4)) 577 | p.addLast("protobufEncoder", new ProtobufEncoder()) 578 | p.addLast("handler", new Handler) 579 | p 580 | } 581 | 582 | 583 | } 584 | 585 | -------------------------------------------------------------------------------- /src/main/scala/com/force/doozer/flange/Messages.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Created by IntelliJ IDEA. 3 | * User: sclasen 4 | * Date: 4/22/11 5 | * Time: 2:57 PM 6 | */ 7 | package com.force.doozer.flange 8 | 9 | import doozer.DoozerMsg 10 | import doozer.DoozerMsg.Request.Verb 11 | import com.google.protobuf.ByteString 12 | import doozer.DoozerMsg.Response.Err 13 | object DoozerRequest { 14 | 15 | } 16 | 17 | object DoozerResponse { 18 | 19 | val valid = 1 20 | val done = 2 21 | val set = 4 22 | val del = 8 23 | 24 | def isOk(msg: DoozerMsg.Response): Boolean = msg.getErrCode == null || (msg.getErrCode == Err.OTHER && (msg.getErrDetail eq "")) 25 | } 26 | 27 | sealed trait DoozerRequest { 28 | type Response 29 | 30 | def builder = DoozerMsg.Request.newBuilder 31 | 32 | def toBuilder: DoozerMsg.Request.Builder 33 | 34 | def toResponse(res: DoozerMsg.Response): Response 35 | 36 | def toError(res: DoozerMsg.Response): ErrorResponse = ErrorResponse(res.getErrCode.name, res.getErrDetail) 37 | 38 | def timeout = 5000L 39 | 40 | } 41 | 42 | case class ErrorResponse(code: String, description: String) 43 | 44 | case class AccessRequest(secret: String) extends DoozerRequest { 45 | type Response = AccessResponse 46 | lazy val toBuilder = builder.setVerb(Verb.ACCESS).setValue(ByteString.copyFromUtf8(secret)) 47 | 48 | def toResponse(res: DoozerMsg.Response): AccessResponse = AccessResponse() 49 | } 50 | 51 | case class AccessResponse() 52 | 53 | case class GetRequest(path: String, rev: Long) extends DoozerRequest { 54 | type Response = GetResponse 55 | lazy val toBuilder = { 56 | val b = builder.setVerb(Verb.GET).setPath(path) 57 | if (rev != 0L) b.setRev(rev) 58 | b 59 | } 60 | 61 | def toResponse(res: DoozerMsg.Response): GetResponse = GetResponse(res.getValue.toByteArray, res.getRev) 62 | } 63 | 64 | case class GetResponse(value: Array[Byte], rev: Long) 65 | 66 | case object RevRequest extends DoozerRequest { 67 | type Response = RevResponse 68 | lazy val toBuilder = builder.setVerb(Verb.REV) 69 | 70 | def toResponse(res: DoozerMsg.Response): RevResponse = RevResponse(res.getRev) 71 | } 72 | 73 | case class RevResponse(rev: Long) 74 | 75 | 76 | case class SetRequest(path: String, body: Array[Byte], rev: Long) extends DoozerRequest { 77 | type Response = SetResponse 78 | lazy val toBuilder = builder.setVerb(Verb.SET).setPath(path).setValue(ByteString.copyFrom(body)).setRev(rev) 79 | 80 | def toResponse(res: DoozerMsg.Response): SetResponse = SetResponse(res.getRev) 81 | } 82 | 83 | case class SetResponse(rev: Long) 84 | 85 | 86 | case class DeleteRequest(path: String, rev: Long) extends DoozerRequest { 87 | type Response = DeleteResponse 88 | lazy val toBuilder = builder.setVerb(Verb.DEL).setPath(path).setRev(rev) 89 | 90 | def toResponse(res: DoozerMsg.Response): DeleteResponse = DeleteResponse(res.getPath) 91 | } 92 | 93 | case class WaitRequest(glob: String, rev: Long, maxWait: Long = Long.MaxValue) extends DoozerRequest { 94 | type Response = WaitResponse 95 | lazy val toBuilder = builder.setVerb(Verb.WAIT).setPath(glob).setRev(rev) 96 | 97 | def toResponse(res: DoozerMsg.Response): WaitResponse = WaitResponse(res.getPath, res.getValue.toByteArray, res.getRev) 98 | 99 | override def timeout = maxWait 100 | } 101 | 102 | case class WaitResponse(path: String, value: Array[Byte], rev: Long) 103 | 104 | case class StatRequest(path: String, rev: Long) extends DoozerRequest { 105 | type Response = StatResponse 106 | lazy val toBuilder = builder.setVerb(Verb.STAT).setPath(path).setRev(rev) 107 | 108 | def toResponse(res: DoozerMsg.Response): StatResponse = StatResponse(res.getPath, res.getLen, res.getRev) 109 | } 110 | 111 | case class StatResponse(path: String, length: Int, rev: Long) 112 | 113 | 114 | case class GetdirRequest(dir: String, rev: Long, offset: Int = 0) extends DoozerRequest { 115 | type Response = GetdirResponse 116 | lazy val toBuilder = builder.setVerb(Verb.GETDIR).setPath(dir).setRev(rev).setOffset(offset) 117 | 118 | def toResponse(res: DoozerMsg.Response): GetdirResponse = GetdirResponse(res.getPath, res.getRev) 119 | 120 | def next() = copy(offset = this.offset + 1) 121 | } 122 | 123 | case class GetdirResponse(path: String, rev: Long) 124 | 125 | case class WalkRequest(path: String, rev: Long, offset: Int = 0) extends DoozerRequest { 126 | type Response = WalkResponse 127 | lazy val toBuilder = builder.setVerb(Verb.WALK).setPath(path).setRev(rev).setOffset(offset) 128 | 129 | def toResponse(res: DoozerMsg.Response): WalkResponse = WalkResponse(res.getPath, res.getValue.toByteArray, res.getRev) 130 | } 131 | 132 | case class WalkResponse(path: String, value: Array[Byte], rev: Long) 133 | 134 | case class DeleteResponse(path: String) 135 | 136 | case class ConnectionFailed() 137 | 138 | case object NoConnectionsLeft -------------------------------------------------------------------------------- /src/test/scala/com/force/doozer/flange/ClientSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Created by IntelliJ IDEA. 3 | * User: sclasen 4 | * Date: 4/23/11 5 | * Time: 12:14 PM 6 | */ 7 | package com.force.doozer.flange 8 | 9 | import org.scalatest.WordSpec 10 | import org.scalatest.BeforeAndAfterAll 11 | import org.scalatest.matchers.MustMatchers 12 | import akka.actor.Actor._ 13 | import com.force.doozer.flange.DoozerClient._ 14 | 15 | class ClientSpec extends WordSpec with MustMatchers with BeforeAndAfterAll with Waiting { 16 | 17 | var client: Flange = null 18 | var uri = "doozer:?ca=localhost:12345&ca=localhost:8046&sk=secret" 19 | 20 | "A Doozer Client" must { 21 | "set and get and stat and delete values correctly" in { 22 | System.out.println("Exceptions are to be expected here as we purposely use a url with a host thats not up to test failover") 23 | (1 to 20) foreach { 24 | i => { 25 | val path = "/" + System.currentTimeMillis.toString 26 | val value = path + "--value" 27 | val response: SetResponse = client.set_!(path, value, 0L) 28 | val getResponse: GetResponse = client.get_!(path) 29 | getResponse.value must be(value.getBytes) 30 | client.stat_!(path,getResponse.rev).length must be(getResponse.value.length) 31 | client.delete_!(path, response.rev) 32 | } 33 | } 34 | val path = "/" + System.currentTimeMillis.toString 35 | val value = path + "--value" 36 | val value2 = path + "--value2" 37 | val response: SetResponse = client.set_!(path, value, 0L) 38 | val response2: SetResponse = client.set_!(path, value2, response.rev) 39 | client.getAsync(path)(asyncGet(value2, _)) 40 | waitForAsync(1000) must be (true) 41 | client.get_!(path, response.rev).value must be(value.getBytes) 42 | client.get_!(path,response2.rev).value must be(value2.getBytes) 43 | client.delete_!(path, response2.rev) 44 | } 45 | 46 | 47 | "getdir correctly" in{ 48 | val path = "/" + System.currentTimeMillis.toString 49 | val a = path + "/a" 50 | val b = path + "/b" 51 | val c = path + "/c" 52 | val resA: SetResponse = client.set_!(a, a, 0) 53 | val resB: SetResponse = client.set_!(b, b, 0) 54 | val resC: SetResponse = client.set_!(c, c, 0) 55 | 56 | client.getdir_!(path, resA.rev, 0).path must be("a") 57 | evaluating {client.getdir_!(path,resA.rev,1)} must produce[ErrorResponseException] 58 | 59 | client.getdir_!(path, resB.rev, 0).path must be("a") 60 | client.getdir_!(path, resB.rev, 1).path must be("b") 61 | evaluating {client.getdir_!(path,resB.rev,2)} must produce[ErrorResponseException] 62 | 63 | client.getdir_!(path, resC.rev, 0).path must be("a") 64 | client.getdir_!(path, resC.rev, 1).path must be("b") 65 | client.getdir_!(path, resC.rev, 2).path must be("c") 66 | evaluating {client.getdir_!(path,resC.rev,3)} must produce[ErrorResponseException] 67 | 68 | client.getdir_all_!(path, resC.rev).map(_.path) must be(List("a","b","c")) 69 | } 70 | 71 | "walk correctly" in{ 72 | val path = "/" + System.currentTimeMillis.toString 73 | val pathglob = path + "/*" 74 | val a = path + "/a" 75 | val b = path + "/b" 76 | val c = path + "/c" 77 | val resA: SetResponse = client.set_!(a, a, 0) 78 | val resB: SetResponse = client.set_!(b, b, 0) 79 | val resC: SetResponse = client.set_!(c, c, 0) 80 | 81 | client.walk_!(pathglob, resA.rev, 0).path must be(a) 82 | client.walk_!(pathglob, resA.rev, 0).value must be(a.getBytes) 83 | evaluating {client.walk_!(path,resA.rev,1)} must produce[ErrorResponseException] 84 | 85 | client.walk_!(pathglob, resB.rev, 0).path must be(a) 86 | client.walk_!(pathglob, resB.rev, 1).path must be(b) 87 | client.walk_!(pathglob, resB.rev, 0).value must be(a.getBytes) 88 | client.walk_!(pathglob, resB.rev, 1).value must be(b.getBytes) 89 | evaluating {client.walk_!(path,resB.rev,2)} must produce[ErrorResponseException] 90 | 91 | client.walk_!(pathglob, resC.rev, 0).path must be(a) 92 | client.walk_!(pathglob, resC.rev, 1).path must be(b) 93 | client.walk_!(pathglob, resC.rev, 2).path must be(c) 94 | client.walk_!(pathglob, resC.rev, 0).value must be(a.getBytes) 95 | client.walk_!(pathglob, resC.rev, 1).value must be(b.getBytes) 96 | client.walk_!(pathglob, resC.rev, 2).value must be(c.getBytes) 97 | evaluating {client.walk_!(path,resC.rev,3)} must produce[ErrorResponseException] 98 | 99 | client.walk_all_!(pathglob,resC.rev).map(w=>new String(w.value)) must be(List(a,b,c)) 100 | client.walk_all_!(pathglob,resC.rev).map(_.path) must be(List(a,b,c)) 101 | } 102 | 103 | "get rev correctly" in { 104 | (client.rev_!.rev) > 0 must be(true) 105 | } 106 | 107 | "wait correctly" in { 108 | reset(1) 109 | 110 | val path1 = "/" + System.currentTimeMillis.toString 111 | Thread.sleep(10) 112 | val path2 = "/" + System.currentTimeMillis.toString 113 | 114 | val response: SetResponse = client.set_!(path1, path1, 0L) 115 | val response2: SetResponse = client.set_!(path2, path2, 0L) 116 | 117 | client.waitAsync(path1, response.rev) { 118 | wr => { 119 | wr match { 120 | case Right(w@WaitResponse(_, value, _)) => { 121 | System.out.println(w.toString) 122 | System.out.println(new String(value)) 123 | signalAsyncDone() 124 | } 125 | case Left(ErrorResponse(code, msg)) => System.out.println(code + " " + msg) 126 | } 127 | } 128 | } 129 | 130 | client.waitAsync(path2, response2.rev) { 131 | wr => { 132 | wr match { 133 | case Right(w@WaitResponse(_, value, _)) => { 134 | System.out.println(w.toString) 135 | System.out.println(new String(value)) 136 | signalAsyncDone() 137 | } 138 | case Left(ErrorResponse(code, msg)) => System.out.println(code + " " + msg) 139 | } 140 | 141 | 142 | } 143 | } 144 | 145 | var set: SetResponse = client.set_!(path2, path1, response2.rev) 146 | client.set_!(path1, path2, response.rev) 147 | 148 | waitForAsync(10000) must be(true) 149 | System.out.println("DONE") 150 | 151 | reset(2) 152 | client.watch(path2,set.rev){ 153 | either=>{ 154 | debug(either) 155 | signalAsyncDone() 156 | true 157 | } 158 | } 159 | 160 | set = client.set_!(path2,"foowait1",set.rev) 161 | client.set_!(path2,"foowait2",set.rev) 162 | waitForAsync(10000) must be(true) 163 | 164 | } 165 | 166 | 167 | } 168 | 169 | def asyncGet(value: String, resp: Either[ErrorResponse, GetResponse]) { 170 | resp match { 171 | case Right(GetResponse(respValue, cas)) => { 172 | respValue must be(value.getBytes) 173 | signalAsyncDone() 174 | } 175 | case x@_ => failure(x) 176 | } 177 | } 178 | 179 | 180 | def debug(any: Any) { 181 | System.out.println(any.toString) 182 | } 183 | 184 | def failure(any: Any) { 185 | System.out.println("Error in Async GET") 186 | fail("Bad response") 187 | } 188 | 189 | "Two Clients" must { 190 | "not blow up" in { 191 | val second = new Flange(uri) 192 | second.set("/second", "second" getBytes, 0) 193 | client.get_!("/second").value must be("second".getBytes) 194 | } 195 | } 196 | 197 | override protected def beforeAll(configMap: Map[String, Any]) { 198 | client = new Flange(uri) 199 | } 200 | 201 | override protected def afterAll() { 202 | registry.shutdownAll() 203 | } 204 | } -------------------------------------------------------------------------------- /src/test/scala/com/force/doozer/flange/ConnectionSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Created by IntelliJ IDEA. 3 | * User: sclasen 4 | * Date: 4/21/11 5 | * Time: 9:36 PM 6 | */ 7 | package com.force.doozer.flange 8 | 9 | import org.scalatest.WordSpec 10 | import org.scalatest.matchers.MustMatchers 11 | import akka.actor.Actor._ 12 | import akka.actor.ActorRef 13 | import DoozerRequest._ 14 | import Flange._ 15 | class ConnectionSpec extends WordSpec with MustMatchers { 16 | 17 | 18 | "a test" must { 19 | "work" in { 20 | var rev = 0L 21 | actorOf(new ConnectionActor(new ClientState("secret",List("localhost:8046").toIterable))).start() 22 | val ref: ActorRef = registry.actorsFor[ConnectionActor].head 23 | ref !! GetRequest("/d/local/foo",rev) match { 24 | case Some(GetResponse(_, curr)) => { 25 | rev = curr 26 | print("got") 27 | } 28 | case Some(e@ErrorResponse(_, _)) => { 29 | print(e) 30 | } 31 | case x@_ => print(x) 32 | } 33 | 34 | 35 | 36 | 37 | ref !! SetRequest("/d/local/foo", ("bar" + rev).getBytes, rev) match { 38 | case Some(SetResponse(cas)) => { 39 | print("Set") 40 | rev = cas 41 | } 42 | case Some(ErrorResponse(code, detail)) => { 43 | print(code) 44 | print(detail) 45 | } 46 | case x@_ => print(x) 47 | } 48 | ref !! SetRequest("/d/local/foo", ("bar" + rev).getBytes, rev) match { 49 | case Some(SetResponse(cas)) => { 50 | print("Set") 51 | rev = cas 52 | } 53 | case Some(ErrorResponse(code, detail)) => { 54 | print(code) 55 | print(detail) 56 | } 57 | case x@_ => print(x) 58 | } 59 | 60 | registry.shutdownAll() 61 | } 62 | } 63 | 64 | def print(any: Any) { 65 | System.out.println("==========>" + any) 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /src/test/scala/com/force/doozer/flange/FailoverSpec.scala: -------------------------------------------------------------------------------- 1 | package com.force.doozer.flange 2 | 3 | /* 4 | * Created by IntelliJ IDEA. 5 | * User: sclasen 6 | * Date: 4/25/11 7 | * Time: 12:21 PM 8 | */ 9 | 10 | import org.scalatest.matchers.MustMatchers 11 | import org.scalatest.{BeforeAndAfterAll, WordSpec} 12 | import akka.actor.Actor 13 | 14 | class FailoverSpec extends WordSpec with MustMatchers with BeforeAndAfterAll with Waiting { 15 | 16 | var client: Flange = null 17 | 18 | 19 | "A Doozer DoozerClient" must { 20 | "fail over properly when no servers are up" in { 21 | val clientWithNoServersUp = new Flange("doozer:?ca=localhost:12321&ca=localhost:12322&sk=foo") 22 | try { 23 | clientWithNoServersUp.set("/nothome", "avalue".getBytes, 0L) match { 24 | case Left(ErrorResponse(err, _)) => err must be(Flange.allConnectionsFailed) 25 | case Right(SetResponse(_)) => fail("Set shouldnt success with no server") 26 | } 27 | clientWithNoServersUp.getAsync("/nothome") { 28 | either => 29 | try { 30 | either match { 31 | case Left(ErrorResponse(err, _)) => { 32 | err must be(Flange.allConnectionsFailed) 33 | } 34 | case Right(GetResponse(_, _)) => fail("get shouldnt success with no server") 35 | } 36 | } finally { 37 | signalAsyncDone() 38 | } 39 | } 40 | waitForAsync() 41 | } catch { 42 | case e => { 43 | signalAsyncDone() 44 | fail(e) 45 | } 46 | } finally { 47 | clientWithNoServersUp.stop 48 | stop() 49 | } 50 | } 51 | 52 | 53 | } 54 | 55 | def stop() { 56 | Actor.registry.shutdownAll() 57 | } 58 | 59 | } -------------------------------------------------------------------------------- /src/test/scala/com/force/doozer/flange/URISpec.scala: -------------------------------------------------------------------------------- 1 | package com.force.doozer.flange 2 | 3 | /* 4 | * Created by IntelliJ IDEA. 5 | * User: sclasen 6 | * Date: 4/25/11 7 | * Time: 9:51 AM 8 | */ 9 | 10 | import org.scalatest.matchers.MustMatchers 11 | import org.scalatest.{BeforeAndAfterAll, WordSpec} 12 | 13 | 14 | class URISpec extends WordSpec with MustMatchers with BeforeAndAfterAll { 15 | 16 | "A Flange" must { 17 | "parse doozer uris correctly" in { 18 | val one = "doozer:?ca=localhost:8046&sk=secret" 19 | Flange.parseDoozerUri(one)._1.headOption must be(Some("localhost:8046")) 20 | val three = "doozer:?ca=localhost:8046&ca=localhost:8047&ca=localhost:8048&sk=secret" 21 | Flange.parseDoozerUri(three)._1 must be(List("localhost:8046","localhost:8047","localhost:8048")) 22 | Flange.parseDoozerUri(three)._2 must be ("secret") 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/test/scala/com/force/doozer/flange/Waiting.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Created by IntelliJ IDEA. 3 | * User: sclasen 4 | * Date: 4/25/11 5 | * Time: 2:01 PM 6 | */ 7 | package com.force.doozer.flange 8 | 9 | import java.util.concurrent.{TimeUnit, CountDownLatch} 10 | 11 | trait Waiting { 12 | 13 | 14 | @volatile var latch = new CountDownLatch(1) 15 | 16 | def reset(count: Int) { 17 | while (latch.getCount > 0) latch.countDown() 18 | latch = new CountDownLatch(count) 19 | } 20 | 21 | def waitForAsync() { 22 | latch.await() 23 | } 24 | 25 | def waitForAsync(timeout: Long): Boolean = { 26 | latch.await(timeout, TimeUnit.MILLISECONDS) 27 | } 28 | 29 | def signalAsyncDone() { 30 | latch.countDown() 31 | } 32 | } -------------------------------------------------------------------------------- /startDoozer.sh: -------------------------------------------------------------------------------- 1 | rm ./doozerd-0.8/dooz.log 2 | 3 | set -e 4 | trap quit INT TERM EXIT 5 | 6 | quit() { 7 | killall doozerd 8 | echo "Unable to successfully start the cluster" 9 | exit 10 | } 11 | 12 | export DOOZER_RWSECRET=secret 13 | 14 | touch ./doozerd-0.8/dooz.log 15 | 16 | OS=linux 17 | UNAME=`uname` 18 | if [ "$UNAME" = "Darwin" ]; then 19 | OS=osx 20 | fi 21 | 22 | ./doozerd-0.8/$OS-386/doozerd -l="127.0.0.1:8046" -w=":8080" >> ./doozerd-0.8/dooz.log 2>&1 & 23 | ./doozerd-0.8/$OS-386/doozerd -l="127.0.0.1:8047" -a="127.0.0.1:8046" -w=":8081" >> ./doozerd-0.8/dooz.log 2>&1 & 24 | ./doozerd-0.8/$OS-386/doozerd -l="127.0.0.1:8048" -a="127.0.0.1:8046" -w=":8082" >> ./doozerd-0.8/dooz.log 2>&1 & 25 | 26 | sleep 1 27 | 28 | printf '' | ./doozerd-0.8/$OS-386/doozer -a "doozer:?ca=127.0.0.1:8046&sk=$DOOZER_RWSECRET" set /ctl/cal/1 0 > /dev/null 29 | printf '' | ./doozerd-0.8/$OS-386/doozer -a "doozer:?ca=127.0.0.1:8046&sk=$DOOZER_RWSECRET" set /ctl/cal/2 0 > /dev/null 30 | 31 | 32 | trap - INT TERM EXIT 33 | echo "Started" 34 | 35 | 36 | -------------------------------------------------------------------------------- /stopDoozer.sh: -------------------------------------------------------------------------------- 1 | killall doozerd --------------------------------------------------------------------------------