[feature] axel support for multithreaded downloads

This commit is contained in:
Vinícius Moreira
2020-05-27 16:18:53 -03:00
parent cec0c06e4f
commit 7aa133be2a
18 changed files with 139 additions and 45 deletions

View File

@@ -29,6 +29,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
<img src="https://raw.githubusercontent.com/vinifmor/bauh/staging/pictures/releases/0.9.4/arch_repo_mthread.png"> <img src="https://raw.githubusercontent.com/vinifmor/bauh/staging/pictures/releases/0.9.4/arch_repo_mthread.png">
</p> </p>
- Settings
- [axel](https://github.com/axel-download-accelerator/axel) added as an alternative multi-threaded download tool. The tool can be defined through the new field **Multi-threaded download tool** on the settings window **Advanced** tab
<p align="center">
<img src="https://raw.githubusercontent.com/vinifmor/bauh/staging/pictures/releases/0.9.4/mthread_tool.png">
</p>
### Improvements ### Improvements
- Arch - Arch

View File

@@ -257,7 +257,8 @@ You can change some application settings via environment variables or arguments
``` ```
download: download:
icons: true # allows bauh to download the applications icons when they are not saved on the disk icons: true # allows bauh to download the applications icons when they are not saved on the disk
multithreaded: true # allows bauh to use a multithreaded download client installed on the system to download applications source files faster ( current only **aria2** is supported ) multithreaded: true # allows bauh to use a multithreaded download client installed on the system to download applications source files faster
multithreaded_client: null # defines the multi-threaded download tool to be used. If null, the default installed tool will be used (priority: aria2 > axel). Possible tools/values: aria2, axel
gems: null # defines the enabled applications types managed by bauh ( a null value means all available ) gems: null # defines the enabled applications types managed by bauh ( a null value means all available )
locale: null # defines a different translation for bauh ( a null value will retrieve the system's default locale ) locale: null # defines a different translation for bauh ( a null value will retrieve the system's default locale )
store_root_password: true # if the root password should be asked only once store_root_password: true # if the root password should be asked only once

View File

@@ -1,4 +1,5 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import Iterable
from bauh.api.abstract.handler import ProcessWatcher from bauh.api.abstract.handler import ProcessWatcher
@@ -26,8 +27,9 @@ class FileDownloader(ABC):
pass pass
@abstractmethod @abstractmethod
def get_default_client_name(self) -> str: def can_work(self) -> bool:
""" pass
:return: retrieve current downloader client name
""" @abstractmethod
def get_supported_multithreaded_clients(self) -> Iterable[str]:
pass pass

View File

@@ -517,16 +517,8 @@ class AppImageManager(SoftwareManager):
res = run_cmd('which sqlite3') res = run_cmd('which sqlite3')
return res and not res.strip().startswith('which ') return res and not res.strip().startswith('which ')
def _is_wget_available(self):
res = run_cmd('which wget')
return res and not res.strip().startswith('which ')
def _is_aria2_available(self):
res = run_cmd('which aria2c')
return res and not res.strip().startswith('which ')
def can_work(self) -> bool: def can_work(self) -> bool:
return self._is_sqlite3_available() and (self._is_wget_available() or self._is_aria2_available()) return self._is_sqlite3_available() and self.file_downloader.can_work()
def requires_root(self, action: str, pkg: AppImage): def requires_root(self, action: str, pkg: AppImage):
return False return False

View File

@@ -38,7 +38,7 @@ def new_manage_panel(app_args: Namespace, app_config: dict, logger: logging.Logg
logger=logger, logger=logger,
distro=util.get_distro(), distro=util.get_distro(),
file_downloader=AdaptableFileDownloader(logger, bool(app_config['download']['multithreaded']), file_downloader=AdaptableFileDownloader(logger, bool(app_config['download']['multithreaded']),
i18n, http_client), i18n, http_client, app_config['download']['multithreaded_client']),
app_name=__app_name__) app_name=__app_name__)
managers = gems.load_managers(context=context, locale=i18n.current_key, config=app_config, default_locale=DEFAULT_I18N_KEY) managers = gems.load_managers(context=context, locale=i18n.current_key, config=app_config, default_locale=DEFAULT_I18N_KEY)

View File

@@ -44,6 +44,7 @@ def read_config(update_file: bool = False) -> dict:
}, },
'download': { 'download': {
'multithreaded': True, 'multithreaded': True,
'multithreaded_client': None,
'icons': True 'icons': True
}, },
'store_root_password': True, 'store_root_password': True,

View File

@@ -432,7 +432,8 @@ class GenericSoftwareManager(SoftwareManager):
self.settings_manager = GenericSettingsManager(managers=self.managers, self.settings_manager = GenericSettingsManager(managers=self.managers,
working_managers=self.working_managers, working_managers=self.working_managers,
logger=self.logger, logger=self.logger,
i18n=self.i18n) i18n=self.i18n,
file_downloader=self.context.file_downloader)
else: else:
self.settings_manager.managers = self.managers self.settings_manager.managers = self.managers
self.settings_manager.working_managers = self.working_managers self.settings_manager.working_managers = self.working_managers

View File

@@ -5,6 +5,7 @@ import time
import traceback import traceback
from math import floor from math import floor
from threading import Thread from threading import Thread
from typing import Iterable
from bauh.api.abstract.download import FileDownloader from bauh.api.abstract.download import FileDownloader
from bauh.api.abstract.handler import ProcessWatcher from bauh.api.abstract.handler import ProcessWatcher
@@ -18,27 +19,27 @@ RE_HAS_EXTENSION = re.compile(r'.+\.\w+$')
class AdaptableFileDownloader(FileDownloader): class AdaptableFileDownloader(FileDownloader):
def __init__(self, logger: logging.Logger, multithread_enabled: bool, i18n: I18n, http_client: HttpClient): def __init__(self, logger: logging.Logger, multithread_enabled: bool, i18n: I18n, http_client: HttpClient, multithread_client: str):
self.logger = logger self.logger = logger
self.multithread_enabled = multithread_enabled self.multithread_enabled = multithread_enabled
self.i18n = i18n self.i18n = i18n
self.http_client = http_client self.http_client = http_client
self.supported_multithread_clients = {'aria2', 'axel'}
self.multithread_client = multithread_client
def is_aria2c_available(self) -> bool: @staticmethod
def is_aria2c_available() -> bool:
return bool(run_cmd('which aria2c', print_error=False)) return bool(run_cmd('which aria2c', print_error=False))
def _get_aria2c_process(self, url: str, output_path: str, cwd: str, root_password: str, max_threads: int, known_size: int) -> SimpleProcess: @staticmethod
def is_axel_available() -> bool:
return bool(run_cmd('which axel', print_error=False))
if max_threads and max_threads > 0: @staticmethod
threads = max_threads def is_wget_available() -> bool:
elif known_size: return bool(run_cmd('which wget', print_error=False))
threads = 16 if known_size >= 16000000 else floor(known_size / 1000000)
if threads <= 0:
threads = 1
else:
threads = 16
def _get_aria2c_process(self, url: str, output_path: str, cwd: str, root_password: str, threads: int) -> SimpleProcess:
cmd = ['aria2c', url, cmd = ['aria2c', url,
'--no-conf', '--no-conf',
'--max-connection-per-server={}'.format(threads), '--max-connection-per-server={}'.format(threads),
@@ -64,6 +65,18 @@ class AdaptableFileDownloader(FileDownloader):
return SimpleProcess(cmd=cmd, root_password=root_password, cwd=cwd) return SimpleProcess(cmd=cmd, root_password=root_password, cwd=cwd)
def _get_axel_process(self, url: str, output_path: str, cwd: str, root_password: str, threads: int) -> SimpleProcess:
cmd = ['axel', url,
'--num-connections={}'.format(threads),
'--ipv4',
'--no-clobber',
'--timeout=5']
if output_path:
cmd.append('--output={}'.format(output_path))
return SimpleProcess(cmd=cmd, cwd=cwd, root_password=root_password)
def _get_wget_process(self, url: str, output_path: str, cwd: str, root_password: str) -> SimpleProcess: def _get_wget_process(self, url: str, output_path: str, cwd: str, root_password: str) -> SimpleProcess:
cmd = ['wget', url, '--continue', '--retry-connrefused', '--tries=10', '--no-config'] cmd = ['wget', url, '--continue', '--retry-connrefused', '--tries=10', '--no-config']
@@ -90,6 +103,19 @@ class AdaptableFileDownloader(FileDownloader):
except: except:
pass pass
def _get_appropriate_threads_number(self, max_threads: int, known_size: int) -> int:
if max_threads and max_threads > 0:
threads = max_threads
elif known_size:
threads = 16 if known_size >= 16000000 else floor(known_size / 1000000)
if threads <= 0:
threads = 1
else:
threads = 16
return threads
def download(self, file_url: str, watcher: ProcessWatcher, output_path: str = None, cwd: str = None, root_password: str = None, substatus_prefix: str = None, display_file_size: bool = True, max_threads: int = None, known_size: int = None) -> bool: def download(self, file_url: str, watcher: ProcessWatcher, output_path: str = None, cwd: str = None, root_password: str = None, substatus_prefix: str = None, display_file_size: bool = True, max_threads: int = None, known_size: int = None) -> bool:
self.logger.info('Downloading {}'.format(file_url)) self.logger.info('Downloading {}'.format(file_url))
handler = ProcessHandler(watcher) handler = ProcessHandler(watcher)
@@ -105,10 +131,18 @@ class AdaptableFileDownloader(FileDownloader):
os.remove(output_path) os.remove(output_path)
self.logger.info("Old file {} removed".format(output_path)) self.logger.info("Old file {} removed".format(output_path))
if self.is_multithreaded(): client = self.get_available_multithreaded_tool()
if client:
threads = self._get_appropriate_threads_number(max_threads, known_size)
if client == 'aria2':
ti = time.time() ti = time.time()
process = self._get_aria2c_process(file_url, output_path, final_cwd, root_password, max_threads, known_size) process = self._get_aria2c_process(file_url, output_path, final_cwd, root_password, threads)
downloader = 'aria2' downloader = 'aria2'
else:
ti = time.time()
process = self._get_axel_process(file_url, output_path, final_cwd, root_password, threads)
downloader = 'axel'
else: else:
ti = time.time() ti = time.time()
process = self._get_wget_process(file_url, output_path, final_cwd, root_password) process = self._get_wget_process(file_url, output_path, final_cwd, root_password)
@@ -150,7 +184,22 @@ class AdaptableFileDownloader(FileDownloader):
return success return success
def is_multithreaded(self) -> bool: def is_multithreaded(self) -> bool:
return self.multithread_enabled and self.is_aria2c_available() return self.multithread_enabled and (self.is_aria2c_available() or self.is_axel_available())
def get_default_client_name(self) -> str: def get_available_multithreaded_tool(self) -> str:
return 'aria2c' if self. is_multithreaded() else 'wget' if self.multithread_enabled:
if self.multithread_client is None:
if self.is_aria2c_available():
return 'aria2'
elif self.is_axel_available():
return 'axel'
elif (self.multithread_client == 'aria2' or self.multithread_client not in self.get_supported_multithreaded_clients()) and self.is_aria2c_available():
return 'aria2'
elif self.is_axel_available():
return 'axel'
def can_work(self) -> bool:
return self.is_wget_available() or self.is_multithreaded()
def get_supported_multithreaded_clients(self) -> Iterable[str]:
return self.supported_multithread_clients

View File

@@ -8,11 +8,13 @@ from PyQt5.QtWidgets import QApplication, QStyleFactory
from bauh import ROOT_DIR from bauh import ROOT_DIR
from bauh.api.abstract.controller import SoftwareManager from bauh.api.abstract.controller import SoftwareManager
from bauh.api.abstract.download import FileDownloader
from bauh.api.abstract.view import ViewComponent, TabComponent, InputOption, TextComponent, MultipleSelectComponent, \ from bauh.api.abstract.view import ViewComponent, TabComponent, InputOption, TextComponent, MultipleSelectComponent, \
PanelComponent, FormComponent, TabGroupComponent, SingleSelectComponent, SelectViewType, TextInputComponent, \ PanelComponent, FormComponent, TabGroupComponent, SingleSelectComponent, SelectViewType, TextInputComponent, \
FileChooserComponent FileChooserComponent
from bauh.view.core import config, timeshift from bauh.view.core import config, timeshift
from bauh.view.core.config import read_config from bauh.view.core.config import read_config
from bauh.view.core.downloader import AdaptableFileDownloader
from bauh.view.util import translation from bauh.view.util import translation
from bauh.view.util.translation import I18n from bauh.view.util.translation import I18n
@@ -20,11 +22,12 @@ from bauh.view.util.translation import I18n
class GenericSettingsManager: class GenericSettingsManager:
def __init__(self, managers: List[SoftwareManager], working_managers: List[SoftwareManager], def __init__(self, managers: List[SoftwareManager], working_managers: List[SoftwareManager],
logger: logging.Logger, i18n: I18n): logger: logging.Logger, i18n: I18n, file_downloader: FileDownloader):
self.i18n = i18n self.i18n = i18n
self.managers = managers self.managers = managers
self.working_managers = working_managers self.working_managers = working_managers
self.logger = logger self.logger = logger
self.file_downloader = file_downloader
def get_settings(self, screen_width: int, screen_height: int) -> ViewComponent: def get_settings(self, screen_width: int, screen_height: int) -> ViewComponent:
tabs = list() tabs = list()
@@ -118,7 +121,22 @@ class GenericSettingsManager:
max_width=default_width, max_width=default_width,
value=core_config['download']['multithreaded']) value=core_config['download']['multithreaded'])
sub_comps = [FormComponent([select_dmthread, select_trim_up, select_dep_check, input_data_exp, input_icon_exp], spaces=False)] supported_mthread_clients = self.file_downloader.get_supported_multithreaded_clients()
mthread_client_opts = [(self.i18n['default'].capitalize(), None, None)]
mthread_client_opts.extend(((d, d, None) for d in supported_mthread_clients))
current_mthread_client = core_config['download']['multithreaded_client']
if current_mthread_client not in supported_mthread_clients:
current_mthread_client = None
select_mthread_client = self._gen_select(label=self.i18n['core.config.download.multithreaded_client'],
tip=self.i18n['core.config.download.multithreaded_client.tip'],
id_="mthread_client",
max_width=default_width,
opts=mthread_client_opts,
value=current_mthread_client)
sub_comps = [FormComponent([select_dmthread, select_mthread_client, select_trim_up, select_dep_check, input_data_exp, input_icon_exp], spaces=False)]
return TabComponent(self.i18n['core.config.tab.advanced'].capitalize(), PanelComponent(sub_comps), None, 'core.adv') return TabComponent(self.i18n['core.config.tab.advanced'].capitalize(), PanelComponent(sub_comps), None, 'core.adv')
def _gen_tray_settings(self, core_config: dict, screen_width: int, screen_height: int) -> TabComponent: def _gen_tray_settings(self, core_config: dict, screen_width: int, screen_height: int) -> TabComponent:
@@ -307,6 +325,13 @@ class GenericSettingsManager:
download_mthreaded = adv_form.get_component('down_mthread').get_selected() download_mthreaded = adv_form.get_component('down_mthread').get_selected()
core_config['download']['multithreaded'] = download_mthreaded core_config['download']['multithreaded'] = download_mthreaded
mthread_client = adv_form.get_component('mthread_client').get_selected()
core_config['download']['multithreaded_client'] = mthread_client
if isinstance(self.file_downloader, AdaptableFileDownloader):
self.file_downloader.multithread_client = mthread_client
self.file_downloader.multithread_enabled = download_mthreaded
single_dep_check = adv_form.get_component('dep_check').get_selected() single_dep_check = adv_form.get_component('dep_check').get_selected()
core_config['system']['single_dependency_checking'] = single_dep_check core_config['system']['single_dependency_checking'] = single_dep_check

View File

@@ -192,7 +192,9 @@ core.config.backup.upgrade=Before upgrading
core.config.download.icons=Download icons core.config.download.icons=Download icons
core.config.download.icons.tip=If the application icons should be downloaded and displayed on the table core.config.download.icons.tip=If the application icons should be downloaded and displayed on the table
core.config.download.multithreaded=Multithreaded download core.config.download.multithreaded=Multithreaded download
core.config.download.multithreaded.tip=Whether applications, packages and files should be downloaded with a tool that works with threads ( faster ). At the moment this setting will only work if the aria2 package is installed core.config.download.multithreaded.tip=Whether applications, packages and files should be downloaded with a tool that works with threads (faster).
core.config.download.multithreaded_client=Multi-threaded download tool
core.config.download.multithreaded_client.tip=The download tool that should be used for multi-threaded downloads. It must be installed on the system for this configuration to work.
core.config.downloads=downloads core.config.downloads=downloads
core.config.locale.label=language core.config.locale.label=language
core.config.mem_cache=Memory storage core.config.mem_cache=Memory storage

View File

@@ -191,7 +191,9 @@ core.config.backup.upgrade=Before upgrading
core.config.download.icons=Download Icons core.config.download.icons=Download Icons
core.config.download.icons.tip=Falls aktiviert werden die Anwendungs-Icons in der Tabelle angezeigt core.config.download.icons.tip=Falls aktiviert werden die Anwendungs-Icons in der Tabelle angezeigt
core.config.download.multithreaded=Paralleler Download core.config.download.multithreaded=Paralleler Download
core.config.download.multithreaded.tip=Falls aktiviert werden Downloads parallel (mit mehreren Threads) heruntergeladen. Dazu muss aria installiert sein. core.config.download.multithreaded.tip=Falls aktiviert werden Downloads parallel (mit mehreren Threads) heruntergeladen.
core.config.download.multithreaded_client=Multi-threaded download tool
core.config.download.multithreaded_client.tip=The download tool that should be used for multi-threaded downloads. It must be installed on the system for this configuration to work.
core.config.downloads=Downloads core.config.downloads=Downloads
core.config.locale.label=Sprache core.config.locale.label=Sprache
core.config.mem_cache=RAM Cache core.config.mem_cache=RAM Cache

View File

@@ -190,8 +190,10 @@ core.config.backup.upgrade=Before upgrading
core.config.backup=Enabled core.config.backup=Enabled
core.config.download.icons.tip=If the application icons should be downloaded and displayed on the table core.config.download.icons.tip=If the application icons should be downloaded and displayed on the table
core.config.download.icons=Download icons core.config.download.icons=Download icons
core.config.download.multithreaded.tip=Whether applications, packages and files should be downloaded with a tool that works with threads ( faster ). At the moment this setting will only work if the aria2 package is installed
core.config.download.multithreaded=Multi-threaded download core.config.download.multithreaded=Multi-threaded download
core.config.download.multithreaded.tip=Whether applications, packages and files should be downloaded with a tool that works with threads (faster).
core.config.download.multithreaded_client=Multi-threaded download tool
core.config.download.multithreaded_client.tip=The download tool that should be used for multi-threaded downloads. It must be installed on the system for this configuration to work.
core.config.downloads=downloads core.config.downloads=downloads
core.config.locale.label=language core.config.locale.label=language
core.config.mem_cache.data_exp.tip=Defines the in-memory data lifetime ( in SECONDS ) core.config.mem_cache.data_exp.tip=Defines the in-memory data lifetime ( in SECONDS )

View File

@@ -192,7 +192,9 @@ core.config.backup.upgrade=Antes de actualizar
core.config.download.icons=Descargar iconos core.config.download.icons=Descargar iconos
core.config.download.icons.tip=Si los íconos de las aplicaciones se deben descargar y mostrar en la tabla core.config.download.icons.tip=Si los íconos de las aplicaciones se deben descargar y mostrar en la tabla
core.config.download.multithreaded=Descarga segmentada core.config.download.multithreaded=Descarga segmentada
core.config.download.multithreaded.tip=Si las aplicaciones, paquetes y archivos deben descargarse con una herramienta que usa segmentación / threads ( más rápido ). Por el momento, esta configuración solo funcionará si el paquete aria2 esté instalado core.config.download.multithreaded.tip=Si las aplicaciones, paquetes y archivos deben descargarse con una herramienta que usa segmentación / threads (más rápido).
core.config.download.multithreaded_client=Herramienta para descarga segmentada
core.config.download.multithreaded_client.tip=La herramienta que debe usarse para descargas segmentadas. Ella debe estar instalada en el sistema para que esta configuración funcione.
core.config.downloads=downloads core.config.downloads=downloads
core.config.locale.label=idioma core.config.locale.label=idioma
core.config.mem_cache=Almacenamiento de memoria core.config.mem_cache=Almacenamiento de memoria

View File

@@ -191,7 +191,9 @@ core.config.backup.upgrade=Before upgrading
core.config.download.icons=Download icons core.config.download.icons=Download icons
core.config.download.icons.tip=If the application icons should be downloaded and displayed on the table core.config.download.icons.tip=If the application icons should be downloaded and displayed on the table
core.config.download.multithreaded=Multithreaded download core.config.download.multithreaded=Multithreaded download
core.config.download.multithreaded.tip=Whether applications, packages and files should be downloaded with a tool that works with threads ( faster ). At the moment this setting will only work if the aria2 package is installed core.config.download.multithreaded.tip=Whether applications, packages and files should be downloaded with a tool that works with threads (faster).
core.config.download.multithreaded_client=Multi-threaded download tool
core.config.download.multithreaded_client.tip=The download tool that should be used for multi-threaded downloads. It must be installed on the system for this configuration to work.
core.config.downloads=downloads core.config.downloads=downloads
core.config.locale.label=language core.config.locale.label=language
core.config.mem_cache=Memory storage core.config.mem_cache=Memory storage

View File

@@ -190,8 +190,10 @@ core.config.backup.upgrade=Antes de atualizar
core.config.backup=Habilitada core.config.backup=Habilitada
core.config.download.icons.tip=Se os ícones dos aplicativos devem ser baixados e exibidos na tabela core.config.download.icons.tip=Se os ícones dos aplicativos devem ser baixados e exibidos na tabela
core.config.download.icons=Baixar ícones core.config.download.icons=Baixar ícones
core.config.download.multithreaded.tip=Se os aplicativos, pacotes e arquivos devem ser baixados através de uma ferramenta que trabalha com segmentação / threads ( mais rápido ). No momento esta propriedade somente funcionará se o pacote aria2 estiver instalado. core.config.download.multithreaded.tip=Se os aplicativos, pacotes e arquivos devem ser baixados através de uma ferramenta que trabalha com segmentação / threads (mais rápido).
core.config.download.multithreaded=Download segmentado core.config.download.multithreaded=Download segmentado
core.config.download.multithreaded_client=Ferramenta para download segmentado
core.config.download.multithreaded_client.tip=A ferramenta que deve ser utilizada para downloads segmentados. Ela precisa estar instalada no sistema para que essa configuração funcione.
core.config.downloads=downloads core.config.downloads=downloads
core.config.locale.label=idioma core.config.locale.label=idioma
core.config.mem_cache.data_exp.tip=Define o tempo de vida dos dados em memória ( em SEGUNDOS ) core.config.mem_cache.data_exp.tip=Define o tempo de vida dos dados em memória ( em SEGUNDOS )

View File

@@ -191,7 +191,9 @@ core.config.backup.upgrade=Before upgrading
core.config.download.icons=Скачать иконки core.config.download.icons=Скачать иконки
core.config.download.icons.tip=Загружать иконки приложения для отображаения на рабочем столе core.config.download.icons.tip=Загружать иконки приложения для отображаения на рабочем столе
core.config.download.multithreaded=Многопоточная загрузка core.config.download.multithreaded=Многопоточная загрузка
core.config.download.multithreaded.tip=Следует ли загружать приложения, пакеты и файлы с помощью инструмента, который работает с потоками ( быстрее ). На данный момент эта настройка будет работать только в том случае, если установлен пакет aria2 core.config.download.multithreaded.tip=Следует ли загружать приложения, пакеты и файлы с помощью инструмента, который работает с потоками (быстрее).
core.config.download.multithreaded_client=Multi-threaded download tool
core.config.download.multithreaded_client.tip=The download tool that should be used for multi-threaded downloads. It must be installed on the system for this configuration to work.
core.config.downloads=downloads core.config.downloads=downloads
core.config.locale.label=Язык core.config.locale.label=Язык
core.config.mem_cache=Запоминающее устройство core.config.mem_cache=Запоминающее устройство

View File

@@ -190,8 +190,10 @@ core.config.backup.upgrade=Önce yükseltiliyor
core.config.backup=Etkin core.config.backup=Etkin
core.config.download.icons.tip=Tabloda görüntüleniyorsa uygulama simgeleri indirilmeli core.config.download.icons.tip=Tabloda görüntüleniyorsa uygulama simgeleri indirilmeli
core.config.download.icons=Simgeleri indir core.config.download.icons=Simgeleri indir
core.config.download.multithreaded.tip=Uygulamaların, paketlerin ve dosyaların iş parçacıklarıyla (daha hızlı) çalışan bir araçla indirilip indirilmeyeceği. Şu anda bu ayar yalnızca aria2 paketi kuruluysa çalışır core.config.download.multithreaded.tip=Uygulamaların, paketlerin ve dosyaların iş parçacıklarıyla (daha hızlı) çalışan bir araçla indirilip indirilmeyeceği.
core.config.download.multithreaded=Çoklu parçalı indirme core.config.download.multithreaded=Çoklu parçalı indirme
core.config.download.multithreaded_client=Multi-threaded download tool
core.config.download.multithreaded_client.tip=The download tool that should be used for multi-threaded downloads. It must be installed on the system for this configuration to work.
core.config.downloads=indirilenler core.config.downloads=indirilenler
core.config.locale.label=dil core.config.locale.label=dil
core.config.mem_cache.data_exp.tip=Bellek içi veri ömrünü tanımlar ( SANİYE ) core.config.mem_cache.data_exp.tip=Bellek içi veri ömrünü tanımlar ( SANİYE )

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB