Class: RStyx::Client::Connection
- Inherits:
-
Object
- Object
- RStyx::Client::Connection
- Defined in:
- lib/rstyx/client.rb
Overview
module StyxClient
Direct Known Subclasses
Instance Attribute Summary collapse
-
#connectstate ⇒ Object
readonly
Returns the value of attribute connectstate.
-
#msize ⇒ Object
readonly
Returns the value of attribute msize.
-
#peerauth ⇒ Object
readonly
Returns the value of attribute peerauth.
-
#pendingclunks ⇒ Object
Returns the value of attribute pendingclunks.
-
#rootdirectory ⇒ Object
readonly
Returns the value of attribute rootdirectory.
-
#rootfid ⇒ Object
readonly
Returns the value of attribute rootfid.
-
#umask ⇒ Object
Returns the value of attribute umask.
-
#usedfids ⇒ Object
Returns the value of attribute usedfids.
-
#version ⇒ Object
readonly
Returns the value of attribute version.
Instance Method Summary collapse
-
#connect(&block) ⇒ Object
Connect to a remote Styx server.
-
#disconnect ⇒ Object
Disconnect from the remote server.
-
#get_free_fid ⇒ Object
Get a new free FID.
-
#initialize(auth = nil) ⇒ Connection
constructor
A new instance of Connection.
-
#open(path, mode = "r", perm = 0666, &block) ⇒ Object
Open a file on the remote server, throwing a StyxException if the file can’t be found or opened in a given mode.
-
#return_fid(fid) ⇒ Object
Returns a fid after we’re done using it.
-
#send_message(msg, timeout = 0) ⇒ Object
Send a message, and return the response.
-
#tclunk(fid, sync = false) ⇒ Object
Fire and forget a Tclunk for some fid.
Constructor Details
#initialize(auth = nil) ⇒ Connection
Returns a new instance of Connection.
194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/rstyx/client.rb', line 194 def initialize(auth=nil) @usedfids = [] @pendingclunks = {} @rpendingclunks = {} @conn = nil @rootfid = nil @eventthread = nil @authenticator = auth @clunklock = Mutex.new @umask = ::File.umask @peerauth = nil end |
Instance Attribute Details
#connectstate ⇒ Object (readonly)
Returns the value of attribute connectstate.
191 192 193 |
# File 'lib/rstyx/client.rb', line 191 def connectstate @connectstate end |
#msize ⇒ Object (readonly)
Returns the value of attribute msize.
191 192 193 |
# File 'lib/rstyx/client.rb', line 191 def msize @msize end |
#peerauth ⇒ Object (readonly)
Returns the value of attribute peerauth.
192 193 194 |
# File 'lib/rstyx/client.rb', line 192 def peerauth @peerauth end |
#pendingclunks ⇒ Object
Returns the value of attribute pendingclunks.
190 191 192 |
# File 'lib/rstyx/client.rb', line 190 def pendingclunks @pendingclunks end |
#rootdirectory ⇒ Object (readonly)
Returns the value of attribute rootdirectory.
192 193 194 |
# File 'lib/rstyx/client.rb', line 192 def rootdirectory @rootdirectory end |
#rootfid ⇒ Object (readonly)
Returns the value of attribute rootfid.
192 193 194 |
# File 'lib/rstyx/client.rb', line 192 def rootfid @rootfid end |
#umask ⇒ Object
Returns the value of attribute umask.
190 191 192 |
# File 'lib/rstyx/client.rb', line 190 def umask @umask end |
#usedfids ⇒ Object
Returns the value of attribute usedfids.
190 191 192 |
# File 'lib/rstyx/client.rb', line 190 def usedfids @usedfids end |
#version ⇒ Object (readonly)
Returns the value of attribute version.
191 192 193 |
# File 'lib/rstyx/client.rb', line 191 def version @version end |
Instance Method Details
#connect(&block) ⇒ Object
Connect to a remote Styx server. If a block is passed, yield self to the block and then do a disconnect when the block finishes.
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 |
# File 'lib/rstyx/client.rb', line 251 def connect(&block) prepare_connection() uname = ENV['USER'] aname = "" # Do Inferno authentication if the @authenticator object is a # keyring authinfo object if @authenticator.is_a?(Keyring::Authinfo) @conn.keyringauth = Keyring::FileWrapper.new(@conn) @peerauth, secret = Keyring.auth(@conn.keyringauth, :client, @authenticator, ["none"]) @conn.keyringauth = nil end # Connection has been established. Begin the handshaking process # with the remote server. # # 1. Send a Tversion message and check the response from the # remote Styx server. # rver = (Message::Tversion.new(:msize => 8216, :version => "9P2000")) if (rver.version != "9P2000") raise StyxException.new("Server uses unsupported Styx version #{rver.version}") end @msize = rver.msize @version = rver.version rfid = nil # 2. Attach to the remote server if @auth.nil? || @authenticator.is_a?(Keyring::Authinfo) # unauthenticated connection rfid = get_free_fid rattach = (Message::Tattach.new(:fid => rfid, :afid => NOFID, :uname => uname, :aname => aname)) else # # 3. Perform authentication based on the passed authenticator # object. # # If we have an authenticator object, we call its authenticator # method with ourself. # rfid = @auth.authenticate(self) end # If we get here, we're connected, and rfid represents the root # fid of the connection @rootfid = rfid if block_given? begin yield self ensure self.disconnect end else return(self) end end |
#disconnect ⇒ Object
Disconnect from the remote server.
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 |
# File 'lib/rstyx/client.rb', line 317 def disconnect # Clunk all outstanding fids in reverse order so the root fid # gets clunked last. while (@usedfids.length > 0) begin rclunk = tclunk(@usedfids[-1], true) rescue # An error is most likely a no such fid error. Return the fid # manually in this case. return_fid(@usedfids[-1]) end end @conn.disconnect @eventthread.kill end |
#get_free_fid ⇒ Object
Get a new free FID.
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/rstyx/client.rb', line 210 def get_free_fid found = false val = nil 0.upto(MAX_FID) do |i| unless @usedfids.include?(i) val = i break end end if val.nil? raise StyxException.new("No more free fids") end @usedfids << val return(val) end |
#open(path, mode = "r", perm = 0666, &block) ⇒ Object
Open a file on the remote server, throwing a StyxException if the file can’t be found or opened in a given mode.
path
-
The path of the file relative to the server root.
mode
-
Integer representing the mode, or one of “r”, “r+”, “w”, “w+”, “a”, “a+”, “e” as aliases
return
-
A File object representing the opened file, or
possibly a Directory object if the file was a directory.
If a block is passed, it will yield the file object to the block and close the file when the block finishes (actually it will pass the block on to the StyxFile#open method, which does just that).
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 |
# File 'lib/rstyx/client.rb', line 401 def open(path, mode="r", perm=0666, &block) file = File.new(self, path) append = false create = false numeric_mode = nil if mode.is_a?(Integer) numeric_mode = mode else case mode.to_s when "r" numeric_mode = OREAD when "r+" numeric_mode = ORDWR when "w" numeric_mode = OTRUNC | OWRITE create = true when "w+" numeric_mode = OTRUNC | ORDWR create = true when "a" numeric_mode = OWRITE append = true create = true when "a+" numeric_mode = ORDWR append = true create = true when "e" numeric_mode = OEXEC end end fp = file.open(numeric_mode, perm, create, &block) if append fp.seek(0, 2) end return(fp) end |
#return_fid(fid) ⇒ Object
Returns a fid after we’re done using it.
230 231 232 |
# File 'lib/rstyx/client.rb', line 230 def return_fid(fid) @usedfids.delete(fid) end |
#send_message(msg, timeout = 0) ⇒ Object
Send a message, and return the response. Delegates to @conn#send_message. Do not use this method to send Tclunk messages!
339 340 341 |
# File 'lib/rstyx/client.rb', line 339 def (msg, timeout=0) @conn.(msg, timeout) end |
#tclunk(fid, sync = false) ⇒ Object
Fire and forget a Tclunk for some fid. When the Rclunk is received, return the fid. USE THIS METHOD, AND THIS METHOD ONLY, to send Tclunk messages.
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 |
# File 'lib/rstyx/client.rb', line 348 def tclunk(fid, sync=false) if @rpendingclunks.has_key?(fid) return end q = nil if sync q = Queue.new end tag = @conn.(Message::Tclunk.new(:fid => fid)) do |tx,rx| # Test whether the response is an Rclunk. if rx.class != Message::Rclunk # this is an error condition, but it will only get reported # if Thread.abort_on_exception is set to true, or if # the tclunk is synchronous exc = StyxException.new("#{tx.to_s} received #{rx.to_s}") if sync q << exc else raise exc end end # return the FID fid = @pendingclunks.delete(tag) @rpendingclunks.delete(fid) return_fid(fid) if sync q << fid end end @pendingclunks[tag] = fid @rpendingclunks[fid] = tag if sync res = q.shift if res.class == StyxException raise res end end end |