Class: QuartzTorrent::PieceManager
- Inherits:
-
Object
- Object
- QuartzTorrent::PieceManager
- Defined in:
- lib/quartz_torrent/filemanager.rb
Overview
A class that spawns a thread for performing PieceIO operations asynchronously. This class is what is used to read and write blocks of a torrent.
Defined Under Namespace
Classes: Result
Instance Attribute Summary collapse
-
#torrentDataLength ⇒ Object
readonly
Returns the value of attribute torrentDataLength.
Instance Method Summary collapse
-
#checkPieceHash(pieceIndex) ⇒ Object
Validate that the hash of the downloaded piece matches the hash from the metainfo.
-
#findExistingPieces ⇒ Object
This is meant to be called when the torrent is first loaded to check what pieces we’ve already downloaded.
-
#flush ⇒ Object
Flush to disk.
-
#hasResults? ⇒ Boolean
Check if there are results ready.
-
#initialize(baseDirectory, torrinfo, alertCallback = nil) ⇒ PieceManager
constructor
Create a new PieceManager that will map to files inside ‘baseDirectory’.
-
#nextResult ⇒ Object
Result retrieval.
-
#progress(requestId) ⇒ Object
Get the progress of the specified request as an integer between 0 and 100.
-
#readBlock(pieceIndex, offset, length) ⇒ Object
Read a block from the torrent asynchronously.
-
#readPiece(pieceIndex) ⇒ Object
Read a block of the torrent asynchronously.
-
#stop ⇒ Object
Stop the PieceManager.
-
#wait ⇒ Object
Wait until the next result is ready.
-
#writeBlock(pieceIndex, offset, block) ⇒ Object
Write a block to the torrent asynchronously.
Constructor Details
#initialize(baseDirectory, torrinfo, alertCallback = nil) ⇒ PieceManager
Create a new PieceManager that will map to files inside ‘baseDirectory’. Parameter ‘torrinfo’ should be a Metainfo::Info object (the info part of the metainfo). Parameter ‘alertCallback’ should be a Proc. It will be called when an operation is complete. The alerted code can then retrieve the events from the completed queue. This callback will be called from a different thread.
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 |
# File 'lib/quartz_torrent/filemanager.rb', line 289 def initialize(baseDirectory, torrinfo, alertCallback = nil) @alertCallback = alertCallback @mutex = Mutex.new @results = [] @requests = [] # The progress of requests as they are being serviced, keyed by request id. @requestProgress = {} @progressMutex = Mutex.new @requestsSemaphore = Semaphore.new @resultsSemaphore = Semaphore.new @baseDirectory = baseDirectory @torrinfo = torrinfo @pieceIO = PieceIO.new(baseDirectory, torrinfo) @requestId = 0 @logger = LogManager.getLogger("piecemanager") @torrentDataLength = torrinfo.dataLength @startedCondition = ConditionVariable.new @startedMutex = Mutex.new @state = :before_start startThread end |
Instance Attribute Details
#torrentDataLength ⇒ Object (readonly)
Returns the value of attribute torrentDataLength.
311 312 313 |
# File 'lib/quartz_torrent/filemanager.rb', line 311 def torrentDataLength @torrentDataLength end |
Instance Method Details
#checkPieceHash(pieceIndex) ⇒ Object
Validate that the hash of the downloaded piece matches the hash from the metainfo. The result is successful? if the hash matches, false otherwise. The data of the result is set to the piece index.
360 361 362 363 364 365 366 |
# File 'lib/quartz_torrent/filemanager.rb', line 360 def checkPieceHash(pieceIndex) id = returnAndIncrRequestId return id if @state == :after_stop @requests.push [id, :hash_piece, pieceIndex] @requestsSemaphore.signal id end |
#findExistingPieces ⇒ Object
This is meant to be called when the torrent is first loaded to check what pieces we’ve already downloaded. The data property of the result for this call is set to a Bitfield representing the complete pieces.
349 350 351 352 353 354 355 |
# File 'lib/quartz_torrent/filemanager.rb', line 349 def findExistingPieces id = returnAndIncrRequestId return id if @state == :after_stop @requests.push [id, :find_existing] @requestsSemaphore.signal id end |
#flush ⇒ Object
Flush to disk. The result for this operation is always successful.
369 370 371 372 373 374 375 |
# File 'lib/quartz_torrent/filemanager.rb', line 369 def flush() id = returnAndIncrRequestId return id if @state == :after_stop @requests.push [id, :flush] @requestsSemaphore.signal id end |
#hasResults? ⇒ Boolean
Check if there are results ready. This method will return immediately without blocking.
409 410 411 |
# File 'lib/quartz_torrent/filemanager.rb', line 409 def hasResults? ! @results.empty? end |
#nextResult ⇒ Object
Result retrieval. Returns the next result, or nil if none are ready. The results that are returned are PieceIOWorker::Result objects. For readBlock operations the data property of the result object contains the block.
381 382 383 384 385 386 387 388 |
# File 'lib/quartz_torrent/filemanager.rb', line 381 def nextResult result = nil @mutex.synchronize do result = @results.shift @progressMutex.synchronize{ @requestProgress.delete result.requestId } if result end result end |
#progress(requestId) ⇒ Object
Get the progress of the specified request as an integer between 0 and 100. Currently, only the findExistingPieces operation registers progress; other operations just return nil for this.
393 394 395 396 397 |
# File 'lib/quartz_torrent/filemanager.rb', line 393 def progress(requestId) result = nil @progressMutex.synchronize{ result = @requestProgress[requestId] } result end |
#readBlock(pieceIndex, offset, length) ⇒ Object
Read a block from the torrent asynchronously. When the operation is complete the result is stored in the ‘results’ list. This method returns an id that can be used to match the response to the request. The readBlock and writeBlock methods are not threadsafe with respect to callers; they shouldn’t be called by multiple threads concurrently.
319 320 321 322 323 324 325 |
# File 'lib/quartz_torrent/filemanager.rb', line 319 def readBlock(pieceIndex, offset, length) id = returnAndIncrRequestId return id if @state == :after_stop @requests.push [id, :read_block, pieceIndex, offset, length] @requestsSemaphore.signal id end |
#readPiece(pieceIndex) ⇒ Object
Read a block of the torrent asynchronously.
337 338 339 340 341 342 343 |
# File 'lib/quartz_torrent/filemanager.rb', line 337 def readPiece(pieceIndex) id = returnAndIncrRequestId return id if @state == :after_stop @requests.push [id, :read_piece, pieceIndex] @requestsSemaphore.signal id end |
#stop ⇒ Object
Stop the PieceManager.
414 415 416 417 418 419 420 |
# File 'lib/quartz_torrent/filemanager.rb', line 414 def stop waitUntilStarted @state = :after_stop id = returnAndIncrRequestId @requests.push [id, :stop] @requestsSemaphore.signal end |
#wait ⇒ Object
Wait until the next result is ready. If this method is used it must always be called before nextResult. This is mostly useful for testing.
401 402 403 404 405 |
# File 'lib/quartz_torrent/filemanager.rb', line 401 def wait waitUntilStarted @resultsSemaphore.wait end |
#writeBlock(pieceIndex, offset, block) ⇒ Object
Write a block to the torrent asynchronously.
328 329 330 331 332 333 334 |
# File 'lib/quartz_torrent/filemanager.rb', line 328 def writeBlock(pieceIndex, offset, block) id = returnAndIncrRequestId return id if @state == :after_stop @requests.push [id, :write_block, pieceIndex, offset, block] @requestsSemaphore.signal id end |