subtraction of already painted area: be fool and
[kdelibs.git] / kio / DESIGN
blob30a037c8159e23a53c56fb484a7ec1e387c15047
1 DESIGN:
2 =======
4 libkio uses kioslaves (separate processes) that handle a given protocol.
5 Launching those slaves is taken care of by the kdeinit/klauncher tandem,
6 which are notified by DCOP.
8 Connection is the most low-level class, the one that encapsulates the pipe.
10 SlaveInterface is the main class for transferring anything to the slave
11 and Slave, which inherits SlaveInterface, is the sub class that Job should handle.
13 A slave inherits SlaveBase, which is the other half of SlaveInterface.
15 The scheduling is supposed to be on a two level basis. One is in the daemon
16 and one is in the application. The daemon one (as opposite to the holy one? :)
17 will determine how many slaves are ok for this app to be opened and it will
18 also assign tasks to actually existing slaves.
19 The application will still have some kind of a scheduler, but it should be
20 a lot simpler as it doesn't have to decide anything besides which
21 task goes to which pool of slaves (related to the protocol/host/user/port)
22 and move tasks around.
23 Currently a design study to name it cool is in scheduler.cpp but in the
24 application side. This is just to test other things like recursive jobs
25 and signals/slots within SlaveInterface. If someone feels brave, the scheduler
26 is yours!
27 On a second thought: at the daemon side there is no real scheduler, but a
28 pool of slaves. So what we need is some kind of load calculation of the
29 scheduler in the application and load balancing in the daemon. 
31 A third thought: Maybe the daemon can just take care of a number of 'unused'
32 slaves. When an application needs a slave, it can request it from the daemon. 
33 The application will get one, either from the pool of unused slaves, 
34 or a new one will be created. This keeps things simple at the daemon level.
35 It is up to the application to give the slaves back to the daemon.
36 The scheduler in the application must take care not to request too many
37 slaves and could implement priorities.
39 Thought on usage:
40 * Typically a single slave-type is used exclusively in one application. E.g.
41 http slaves are used in a web-browser. POP3 slaves used in a mail program.
43 * Sometimes a single program can have multiple roles. E.g. konqueror is
44 both a web-browser and a file-manager. As a web-browser it primarily uses
45 http-slaves as a file-manager file-slaves.
47 * Selecting a link in konqueror: konqueror does a partial download of
48 the file to check the mimetype (right??) then the application is
49 started which downloads the complete file. In this case it should 
50 be able to pass the slave which does the partial download from konqueror
51 to the application where it can do the complete download.
53 Do we need to have a hard limit on the number of slaves/host?
54 It seems so, because some protocols are about to fail if you
55 have two slaves running in parralel (e.g. POP3) 
56 This has to be implemented in the daemon because only at daemon
57 level all the slaves are known. As a consequence slaves must 
58 be returned to the daemon before connecting to another host.
59 (Returning the slaves back to the daemon after every job is not
60 strictly needed and only causes extra overhead) 
62 Instead of actually returning the slave to the daemon, it could 
63 be enough to ask 'recycling permission' from the daemon: the 
64 application asks the daemon whether it is ok to use a slave for 
65 another host. The daemon can then update its administration of
66 which slave is connected to which host.
68 The above does of course not apply to hostless protocols (like file).
69 (They will never change host).
71 Apart from a 'hard limit' on the number of slaves/host we can have
72 a 'soft limit'. E.g. upon connection to a HTTP 1.1 server, the web-
73 server tells the slave the number of parallel connections allowed.
74 THe simplest solution seems to be to treat 'soft limits' the same
75 as 'hard limits'. This means that the slave has to communicate the
76 'soft limit' to the daemon.
78 Jobs using multiple slaves.
80 If a job needs multiple slaves in parallel (e.g. copying a file from 
81 a web-server to a ftp-server or browsing a tar-file on a ftp-site)
82 we must make sure to request the daemon for all slaves together since 
83 otherwise there is a risk of deadlock. 
85 (If two applications both need a 'pop3' and a 'ftp' slave for a single 
86 job and only a single slave/host is allowed for pop3 and ftp, we must 
87 prevent giving the single pop3 slave to application #1 and the single 
88 ftp slave to application #2. Both applications will then wait till the 
89 end of times till they get the other slave so that they can start the 
90 job. (This is a quite unlikely situation, but nevertheless possible))
93 File Operations:
94 listRecursive is implemented as listDir and finding out if in the result
95  is a directory. If there is, another listDir job is issued. As listDir
96  is a readonly operation it fails when a directory isn't readable
97   .. but the main job goes on and discards the error, because
98 bIgnoreSubJobsError is true, which is what we want (David)
100 del is implemented as listRecursive, removing all files and removing all
101  empty directories. This basically means if one directory isn't readable
102  we don't remove it as listRecursive didn't find it. But the del will later
103  on try to remove it's parent directory and fail. But there are cases when
104  it would be possible to delete the dir in chmod the dir before. On the
105  other hand del("/") shouldn't list the whole file system and remove all
106  user owned files just to find out it can't remove everything else (this
107  basically means we have to take care of things we can remove before we try)
109  ... Well, rm -rf / refuses to do anything, so we should just do the same:
110  use a listRecursive with bIgnoreSubJobsError = false. If anything can't
111  be removed, we just abort. (David)
113  ... My concern was more that the fact we can list / doesn't mean we can
114  remove it. So we shouldn't remove everything we could list without checking
115  we can. But then the question arises how do we check whether we can remove it?
116  (Stephan)
118  ... I was wrong, rm -rf /, even as a user, lists everything and removes
119  everything it can (don't try this at home!). I don't think we can do
120  better, unless we add a protocol-dependent "canDelete(path)", which is
121  _really_ not easy to implement, whatever protocol. (David)
124 Lib docu
125 ========
127 mkdir: ...
129 rmdir: ...
131 chmod: ...
133 special: ...
135 stat: ...
137 get is implemented as TransferJob. Clients get 'data' signals with the data.
138 A data block of zero size indicates end of data (EOD)
140 put is implemented as TransferJob. Clients have to connect to the 
141 'dataReq' signal. The slave will call you when it needs your data.
143 mimetype: ...
145 file_copy: copies a single file, either using CMD_COPY if the slave 
146            supports that or get & put otherwise.
148 file_move: moves a single file, either using CMD_RENAME if the slave
149            supports that, CMD_COPY + del otherwise, or eventually
150            get & put & del.
152 file_delete: delete a single file. 
154 copy: copies a file or directory, recursively if the latter
156 move: moves a file or directory, recursively if the latter
158 del: deletes a file or directory, recursively if the latter
160 PROGRESS DISPLAYING :
161 =====================
162 Taj brought up the idea of deligating all progress informations to an extern
163 GUI daemon which could be provided in several implementations - examples
164 are popup dialogs (most are annoyed by them, like me :) or a kicker applet
165 or something completely different. This would also remove the dependency on
166 libkdeui (I hope).
167 Conclusion: kio_uiserver is this single GUI daemon, but the dependency on
168 libkdeui couldn't be removed (for many reasons, including Job::showErrorDialog())
170 A. progress handling
171 ---------------------
172 There will be two ways how the application can display progress :
174 1. regular apps will use NetAccess for all kio operations and will not  care
175     about progress handling :
176  - NetAccess creates Job
177  - NetAccess creates JobObserver that will connect to the Job's signals and
178     pass them via dcop to the running GUI Progress Server
180 2. apps that want to do some handling with progress dialogs like Caitoo or
181     KMail  :
182  - app creates Job
183  - app creates a progress dialog : this should be a ProgressBase descendant
184     e.g. StatusProgress or custom progress dialog
185  - app calls progress->setJob( job ) in order to connect job's signals with
186     progress dialog slots
188 B. customized progress dialogs
189 -------------------------------
190  This will be similar to what we had before.
192  - ProgressBase class that all other dialogs will inherit.
193     will contain an initialization method setJob( KIO::Job*) for apps of the
194     second class (see A.2 above), that will connect job's signals to dialog's
195     slots
197  - DefaultProgress ( former KIOSimpleProgressDialog ) that will be used for    
198     regular progress dialogs created by GUI Progress Server
200  - StatusProgress ( former KIOLittleProgressDialog ) that can be used for      
201     embedding in status bar
203 C. GUI Progress Server
204 -----------------------
205  This is a special progress server.
206  - createProgress() will either create a DefaultProgress dialog or add new entry
207     in a ListProgress ( an all-jobs-in-one progress dialog )
208  - after receiving signals from the JobObserver via DCOP it will call
209     appropriate method of progress dialog ( either in DefaultProgress or ListProgress )
210  - ListProgres can be a Caitoo style dialog, kicker applet or both in one.
212 D. Some notes
213 --------------
214  1. most of the apps will not care at all about the progress display
215  2. user will be able to choose whether he wants to see separate progress
216     dialogs or all-in-one ListProgress dialog
217  3. developers can create their custom progress dialogs that inherit
218     ProgressBase and do any manipulation with a dialog if they use a second
219     approach ( see A.2 above )
222 Streaming 
223 ---------
225  1. We currently support a streaming "GET": e.g. file:/tmp/test.gz#gzip:/
226     works. The following should also work: file:/tmp/test.gz.gz#gzip:/#gzip:/
227     The current approach makes a TrasnferJob for gzip:/ and then adds a
228     subjob for "file:/tmp/test.gz.gz#gzip:/" which itself adds a subjob
229     for "file:/tmp/test.gz.gz".
230  2. This doesn't extend very well to PUT, because there the order should
231     basically be the other way around, but the "input" to the job as a whole
232     should go to the "gzip:/" job, not to the "file:/tmp/test.gz.gz."
233     It would probably be easier to implement such a job in the way the 
234     current "CopyJob" is done. Have a Job and make all sub-urls sub-jobs of
235     this Job.
236  3. As a result of 1. COPY FROM an url like file:/tmp/test.gz#gzip:/ should
237     work. COPY TO does not, because that would require PUT.
238     
240 Resuming
241 --------
243 A rough note for now, just to have this somewhere :
244 (PJ=put-job, GJ=get-job)
246 PJ can't resume:
247 PJ-->app: canResume(0)  (emitted by dataReq)
248 GJ-->app: data()
249 PJ-->app: dataReq()
250 app->PJ: data()
252 PJ can resume but GJ can't resume:
253 PJ-->app: canResume(xx)
254 app->GJ: start job with "resume=xxx" metadata.
255 GJ-->app: data()
256 PJ-->app: dataReq()
257 app->PJ: data()
259 PJ can resume and GJ can resume:
260 PJ-->app: canResume(xx)
261 app->GJ: start job with "resume=xxx" metadata.
262 GJ-->app: canResume(xx)
263 GJ-->app: data()
264 PJ-->app: dataReq()
265 app->PJ: canResume(xx)
266 app->PJ: data()
268 So when the slave supports resume for "put" it has to check after the first 
269 dataRequest() whether it has got a canResume() back from the app. If it did 
270 it must resume. Otherwise it must start from 0.