0. Résumé exécutif
Ce dossier ferme plusieurs questions ouvertes par D06, D07 et D08.
Le moteur A4AF de la branche Community 0.72a est déjà sophistiqué :
un CUpDownClient
→ un m_reqfile actif
→ plusieurs fichiers alternatifs
m_OtherRequests_list
m_OtherNoNeeded_list
chaque CPartFile
→ srclist active
→ A4AFsrclist
Le swap prend en compte :
priorités catégories/fichiers
source limits
reask timers
NNP
Source Exchange
Remote Queue Rank
suspensions de swap
La découverte la plus importante est toutefois sémantique :
DS_NONEEDEDPARTS peut représenter plus d’une cause.
Dans SendBlockRequests(), si CreateBlockRequests() ne parvient à produire aucun nouveau bloc, le client est immédiatement :
SendCancelTransfer()
SetDownloadState(DS_NONEEDEDPARTS)
SwapToAnotherFile(...)
Or l’absence de bloc nouveau ne prouve pas nécessairement :
le pair ne possède aucune partie dont nous avons besoin
Elle peut aussi signifier :
le pair possède des parties utiles
mais tous les gaps correspondants sont déjà réservés
Cette différence est particulièrement importante avec Endgame by Akshaan E6bis.
Deuxième découverte importante :
FILEREASKTIME = 29 min
NNP reask = 58 min
et SwapToRightFile() introduit en plus une rotation NNP :
58 min × nombre de fichiers NNP associés au client
afin d’espacer les reasks entre plusieurs NNP.
Sur un client associé à de nombreux fichiers, une association NNP peut donc rester longtemps sans être revisitée.
C’est raisonnable si le pair distant n’a rien changé.
Mais D07 a montré que notre propre gap list peut changer localement après :
corruption
AICH Recovery
ICH
Endgame reservation release
Une source NNP peut donc redevenir utile sans aucun changement de Part Status distant.
Event-Driven A4AF Reclassification
Principe :
événement local qui change les gaps
→ reclassifier localement les A4AF/NNP
→ aucun paquet réseau nécessaire
→ les timers réseau restent respectés
→ Tail Source Wakeup reçoit immédiatement
une vue correcte des sources potentiellement utiles
Le vieux Delayed NNP NetF reste pertinent comme protection supplémentaire pour une source actuellement en téléchargement juste avant son passage NNP.
Mais il ne devrait probablement pas être porté sous forme d’un simple timer global fixe de 30 s.
1. A4AF : modèle de données réel
1.1 Fichier actif
Chaque CUpDownClient possède :
m_reqfileLe client appartient alors à :
m_reqfile->srclist1.2 Fichiers alternatifs
Le même client conserve :
m_OtherRequests_list
m_OtherNoNeeded_listet chacun de ces fichiers conserve le client dans :
CPartFile::A4AFsrclistIl existe donc une relation bidirectionnelle.
2. AddRequestForAnotherFile()
Dans 0.72a :
if (m_OtherNoNeeded_list.Find(file)
|| m_OtherRequests_list.Find(file))
return false;
m_OtherRequests_list.AddTail(file);
file->A4AFsrclist.AddTail(this);Sens
Une source découverte pour un fichier alors qu’elle est déjà utilisée ailleurs :
n’est pas clonée
Elle devient une source A4AF de l’autre fichier.
C’est exactement ce que D08 observait lors du dédoublonnage inter-fichiers.
3. Deux classes A4AF
m_OtherRequests_list
Association connue et potentiellement utilisable.
m_OtherNoNeeded_list
Association pour laquelle le client a précédemment été classé :
NNP
Cela permet des reask plus espacés et une sélection différente dans SwapToRightFile().
4. DoSwap() : ce que signifie réellement un swap
Séquence :
ancien m_reqfile
↓
retiré de srclist
nouveau fichier
↓
retiré de son A4AFsrclist
ancien fichier
↓
ajouté dans A4AFsrclist
↓
OtherRequests ou OtherNoNeeded
client
↓
SetDownloadState(DS_NONE)
SetRequestFile(nouveau)
nouveau fichier
↓
client ajouté dans srclist
Le client réseau reste le même.
5. Classification de l’ancien fichier pendant le swap
Dans DoSwap() :
if (GetDownloadState() == DS_NONEEDEDPARTS)
m_OtherNoNeeded_list.AddTail(m_reqfile);
else
m_OtherRequests_list.AddTail(m_reqfile);Conséquence
L’état du client au moment du swap détermine durablement quelle liste A4AF recevra l’ancien fichier.
C’est une raison supplémentaire pour ne pas classifier NNP trop tôt en Endgame.
6. État NNP : origine par Part Status
ProcessFileStatus() compare la carte distante avec nos besoins locaux.
Si aucun besoin n’est visible en TCP :
SetDownloadState(DS_NONEEDEDPARTS);
SwapToAnotherFile(...);Donc :
NNP → A4AF swap immédiat
dans ce chemin.
UDP
Le même traitement UDP peut définir :
DS_NONEEDEDPARTS
mais l’appel SwapToAnotherFile() correspondant est commenté dans la branche étudiée.
Ce n’est donc pas parfaitement symétrique.
7. État NNP : origine par scheduler de blocs
Dans SendBlockRequests() :
CreateBlockRequests(blockCount);
if (m_PendingBlocks_list.IsEmpty()) {
SendCancelTransfer();
SetDownloadState(DS_NONEEDEDPARTS);
SwapToAnotherFile(...);
return;
}C’est le point le plus important du dossier.
Cette branche ne demande pas :
« la Part Status du pair
a-t-elle zéro intersection avec nos gaps ? »
Elle constate seulement :
« aucun nouveau bloc n'a été placé
dans la pending list »
8. NNP sémantiquement ambigu
Il faut donc distinguer au moins :
NNP-1 — réellement aucune partie utile
remote available parts
∩
local gaps
=
vide
NNP-2 — parties utiles mais travail déjà réservé
remote available parts
∩
local gaps
!=
vide
mais
toutes les plages pertinentes
sont déjà requested/reserved
Dans eMule historique, les deux peuvent converger vers :
DS_NONEEDEDPARTS
10. Baseline E6bis
D06 établit :
Endgame by Akshaan E6bis = baseline
et documente déjà :
Locked Block Recovery
Speculative Block Racing
Partial Final-Tail Rescue
Stale Pipeline Bypass
Tail Source Wakeup
SOURCE_LIMITED
D09 ne doit pas créer un second scheduler concurrent.
Il doit fournir à E6bis une classification correcte du cycle de vie des sources.
11. SetDownloadState(DS_NONEEDEDPARTS) modifie aussi le timer
Le code contient explicitement :
case DS_NONEEDEDPARTS:
SetLastAskedTime();Commentaire :
TCP asks never set re-ask time
if the result is NNP
Donc le passage NNP n’est pas seulement visuel.
Il modifie la prochaine fenêtre de reask.
12. Timers de base
Opcodes.h 0.72a :
FILEREASKTIME = 29 min
MIN_REQUESTTIME = 10 min
PURGESOURCESWAPSTOP = 15 min
GetTimeUntilReask() applique :
normal → 29 min
NNP → 58 min
short/aggr. → 10 min
Les 58 min sont :
FILEREASKTIME × 2
13. Pourquoi le 29 min historique existe
Ce timer protège le réseau contre les requêtes répétées.
D09 ne propose pas de réduire globalement :
29 min
ni :
58 min
Le problème identifié n’est pas :
« les timers sont trop longs »
mais :
« un événement local peut rendre une source utile
sans nécessiter un nouveau reask réseau »
14. Rotation de plusieurs NNP : détail remarquable
Dans SwapToRightFile() :
allNnpReaskTime =
FILEREASKTIME * 2 *
(m_OtherNoNeeded_list.GetCount()
+ (current == NNP ? 1 : 0));Avec :
FILEREASKTIME = 29 min
cela donne :
1 NNP → 58 min
2 NNP → 116 min
3 NNP → 174 min
5 NNP → 290 min
10 NNP → 580 min
Important
Ce n’est pas un délai global de connexion.
C’est une logique de rotation/revisite des associations NNP d’un même client.
Elle cherche à répartir les reasks entre plusieurs fichiers NNP.
15. Intention historique
Commentaire du source :
wait two re-ask interval for each nnp file
before re-asking an nnp file
L’intention est raisonnable :
ne pas reposer la même question
à la même source
pour dix fichiers
toutes les 58 minutes simultanément
Cela répartit l’overhead.
17. D07 donne la pièce manquante
AICH peut transformer :
partie complète
en :
une ou plusieurs gaps de 180 KiB
ou ICH peut rouvrir la partie.
À cet instant :
les besoins locaux changent immédiatement
mais les Part Status distantes déjà connues restent potentiellement exploitables.
Conclusion D07 → D09
Après :
PART_CORRUPT
AICH_RECOVERY
GAP_REOPENED
il faut envisager une réévaluation locale A4AF/NNP.
18. Réévaluer localement ≠ reask réseau
C’est le cœur de la proposition.
Nous possédons déjà souvent :
source->PartStatus
Donc après AddGap() :
for each A4AF/NNP source:
cached remote PartStatus
∩
new local gap map
peut être recalculé sans paquet.
19. Nouveau statut conceptuel
Nom de travail :
A4AF_RECLASSIFY_LOCAL
ou :
SourceNeedReevaluation
Événement :
Gap topology changed
Causes :
corruption
AICH
ICH
Endgame block release
file completion of a part
possibly manual priority/state change
20. Ce qui peut être recalculé immédiatement
Sans réseau :
source owns newly-needed part?
source belongs to this file?
source currently A4AF?
source in OtherNoNeeded?
file priority
current source count
Endgame SOURCE_LIMITED
Ce qui ne peut pas être garanti :
source still online
source still owns the part now
remote queue state
fresh QR
fresh Part Status
Dossier 05 :
cached PartStatus remains REMOTE_CLAIM
mais c’est déjà la même base que le scheduler historique utilisait.
21. Classification proposée des causes NNP
NNP_NO_PART_OVERLAP
Aucune partie annoncée du pair ne croise les gaps actuelles.
NNP_ALL_WORK_RESERVED
La source possède des parties utiles, mais toutes les plages pertinentes sont déjà réservées.
NNP_ENDGAME_TRANSIENT
Cas précédent dans un fichier E6bis actif avec forte probabilité de libération/racing/reallocation.
NNP_POST_INTEGRITY_CHANGE
Gap récemment rouverte par MD4/AICH/ICH.
NNP_STATUS_UNKNOWN
Part Status absente ou non exploitable.
NNP_STABLE
Classification stable après revalidation locale.
22. Pourquoi cette classification est préférable à « Delayed NNP partout »
Un délai uniforme de 30 s ferait aussi attendre :
une source réellement inutile
alors qu’elle pourrait immédiatement servir un autre fichier A4AF.
Cela peut réduire le débit total.
23. NetF Delayed NNP
Le rapport historique NetF établit :
grâce ≈ 30 s
reask Part Status
puis seulement :
CancelTransfer
DS_NONEEDEDPARTS
SwapToAnotherFile
Le descriptif NetF explique explicitement l’objectif :
keeps downloading sources a little bit longer
in case a part turns out corrupt
Ce mécanisme répond donc bien à un vrai problème.
24. Pourquoi ne pas copier les 30 secondes
Trois raisons.
1. Matériel/réseau
30 s vient d’un contexte ancien.
2. E6bis
Nous savons déjà mesurer :
rate collapse
tail risk
remaining work
owners
source limited
3. Local gap events
Après corruption, nous n’avons pas forcément besoin d’attendre une nouvelle Part Status.
Nous pouvons souvent savoir immédiatement que la source redevient potentiellement utile.
25. Delayed NNP adaptatif éventuel
Si un délai de grâce reste nécessaire pour une source actuellement en téléchargement :
grace = bornée
et dérivée de facteurs comme :
RTT
débit actuel
temps depuis dernier payload
Endgame state
probabilité de gap liberation
A4AF alternative disponible
Pas besoin de fixer maintenant une formule.
Première phase :
shadow telemetry
26. Xtreme Just In Time Swapping
Changelog Xtreme 4.2 beta 1 :
when you are downloading from a client
and this client doesn't have anymore chunks for you,
the download is continued with an A4AF
La branche 0.72a étudiée possède aujourd’hui :
SendBlockRequests()
→ no pending block
→ Cancel
→ NNP
→ SwapToAnotherFile
Conclusion historique prudente
Le même problème et le même comportement général apparaissent dans Xtreme puis dans la branche moderne.
Nous n’avons pas ici la preuve documentaire suffisante pour attribuer directement l’implémentation 0.72a à Xtreme.
27. Pourquoi Just-In-Time Swapping est encore une bonne idée
Hors Endgame :
source A n'a plus rien pour Fichier X
mais possède Fichier Y
slot distant déjà obtenu
Réutiliser immédiatement ce slot pour Y peut éviter :
perdre une occasion de transfert
Le problème n’est donc pas le swap lui-même.
Le problème est de savoir si le diagnostic :
« plus rien pour X »
est réellement stable.
28. Auto-A4AF
Le changelog Xtreme indique aussi :
Auto-A4AF-check
et le corpus Mods souligne l’importance historique de la gestion A4AF dans Xtreme/Sivka/ZZUL.
Ces références sont utiles pour la suite.
Mais sans les sources exactes de chaque version, D09 ne transforme pas les noms de features en algorithmes supposés.
Règle corpus
changelog = preuve d’existence/intention
source = preuve de comportement détaillé
30. Sources limits dans SwapToRightFile()
Le swap essaie de ne pas déplacer la source vers un fichier déjà saturé.
Il traite aussi plus sévèrement les NNP autour d’environ :
80 % de MaxSources
dans certaines branches.
Sens
A4AF est également un mécanisme de répartition des sources entre fichiers.
31. Source Exchange et A4AF
La logique compare aussi :
IsSourceRequestAllowed(file)
AllowSwapForSourceExchange()
et peut conserver/déplacer la source afin d’obtenir une opportunité SX.
Protection :
30 s
sur lastSwapForSourceExchangeTick.
D08 recommande de conserver cette hystérésis.
32. Remote QR dans A4AF
SwapToRightFile() contient :
DS_ONQUEUE && RemoteQueueRank <= 50
et l’inverse :
RemoteQueueRank > 50
dans les décisions liées à SX.
D05 a établi :
Remote QR = REMOTE_CLAIM
D09
Ajouter aux traces :
remote_qr_influenced_swap=yes/no
sans modifier immédiatement le comportement.
33. DS_REMOTEQUEUEFULL : fossile intéressant
ClientStateDefs.h de la 0.72a contient :
DS_REMOTEQUEUEFULL
// not used yet, except in statisticsPourtant SwapToAnotherFile() et SwapToRightFile() contiennent encore des branches qui le testent.
Hypothèse
Il s’agit probablement :
d’une branche historique / défensive
ou d’un état devenu pratiquement mort
34. Le vrai état Queue Full moderne
La branche possède en parallèle un booléen/état :
RemoteQueueFull
distinct de EDownloadState.
Au début d’un FileRequest vers un eMule :
SetRemoteQueueFull(true)
SetRemoteQueueRank(0)
jusqu’à réception d’une information de queue.
Les deux concepts ne doivent donc pas être confondus :
DS_REMOTEQUEUEFULL
vs
m_bRemoteQueueFull / IsRemoteQueueFull()
35. A4AF Save CPU
La branche possède :
A4AFSaveCpu
défaut :
false
Lorsque activé, SwapToAnotherFile() peut renoncer très tôt à certaines évaluations si le client peut rester sur le fichier courant.
Historique
Cette option témoigne d’une époque où scanner fréquemment les associations A4AF pouvait être considéré coûteux.
36. DontSwapTo() et suspension
DontSwapTo(file) enregistre un timestamp.
IsSwapSuspended() bloque alors un retour sur ce fichier pendant :
PURGESOURCESWAPSTOP = 15 min
sauf expiration.
Exemples d’usage retrouvés :
File Not Found
AICH mismatch
Important
Dans SetDownloadState(DS_NONEEDEDPARTS) :
//DontSwapTo(m_reqfile);est commenté.
Un simple NNP ne déclenche donc pas ce verrouillage par cette voie.
37. Pourquoi c’est logique
NNP peut être temporaire.
Interdire pendant 15 min tout retour au fichier après chaque NNP aurait pu empêcher des réaffectations utiles.
Les reask timers suffisent déjà largement à limiter l’agitation.
38. FNF ≠ NNP
UDPReaskFNF() :
source dit :
« je n'ai pas ce fichier »
→ DontSwapTo(m_reqfile) → tentative d’autre fichier → sinon suppression source
C’est beaucoup plus fort que :
« je possède le fichier
mais rien dont tu as besoin maintenant »
Trust semantics
FNF
≠
NNP
39. AICH mismatch ≠ simple NNP
Si le FileIdentifier/AICH ne correspond pas :
DontSwapTo(file)
→ tentative A4AF
→ sinon suppression
C’est encore une autre raison de changement de fichier.
40. Le booléen reason actuel n’est pas structuré
SwapToAnotherFile() reçoit une chaîne :
"A4AF for NNP file..."
"Source says it doesn't have the file..."
...
utile au log.
Mais pour l’analyse automatisée, une chaîne n’est pas idéale.
41. Enum proposé
PeriodicReask
NNPPartStatus
NNPNoRequestableBlock
FileNotFound
AICHMismatch
SourceExchangeOpportunity
FileCompleted
ManualSwap
EndgameTailWakeup
IntegrityGapReopened
Unknown
V1 :
observation seulement
42. A4AF Decision Trace
Format proposé :
[A4AF_DECISION]
client=session:42
from=file:A
to=file:B
reason=NNP_NO_REQUESTABLE_BLOCK
from_state=DOWNLOADING
to_is_nnp=no
priority_from=normal
priority_to=high
sources_from=38
sources_to=5
remote_qr=27
remote_qr_trust=UNVERIFIED
sx_from_allowed=no
sx_to_allowed=yes
endgame=ACTIVE
source_limited=yes
decision=SWAP
43. Pourquoi la raison NNP doit être déterminée avant SetDownloadState
Aujourd’hui, dans le chemin :
CreateBlockRequests()
→ Pending empty
→ NNP
l’information :
« pourquoi aucun bloc ? »
est perdue.
44. Lien avec Dynamic Request Size D06
Si Dynamic Request Size est un jour testé :
moins de grandes réservations
→ moins de ALL_USEFUL_GAPS_RESERVED
→ moins de faux/transitoires NNP
D09 fournit donc une métrique indirecte pour juger ce candidat.
45. Lien avec Stale Pipeline Bypass
E6 avait justement trouvé :
anciennes réservations gagnées
→ encore présentes
→ fausse impression que tout est occupé
Stale Pipeline Bypass corrige ce type de situation.
D09
Compteur intéressant :
NNP_NO_REQUESTABLE_BLOCK
avant/après stale-pipeline filtering
Cela peut confirmer que le problème est déjà largement résolu par E6bis.
46. Lien avec Speculative Racing
Si :
source rapide possède le dernier bloc
mais bloc déjà réservé
ancien eMule peut atteindre :
no requestable block
E6bis peut au contraire :
challenger/race
avant de déclarer la source NNP.
Invariant
E6bis opportunity
doit être évaluée
avant A4AF NNP fallback
47. Lien avec Partial Final-Tail Rescue
Même logique.
Si une partie d’un bloc reste gap :
la source peut être utile
sur cette sous-plage
avant que le client soit classé NNP.
Audit
Vérifier l’ordre d’appel réel :
gap discovery
→ E6bis rescue
→ pending construction
→ NNP fallback
48. Lien avec corruption
D07 :
AICH Recovery
→ FillGap bons blocs
→ mauvaises zones restent gaps
ou un hash failure peut :
AddGap()
Question D09
Après cette mutation :
les sources dans m_OtherNoNeeded_list
sont-elles reclassées immédiatement ?
Dans le code officiel inspecté :
UpdatePartsInfo()
recalcule les fréquences depuis srclist.
Il ne constitue pas, à lui seul, un moteur général visible de migration :
OtherNoNeeded → OtherRequests
sur changement local de gaps.
Statut
49. Event-Driven A4AF Reclassification
Nom proposé :
A4AF Need Reclassifier
Entrées :
FileGapChanged
PartCorrupted
AICHRecoveryFinished
EndgameReservationReleased
EndgameSourceLimitedEntered
Sortie :
liste de sources A4AF devenues potentiellement utiles
50. Première version : shadow
Ne déplacer aucune source.
Pour chaque événement :
scan A4AFsrclist
scan source PartStatus
compare new gaps
Log :
[A4AF_RECLASS_SHADOW]
event=AICH_GAP_REOPENED
file=anon:A
a4af_sources=37
previous_nnp=19
now_locally_useful=4
best_candidate=session:72
connected=yes
current_file=B
current_file_priority=normal
target_priority=high
51. Coût CPU
Le scan peut être évité sur :
tous les fichiers
et limité au fichier dont la gap map change.
Complexité approximative :
A4AF sources du fichier
×
part intersection
Sur un PC moderne, probablement faible.
Mais mesurer avant de supprimer A4AFSaveCpu.
52. Optimisation possible par part touchée
Après AICH :
part 42 a changé
Il est inutile de rescanner toutes les parties.
On peut rechercher uniquement :
source->IsPartAvailable(42)
pour chaque A4AF source.
Encore plus léger.
53. Après un Endgame reservation release
Le besoin n’est pas une nouvelle partie.
C’est une nouvelle plage libre dans une partie déjà manquante.
Si la source possède cette partie :
candidate useful
E6bis peut alors utiliser son propre scheduler pour déterminer la plage précise.
54. Ne pas convertir immédiatement la liste
Une source dans OtherNoNeeded peut devenir localement utile, mais :
elle peut être occupée ailleurs
être sous reask timer
ne plus être connectée
avoir une PartStatus ancienne
V1 doit simplement poser un marqueur :
locally_useful_again=true
55. Promotion possible à terme
Après validation :
OtherNoNeeded
→ candidate for OtherRequests / swap
mais seulement à travers les mêmes règles :
priorité
timers
source limit
A4AF
Endgame policy
Ne pas modifier directement les listes depuis l’événement d’intégrité sans passer par le scheduler.
58. Ce que la shadow telemetry doit mesurer
si nous avions attendu :
la source serait-elle redevenue utile ?
combien de temps ?
combien d'octets aurait-elle pu servir ?
pendant ce temps :
un A4AF réel aurait-il transféré sur un autre fichier ?
Cette dernière métrique est essentielle.
Delayed NNP a un coût d’opportunité.
59. Métrique NetF historique
Le rapport Endgame proposait déjà :
NNPGraceRecovered
D09 l’étend :
NNP_GRACE_REUSED
NNP_GRACE_WASTED_TIME
NNP_GRACE_A4AF_OPPORTUNITY_COST
60. Pas de délai fixe sans résultats
30 secondes est une excellente valeur historique de comparaison.
Comparaisons shadow possibles :
5 s
10 s
15 s
30 s
adaptatif
sans réellement retenir la source.
61. Reask Part Status pendant la grâce
NetF redemandait la Part Status.
Local need changed
Exemple corruption locale :
PartStatus distante encore suffisante
Pas forcément besoin de reask.
Remote availability suspected changed
Exemple source vient de finir une partie :
reask peut être utile
mais seulement si les timers/protocole le permettent.
62. Éviter un nouveau flood
chaque NNP
→ PartStatus reask immédiat
La philosophie D01/D08 reste :
réduire les requêtes inutiles
La reclassification locale est justement intéressante parce qu’elle coûte :
0 paquet
63. A4AF et Remote Queue Rank
D05 a démontré que le QR distant est falsifiable.
D09 confirme qu’il influence effectivement :
SwapToRightFile()
Première évolution sûre
Trace :
QR condition changed outcome?
yes/no
Puis simulation :
decision without Remote QR
sans changer le comportement réel.
64. Question à mesurer
Combien de swaps seraient différents si :
Remote QR
était retiré de l’heuristique ?
Si :
presque aucun
le code historique peut être simplifié.
Si :
beaucoup
il faudra étudier une alternative basée sur des observations locales.
65. Possible remplacement à long terme
Pas une recommandation immédiate.
Facteurs vérifiables :
temps depuis dernier transfert
source count réel
file priority
source useful parts
connection success
local queue wait estimate impossible à connaître
Il n’existe pas de substitut parfait au QR parce que le QR apporte précisément une information sur la file distante.
Il faut donc mesurer la valeur de cette information avant de la supprimer.
66. A4AF et SX Provider Quality
D08 proposait :
provider quality
→ tie-break pour choisir à qui demander SX
Cette métrique ne doit pas devenir :
file swap priority générale
Elle ne concerne qu’un rôle :
qualité comme fournisseur de sources
D09 garde les dimensions séparées.
67. A4AF et source quality
Même prudence.
Une source qui transfère bien Fichier A peut être excellente pour A et NNP pour B.
La qualité n’est pas seulement :
client global
mais souvent :
client × fichier × moment
68. Historique Sivka
Le changelog Sivka documente :
A4AF handling v1.2
A4AF counter
R4AF listing
manual swapping all A4AF
Il montre que le sujet était déjà considéré comme complexe assez tôt dans l’histoire des Mods.
Mais D09 ne déduit pas le comportement exact de ces fonctions sans source détaillée correspondante.
69. Historique Xtreme
Le corpus documente :
Auto-A4AF-check
Just in Time Swapping
drop NoNeeded
drop FullQueue
drop HighQR
Cela montre deux philosophies historiques :
réutiliser vite une source
et :
nettoyer les sources jugées peu productives
84. Première implémentation recommandée
D09-V1 — A4AF Decision Trace
Aucun changement de comportement.
Ajouter :
raison
from/to file
list origin
NNP classification shadow
timers
priority
source counts
QR influence
SX influence
E6bis state
85. D09-V2 — NNP Reason Classifier Shadow
Dans le chemin SendBlockRequests() :
avant :
SetDownloadState(DS_NONEEDEDPARTS)
calculer seulement pour log :
NO_PART_OVERLAP
ALL_WORK_RESERVED
ENDGAME_TRANSIENT
UNKNOWN
Aucune modification des décisions.
86. D09-V3 — Gap Event Reclassification Shadow
Sur :
AddGap / corruption
AICH recovery
Endgame reservation release
rechercher les sources dans :
A4AFsrclist
qui redeviennent localement utiles.
Aucun swap.
88. D09-V5 — Adaptive NNP Grace
Seulement si :
des sources actives utiles sont encore perdues
malgré V4 + E6bis
Alors tester une grâce ciblée.
Pas avant.
89. Pourquoi cet ordre est préférable
Il est possible que :
Stale Pipeline Bypass
+
Locked Recovery
+
local reclassification
résolvent presque tous les cas où NetF avait besoin de 30 secondes de délai.
Dans ce cas :
pas besoin d'ajouter une nouvelle attente
mesurer
avant d'empiler des heuristiques
90. Architecture proposée
A4AFManager
├── ActiveFile
├── OtherRequests
├── OtherNoNeeded
├── SwapPolicy
└── ReaskPolicy
NeedClassifier
├── NoPartOverlap
├── AllWorkReserved
├── EndgameTransient
└── IntegrityReopened
A4AFEventReclassifier
├── GapChanged
├── Corruption
├── AICH
└── ReservationReleased
A4AFDecisionTrace
├── priority
├── timers
├── SX
├── QR
└── Endgame
Ces noms sont conceptuels.
Le premier port ne doit pas imposer un grand refactor.
91. Invariant de protocole
Tout ce travail reste :
100 % local
Aucun nouveau :
opcode
tag
packet
source exchange version
server feature
n’est nécessaire.
92. Invariant Endgame
Baseline :
E6bis
Toute nouveauté D09 doit démontrer :
meilleur que E6bis
et non simplement :
meilleur que 0.72a officiel
93. Invariant Trust
Ne pas accorder un privilège parce que :
Remote QR dit 4
ModString dit X
client prétend être Complete Source
Les informations distantes restent des assertions.
Les événements locaux :
gap reopened
reservation released
valid bytes received
ont davantage de poids.
94. Invariant réseau
Ne pas transformer la réévaluation locale en :
reask immédiat massif
Le principal intérêt de la proposition est justement :
réagir plus vite
sans augmenter l'overhead
95. Découverte majeure du dossier
D09 permet finalement de reformuler NNP.
Dans l’interface historique :
No Needed Parts
semble décrire uniquement le pair.
En réalité :
NNP est une relation entre la Part Status du pair, notre gap list, l’état des réservations et l’instant où la décision est prise.
C’est beaucoup plus important.
96. Décision actuelle
Pas de port immédiat :
Delayed NNP = 30 s
La priorité est :
D09-V1 Decision Trace
D09-V2 NNP reason shadow
D09-V3 Event-driven reclassification shadow
Si les traces montrent que des sources fraîchement utiles restent dormantes à cause du modèle NNP historique :
97. Gain potentiel attendu
Pas nécessairement un gain sur tous les fichiers.
Principalement :
fichiers rares
corruption proche de la fin
AICH recovery
SOURCE_LIMITED
beaucoup d'A4AF
derniers blocs fortement disputés
Le gain attendu est surtout :
réduire le temps où
une source utile existe déjà
mais reste mal classée localement
98. Ce que nous ne devons pas faire
réduire FILEREASKTIME globalement
supprimer les timers NNP
attendre 30 s sur tous les NNP
forcer tous les A4AF vers le fichier presque fini
bannir les HighQR
utiliser le QR distant comme vérité
réinterroger le réseau après chaque AddGap
dupliquer des CUpDownClient par fichier
99. Relation avec les vieux Mods
NetF WARP
Apporte :
Delayed NNP
et l’explication corruption/endgame.
Xtreme
Apporte historiquement :
Just In Time Swapping
Auto-A4AF
et une forte culture de gestion dynamique des sources.
Sivka
Documente :
A4AF handling
R4AF
compteurs/visibilité
ZZ / ZZUL
La branche officielle étudiée porte explicitement de nombreux marqueurs :
ZZ:DownloadManager
dans l’implémentation A4AF actuelle.
Le moteur moderne est donc déjà le résultat d’années d’évolution communautaire.
100. Conclusion
A4AF n’est pas une petite option d’interface.
C’est un véritable ordonnanceur d’affectation des pairs aux fichiers.
La branche 0.72a sait déjà :
éviter les doublons de clients
mémoriser plusieurs fichiers par source
classer les associations NNP
respecter les priorités
espacer les reasks
tenir compte de SX
réutiliser une source quand elle devient meilleure ailleurs
Mais son modèle NNP reste fondé sur une logique historique où :
« plus de bloc immédiatement demandable »
est très proche de :
« plus rien d'utile chez cette source »
Endgame E6bis, AICH et notre Trust Model rendent cette assimilation moins satisfaisante.
Delayed NNP 30 s partout
mais :
rendre NNP explicable, détecter pourquoi une source est momentanément inutile et réévaluer les associations A4AF lorsqu’un événement local change réellement nos besoins.
C’est une amélioration entièrement locale, compatible avec le réseau existant, directement utile à Tail Source Wakeup et particulièrement pertinente après corruption ou en SOURCE_LIMITED.