Merge lp:~aptdaemon-developers/aptdaemon/threading into lp:aptdaemon
- threading
- Merge into main
Proposed by
Sebastian Heinlein
Status: | Merged |
---|---|
Merged at revision: | 701 |
Proposed branch: | lp:~aptdaemon-developers/aptdaemon/threading |
Merge into: | lp:aptdaemon |
Diff against target: |
970 lines (+252/-111) 6 files modified
NEWS (+2/-0) aptdaemon/core.py (+182/-43) aptdaemon/loop.py (+0/-32) aptdaemon/progress.py (+8/-14) aptdaemon/utils.py (+30/-0) aptdaemon/worker.py (+30/-22) |
To merge this branch: | bzr merge lp:~aptdaemon-developers/aptdaemon/threading |
Related bugs: | |
Related blueprints: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Aptdaemon Developers | Pending | ||
Review via email: mp+77802@code.launchpad.net |
Commit message
Description of the change
Moves the worker and the simulate actions to separate threads. This makes the daemon more responsive and allows to easily queue simulate and the comming PK query methods.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'NEWS' | |||
2 | --- NEWS 2011-08-27 11:37:42 +0000 | |||
3 | +++ NEWS 2011-10-02 05:32:23 +0000 | |||
4 | @@ -2,6 +2,8 @@ | |||
5 | 2 | 2 | ||
6 | 3 | * Enhancements: | 3 | * Enhancements: |
7 | 4 | 4 | ||
8 | 5 | - Use threading internally instead for the worker | ||
9 | 6 | |||
10 | 5 | - Support multiarch package names like apt-get, e.g. xterm:amd64 | 7 | - Support multiarch package names like apt-get, e.g. xterm:amd64 |
11 | 6 | 8 | ||
12 | 7 | - Store the transaction role and sender in apt's history log | 9 | - Store the transaction role and sender in apt's history log |
13 | 8 | 10 | ||
14 | === modified file 'aptdaemon/core.py' | |||
15 | --- aptdaemon/core.py 2011-09-15 14:23:50 +0000 | |||
16 | +++ aptdaemon/core.py 2011-10-02 05:32:23 +0000 | |||
17 | @@ -47,24 +47,27 @@ | |||
18 | 47 | import signal | 47 | import signal |
19 | 48 | import sys | 48 | import sys |
20 | 49 | import time | 49 | import time |
21 | 50 | import threading | ||
22 | 50 | import uuid | 51 | import uuid |
23 | 51 | 52 | ||
24 | 53 | from defer import inline_callbacks, return_value | ||
25 | 54 | from defer.utils import dbus_deferred_method | ||
26 | 52 | import gobject | 55 | import gobject |
27 | 56 | gobject.threads_init() | ||
28 | 53 | import dbus.exceptions | 57 | import dbus.exceptions |
29 | 54 | import dbus.service | 58 | import dbus.service |
30 | 55 | import dbus.mainloop.glib | 59 | import dbus.mainloop.glib |
32 | 56 | import dbus.glib | 60 | dbus.mainloop.glib.threads_init() |
33 | 57 | from softwareproperties.AptAuth import AptAuth | 61 | from softwareproperties.AptAuth import AptAuth |
34 | 58 | import apt_pkg | 62 | import apt_pkg |
35 | 59 | 63 | ||
36 | 60 | from config import ConfigWriter | 64 | from config import ConfigWriter |
37 | 61 | import errors | 65 | import errors |
38 | 62 | import enums | 66 | import enums |
39 | 63 | from defer import inline_callbacks, return_value | ||
40 | 64 | from defer.utils import dbus_deferred_method | ||
41 | 65 | import policykit1 | 67 | import policykit1 |
42 | 66 | from worker import AptWorker, DummyWorker | 68 | from worker import AptWorker, DummyWorker |
44 | 67 | from loop import mainloop | 69 | from utils import locked |
45 | 70 | |||
46 | 68 | 71 | ||
47 | 69 | # Setup i18n | 72 | # Setup i18n |
48 | 70 | _ = lambda msg: gettext.dgettext("aptdaemon", msg) | 73 | _ = lambda msg: gettext.dgettext("aptdaemon", msg) |
49 | @@ -313,6 +316,7 @@ | |||
50 | 313 | connect -- if the Transaction should connect to DBus (default is True) | 316 | connect -- if the Transaction should connect to DBus (default is True) |
51 | 314 | bus -- the DBus connection which should be used (defaults to system bus) | 317 | bus -- the DBus connection which should be used (defaults to system bus) |
52 | 315 | """ | 318 | """ |
53 | 319 | self.lock = threading.Lock() | ||
54 | 316 | tid = uuid.uuid4().get_hex() | 320 | tid = uuid.uuid4().get_hex() |
55 | 317 | self.tid = "/org/debian/apt/transaction/%s" % tid | 321 | self.tid = "/org/debian/apt/transaction/%s" % tid |
56 | 318 | if connect == True: | 322 | if connect == True: |
57 | @@ -330,18 +334,20 @@ | |||
58 | 330 | packages = ([], [], [], [], [], []) | 334 | packages = ([], [], [], [], [], []) |
59 | 331 | if not kwargs: | 335 | if not kwargs: |
60 | 332 | kwargs = {} | 336 | kwargs = {} |
61 | 337 | self.sender = sender | ||
62 | 333 | self.queue = queue | 338 | self.queue = queue |
63 | 334 | self.uid = uid | 339 | self.uid = uid |
67 | 335 | self.locale = dbus.String("") | 340 | self.kwargs = kwargs |
68 | 336 | self.allow_unauthenticated = dbus.Boolean(False) | 341 | # Mutable properties which need to be protected by a lock |
69 | 337 | self.remove_obsoleted_depends = dbus.Boolean(False) | 342 | self._locale = dbus.String("") |
70 | 343 | self._allow_unauthenticated = dbus.Boolean(False) | ||
71 | 344 | self._remove_obsoleted_depends = dbus.Boolean(False) | ||
72 | 338 | self.http_proxy = dbus.String("") | 345 | self.http_proxy = dbus.String("") |
76 | 339 | self.terminal = dbus.String("") | 346 | self._terminal = dbus.String("") |
77 | 340 | self.debconf = dbus.String("") | 347 | self._debconf = dbus.String("") |
75 | 341 | self.kwargs = kwargs | ||
78 | 342 | self._translation = None | 348 | self._translation = None |
79 | 343 | # The transaction which should be executed after this one | 349 | # The transaction which should be executed after this one |
81 | 344 | self.after = None | 350 | self._after = None |
82 | 345 | self._role = dbus.String(role) | 351 | self._role = dbus.String(role) |
83 | 346 | self._progress = dbus.Int32(0) | 352 | self._progress = dbus.Int32(0) |
84 | 347 | # items_done, total_items, bytes_done, total_bytes, speed, time | 353 | # items_done, total_items, bytes_done, total_bytes, speed, time |
85 | @@ -359,8 +365,9 @@ | |||
86 | 359 | self._required_medium = dbus.Struct(("", ""), signature="ss") | 365 | self._required_medium = dbus.Struct(("", ""), signature="ss") |
87 | 360 | self._config_file_conflict = dbus.Struct(("", ""), signature="ss") | 366 | self._config_file_conflict = dbus.Struct(("", ""), signature="ss") |
88 | 361 | self._config_file_conflict_resolution = "" | 367 | self._config_file_conflict_resolution = "" |
91 | 362 | self.cancelled = dbus.Boolean(False) | 368 | self._cancelled = dbus.Boolean(False) |
92 | 363 | self.paused = dbus.Boolean(False) | 369 | self._paused = dbus.Boolean(False) |
93 | 370 | self.feedback = threading.Event() | ||
94 | 364 | self._meta_data = dbus.Dictionary(signature="sv") | 371 | self._meta_data = dbus.Dictionary(signature="sv") |
95 | 365 | self._download = dbus.Int64(0) | 372 | self._download = dbus.Int64(0) |
96 | 366 | self._space = dbus.Int64(0) | 373 | self._space = dbus.Int64(0) |
97 | @@ -376,15 +383,64 @@ | |||
98 | 376 | self._idle_watch = gobject.timeout_add_seconds( | 383 | self._idle_watch = gobject.timeout_add_seconds( |
99 | 377 | TRANSACTION_IDLE_TIMEOUT, self._remove_from_connection_no_raise) | 384 | TRANSACTION_IDLE_TIMEOUT, self._remove_from_connection_no_raise) |
100 | 378 | # Handle a disconnect of the client application | 385 | # Handle a disconnect of the client application |
102 | 379 | self.sender_alive = True | 386 | self._sender_alive = True |
103 | 380 | if bus: | 387 | if bus: |
104 | 381 | self._sender_watch = bus.watch_name_owner(sender, | 388 | self._sender_watch = bus.watch_name_owner(sender, |
105 | 382 | self._sender_owner_changed) | 389 | self._sender_owner_changed) |
106 | 383 | else: | 390 | else: |
107 | 384 | self._sender_watch = None | 391 | self._sender_watch = None |
111 | 385 | self.sender = sender | 392 | self._output = "" |
112 | 386 | self.output = "" | 393 | self._simulated = None |
113 | 387 | self.simulated = None | 394 | |
114 | 395 | @locked | ||
115 | 396 | def _get_cancelled(self): | ||
116 | 397 | return self._cancelled | ||
117 | 398 | |||
118 | 399 | @locked | ||
119 | 400 | def _set_cancelled(self, txt): | ||
120 | 401 | self._cancelled = txt | ||
121 | 402 | |||
122 | 403 | cancelled = property(_get_cancelled, _set_cancelled) | ||
123 | 404 | |||
124 | 405 | @locked | ||
125 | 406 | def _get_paused(self): | ||
126 | 407 | return self._paused | ||
127 | 408 | |||
128 | 409 | @locked | ||
129 | 410 | def _set_paused(self, bool): | ||
130 | 411 | self._paused = bool | ||
131 | 412 | |||
132 | 413 | paused = property(_get_paused, _set_paused) | ||
133 | 414 | |||
134 | 415 | @locked | ||
135 | 416 | def _get_simulated(self): | ||
136 | 417 | return self._simulated | ||
137 | 418 | |||
138 | 419 | @locked | ||
139 | 420 | def _set_simulated(self, txt): | ||
140 | 421 | self._simulated = txt | ||
141 | 422 | |||
142 | 423 | simulated = property(_get_simulated, _set_simulated) | ||
143 | 424 | |||
144 | 425 | @locked | ||
145 | 426 | def _get_output(self): | ||
146 | 427 | return self._output | ||
147 | 428 | |||
148 | 429 | @locked | ||
149 | 430 | def _set_output(self, txt): | ||
150 | 431 | self._output = txt | ||
151 | 432 | |||
152 | 433 | output = property(_get_output, _set_output) | ||
153 | 434 | |||
154 | 435 | @locked | ||
155 | 436 | def _get_sender_alive(self): | ||
156 | 437 | return self._sender_alive | ||
157 | 438 | |||
158 | 439 | @locked | ||
159 | 440 | def _set_sender_alive(self, alive): | ||
160 | 441 | self._sender_alive = alive | ||
161 | 442 | |||
162 | 443 | sender_alive = property(_get_sender_alive, _set_sender_alive) | ||
163 | 388 | 444 | ||
164 | 389 | def _sender_owner_changed(self, connection): | 445 | def _sender_owner_changed(self, connection): |
165 | 390 | """Callback if the owner of the original sender changed, e.g. | 446 | """Callback if the owner of the original sender changed, e.g. |
166 | @@ -458,9 +514,11 @@ | |||
167 | 458 | raise errors.InvalidMetaDataError("The value has to be a " | 514 | raise errors.InvalidMetaDataError("The value has to be a " |
168 | 459 | "string: %s" % value) | 515 | "string: %s" % value) |
169 | 460 | # Merge new data into existing one: | 516 | # Merge new data into existing one: |
172 | 461 | self._meta_data.update(data) | 517 | with self.lock: |
173 | 462 | self.PropertyChanged("MetaData", self._meta_data) | 518 | self._meta_data.update(data) |
174 | 519 | self.PropertyChanged("MetaData", self._meta_data) | ||
175 | 463 | 520 | ||
176 | 521 | @locked | ||
177 | 464 | def _get_meta_data(self): | 522 | def _get_meta_data(self): |
178 | 465 | return self._meta_data | 523 | return self._meta_data |
179 | 466 | 524 | ||
180 | @@ -468,22 +526,26 @@ | |||
181 | 468 | doc="Allows client applications to store meta data " | 526 | doc="Allows client applications to store meta data " |
182 | 469 | "for the transaction in a dictionary.") | 527 | "for the transaction in a dictionary.") |
183 | 470 | 528 | ||
184 | 529 | @locked | ||
185 | 471 | def _set_role(self, enum): | 530 | def _set_role(self, enum): |
186 | 472 | if self._role != enums.ROLE_UNSET: | 531 | if self._role != enums.ROLE_UNSET: |
187 | 473 | raise errors.TransactionRoleAlreadySet() | 532 | raise errors.TransactionRoleAlreadySet() |
188 | 474 | self._role = dbus.String(enum) | 533 | self._role = dbus.String(enum) |
189 | 475 | self.PropertyChanged("Role", self._role) | 534 | self.PropertyChanged("Role", self._role) |
190 | 476 | 535 | ||
191 | 536 | @locked | ||
192 | 477 | def _get_role(self): | 537 | def _get_role(self): |
193 | 478 | return self._role | 538 | return self._role |
194 | 479 | 539 | ||
195 | 480 | role = property(_get_role, _set_role, doc="Operation type of transaction.") | 540 | role = property(_get_role, _set_role, doc="Operation type of transaction.") |
196 | 481 | 541 | ||
197 | 542 | @locked | ||
198 | 482 | def _set_progress_details(self, details): | 543 | def _set_progress_details(self, details): |
199 | 483 | # items_done, total_items, bytes_done, total_bytes, speed, time | 544 | # items_done, total_items, bytes_done, total_bytes, speed, time |
200 | 484 | self._progress_details = self._convert_struct(details, "iixxdx") | 545 | self._progress_details = self._convert_struct(details, "iixxdx") |
201 | 485 | self.PropertyChanged("ProgressDetails", self._progress_details) | 546 | self.PropertyChanged("ProgressDetails", self._progress_details) |
202 | 486 | 547 | ||
203 | 548 | @locked | ||
204 | 487 | def _get_progress_details(self): | 549 | def _get_progress_details(self): |
205 | 488 | return self._progress_details | 550 | return self._progress_details |
206 | 489 | 551 | ||
207 | @@ -493,12 +555,14 @@ | |||
208 | 493 | "bytes done, total bytes, speed and " | 555 | "bytes done, total bytes, speed and " |
209 | 494 | "remaining time") | 556 | "remaining time") |
210 | 495 | 557 | ||
211 | 558 | @locked | ||
212 | 496 | def _set_error(self, excep): | 559 | def _set_error(self, excep): |
213 | 497 | self._error = excep | 560 | self._error = excep |
214 | 498 | msg = self.gettext(excep.details) % excep.details_args | 561 | msg = self.gettext(excep.details) % excep.details_args |
215 | 499 | self._error_property = self._convert_struct((excep.code, msg), "ss") | 562 | self._error_property = self._convert_struct((excep.code, msg), "ss") |
216 | 500 | self.PropertyChanged("Error", self._error_property) | 563 | self.PropertyChanged("Error", self._error_property) |
217 | 501 | 564 | ||
218 | 565 | @locked | ||
219 | 502 | def _get_error(self): | 566 | def _get_error(self): |
220 | 503 | return self._error | 567 | return self._error |
221 | 504 | 568 | ||
222 | @@ -506,9 +570,10 @@ | |||
223 | 506 | 570 | ||
224 | 507 | def _set_exit(self, enum): | 571 | def _set_exit(self, enum): |
225 | 508 | self.status = enums.STATUS_FINISHED | 572 | self.status = enums.STATUS_FINISHED |
229 | 509 | self._exit = dbus.String(enum) | 573 | with self.lock: |
230 | 510 | self.PropertyChanged("ExitState", self._exit) | 574 | self._exit = dbus.String(enum) |
231 | 511 | self.Finished(self._exit) | 575 | self.PropertyChanged("ExitState", self._exit) |
232 | 576 | self.Finished(self._exit) | ||
233 | 512 | if self._sender_watch: | 577 | if self._sender_watch: |
234 | 513 | self._sender_watch.cancel() | 578 | self._sender_watch.cancel() |
235 | 514 | # Remove the transaction from the Bus after it is complete. A short | 579 | # Remove the transaction from the Bus after it is complete. A short |
236 | @@ -516,15 +581,18 @@ | |||
237 | 516 | gobject.timeout_add_seconds(TRANSACTION_DEL_TIMEOUT, | 581 | gobject.timeout_add_seconds(TRANSACTION_DEL_TIMEOUT, |
238 | 517 | self._remove_from_connection_no_raise) | 582 | self._remove_from_connection_no_raise) |
239 | 518 | 583 | ||
240 | 584 | @locked | ||
241 | 519 | def _get_exit(self): | 585 | def _get_exit(self): |
242 | 520 | return self._exit | 586 | return self._exit |
243 | 521 | 587 | ||
244 | 522 | exit = property(_get_exit, _set_exit, | 588 | exit = property(_get_exit, _set_exit, |
245 | 523 | doc="The exit state of the transaction.") | 589 | doc="The exit state of the transaction.") |
246 | 524 | 590 | ||
247 | 591 | @locked | ||
248 | 525 | def _get_download(self): | 592 | def _get_download(self): |
249 | 526 | return self._download | 593 | return self._download |
250 | 527 | 594 | ||
251 | 595 | @locked | ||
252 | 528 | def _set_download(self, size): | 596 | def _set_download(self, size): |
253 | 529 | self._download = dbus.Int64(size) | 597 | self._download = dbus.Int64(size) |
254 | 530 | self.PropertyChanged("Download", self._download) | 598 | self.PropertyChanged("Download", self._download) |
255 | @@ -532,9 +600,11 @@ | |||
256 | 532 | download = property(_get_download, _set_download, | 600 | download = property(_get_download, _set_download, |
257 | 533 | doc="The download size of the transaction.") | 601 | doc="The download size of the transaction.") |
258 | 534 | 602 | ||
259 | 603 | @locked | ||
260 | 535 | def _get_space(self): | 604 | def _get_space(self): |
261 | 536 | return self._space | 605 | return self._space |
262 | 537 | 606 | ||
263 | 607 | @locked | ||
264 | 538 | def _set_space(self, size): | 608 | def _set_space(self, size): |
265 | 539 | self._space = dbus.Int64(size) | 609 | self._space = dbus.Int64(size) |
266 | 540 | self.PropertyChanged("Space", self._space) | 610 | self.PropertyChanged("Space", self._space) |
267 | @@ -542,12 +612,14 @@ | |||
268 | 542 | space = property(_get_space, _set_space, | 612 | space = property(_get_space, _set_space, |
269 | 543 | doc="The required disk space of the transaction.") | 613 | doc="The required disk space of the transaction.") |
270 | 544 | 614 | ||
271 | 615 | @locked | ||
272 | 545 | def _set_packages(self, packages): | 616 | def _set_packages(self, packages): |
273 | 546 | self._packages = dbus.Struct([dbus.Array(pkgs, signature="s") | 617 | self._packages = dbus.Struct([dbus.Array(pkgs, signature="s") |
274 | 547 | for pkgs in packages], | 618 | for pkgs in packages], |
275 | 548 | signature="as") | 619 | signature="as") |
276 | 549 | self.PropertyChanged("Packages", self._packages) | 620 | self.PropertyChanged("Packages", self._packages) |
277 | 550 | 621 | ||
278 | 622 | @locked | ||
279 | 551 | def _get_packages(self): | 623 | def _get_packages(self): |
280 | 552 | return self._packages | 624 | return self._packages |
281 | 553 | 625 | ||
282 | @@ -556,9 +628,11 @@ | |||
283 | 556 | "reinstalled, removed, purged, upgraded or " | 628 | "reinstalled, removed, purged, upgraded or " |
284 | 557 | "downgraded.") | 629 | "downgraded.") |
285 | 558 | 630 | ||
286 | 631 | @locked | ||
287 | 559 | def _get_unauthenticated(self): | 632 | def _get_unauthenticated(self): |
288 | 560 | return self._unauthenticated | 633 | return self._unauthenticated |
289 | 561 | 634 | ||
290 | 635 | @locked | ||
291 | 562 | def _set_unauthenticated(self, unauthenticated): | 636 | def _set_unauthenticated(self, unauthenticated): |
292 | 563 | self._unauthenticated = dbus.Array(unauthenticated, signature="s") | 637 | self._unauthenticated = dbus.Array(unauthenticated, signature="s") |
293 | 564 | self.PropertyChanged("Unauthenticated", self._unauthenticated) | 638 | self.PropertyChanged("Unauthenticated", self._unauthenticated) |
294 | @@ -567,9 +641,11 @@ | |||
295 | 567 | doc="Unauthenticated packages in this " | 641 | doc="Unauthenticated packages in this " |
296 | 568 | "transaction") | 642 | "transaction") |
297 | 569 | 643 | ||
298 | 644 | @locked | ||
299 | 570 | def _get_depends(self): | 645 | def _get_depends(self): |
300 | 571 | return self._depends | 646 | return self._depends |
301 | 572 | 647 | ||
302 | 648 | @locked | ||
303 | 573 | def _set_depends(self, depends): | 649 | def _set_depends(self, depends): |
304 | 574 | self._depends = dbus.Struct([dbus.Array(deps, signature="s") | 650 | self._depends = dbus.Struct([dbus.Array(deps, signature="s") |
305 | 575 | for deps in depends], | 651 | for deps in depends], |
306 | @@ -580,9 +656,11 @@ | |||
307 | 580 | doc="The additional dependencies: installs, removals, " | 656 | doc="The additional dependencies: installs, removals, " |
308 | 581 | "upgrades and downgrades.") | 657 | "upgrades and downgrades.") |
309 | 582 | 658 | ||
310 | 659 | @locked | ||
311 | 583 | def _get_status(self): | 660 | def _get_status(self): |
312 | 584 | return self._status | 661 | return self._status |
313 | 585 | 662 | ||
314 | 663 | @locked | ||
315 | 586 | def _set_status(self, enum): | 664 | def _set_status(self, enum): |
316 | 587 | self._status = dbus.String(enum) | 665 | self._status = dbus.String(enum) |
317 | 588 | self.PropertyChanged("Status", self._status) | 666 | self.PropertyChanged("Status", self._status) |
318 | @@ -590,9 +668,11 @@ | |||
319 | 590 | status = property(_get_status, _set_status, | 668 | status = property(_get_status, _set_status, |
320 | 591 | doc="The status of the transaction.") | 669 | doc="The status of the transaction.") |
321 | 592 | 670 | ||
322 | 671 | @locked | ||
323 | 593 | def _get_status_details(self): | 672 | def _get_status_details(self): |
324 | 594 | return self._status_details | 673 | return self._status_details |
325 | 595 | 674 | ||
326 | 675 | @locked | ||
327 | 596 | def _set_status_details(self, text): | 676 | def _set_status_details(self, text): |
328 | 597 | self._status_details = get_dbus_string(text) | 677 | self._status_details = get_dbus_string(text) |
329 | 598 | self.PropertyChanged("StatusDetails", self._status_details) | 678 | self.PropertyChanged("StatusDetails", self._status_details) |
330 | @@ -600,9 +680,11 @@ | |||
331 | 600 | status_details = property(_get_status_details, _set_status_details, | 680 | status_details = property(_get_status_details, _set_status_details, |
332 | 601 | doc="The status message from apt.") | 681 | doc="The status message from apt.") |
333 | 602 | 682 | ||
334 | 683 | @locked | ||
335 | 603 | def _get_progress(self): | 684 | def _get_progress(self): |
336 | 604 | return self._progress | 685 | return self._progress |
337 | 605 | 686 | ||
338 | 687 | @locked | ||
339 | 606 | def _set_progress(self, percent): | 688 | def _set_progress(self, percent): |
340 | 607 | self._progress = dbus.Int32(percent) | 689 | self._progress = dbus.Int32(percent) |
341 | 608 | self.PropertyChanged("Progress", self._progress) | 690 | self.PropertyChanged("Progress", self._progress) |
342 | @@ -610,9 +692,11 @@ | |||
343 | 610 | progress = property(_get_progress, _set_progress, | 692 | progress = property(_get_progress, _set_progress, |
344 | 611 | doc="The progress of the transaction in percent.") | 693 | doc="The progress of the transaction in percent.") |
345 | 612 | 694 | ||
346 | 695 | @locked | ||
347 | 613 | def _get_progress_download(self): | 696 | def _get_progress_download(self): |
348 | 614 | return self._progress_download | 697 | return self._progress_download |
349 | 615 | 698 | ||
350 | 699 | @locked | ||
351 | 616 | def _set_progress_download(self, progress_download): | 700 | def _set_progress_download(self, progress_download): |
352 | 617 | self._progress_download = self._convert_struct(progress_download, | 701 | self._progress_download = self._convert_struct(progress_download, |
353 | 618 | "sssxxs") | 702 | "sssxxs") |
354 | @@ -626,9 +710,11 @@ | |||
355 | 626 | "partially downloaded size and a status " | 710 | "partially downloaded size and a status " |
356 | 627 | "message.") | 711 | "message.") |
357 | 628 | 712 | ||
358 | 713 | @locked | ||
359 | 629 | def _get_cancellable(self): | 714 | def _get_cancellable(self): |
360 | 630 | return self._cancellable | 715 | return self._cancellable |
361 | 631 | 716 | ||
362 | 717 | @locked | ||
363 | 632 | def _set_cancellable(self, cancellable): | 718 | def _set_cancellable(self, cancellable): |
364 | 633 | self._cancellable = dbus.Boolean(cancellable) | 719 | self._cancellable = dbus.Boolean(cancellable) |
365 | 634 | self.PropertyChanged("Cancellable", self._cancellable) | 720 | self.PropertyChanged("Cancellable", self._cancellable) |
366 | @@ -637,9 +723,11 @@ | |||
367 | 637 | doc="If it's currently allowed to cancel the " | 723 | doc="If it's currently allowed to cancel the " |
368 | 638 | "transaction.") | 724 | "transaction.") |
369 | 639 | 725 | ||
370 | 726 | @locked | ||
371 | 640 | def _get_term_attached(self): | 727 | def _get_term_attached(self): |
372 | 641 | return self._term_attached | 728 | return self._term_attached |
373 | 642 | 729 | ||
374 | 730 | @locked | ||
375 | 643 | def _set_term_attached(self, attached): | 731 | def _set_term_attached(self, attached): |
376 | 644 | self._term_attached = dbus.Boolean(attached) | 732 | self._term_attached = dbus.Boolean(attached) |
377 | 645 | self.PropertyChanged("TerminalAttached", self._term_attached) | 733 | self.PropertyChanged("TerminalAttached", self._term_attached) |
378 | @@ -649,9 +737,11 @@ | |||
379 | 649 | "attached to the dpkg call of the " | 737 | "attached to the dpkg call of the " |
380 | 650 | "transaction.") | 738 | "transaction.") |
381 | 651 | 739 | ||
382 | 740 | @locked | ||
383 | 652 | def _get_required_medium(self): | 741 | def _get_required_medium(self): |
384 | 653 | return self._required_medium | 742 | return self._required_medium |
385 | 654 | 743 | ||
386 | 744 | @locked | ||
387 | 655 | def _set_required_medium(self, medium): | 745 | def _set_required_medium(self, medium): |
388 | 656 | self._required_medium = self._convert_struct(medium, "ss") | 746 | self._required_medium = self._convert_struct(medium, "ss") |
389 | 657 | self.PropertyChanged("RequiredMedium", self._required_medium) | 747 | self.PropertyChanged("RequiredMedium", self._required_medium) |
390 | @@ -662,9 +752,11 @@ | |||
391 | 662 | "of a required CD/DVD to install packages " | 752 | "of a required CD/DVD to install packages " |
392 | 663 | "from.") | 753 | "from.") |
393 | 664 | 754 | ||
394 | 755 | @locked | ||
395 | 665 | def _get_config_file_conflict(self): | 756 | def _get_config_file_conflict(self): |
396 | 666 | return self._config_file_conflict | 757 | return self._config_file_conflict |
397 | 667 | 758 | ||
398 | 759 | @locked | ||
399 | 668 | def _set_config_file_conflict(self, prompt): | 760 | def _set_config_file_conflict(self, prompt): |
400 | 669 | if prompt is None: | 761 | if prompt is None: |
401 | 670 | self._config_file_conflict = dbus.Struct(("", ""), signature="ss") | 762 | self._config_file_conflict = dbus.Struct(("", ""), signature="ss") |
402 | @@ -739,6 +831,18 @@ | |||
403 | 739 | 831 | ||
404 | 740 | # Methods | 832 | # Methods |
405 | 741 | 833 | ||
406 | 834 | def _get_after(self): | ||
407 | 835 | return self._after | ||
408 | 836 | |||
409 | 837 | def _set_after(self, tid): | ||
410 | 838 | self.after = tid | ||
411 | 839 | |||
412 | 840 | after = property(_get_after, _set_after) | ||
413 | 841 | |||
414 | 842 | @locked | ||
415 | 843 | def _get_locale(self): | ||
416 | 844 | return self._locale | ||
417 | 845 | |||
418 | 742 | def _set_locale(self, locale_str): | 846 | def _set_locale(self, locale_str): |
419 | 743 | """Set the language and encoding. | 847 | """Set the language and encoding. |
420 | 744 | 848 | ||
421 | @@ -755,11 +859,14 @@ | |||
422 | 755 | except ValueError: | 859 | except ValueError: |
423 | 756 | raise | 860 | raise |
424 | 757 | else: | 861 | else: |
430 | 758 | self.locale = dbus.String("%s.%s" % (lang, encoding)) | 862 | with self.lock: |
431 | 759 | self._translation = gettext.translation("aptdaemon", | 863 | self._locale = dbus.String("%s.%s" % (lang, encoding)) |
432 | 760 | fallback=True, | 864 | self._translation = gettext.translation("aptdaemon", |
433 | 761 | languages=[lang]) | 865 | fallback=True, |
434 | 762 | self.PropertyChanged("locale", self.locale) | 866 | languages=[lang]) |
435 | 867 | self.PropertyChanged("locale", self._locale) | ||
436 | 868 | |||
437 | 869 | locale = property(_get_locale, _set_locale) | ||
438 | 763 | 870 | ||
439 | 764 | @inline_callbacks | 871 | @inline_callbacks |
440 | 765 | def _set_http_proxy(self, url, sender): | 872 | def _set_http_proxy(self, url, sender): |
441 | @@ -776,6 +883,7 @@ | |||
442 | 776 | self.http_proxy = dbus.String(url) | 883 | self.http_proxy = dbus.String(url) |
443 | 777 | self.PropertyChanged("HttpProxy", self.http_proxy) | 884 | self.PropertyChanged("HttpProxy", self.http_proxy) |
444 | 778 | 885 | ||
445 | 886 | @locked | ||
446 | 779 | def _set_remove_obsoleted_depends(self, remove_obsoleted_depends): | 887 | def _set_remove_obsoleted_depends(self, remove_obsoleted_depends): |
447 | 780 | """Set the handling of the removal of automatically installed | 888 | """Set the handling of the removal of automatically installed |
448 | 781 | dependencies which are now obsoleted. | 889 | dependencies which are now obsoleted. |
449 | @@ -788,6 +896,14 @@ | |||
450 | 788 | self.PropertyChanged("RemoveObsoletedDepends", | 896 | self.PropertyChanged("RemoveObsoletedDepends", |
451 | 789 | self.remove_obsoleted_depends) | 897 | self.remove_obsoleted_depends) |
452 | 790 | 898 | ||
453 | 899 | @locked | ||
454 | 900 | def _get_remove_obsoleted_depends(self): | ||
455 | 901 | return self._remove_obsoleted_depends | ||
456 | 902 | |||
457 | 903 | remove_obsoleted_depends = property(_get_remove_obsoleted_depends, | ||
458 | 904 | _set_remove_obsoleted_depends) | ||
459 | 905 | |||
460 | 906 | @locked | ||
461 | 791 | def _set_allow_unauthenticated(self, allow_unauthenticated): | 907 | def _set_allow_unauthenticated(self, allow_unauthenticated): |
462 | 792 | """Set the handling of unauthenticated packages | 908 | """Set the handling of unauthenticated packages |
463 | 793 | 909 | ||
464 | @@ -795,8 +911,16 @@ | |||
465 | 795 | allow_unauthenticated -- True to allow packages that come from a | 911 | allow_unauthenticated -- True to allow packages that come from a |
466 | 796 | repository without a valid authentication signature | 912 | repository without a valid authentication signature |
467 | 797 | """ | 913 | """ |
470 | 798 | self.allow_unauthenticated = dbus.Boolean(allow_unauthenticated) | 914 | self._allow_unauthenticated = dbus.Boolean(allow_unauthenticated) |
471 | 799 | self.PropertyChanged("AllowUnauthenticated", self.allow_unauthenticated) | 915 | self.PropertyChanged("AllowUnauthenticated", |
472 | 916 | self._allow_unauthenticated) | ||
473 | 917 | |||
474 | 918 | @locked | ||
475 | 919 | def _get_allow_unauthenticated(self): | ||
476 | 920 | return self._allow_unauthenticated | ||
477 | 921 | |||
478 | 922 | allow_unauthenticated = property(_get_allow_unauthenticated, | ||
479 | 923 | _set_allow_unauthenticated) | ||
480 | 800 | 924 | ||
481 | 801 | # pylint: disable-msg=C0103,C0322 | 925 | # pylint: disable-msg=C0103,C0322 |
482 | 802 | @dbus.service.method(APTDAEMON_TRANSACTION_DBUS_INTERFACE, | 926 | @dbus.service.method(APTDAEMON_TRANSACTION_DBUS_INTERFACE, |
483 | @@ -837,12 +961,12 @@ | |||
484 | 837 | def _run(self, sender): | 961 | def _run(self, sender): |
485 | 838 | yield self._check_foreign_user(sender) | 962 | yield self._check_foreign_user(sender) |
486 | 839 | yield self._check_auth() | 963 | yield self._check_auth() |
488 | 840 | self.queue.put(self.tid) | 964 | yield self.queue.put(self.tid) |
489 | 841 | self.status = enums.STATUS_WAITING | 965 | self.status = enums.STATUS_WAITING |
490 | 842 | next_trans = self.after | 966 | next_trans = self.after |
491 | 843 | while next_trans: | 967 | while next_trans: |
492 | 844 | yield next_trans._check_auth() | 968 | yield next_trans._check_auth() |
494 | 845 | self.queue.put(next_trans.tid) | 969 | yield self.queue.put(next_trans.tid) |
495 | 846 | next_trans.status = enums.STATUS_WAITING | 970 | next_trans.status = enums.STATUS_WAITING |
496 | 847 | next_trans = next_trans.after | 971 | next_trans = next_trans.after |
497 | 848 | 972 | ||
498 | @@ -921,6 +1045,7 @@ | |||
499 | 921 | log_trans.debug("Setting cancel event") | 1045 | log_trans.debug("Setting cancel event") |
500 | 922 | self.cancelled = True | 1046 | self.cancelled = True |
501 | 923 | self.status = enums.STATUS_CANCELLING | 1047 | self.status = enums.STATUS_CANCELLING |
502 | 1048 | self.feedback.set() | ||
503 | 924 | self.paused = False | 1049 | self.paused = False |
504 | 925 | return | 1050 | return |
505 | 926 | raise errors.AptDaemonError("Could not cancel transaction") | 1051 | raise errors.AptDaemonError("Could not cancel transaction") |
506 | @@ -944,7 +1069,7 @@ | |||
507 | 944 | if self.status != enums.STATUS_SETTING_UP: | 1069 | if self.status != enums.STATUS_SETTING_UP: |
508 | 945 | raise errors.TransactionAlreadyRunning() | 1070 | raise errors.TransactionAlreadyRunning() |
509 | 946 | yield self._check_foreign_user(sender) | 1071 | yield self._check_foreign_user(sender) |
511 | 947 | self.queue.worker.simulate(self) | 1072 | yield self.queue.worker.simulate(self) |
512 | 948 | if self._idle_watch is not None: | 1073 | if self._idle_watch is not None: |
513 | 949 | gobject.source_remove(self._idle_watch) | 1074 | gobject.source_remove(self._idle_watch) |
514 | 950 | self._idle_watch = None | 1075 | self._idle_watch = None |
515 | @@ -974,13 +1099,20 @@ | |||
516 | 974 | try: | 1099 | try: |
517 | 975 | slave_fd = os.open(ttyname, os.O_RDWR | os.O_NOCTTY) | 1100 | slave_fd = os.open(ttyname, os.O_RDWR | os.O_NOCTTY) |
518 | 976 | if os.isatty(slave_fd): | 1101 | if os.isatty(slave_fd): |
521 | 977 | self.terminal = dbus.String(ttyname) | 1102 | with self.lock: |
522 | 978 | self.PropertyChanged("Terminal", self.terminal) | 1103 | self._terminal = dbus.String(ttyname) |
523 | 1104 | self.PropertyChanged("Terminal", self._terminal) | ||
524 | 979 | else: | 1105 | else: |
525 | 980 | raise errors.AptDaemonError("%s isn't a tty" % ttyname) | 1106 | raise errors.AptDaemonError("%s isn't a tty" % ttyname) |
526 | 981 | finally: | 1107 | finally: |
527 | 982 | os.close(slave_fd) | 1108 | os.close(slave_fd) |
528 | 983 | 1109 | ||
529 | 1110 | @locked | ||
530 | 1111 | def _get_terminal(self): | ||
531 | 1112 | return self._terminal | ||
532 | 1113 | |||
533 | 1114 | terminal = property(_get_terminal, _set_terminal) | ||
534 | 1115 | |||
535 | 984 | def _set_debconf(self, debconf_socket): | 1116 | def _set_debconf(self, debconf_socket): |
536 | 985 | """Set the socket of the debconf proxy. | 1117 | """Set the socket of the debconf proxy. |
537 | 986 | 1118 | ||
538 | @@ -1002,8 +1134,15 @@ | |||
539 | 1002 | raise errors.AptDaemonError("socket '%s' has to be owned by the " | 1134 | raise errors.AptDaemonError("socket '%s' has to be owned by the " |
540 | 1003 | "owner of the " | 1135 | "owner of the " |
541 | 1004 | "transaction" % debconf_socket) | 1136 | "transaction" % debconf_socket) |
544 | 1005 | self.debconf = dbus.String(debconf_socket) | 1137 | with self.lock: |
545 | 1006 | self.PropertyChanged("DebconfSocket", self.debconf) | 1138 | self._debconf = dbus.String(debconf_socket) |
546 | 1139 | self.PropertyChanged("DebconfSocket", self._debconf) | ||
547 | 1140 | |||
548 | 1141 | @locked | ||
549 | 1142 | def _get_debconf(self): | ||
550 | 1143 | return self._debconf | ||
551 | 1144 | |||
552 | 1145 | debconf = property(_get_debconf, _set_debconf) | ||
553 | 1007 | 1146 | ||
554 | 1008 | # pylint: disable-msg=C0103,C0322 | 1147 | # pylint: disable-msg=C0103,C0322 |
555 | 1009 | @dbus_deferred_method(APTDAEMON_TRANSACTION_DBUS_INTERFACE, | 1148 | @dbus_deferred_method(APTDAEMON_TRANSACTION_DBUS_INTERFACE, |
556 | @@ -1030,6 +1169,7 @@ | |||
557 | 1030 | if not self.required_medium[0] == medium: | 1169 | if not self.required_medium[0] == medium: |
558 | 1031 | raise errors.AptDaemonError("The medium '%s' isn't " | 1170 | raise errors.AptDaemonError("The medium '%s' isn't " |
559 | 1032 | "requested." % medium) | 1171 | "requested." % medium) |
560 | 1172 | self.feedback.set() | ||
561 | 1033 | self.paused = False | 1173 | self.paused = False |
562 | 1034 | 1174 | ||
563 | 1035 | # pylint: disable-msg=C0103,C0322 | 1175 | # pylint: disable-msg=C0103,C0322 |
564 | @@ -1066,6 +1206,7 @@ | |||
565 | 1066 | if not self.config_file_conflict[0] == config: | 1206 | if not self.config_file_conflict[0] == config: |
566 | 1067 | raise errors.AptDaemonError("Invalid config file: %s" % config) | 1207 | raise errors.AptDaemonError("Invalid config file: %s" % config) |
567 | 1068 | self.config_file_conflict_resolution = answer | 1208 | self.config_file_conflict_resolution = answer |
568 | 1209 | self.feedback.set() | ||
569 | 1069 | self.paused = False | 1210 | self.paused = False |
570 | 1070 | 1211 | ||
571 | 1071 | @inline_callbacks | 1212 | @inline_callbacks |
572 | @@ -1132,10 +1273,6 @@ | |||
573 | 1132 | if self.uid != uid: | 1273 | if self.uid != uid: |
574 | 1133 | raise errors.ForeignTransaction() | 1274 | raise errors.ForeignTransaction() |
575 | 1134 | 1275 | ||
576 | 1135 | def _set_kwargs(self, kwargs): | ||
577 | 1136 | """Set the kwargs which will be send to the AptWorker.""" | ||
578 | 1137 | self.kwargs = kwargs | ||
579 | 1138 | |||
580 | 1139 | def gettext(self, msg): | 1276 | def gettext(self, msg): |
581 | 1140 | """Translate the given message to the language of the transaction. | 1277 | """Translate the given message to the language of the transaction. |
582 | 1141 | Fallback to the system default. | 1278 | Fallback to the system default. |
583 | @@ -1184,6 +1321,7 @@ | |||
584 | 1184 | log.debug("emitting queue changed") | 1321 | log.debug("emitting queue changed") |
585 | 1185 | self.emit("queue-changed") | 1322 | self.emit("queue-changed") |
586 | 1186 | 1323 | ||
587 | 1324 | @inline_callbacks | ||
588 | 1187 | def put(self, tid): | 1325 | def put(self, tid): |
589 | 1188 | """Add an item to the queue.""" | 1326 | """Add an item to the queue.""" |
590 | 1189 | trans = self.limbo.pop(tid) | 1327 | trans = self.limbo.pop(tid) |
591 | @@ -1197,7 +1335,7 @@ | |||
592 | 1197 | # the transaction has been started | 1335 | # the transaction has been started |
593 | 1198 | if not self.worker.trans: | 1336 | if not self.worker.trans: |
594 | 1199 | trans.progress = 9 | 1337 | trans.progress = 9 |
596 | 1200 | self.worker.simulate(trans) | 1338 | yield self.worker.simulate(trans) |
597 | 1201 | 1339 | ||
598 | 1202 | if trans._idle_watch is not None: | 1340 | if trans._idle_watch is not None: |
599 | 1203 | gobject.source_remove(trans._idle_watch) | 1341 | gobject.source_remove(trans._idle_watch) |
600 | @@ -1271,6 +1409,7 @@ | |||
601 | 1271 | signal.signal(signal.SIGQUIT, self._sigquit) | 1409 | signal.signal(signal.SIGQUIT, self._sigquit) |
602 | 1272 | signal.signal(signal.SIGTERM, self._sigquit) | 1410 | signal.signal(signal.SIGTERM, self._sigquit) |
603 | 1273 | self.options = options | 1411 | self.options = options |
604 | 1412 | self.mainloop = gobject.MainLoop() | ||
605 | 1274 | if connect == True: | 1413 | if connect == True: |
606 | 1275 | if bus is None: | 1414 | if bus is None: |
607 | 1276 | bus = dbus.SystemBus() | 1415 | bus = dbus.SystemBus() |
608 | @@ -1362,7 +1501,7 @@ | |||
609 | 1362 | self._check_for_inactivity) | 1501 | self._check_for_inactivity) |
610 | 1363 | log.debug("Waiting for calls") | 1502 | log.debug("Waiting for calls") |
611 | 1364 | try: | 1503 | try: |
613 | 1365 | mainloop.run() | 1504 | self.mainloop.run() |
614 | 1366 | except KeyboardInterrupt: | 1505 | except KeyboardInterrupt: |
615 | 1367 | self.Quit(None) | 1506 | self.Quit(None) |
616 | 1368 | 1507 | ||
617 | @@ -1853,7 +1992,7 @@ | |||
618 | 1853 | """Request a shutdown of the daemon.""" | 1992 | """Request a shutdown of the daemon.""" |
619 | 1854 | log.info("Quitting was requested") | 1993 | log.info("Quitting was requested") |
620 | 1855 | log.debug("Quitting main loop...") | 1994 | log.debug("Quitting main loop...") |
622 | 1856 | mainloop.quit() | 1995 | self.mainloop.quit() |
623 | 1857 | log.debug("Exit") | 1996 | log.debug("Exit") |
624 | 1858 | 1997 | ||
625 | 1859 | @inline_callbacks | 1998 | @inline_callbacks |
626 | 1860 | 1999 | ||
627 | === removed file 'aptdaemon/loop.py' | |||
628 | --- aptdaemon/loop.py 2010-05-03 05:49:33 +0000 | |||
629 | +++ aptdaemon/loop.py 1970-01-01 00:00:00 +0000 | |||
630 | @@ -1,32 +0,0 @@ | |||
631 | 1 | #!/usr/bin/env python | ||
632 | 2 | # -*- coding: utf-8 -*- | ||
633 | 3 | """Main loop for aptdaemon.""" | ||
634 | 4 | # Copyright (C) 2008-2009 Sebastian Heinlein <devel@glatzor.de> | ||
635 | 5 | # | ||
636 | 6 | # This program is free software; you can redistribute it and/or modify | ||
637 | 7 | # it under the terms of the GNU General Public License as published by | ||
638 | 8 | # the Free Software Foundation; either version 2 of the License, or | ||
639 | 9 | # any later version. | ||
640 | 10 | # | ||
641 | 11 | # This program is distributed in the hope that it will be useful, | ||
642 | 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
643 | 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
644 | 14 | # GNU General Public License for more details. | ||
645 | 15 | # | ||
646 | 16 | # You should have received a copy of the GNU General Public License along | ||
647 | 17 | # with this program; if not, write to the Free Software Foundation, Inc., | ||
648 | 18 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
649 | 19 | |||
650 | 20 | __author__ = "Sebastian Heinlein <devel@glatzor.de>" | ||
651 | 21 | |||
652 | 22 | __all__ = ("mainloop", "get_main_loop") | ||
653 | 23 | |||
654 | 24 | import gobject | ||
655 | 25 | |||
656 | 26 | mainloop = gobject.MainLoop() | ||
657 | 27 | |||
658 | 28 | def get_main_loop(): | ||
659 | 29 | """Return the gobject main loop as a singelton.""" | ||
660 | 30 | return mainloop | ||
661 | 31 | |||
662 | 32 | # vim:ts=4:sw=4:et | ||
663 | 33 | 0 | ||
664 | === modified file 'aptdaemon/progress.py' | |||
665 | --- aptdaemon/progress.py 2011-09-30 15:22:13 +0000 | |||
666 | +++ aptdaemon/progress.py 2011-10-02 05:32:23 +0000 | |||
667 | @@ -33,7 +33,6 @@ | |||
668 | 33 | 33 | ||
669 | 34 | import enums | 34 | import enums |
670 | 35 | import lock | 35 | import lock |
671 | 36 | from loop import mainloop | ||
672 | 37 | 36 | ||
673 | 38 | # Required to get translatable strings extraced by xgettext | 37 | # Required to get translatable strings extraced by xgettext |
674 | 39 | _ = lambda s: s | 38 | _ = lambda s: s |
675 | @@ -210,9 +209,6 @@ | |||
676 | 210 | len(items)) % {"files": | 209 | len(items)) % {"files": |
677 | 211 | " ".join(items)} | 210 | " ".join(items)} |
678 | 212 | self.transaction.status_details = msg | 211 | self.transaction.status_details = msg |
679 | 213 | |||
680 | 214 | while gobject.main_context_default().pending(): | ||
681 | 215 | gobject.main_context_default().iteration() | ||
682 | 216 | return True | 212 | return True |
683 | 217 | 213 | ||
684 | 218 | def start(self): | 214 | def start(self): |
685 | @@ -232,8 +228,7 @@ | |||
686 | 232 | self.transaction.required_medium = medium, drive | 228 | self.transaction.required_medium = medium, drive |
687 | 233 | self.transaction.paused = True | 229 | self.transaction.paused = True |
688 | 234 | self.transaction.status = enums.STATUS_WAITING_MEDIUM | 230 | self.transaction.status = enums.STATUS_WAITING_MEDIUM |
691 | 235 | while self.transaction.paused: | 231 | self.transaction.feedback.wait() |
690 | 236 | gobject.main_context_default().iteration() | ||
692 | 237 | self.transaction.status = enums.STATUS_DOWNLOADING | 232 | self.transaction.status = enums.STATUS_DOWNLOADING |
693 | 238 | if self.transaction.cancelled: | 233 | if self.transaction.cancelled: |
694 | 239 | return False | 234 | return False |
695 | @@ -309,6 +304,7 @@ | |||
696 | 309 | self.child_pid = pid | 304 | self.child_pid = pid |
697 | 310 | os.close(self.status_child_fd) | 305 | os.close(self.status_child_fd) |
698 | 311 | log.debug("Child pid: %s", pid) | 306 | log.debug("Child pid: %s", pid) |
699 | 307 | loop = gobject.MainLoop() | ||
700 | 312 | watchers = [] | 308 | watchers = [] |
701 | 313 | flags = gobject.IO_IN | gobject.IO_ERR | gobject.IO_HUP | 309 | flags = gobject.IO_IN | gobject.IO_ERR | gobject.IO_HUP |
702 | 314 | if self.transaction.terminal: | 310 | if self.transaction.terminal: |
703 | @@ -318,13 +314,12 @@ | |||
704 | 318 | watchers.append(gobject.io_add_watch(self.master_fd, flags, | 314 | watchers.append(gobject.io_add_watch(self.master_fd, flags, |
705 | 319 | self._copy_io_master, terminal_fd)) | 315 | self._copy_io_master, terminal_fd)) |
706 | 320 | # Monitor the child process | 316 | # Monitor the child process |
708 | 321 | watchers.append(gobject.child_watch_add(pid, self._on_child_exit)) | 317 | watchers.append(gobject.child_watch_add(pid, self._on_child_exit, loop)) |
709 | 322 | # Watch for status updates | 318 | # Watch for status updates |
710 | 323 | watchers.append(gobject.io_add_watch(self.status_parent_fd, | 319 | watchers.append(gobject.io_add_watch(self.status_parent_fd, |
711 | 324 | gobject.IO_IN, | 320 | gobject.IO_IN, |
712 | 325 | self._on_status_update)) | 321 | self._on_status_update)) |
715 | 326 | while self._child_exit == -1: | 322 | loop.run() |
714 | 327 | gobject.main_context_default().iteration() | ||
716 | 328 | for id in watchers: | 323 | for id in watchers: |
717 | 329 | gobject.source_remove(id) | 324 | gobject.source_remove(id) |
718 | 330 | # Restore the settings of the transaction terminal | 325 | # Restore the settings of the transaction terminal |
719 | @@ -341,9 +336,10 @@ | |||
720 | 341 | pass | 336 | pass |
721 | 342 | return os.WEXITSTATUS(self._child_exit) | 337 | return os.WEXITSTATUS(self._child_exit) |
722 | 343 | 338 | ||
724 | 344 | def _on_child_exit(self, pid, condition): | 339 | def _on_child_exit(self, pid, condition, loop): |
725 | 345 | log.debug("Child exited: %s", condition) | 340 | log.debug("Child exited: %s", condition) |
726 | 346 | self._child_exit = condition | 341 | self._child_exit = condition |
727 | 342 | loop.quit() | ||
728 | 347 | return False | 343 | return False |
729 | 348 | 344 | ||
730 | 349 | def _on_status_update(self, source, condition): | 345 | def _on_status_update(self, source, condition): |
731 | @@ -397,8 +393,6 @@ | |||
732 | 397 | signal.signal(signal.SIGINT, interrupt_handler) | 393 | signal.signal(signal.SIGINT, interrupt_handler) |
733 | 398 | # Make sure that exceptions of the child are not catched by apport | 394 | # Make sure that exceptions of the child are not catched by apport |
734 | 399 | sys.excepthook = sys.__excepthook__ | 395 | sys.excepthook = sys.__excepthook__ |
735 | 400 | |||
736 | 401 | mainloop.quit() | ||
737 | 402 | # Switch to the language of the user | 396 | # Switch to the language of the user |
738 | 403 | if self.transaction.locale: | 397 | if self.transaction.locale: |
739 | 404 | os.putenv("LANG", self.transaction.locale) | 398 | os.putenv("LANG", self.transaction.locale) |
740 | @@ -496,8 +490,8 @@ | |||
741 | 496 | self.transaction.config_file_conflict = (current, new) | 490 | self.transaction.config_file_conflict = (current, new) |
742 | 497 | self.transaction.paused = True | 491 | self.transaction.paused = True |
743 | 498 | self.transaction.status = enums.STATUS_WAITING_CONFIG_FILE_PROMPT | 492 | self.transaction.status = enums.STATUS_WAITING_CONFIG_FILE_PROMPT |
746 | 499 | while self.transaction.paused: | 493 | #FIXME: Should we only wait some time? |
747 | 500 | gobject.main_context_default().iteration() | 494 | self.transaction.feedback.wait() |
748 | 501 | log.debug("Sending config file answer: %s", | 495 | log.debug("Sending config file answer: %s", |
749 | 502 | self.transaction.config_file_conflict_resolution) | 496 | self.transaction.config_file_conflict_resolution) |
750 | 503 | if self.transaction.config_file_conflict_resolution == "replace": | 497 | if self.transaction.config_file_conflict_resolution == "replace": |
751 | 504 | 498 | ||
752 | === modified file 'aptdaemon/utils.py' | |||
753 | --- aptdaemon/utils.py 2010-05-03 05:49:33 +0000 | |||
754 | +++ aptdaemon/utils.py 2011-10-02 05:32:23 +0000 | |||
755 | @@ -25,8 +25,11 @@ | |||
756 | 25 | __all__ = ("deprecated",) | 25 | __all__ = ("deprecated",) |
757 | 26 | 26 | ||
758 | 27 | import functools | 27 | import functools |
759 | 28 | import threading | ||
760 | 28 | import warnings | 29 | import warnings |
761 | 29 | 30 | ||
762 | 31 | from defer import Deferred | ||
763 | 32 | |||
764 | 30 | def deprecated(func): | 33 | def deprecated(func): |
765 | 31 | """This is a decorator which can be used to mark functions | 34 | """This is a decorator which can be used to mark functions |
766 | 32 | as deprecated. It will result in a warning being emitted | 35 | as deprecated. It will result in a warning being emitted |
767 | @@ -48,4 +51,31 @@ | |||
768 | 48 | return func(*args, **kwargs) | 51 | return func(*args, **kwargs) |
769 | 49 | return new_func | 52 | return new_func |
770 | 50 | 53 | ||
771 | 54 | def locked(func): | ||
772 | 55 | """Protect the called method by a lock.""" | ||
773 | 56 | def _locked(*args, **kwargs): | ||
774 | 57 | self = args[0] | ||
775 | 58 | with self.lock: | ||
776 | 59 | return func(*args, **kwargs) | ||
777 | 60 | return _locked | ||
778 | 61 | |||
779 | 62 | def defer_to_thread(func): | ||
780 | 63 | """Wrap the decorated message to a Deferred which will be called | ||
781 | 64 | in a separated thread. | ||
782 | 65 | """ | ||
783 | 66 | def _deferred_to_thread(*args, **kwargs): | ||
784 | 67 | def __deferred_to_thread(deferred): | ||
785 | 68 | try: | ||
786 | 69 | result = func(*args, **kwargs) | ||
787 | 70 | except Exception, error: | ||
788 | 71 | deferred.errback(error) | ||
789 | 72 | else: | ||
790 | 73 | deferred.callback(result) | ||
791 | 74 | deferred = Deferred() | ||
792 | 75 | #FIXME: Would be nice to have a thread pool and a Queue here | ||
793 | 76 | thread = threading.Thread(target=__deferred_to_thread, args=[deferred]) | ||
794 | 77 | thread.run() | ||
795 | 78 | return deferred | ||
796 | 79 | return _deferred_to_thread | ||
797 | 80 | |||
798 | 51 | # vim:ts=4:sw=4:et | 81 | # vim:ts=4:sw=4:et |
799 | 52 | 82 | ||
800 | === modified file 'aptdaemon/worker.py' | |||
801 | --- aptdaemon/worker.py 2011-09-18 06:31:09 +0000 | |||
802 | +++ aptdaemon/worker.py 2011-10-02 05:32:23 +0000 | |||
803 | @@ -1,4 +1,4 @@ | |||
805 | 1 | #!/usr/bin/env python | 1 | #/usr/bin/env python |
806 | 2 | # -*- coding: utf-8 -*- | 2 | # -*- coding: utf-8 -*- |
807 | 3 | """Provides AptWorker which processes transactions.""" | 3 | """Provides AptWorker which processes transactions.""" |
808 | 4 | # Copyright (C) 2008-2009 Sebastian Heinlein <devel@glatzor.de> | 4 | # Copyright (C) 2008-2009 Sebastian Heinlein <devel@glatzor.de> |
809 | @@ -29,6 +29,7 @@ | |||
810 | 29 | import sys | 29 | import sys |
811 | 30 | import tempfile | 30 | import tempfile |
812 | 31 | import time | 31 | import time |
813 | 32 | import threading | ||
814 | 32 | import traceback | 33 | import traceback |
815 | 33 | 34 | ||
816 | 34 | import apt | 35 | import apt |
817 | @@ -54,6 +55,7 @@ | |||
818 | 54 | DaemonDpkgInstallProgress, \ | 55 | DaemonDpkgInstallProgress, \ |
819 | 55 | DaemonDpkgReconfigureProgress, \ | 56 | DaemonDpkgReconfigureProgress, \ |
820 | 56 | DaemonDpkgRecoverProgress | 57 | DaemonDpkgRecoverProgress |
821 | 58 | from utils import locked, defer_to_thread | ||
822 | 57 | 59 | ||
823 | 58 | log = logging.getLogger("AptDaemon.Worker") | 60 | log = logging.getLogger("AptDaemon.Worker") |
824 | 59 | 61 | ||
825 | @@ -105,6 +107,8 @@ | |||
826 | 105 | self._status_frozen = None | 107 | self._status_frozen = None |
827 | 106 | self.plugins = {} | 108 | self.plugins = {} |
828 | 107 | self._load_plugins() | 109 | self._load_plugins() |
829 | 110 | self.lock = threading.Lock() | ||
830 | 111 | self.worker_thread = None | ||
831 | 108 | 112 | ||
832 | 109 | def _load_plugins(self): | 113 | def _load_plugins(self): |
833 | 110 | """Load the plugins from setuptools' entry points.""" | 114 | """Load the plugins from setuptools' entry points.""" |
834 | @@ -153,10 +157,14 @@ | |||
835 | 153 | transaction -- core.Transcation instance to run | 157 | transaction -- core.Transcation instance to run |
836 | 154 | """ | 158 | """ |
837 | 155 | log.info("Processing transaction %s", transaction.tid) | 159 | log.info("Processing transaction %s", transaction.tid) |
842 | 156 | if self.trans: | 160 | with self.lock: |
843 | 157 | raise Exception("There is already a running transaction") | 161 | if self.trans: |
844 | 158 | self.trans = transaction | 162 | raise Exception("There is already a running transaction") |
845 | 159 | gobject.idle_add(self._process_transaction, transaction) | 163 | self.trans = transaction |
846 | 164 | self.worker_thread = threading.Thread(target=self._process_transaction, | ||
847 | 165 | args=[transaction], | ||
848 | 166 | name="WorkerThread") | ||
849 | 167 | self.worker_thread.start() | ||
850 | 160 | 168 | ||
851 | 161 | def _emit_transaction_done(self, trans): | 169 | def _emit_transaction_done(self, trans): |
852 | 162 | """Emit the transaction-done signal. | 170 | """Emit the transaction-done signal. |
853 | @@ -174,6 +182,7 @@ | |||
854 | 174 | trans.progress = 11 | 182 | trans.progress = 11 |
855 | 175 | # FIXME: Check if the transaction has been just simulated. So we could | 183 | # FIXME: Check if the transaction has been just simulated. So we could |
856 | 176 | # skip marking the changes a second time. | 184 | # skip marking the changes a second time. |
857 | 185 | self.lock.acquire() | ||
858 | 177 | try: | 186 | try: |
859 | 178 | lock.wait_for_lock(trans) | 187 | lock.wait_for_lock(trans) |
860 | 179 | # Prepare the package cache | 188 | # Prepare the package cache |
861 | @@ -236,14 +245,15 @@ | |||
862 | 236 | else: | 245 | else: |
863 | 237 | trans.exit = EXIT_SUCCESS | 246 | trans.exit = EXIT_SUCCESS |
864 | 238 | finally: | 247 | finally: |
865 | 248 | self.lock.release() | ||
866 | 239 | trans.progress = 100 | 249 | trans.progress = 100 |
867 | 240 | self.last_action_timestamp = time.time() | 250 | self.last_action_timestamp = time.time() |
868 | 241 | tid = trans.tid[:] | 251 | tid = trans.tid[:] |
870 | 242 | self.trans = None | 252 | with self.lock: |
871 | 253 | self.trans = None | ||
872 | 243 | self._emit_transaction_done(trans) | 254 | self._emit_transaction_done(trans) |
873 | 244 | lock.release() | 255 | lock.release() |
874 | 245 | log.info("Finished transaction %s", tid) | 256 | log.info("Finished transaction %s", tid) |
875 | 246 | return False | ||
876 | 247 | 257 | ||
877 | 248 | def commit_packages(self, trans, install, reinstall, remove, purge, upgrade, | 258 | def commit_packages(self, trans, install, reinstall, remove, purge, upgrade, |
878 | 249 | downgrade, simulate=False): | 259 | downgrade, simulate=False): |
879 | @@ -360,7 +370,6 @@ | |||
880 | 360 | "available."), pkg_ver, pkg_name) | 370 | "available."), pkg_ver, pkg_name) |
881 | 361 | elif pkg_rel: | 371 | elif pkg_rel: |
882 | 362 | self._set_candidate_release(pkg, pkg_rel) | 372 | self._set_candidate_release(pkg, pkg_rel) |
883 | 363 | |||
884 | 364 | 373 | ||
885 | 365 | def enable_distro_comp(self, trans, component): | 374 | def enable_distro_comp(self, trans, component): |
886 | 366 | """Enable given component in the sources list. | 375 | """Enable given component in the sources list. |
887 | @@ -381,7 +390,8 @@ | |||
888 | 381 | finally: | 390 | finally: |
889 | 382 | os.umask(old_umask) | 391 | os.umask(old_umask) |
890 | 383 | 392 | ||
892 | 384 | def add_repository(self, trans, src_type, uri, dist, comps, comment, sourcesfile): | 393 | def add_repository(self, trans, src_type, uri, dist, comps, comment, |
893 | 394 | sourcesfile): | ||
894 | 385 | """Add given repository to the sources list. | 395 | """Add given repository to the sources list. |
895 | 386 | 396 | ||
896 | 387 | Keyword arguments: | 397 | Keyword arguments: |
897 | @@ -444,7 +454,6 @@ | |||
898 | 444 | log.info("Adding vendor key from keyserver: %s %s", keyid, keyserver) | 454 | log.info("Adding vendor key from keyserver: %s %s", keyid, keyserver) |
899 | 445 | trans.status = STATUS_DOWNLOADING | 455 | trans.status = STATUS_DOWNLOADING |
900 | 446 | trans.progress = 101 | 456 | trans.progress = 101 |
901 | 447 | last_pulse = time.time() | ||
902 | 448 | #FIXME: Use gobject.spawn_async and deferreds in the worker | 457 | #FIXME: Use gobject.spawn_async and deferreds in the worker |
903 | 449 | # Alternatively we could use python-pyme directly for a better | 458 | # Alternatively we could use python-pyme directly for a better |
904 | 450 | # error handling. Or the --status-fd of gpg | 459 | # error handling. Or the --status-fd of gpg |
905 | @@ -453,12 +462,8 @@ | |||
906 | 453 | "--recv", keyid], stderr=subprocess.STDOUT, | 462 | "--recv", keyid], stderr=subprocess.STDOUT, |
907 | 454 | stdout=subprocess.PIPE, close_fds=True) | 463 | stdout=subprocess.PIPE, close_fds=True) |
908 | 455 | while proc.poll() is None: | 464 | while proc.poll() is None: |
915 | 456 | while gobject.main_context_default().pending(): | 465 | time.sleep(0.5) |
916 | 457 | gobject.main_context_default().iteration() | 466 | trans.progress = 101 |
911 | 458 | time.sleep(0.05) | ||
912 | 459 | if time.time() - last_pulse > 0.3: | ||
913 | 460 | trans.progress = 101 | ||
914 | 461 | last_pulse = time.time() | ||
917 | 462 | if proc.returncode != 0: | 467 | if proc.returncode != 0: |
918 | 463 | stdout = unicode(proc.stdout.read(), | 468 | stdout = unicode(proc.stdout.read(), |
919 | 464 | # that can return "None", in this case, just | 469 | # that can return "None", in this case, just |
920 | @@ -941,12 +946,15 @@ | |||
921 | 941 | frozen_dir = tempfile.mkdtemp(prefix="aptdaemon-frozen-status") | 946 | frozen_dir = tempfile.mkdtemp(prefix="aptdaemon-frozen-status") |
922 | 942 | shutil.copy(self._status_orig, frozen_dir) | 947 | shutil.copy(self._status_orig, frozen_dir) |
923 | 943 | self._status_frozen = os.path.join(frozen_dir, "status") | 948 | self._status_frozen = os.path.join(frozen_dir, "status") |
924 | 949 | self.lock.release() | ||
925 | 944 | try: | 950 | try: |
926 | 945 | yield | 951 | yield |
927 | 946 | finally: | 952 | finally: |
928 | 953 | self.lock.acquire() | ||
929 | 947 | shutil.rmtree(frozen_dir) | 954 | shutil.rmtree(frozen_dir) |
930 | 948 | self._status_frozen = None | 955 | self._status_frozen = None |
931 | 949 | 956 | ||
932 | 957 | @defer_to_thread | ||
933 | 950 | def simulate(self, trans): | 958 | def simulate(self, trans): |
934 | 951 | """Return the dependencies which will be installed by the transaction, | 959 | """Return the dependencies which will be installed by the transaction, |
935 | 952 | the content of the dpkg status file after the transaction would have | 960 | the content of the dpkg status file after the transaction would have |
936 | @@ -958,8 +966,9 @@ | |||
937 | 958 | log.info("Simulating trans: %s" % trans.tid) | 966 | log.info("Simulating trans: %s" % trans.tid) |
938 | 959 | trans.status = STATUS_RESOLVING_DEP | 967 | trans.status = STATUS_RESOLVING_DEP |
939 | 960 | try: | 968 | try: |
942 | 961 | trans.depends, trans.download, trans.space, \ | 969 | with self.lock: |
943 | 962 | trans.unauthenticated = self._simulate_helper(trans) | 970 | trans.depends, trans.download, trans.space, \ |
944 | 971 | trans.unauthenticated = self._simulate_helper(trans) | ||
945 | 963 | except TransactionFailed, excep: | 972 | except TransactionFailed, excep: |
946 | 964 | trans.error = excep | 973 | trans.error = excep |
947 | 965 | except Exception, excep: | 974 | except Exception, excep: |
948 | @@ -980,7 +989,6 @@ | |||
949 | 980 | trans.exit = EXIT_FAILED | 989 | trans.exit = EXIT_FAILED |
950 | 981 | trans.progress = 100 | 990 | trans.progress = 100 |
951 | 982 | self.last_action_timestamp = time.time() | 991 | self.last_action_timestamp = time.time() |
952 | 983 | raise trans.error | ||
953 | 984 | 992 | ||
954 | 985 | def _simulate_helper(self, trans): | 993 | def _simulate_helper(self, trans): |
955 | 986 | depends = [[], [], [], [], [], [], []] | 994 | depends = [[], [], [], [], [], [], []] |
956 | @@ -1341,11 +1349,11 @@ | |||
957 | 1341 | trans.status = STATUS_FINISHED | 1349 | trans.status = STATUS_FINISHED |
958 | 1342 | self.last_action_timestamp = time.time() | 1350 | self.last_action_timestamp = time.time() |
959 | 1343 | tid = self.trans.tid[:] | 1351 | tid = self.trans.tid[:] |
962 | 1344 | trans = self.trans | 1352 | with self.lock: |
963 | 1345 | self.trans = None | 1353 | trans = self.trans |
964 | 1354 | self.trans = None | ||
965 | 1346 | self._emit_transaction_done(trans) | 1355 | self._emit_transaction_done(trans) |
966 | 1347 | log.info("Finished transaction %s", tid) | 1356 | log.info("Finished transaction %s", tid) |
967 | 1348 | return False | ||
968 | 1349 | 1357 | ||
969 | 1350 | def simulate(self, trans): | 1358 | def simulate(self, trans): |
970 | 1351 | depends = [[], [], [], [], [], [], []] | 1359 | depends = [[], [], [], [], [], [], []] |