mirror of https://github.com/ipxe/ipxe.git
[peerdist] Gather and report peer statistics during download
Record and report the number of peers (calculated as the maximum number of peers discovered for a block's segment at the time that the block download is complete), and the percentage of blocks retrieved from peers rather than from the origin server. Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/66/head
parent
4674df25ef
commit
7e673a6b67
|
@ -109,6 +109,12 @@ peerdisc_init ( struct peerdisc_client *peerdisc,
|
|||
|
||||
extern unsigned int peerdisc_timeout_secs;
|
||||
|
||||
extern void peerdisc_stat ( struct interface *intf, struct peerdisc_peer *peer,
|
||||
struct list_head *peers );
|
||||
#define peerdisc_stat_TYPE( object_type ) \
|
||||
typeof ( void ( object_type, struct peerdisc_peer *peer, \
|
||||
struct list_head *peers ) )
|
||||
|
||||
extern int peerdisc_open ( struct peerdisc_client *peerdisc, const void *id,
|
||||
size_t len );
|
||||
extern void peerdisc_close ( struct peerdisc_client *peerdisc );
|
||||
|
|
|
@ -41,6 +41,16 @@ struct peerdist_multiplexed_block {
|
|||
struct interface xfer;
|
||||
};
|
||||
|
||||
/** PeerDist statistics */
|
||||
struct peerdist_statistics {
|
||||
/** Maximum observed number of peers */
|
||||
unsigned int peers;
|
||||
/** Number of blocks downloaded in total */
|
||||
unsigned int total;
|
||||
/** Number of blocks downloaded from peers */
|
||||
unsigned int local;
|
||||
};
|
||||
|
||||
/** A PeerDist download multiplexer */
|
||||
struct peerdist_multiplexer {
|
||||
/** Reference count */
|
||||
|
@ -65,6 +75,9 @@ struct peerdist_multiplexer {
|
|||
struct list_head idle;
|
||||
/** Block downloads */
|
||||
struct peerdist_multiplexed_block block[PEERMUX_MAX_BLOCKS];
|
||||
|
||||
/** Statistics */
|
||||
struct peerdist_statistics stats;
|
||||
};
|
||||
|
||||
extern int peermux_filter ( struct interface *xfer, struct interface *info,
|
||||
|
|
|
@ -270,6 +270,9 @@ static int peerblk_deliver ( struct peerdist_block *peerblk,
|
|||
*/
|
||||
static void peerblk_done ( struct peerdist_block *peerblk, int rc ) {
|
||||
struct digest_algorithm *digest = peerblk->digest;
|
||||
struct peerdisc_segment *segment = peerblk->discovery.segment;
|
||||
struct peerdisc_peer *head;
|
||||
struct peerdisc_peer *peer;
|
||||
uint8_t hash[digest->digestsize];
|
||||
unsigned long now = peerblk_timestamp();
|
||||
|
||||
|
@ -296,6 +299,11 @@ static void peerblk_done ( struct peerdist_block *peerblk, int rc ) {
|
|||
profile_custom ( &peerblk_attempt_success_profiler,
|
||||
( now - peerblk->attempted ) );
|
||||
|
||||
/* Report peer statistics */
|
||||
head = list_entry ( &segment->peers, struct peerdisc_peer, list );
|
||||
peer = ( ( peerblk->peer == head ) ? NULL : peerblk->peer );
|
||||
peerdisc_stat ( &peerblk->xfer, peer, &segment->peers );
|
||||
|
||||
/* Close download */
|
||||
peerblk_close ( peerblk, 0 );
|
||||
return;
|
||||
|
|
|
@ -76,6 +76,36 @@ static struct peerdisc_segment * peerdisc_find ( const char *id );
|
|||
static int peerdisc_discovered ( struct peerdisc_segment *segment,
|
||||
const char *location );
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Statistics reporting
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Report peer discovery statistics
|
||||
*
|
||||
* @v intf Interface
|
||||
* @v peer Selected peer (or NULL)
|
||||
* @v peers List of available peers
|
||||
*/
|
||||
void peerdisc_stat ( struct interface *intf, struct peerdisc_peer *peer,
|
||||
struct list_head *peers ) {
|
||||
struct interface *dest;
|
||||
peerdisc_stat_TYPE ( void * ) *op =
|
||||
intf_get_dest_op ( intf, peerdisc_stat, &dest );
|
||||
void *object = intf_object ( dest );
|
||||
|
||||
if ( op ) {
|
||||
op ( object, peer, peers );
|
||||
} else {
|
||||
/* Default is to do nothing */
|
||||
}
|
||||
|
||||
intf_put ( dest );
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Discovery sockets
|
||||
|
|
|
@ -24,9 +24,11 @@
|
|||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <ipxe/uri.h>
|
||||
#include <ipxe/xferbuf.h>
|
||||
#include <ipxe/job.h>
|
||||
#include <ipxe/peerblk.h>
|
||||
#include <ipxe/peermux.h>
|
||||
|
||||
|
@ -74,6 +76,28 @@ static void peermux_close ( struct peerdist_multiplexer *peermux, int rc ) {
|
|||
intf_shutdown ( &peermux->info, rc );
|
||||
}
|
||||
|
||||
/**
|
||||
* Report progress of PeerDist download
|
||||
*
|
||||
* @v peermux PeerDist download multiplexer
|
||||
* @v progress Progress report to fill in
|
||||
* @ret ongoing_rc Ongoing job status code (if known)
|
||||
*/
|
||||
static int peermux_progress ( struct peerdist_multiplexer *peermux,
|
||||
struct job_progress *progress ) {
|
||||
struct peerdist_statistics *stats = &peermux->stats;
|
||||
unsigned int percentage;
|
||||
|
||||
/* Construct PeerDist status message */
|
||||
if ( stats->total ) {
|
||||
percentage = ( ( 100 * stats->local ) / stats->total );
|
||||
snprintf ( progress->message, sizeof ( progress->message ),
|
||||
"%3d%% from %d peers", percentage, stats->peers );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive content information
|
||||
*
|
||||
|
@ -274,6 +298,35 @@ peermux_block_buffer ( struct peerdist_multiplexed_block *peermblk ) {
|
|||
return xfer_buffer ( &peermux->xfer );
|
||||
}
|
||||
|
||||
/**
|
||||
* Record peer discovery statistics
|
||||
*
|
||||
* @v peermblk PeerDist multiplexed block download
|
||||
* @v peer Selected peer (or NULL)
|
||||
* @v peers List of available peers
|
||||
*/
|
||||
static void peermux_block_stat ( struct peerdist_multiplexed_block *peermblk,
|
||||
struct peerdisc_peer *peer,
|
||||
struct list_head *peers ) {
|
||||
struct peerdist_multiplexer *peermux = peermblk->peermux;
|
||||
struct peerdist_statistics *stats = &peermux->stats;
|
||||
struct peerdisc_peer *tmp;
|
||||
unsigned int count = 0;
|
||||
|
||||
/* Record maximum number of available peers */
|
||||
list_for_each_entry ( tmp, peers, list )
|
||||
count++;
|
||||
if ( count > stats->peers )
|
||||
stats->peers = count;
|
||||
|
||||
/* Update block counts */
|
||||
if ( peer )
|
||||
stats->local++;
|
||||
stats->total++;
|
||||
DBGC2 ( peermux, "PEERMUX %p downloaded %d/%d from %d peers\n",
|
||||
peermux, stats->local, stats->total, stats->peers );
|
||||
}
|
||||
|
||||
/**
|
||||
* Close multiplexed block download
|
||||
*
|
||||
|
@ -303,6 +356,8 @@ static void peermux_block_close ( struct peerdist_multiplexed_block *peermblk,
|
|||
|
||||
/** Data transfer interface operations */
|
||||
static struct interface_operation peermux_xfer_operations[] = {
|
||||
INTF_OP ( job_progress, struct peerdist_multiplexer *,
|
||||
peermux_progress ),
|
||||
INTF_OP ( intf_close, struct peerdist_multiplexer *, peermux_close ),
|
||||
};
|
||||
|
||||
|
@ -330,6 +385,8 @@ static struct interface_operation peermux_block_operations[] = {
|
|||
peermux_block_deliver ),
|
||||
INTF_OP ( xfer_buffer, struct peerdist_multiplexed_block *,
|
||||
peermux_block_buffer ),
|
||||
INTF_OP ( peerdisc_stat, struct peerdist_multiplexed_block *,
|
||||
peermux_block_stat ),
|
||||
INTF_OP ( intf_close, struct peerdist_multiplexed_block *,
|
||||
peermux_block_close ),
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue