Merge lp:~openerp-dev/openobject-server/6.0-opw-577963-msh into lp:openobject-server/6.0

Proposed by Mohammed Shekha(Open ERP)
Status: Rejected
Rejected by: Olivier Dony (Odoo)
Proposed branch: lp:~openerp-dev/openobject-server/6.0-opw-577963-msh
Merge into: lp:openobject-server/6.0
Diff against target: 38 lines (+8/-13)
1 file modified
bin/addons/base/ir/ir_attachment.py (+8/-13)
To merge this branch: bzr merge lp:~openerp-dev/openobject-server/6.0-opw-577963-msh
Reviewer Review Type Date Requested Status
Olivier Dony (Odoo) Disapprove
Mohammed Shekha(Open ERP) (community) Abstain
Review via email: mp+120138@code.launchpad.net

Description of the change

Hello,

Fixed the issue of ir_attachment which reads all the records for checking ir.access due to which ir_attachment tree view becomes to slow even if it loads only 20 records, changed the code and do the same with DISTINCT res_model, if user don't have rights then and only then read the ids of that object and remove it from ids.

When we click on document menu so it will read first 20 records and then it will call search_count(obviously without limit) for pager limit, search_count will call search method which is overridden in ir_atachment.py, and as there is not limit(search is called from search_count) so it will read all the attachments and then check for the user access on res_model, if user dont have rights then that attachment should not be shown to him but reading of all record will take time when there are lots of attachment and here we don't need to read all record because we only remove those ids of model on which user don't have access.

So fetched all distinct res_model and check it with ir.access and read only those ids on model on which user don't have access, this way it will save the time of fetching search result.

I have scenario in which I have 90000 attachments and loading of document tree view with only 20 records taking approximately 10 second, after this patch it will take 3 to 4 second.

Thanks.

To post a comment you must log in.
Revision history for this message
Mohammed Shekha(Open ERP) (msh-openerp) :
review: Abstain
Revision history for this message
Olivier Dony (Odoo) (odo-openerp) wrote :

This is not correct, the logic for filtering based on access rights was already done efficiently.
Your patch makes it check the access right of only 1 document of each model, but every document may have different access restrictions depending on access rules (e.g. multicompany, etc.).

BTW the OPW case has already been closed and a different patch was merged, so you don't need to work on this anymore.
The bulk of the performance problem with large databases was caused by the numerous calls to list.remove(), which are very slow on large lists. Using a set() instead made it a lot faster (50s -> 3s for a real database with 100k random attachments). Your measures were a lost faster than that, probably because most attachments were duplicates and therefore attached to the same (model,res_id) - biasing the result heavily.

Thanks,

PS: why did you review your own MP with "Abstain"?

review: Disapprove
Revision history for this message
Mohammed Shekha(Open ERP) (msh-openerp) wrote :

Hello Olivier,

Thanks for the review, yes I am agree that logic is not correct, I have checked with scenario in which this was improving latency but afterward I found that this will not be the proper fix, hence I have temporarily set it as a abstain and decided to improve it but afterward it has been improved with other fix and case is closed.

Hence now this branch is no more needed.

Thanks.

Unmerged revisions

3633. By Mohammed Shekha(Open ERP)

[FIX]Fixed the issue of ir_attachment which reads all the records for checking ir.access due to which ir_attachment tree view becomes to slow even if it loads only 20 records, changed the code and do the same with DISTINCT res_model, if user don't have rights then and only then read the ids of that object and remove it from ids.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/addons/base/ir/ir_attachment.py'
2--- bin/addons/base/ir/ir_attachment.py 2011-05-02 11:57:10 +0000
3+++ bin/addons/base/ir/ir_attachment.py 2012-08-17 10:56:22 +0000
4@@ -68,26 +68,21 @@
5 # For attachments, the permissions of the document they are attached to
6 # apply, so we must remove attachments for which the user cannot access
7 # the linked document.
8- targets = super(ir_attachment,self).read(cr, uid, ids, ['id', 'res_model', 'res_id'])
9 model_attachments = {}
10- for target_dict in targets:
11- if not (target_dict['res_id'] and target_dict['res_model']):
12- continue
13- # model_attachments = { 'model': { 'res_id': [id1,id2] } }
14- model_attachments.setdefault(target_dict['res_model'],{}).setdefault(target_dict['res_id'],set()).add(target_dict['id'])
15-
16 # To avoid multiple queries for each attachment found, checks are
17 # performed in batch as much as possible.
18 ima = self.pool.get('ir.model.access')
19- for model, targets in model_attachments.iteritems():
20+ cr.execute("select DISTINCT res_model, res_id from ir_attachment")
21+ for model, res_id in cr.fetchall():
22+ if model and res_id:
23+ model_attachments[model] = res_id
24+ for model,targets in model_attachments.iteritems():
25 if not ima.check(cr, uid, model, 'read', raise_exception=False, context=context):
26- # remove all corresponding attachment ids
27- for attach_id in itertools.chain(*targets.values()):
28+ read_ids = super(ir_attachment,self).search(cr, uid, [('res_model', '=', model)], context=context)
29+ for attach_id in read_ids:
30 ids.remove(attach_id)
31 continue # skip ir.rule processing, these ones are out already
32-
33- # filter ids according to what access rules permit
34- target_ids = targets.keys()
35+ target_ids = [targets]
36 allowed_ids = self.pool.get(model).search(cr, uid, [('id', 'in', target_ids)], context=context)
37 disallowed_ids = set(target_ids).difference(allowed_ids)
38 for res_id in disallowed_ids: