source: lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore/plugins/cacheManager.py

Last change on this file was 8226, checked in by Juanma, 14 months ago

Add vlc-3 as external appimage

File size: 8.2 KB
Line 
1#The name of the main class must match the file name in lowercase
2#Init: Could accept parameters if we declare them in storeManager's threads dict
3import os
4#import lliurexstore.plugins.debManager
5import lliurexstore.plugins.appImageManager
6import lliurexstore.plugins.snapManager 
7import lliurexstore.plugins.infoManager 
8import lliurexstore.plugins.zmdManager 
9import random
10import sqlite3
11import threading
12import time
13import psutil
14from queue import Queue as pool
15class cachemanager:
16        def __init__(self):
17                self.dbg=False
18                self.progress=0
19                self.plugin_actions={'cache':'*','pkginfo':'*'}
20                self.cli_mode=False
21                self.autostart_actions={'cache':'store=self.store'} #List with actions that storeManager must launch automatically. The parameter list refers to 'stringfieds' storeManager members !!
22#               self.postaction_actions={'install':'app','remove':'app'}
23                self.requires={'cache':'store=self.store'}
24                self.cache_dir=os.getenv("HOME")+"/.cache/lliurex-store"
25                self.cache_db=self.cache_dir+'/data/info.db'
26                self.db_cursor=''
27                self.db=''
28                self.processed=0
29                self.total=0
30                self.result={}
31                self.disabled=None
32                self.infomanager=lliurexstore.plugins.infoManager.infomanager()
33                self.debmanager=lliurexstore.plugins.debManager.debmanager()
34                self.appimagemanager=lliurexstore.plugins.appImageManager.appimagemanager()
35                self.snapmanager=lliurexstore.plugins.snapManager.snapmanager()
36                self.zmdmanager=lliurexstore.plugins.zmdManager.zmdmanager()
37                self.insert_count=0
38                self.data_pool=pool()
39                self.apps_per_cycle=5 #Apps that will be processed per cycle
40                self.cycles_for_commit=1 #Processed cycles needed for a commit
41                self.sleep_between_cycles=10 #Time the cache plugin will sleep between a process cycle and the next
42                self.sleep_between_apps=0.1 #Time the cache plugin will sleep between process one app and the next
43        #def __init__
44       
45        def set_debug(self,dbg=True):
46                self.dbg=dbg
47                #self._debug ("Debug enabled")
48        #def set_debug
49
50        def _debug(self,msg=''):
51                if self.dbg:
52                        print ('DEBUG Cache: %s'%msg)
53        #def debug
54
55        def register(self):
56                return(self.plugin_actions)
57        #def register
58
59        def execute_action(self,action,store=None,applist=None):
60                self.progress=0
61                self.store=store
62                self.result['status']={'status':-1,'msg':''}
63                self.result['data']=''
64                if self.disabled:
65                        self._set_status(9)
66                else:
67                        self._set_db()
68                        if action=='cache':
69                                self._build_cache()
70                        if action=='install':
71                                self._update(applist,'installed')
72                        if action=='remove':
73                                self._update(applist,'available')
74                        if action=='pkginfo':
75                                dataList=[]
76                                for appinfo in applist:
77                                        #self._debug("Looking for %s"%appinfo['package'])
78                                        dataList.append(self._get_info(appinfo))
79                                self.result['data']=list(dataList)
80                        self.progress=100 #When all actions are launched we must assure that progress=100.
81                        self.db.close()
82                return(self.result)
83        #def execute_action
84
85        def set_sleep_between_apps(self,seconds):
86                self.sleep_between_apps=seconds
87        #def set_sleep_between_apps
88
89        def set_sleep_between_cycles(self,seconds):
90                self.sleep_between_cycles=seconds
91        #def set_sleep_between_cycles
92
93        def set_cycles_for_commit(self,count):
94                self.cycles_for_commit=count
95        #def set_cycles_for_commit
96
97        def set_apps_per_cycle(self,count):
98                self.apps_per_cycle=count
99        #def set_apps_per_cycle
100
101        def _callback(self):
102                self.progress=self.progress+1
103        #def _callback
104
105        def _set_status(self,status,msg=''):
106                self.result['status']={'status':status,'msg':msg}
107        #def _set_status
108       
109        def _set_db(self):
110                sw_db_exists=False
111                if os.path.isfile(self.cache_db):
112                        sw_db_exists=True
113                else:
114                        try:
115                                os.makedirs(os.path.dirname(self.cache_db))
116                        except Exception as e:
117                                #self._debug(e)
118                                pass
119                try:
120                        self.db=sqlite3.connect(self.cache_db)
121                except Exception as e:
122                        #self._debug(e)
123                        pass
124                self.db_cursor=self.db.cursor()
125                if sw_db_exists==False:
126                        #self._debug("Creating cache table")
127                        self.db_cursor.execute('''CREATE TABLE data(app TEXT PRIMARY KEY, size INTEGER, state TEXT, version TEXT)''')
128                self.db_cursor.execute("SELECT count(*) FROM data")
129                self.processed=self.db_cursor.fetchone()
130                #self._debug("%s apps present"%self.processed)
131        #def _set_db
132
133        def _build_cache(self):
134                threads=[]
135                semaphore = threading.BoundedSemaphore(value=self.apps_per_cycle)
136                storeapps=self.store.get_apps()
137                processed=[]
138                for item in range(len(storeapps)-1):
139                        cursor=random.randint(0,len(storeapps)-1)
140                        app=storeapps[cursor]
141                        pkgname=app.get_pkgname_default()
142                        while pkgname in processed and len(processed)<len(storeapps):
143                                #self._debug("%s already processed"%pkgname)
144                                cursor=random.randint(0,len(storeapps)-1)
145                                app=storeapps[cursor]
146                                pkgname=app.get_pkgname_default()
147                        processed.append(pkgname)
148                        th=threading.Thread(target=self._th_get_data_for_app, args = (app,semaphore))
149                        threads.append(th)
150                        th.start()
151                        self.insert_count+=1
152                        if self.insert_count==self.apps_per_cycle:
153                                for thread in threads:
154                                        try:
155                                                thread.join()
156                                        except:
157                                                pass
158                                time.sleep(self.sleep_between_cycles)
159                                threads=[]
160                        if self.insert_count==self.cycles_for_commit*self.apps_per_cycle:
161                                self.insert_count=0
162                                self._write_info()
163                        time.sleep(self.sleep_between_apps)
164                #self._debug("Cache finished. Processed %s apps"%str(len(storeapps)-1))
165        #def _build_cache
166
167        def _write_info(self):
168                processed=[]
169                while self.data_pool.qsize():
170                        appinfo=self.data_pool.get()
171                        if appinfo in processed:
172                                #self._debug("Duplicated %s"%appinfo['package'])
173                                continue
174                        processed.append(appinfo)
175                        #self._debug("Writing %s to db"%appinfo['package'])
176                        self.db_cursor.execute('''REPLACE into data values (?,?,?,?)''', (appinfo['package'],appinfo['size'],appinfo['state'],appinfo['version']))
177                        time.sleep(self.sleep_between_apps)
178                self._commit_bd()
179        #def _write_info
180
181        def _commit_bd(self):
182                try:
183                        self.db.commit()
184                except Exception as e:
185                        #self._debug("Commit error: %s. Rollback launched\n"%e)
186                        self.db.rollback()
187        #def _commit_bd
188
189        def _th_get_data_for_app(self,app,semaphore):
190                #self._debug("Processing %s"%app.get_pkgname_default())
191                app_info=self.infomanager.execute_action('info',[app],True)['data']
192                package_type=self._check_package_type(app_info[0])
193                #self._debug("Type %s"%package_type)
194                appinfo=None
195                if package_type=='deb':
196                        appinfo=self.debmanager.execute_action('pkginfo',app_info)['data']
197                if package_type=='appimage':
198                        appinfo=self.appimagemanager.execute_action('pkginfo',app_info)['data']
199                if package_type=='zmd':
200                        appinfo=self.zmdmanager.execute_action('pkginfo',app_info)['data']
201                if package_type=='snap':
202                        appinfo=self.snapmanager.execute_action('pkginfo',app_info)['data']
203                #Disabling state
204                try:
205                        appinfo[-1]['state']=''
206                        #self._debug("Storing %s"%appinfo[-1]['package'])
207                        self.data_pool.put(appinfo[-1])
208                except Exception as e:
209                        #self._debug("_th_get_data_for_app: %s"%e)
210                        pass
211        #def _th_get_data_for_app
212
213        def _check_package_type(self,appinfo):
214                #Standalone installers must have the subcategory "installer"
215                #Zomandos must have the subcategory "Zomando"
216                #self._debug("Checking package type for app "+appinfo['name'])
217                package_type=''
218                if appinfo['bundle']:
219                        package_type=appinfo['bundle']
220                        if type(package_type)==type([]):
221                                package_type=package_type[0]
222                else:
223                        if "Zomando" in appinfo['categories']:
224                                package_type="zmd"
225                        if 'component' in appinfo.keys():
226                                if appinfo['component']!='':
227                                        package_type='deb'
228                #Standalone installers must have an installerUrl field loaded from a bundle type=script description
229                        if appinfo['installerUrl']!='':
230                                package_type="sh"
231                return(package_type)
232        #def _check_package_type
233
234        def _get_info(self,appinfo):
235                #self._debug("Searching %s"%appinfo['package'])
236                self.db_cursor.execute('''SELECT * FROM data WHERE app=?''',(appinfo['package'],))
237                row=self.db_cursor.fetchone()
238                if row:
239                        #self._debug("Row: %s"%str(row))
240                        appinfo['size']=str(row[1])
241#                       appinfo['state']=row[2]
242                        appinfo['state']=''
243                        appinfo['version']=row[3]
244                        self._set_status(0)
245                else:
246                        self._set_status(1)
247                return(appinfo)
248        #def _get_info
249
250        def _update(self,app,state):
251                return
252                self.db_cursor.execute('''SELECT * FROM data WHERE app=?''',(app,))
253                row=self.db_cursor.fetchone()
254                if row:
255                        #self._debug("Updating %s with state %s"%(app,state))
256                        query_data=(state,app)
257                        self.db_cursor.execute('''UPDATE data set state=? WHERE app=?''',(query_data))
258                        self._commit_bd()
259        #def _update
Note: See TracBrowser for help on using the repository browser.