]> git.saurik.com Git - redis.git/blob - client-libraries/scala/src/main/scala/com/redis/SocketOperations.scala
137ecae34011014df557c6597991402d376239e7
[redis.git] / client-libraries / scala / src / main / scala / com / redis / SocketOperations.scala
1 package com.redis
2
3 /**
4 * Socket operations
5 *
6 */
7
8 import java.io._
9 import java.net.Socket
10
11 trait SocketOperations {
12
13 // Response codes from the Redis server
14 // they tell you what's coming next from the server.
15 val ERR: String = "-"
16 val OK: String = "+OK"
17 val SINGLE: String = "+"
18 val BULK: String = "$"
19 val MULTI: String = "*"
20 val INT:String = ":"
21
22 val host: String
23 val port: Int
24
25 // File descriptors.
26 var socket: Socket = null
27 var out: OutputStream = null
28 var in: BufferedReader = null
29
30 def getOutputStream: OutputStream = out
31 def getInputStream: BufferedReader = in
32 def getSocket: Socket = socket
33
34 def connected = { getSocket != null }
35 def reconnect = { disconnect && connect; }
36
37 // Connects the socket, and sets the input and output streams.
38 def connect: Boolean = {
39 try {
40 socket = new Socket(host, port)
41 out = getSocket.getOutputStream
42 in = new BufferedReader(new InputStreamReader(getSocket.getInputStream));
43 true
44 } catch {
45 case _ => clear_fd; false;
46 }
47 }
48
49 // Disconnects the socket.
50 def disconnect: Boolean = {
51 try {
52 socket.close
53 out.close
54 in.close
55 clear_fd
56 true
57 } catch {
58 case _ => false
59 }
60 }
61
62 def clear_fd = {
63 socket = null
64 out = null
65 in = null
66 }
67
68 // Reads the server responses as Scala types.
69 def readString: String = readResponse.toString // Reads the server response as an Int
70 def readInt: Int = Integer.parseInt(readResponse.toString) // Reads the server response as an Int
71 def readList: List[String] = listReply(readResponse.toString) // Reads the server response as a List
72 def readSet: Set[String] = setReply(readResponse.toString) // Reads the server response as a String
73 def readBoolean: Boolean = readResponse match {
74 case 1 => true
75 case OK => true
76 case _ => false
77 }
78
79 // Read from Input Stream.
80 def readline: String = {
81 try {
82 getInputStream.readLine()
83 } catch {
84 case _ => ERR;
85 }
86 }
87
88 // Gets the type of response the server is going to send.
89 def readtype = {
90 val res = readline
91 if(res !=null){
92 (res(0).toString(), res)
93 }else{
94 ("-", "")
95 }
96 }
97
98 // Reads the response from the server based on the response code.
99 def readResponse = {
100
101 val responseType = readtype
102 try{
103 responseType._1 match {
104 case ERR => reconnect; // RECONNECT
105 case SINGLE => lineReply(responseType._2)
106 case BULK => bulkReply(responseType._2)
107 case MULTI => responseType._2
108 case INT => integerReply(responseType._2)
109 case _ => reconnect; // RECONNECT
110 }
111 }catch{
112 case e: Exception => false
113 }
114 }
115
116 def integerReply(response: String): Int = Integer.parseInt(response.split(":")(1).toString)
117
118 def lineReply(response: String): String = response
119
120 def listReply(response: String): List[String] = {
121 val total = Integer.parseInt(response.split('*')(1))
122 var list: List[String] = List()
123 for(i <- 1 to total){
124 list = (list ::: List(bulkReply(readtype._2)))
125 }
126 list
127 }
128
129 def bulkReply(response: String) = {
130 if(response(1).toString() != ERR){
131 var length: Int = Integer.parseInt(response.split('$')(1).split("\r\n")(0))
132 var line, res: String = ""
133 while(length >= 0){
134 line = readline
135 length -= (line.length+2)
136 res += line
137 if(length > 0) res += "\r\n"
138 }
139 res
140 }else{ null }
141 }
142
143 def setReply(response: String): Set[String] = {
144 val total = Integer.parseInt(response.split('*')(1))
145 var set: Set[String] = Set()
146 for(i <- 1 to total){
147 set += bulkReply(readtype._2)
148 }
149 set
150 }
151
152 // Wraper for the socket write operation.
153 def write_to_socket(data: String)(op: OutputStream => Unit) = op(getOutputStream)
154
155 // Writes data to a socket using the specified block.
156 def write(data: String) = {
157 if(!connected) connect;
158 write_to_socket(data){
159 getSocket =>
160 try {
161 getSocket.write(data.getBytes)
162 } catch {
163 case _ => reconnect;
164 }
165 }
166 }
167 }