MorphOS Developer
Posts: 1107 from 2003/6/11
From: Białystok...
@igracki
In fact direct connection won't work. First, it is not possible to have multiple
file.output instances writing to one file. This is because every instance creates a process and this process opens the output file in exclusive mode. Then the second (and any further) instance will fail in
NewObject(), as it will be unable to open the file for writing.
On the other hand it is perfectly possible to have multiple
http.stream instances downloading the same resource. While API of the class does not have specific attributes for accessing particular fragment of a resource, it may be easily done with extra header fields (there is an attribute for it). The
http.stream has a set of methods and attributes for getting HTTP header fields from server response and adding additional HTTP fields to a request. Then response may be examined for "Accept-Ranges", and later "Content-Range", also "Range" may be injected in requests. Application should handle 206 and 416 responses. RFC 2616 contains all the details.
So we are able to have multiple
http.stream objects asynchronously downloading different chunks of the same file. Then we need a way to push those chunks into a single
file.output. It needs three features, one is already implemented, two are not:
1. Ability to dynamically disconnect and connect sources on input port. It is fully supported to issue MMM_Pause() to
file.output, connect another input with MediaConnectTagList() and resume operation with MMM_Start().
2. Ability to perform seek in the output file. It is not yet implemented. Without it, we have to write chunks in linear order, so it may happen than some downloading objects will have to wait on other objects. This effectively kills the idea of concurrent downloading. It can be easily implemented with additional attribute.
3. Ability to set the output file size in advance. As you have stated, it decreases fragmentation. This can be done with an attribute, which will read source length and call SetFileSize(). However it is not implemented in the current version.
It should be noted that implementing features 2. and 3. will need some checks. Currently
file.output does only sequential writes, so it can write to things like pipes, consoles, remote filesystems and other DOS pseudodevices. Most of them won't handle Seek() or SetFileSize().
Another important thing is effective buffering. When
file.output is connected to
http.stream and then started, its worker process will pull data from stream synchronously. You can't manipulate the output object until the data block is received and saved.
Then if I was designing a concurrent downloader, I would use only
http.stream instances and handle buffering and writing either directly by application or by writing some clever custom Reggae class with many inputs and one output. The second solution would require the above feature 2. and 3. to be implemented in
file.output. Such Reggae class will launch a thread for every input and then multiplex buffers and change output position accordingly.