Spaces:
Running
Running
| #!/usr/bin/env python3 | |
| # offload_lib.py | |
| import time | |
| import math | |
| import random | |
| import psutil | |
| import requests | |
| import socket | |
| from functools import wraps | |
| from zeroconf import Zeroconf, ServiceBrowser | |
| import logging | |
| # إعداد السجل | |
| logging.basicConfig( | |
| level=logging.INFO, | |
| format='%(asctime)s - %(levelname)s - %(message)s' | |
| ) | |
| # إعدادات التحميل | |
| MAX_CPU = 0.6 # عتبة استخدام CPU فقط | |
| class PeerListener: | |
| def __init__(self): | |
| self.peers = [] | |
| def add_service(self, zc, type, name): | |
| info = zc.get_service_info(type, name) | |
| if info: | |
| ip = socket.inet_ntoa(info.addresses[0]) | |
| self.peers.append(f"{ip}:{info.port}") | |
| logging.info(f"🔗 جهاز مكتشف: {ip}:{info.port}") | |
| def update_service(self, zc, type, name): | |
| logging.debug(f"🔄 تم تحديث الخدمة: {name}") | |
| pass # هنا فقط لتفادي التحذير | |
| def discover_peers(timeout=1.5): | |
| """اكتشاف الأجهزة المتاحة - أولوية LAN ثم WAN ثم الإنترنت مع فحص المشروع""" | |
| import peer_discovery | |
| from project_identifier import verify_project_compatibility | |
| zc = Zeroconf() | |
| listener = PeerListener() | |
| ServiceBrowser(zc, "_http._tcp.local.", listener) | |
| time.sleep(timeout) | |
| zc.close() | |
| lan_peers = [] | |
| wan_peers = [] | |
| internet_peers = [] | |
| for peer in listener.peers: | |
| ip = peer.split(':')[0] | |
| if verify_peer_project(ip): | |
| if is_local_network(ip): | |
| lan_peers.append(peer) | |
| else: | |
| wan_peers.append(peer) | |
| all_discovered = list(peer_discovery.PEERS) | |
| for peer_url in all_discovered: | |
| peer_ip = peer_url.split("://")[1].split(":")[0] | |
| if verify_peer_project(peer_ip): | |
| if is_local_network(peer_ip): | |
| if peer_url not in lan_peers: | |
| lan_peers.append(peer_url) | |
| else: | |
| if peer_url not in wan_peers: | |
| internet_peers.append(peer_url) | |
| all_peers = lan_peers + wan_peers + internet_peers | |
| logging.info(f"اكتُشف {len(all_peers)} جهاز DTS متوافق - LAN: {len(lan_peers)}, WAN: {len(wan_peers)}, Internet: {len(internet_peers)}") | |
| return all_peers | |
| def verify_peer_project(ip, port=7520): | |
| """فحص إذا كان الجهاز يحتوي على نفس المشروع""" | |
| try: | |
| from project_identifier import verify_project_compatibility | |
| project_url = f"http://{ip}:{port}/project_info" | |
| response = requests.get(project_url, timeout=2) | |
| if response.status_code == 200: | |
| remote_info = response.json() | |
| return verify_project_compatibility(remote_info) | |
| except: | |
| pass | |
| return False | |
| def is_local_network(ip): | |
| """فحص إذا كان IP في الشبكة المحلية""" | |
| try: | |
| import ipaddress | |
| addr = ipaddress.ip_address(ip) | |
| return ( | |
| addr.is_private or | |
| str(addr).startswith('192.168.') or | |
| str(addr).startswith('10.') or | |
| str(addr).startswith('172.') | |
| ) | |
| except: | |
| return False | |
| def try_offload(peer, payload, max_retries=3): | |
| """محاولة إرسال المهمة إلى جهاز آخر""" | |
| url = f"http://{peer}/run" | |
| for attempt in range(max_retries): | |
| try: | |
| response = requests.post(url, json=payload, timeout=10) | |
| response.raise_for_status() | |
| return response.json() | |
| except Exception as e: | |
| logging.warning(f"فشل المحاولة {attempt + 1} لـ {peer}: {str(e)}") | |
| time.sleep(0.5 * (attempt + 1)) | |
| raise ConnectionError(f"فشل جميع المحاولات لـ {peer}") | |
| def estimate_complexity(func, args, kwargs): | |
| """تقدير تعقيد المهمة""" | |
| if func.__name__ == "matrix_multiply": | |
| return args[0] ** 2 | |
| elif func.__name__ == "prime_calculation": | |
| return args[0] / 100 | |
| elif func.__name__ == "data_processing": | |
| return args[0] / 10 | |
| elif func.__name__ == "image_processing_emulation": | |
| return args[0] * 5 | |
| return 1 # قيمة افتراضية | |
| def offload(func): | |
| """ديكوراتور لتوزيع المهام""" | |
| def wrapper(*args, **kwargs): | |
| cpu = psutil.cpu_percent(interval=0.5) / 100.0 | |
| mem = psutil.virtual_memory().available / (1024**2) | |
| complexity = estimate_complexity(func, args, kwargs) | |
| logging.info(f"حمل النظام - CPU: {cpu:.2f}, الذاكرة: {mem:.1f}MB, تعقيد المهمة: {complexity}") | |
| if complexity > 50 or cpu > MAX_CPU: | |
| try: | |
| peers = discover_peers() | |
| if peers: | |
| payload = { | |
| "func": func.__name__, | |
| "args": args, | |
| "kwargs": kwargs, | |
| "complexity": complexity | |
| } | |
| selected_peer = random.choice(peers) | |
| logging.info(f"إرسال المهمة إلى {selected_peer}") | |
| return try_offload(selected_peer, payload) | |
| except Exception as e: | |
| logging.error(f"خطأ في التوزيع: {str(e)}") | |
| logging.info("تنفيذ المهمة محلياً") | |
| return func(*args, **kwargs) | |
| return wrapper | |
| # المهام القابلة للتوزيع: | |
| def matrix_multiply(size): | |
| """ضرب مصفوفتين عشوائيتين بالحجم""" | |
| import numpy as np | |
| A = np.random.rand(size, size) | |
| B = np.random.rand(size, size) | |
| return np.dot(A, B).tolist() | |
| def prime_calculation(n): | |
| """حساب الأعداد الأولية""" | |
| primes = [] | |
| for num in range(2, n + 1): | |
| is_prime = True | |
| for i in range(2, int(math.sqrt(num)) + 1): | |
| if num % i == 0: | |
| is_prime = False | |
| break | |
| if is_prime: | |
| primes.append(num) | |
| return {"primes_count": len(primes), "primes": primes} | |
| def data_processing(data_size): | |
| """معالجة بيانات كبيرة""" | |
| processed_data = [] | |
| for i in range(data_size): | |
| result = sum(math.sin(x) * math.cos(x) for x in range(i, i + 100)) | |
| processed_data.append(result) | |
| return {"processed_items": len(processed_data)} | |
| def image_processing_emulation(iterations): | |
| """محاكاة معالجة الصور""" | |
| results = [] | |
| for i in range(iterations): | |
| fake_processing = sum(math.sqrt(x) for x in range(i * 100, (i + 1) * 100)) | |
| results.append(fake_processing) | |
| time.sleep(0.01) | |
| return {"iterations": iterations, "results": results} | |