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 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,
|
extern int peerdisc_open ( struct peerdisc_client *peerdisc, const void *id,
|
||||||
size_t len );
|
size_t len );
|
||||||
extern void peerdisc_close ( struct peerdisc_client *peerdisc );
|
extern void peerdisc_close ( struct peerdisc_client *peerdisc );
|
||||||
|
|
|
@ -41,6 +41,16 @@ struct peerdist_multiplexed_block {
|
||||||
struct interface xfer;
|
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 */
|
/** A PeerDist download multiplexer */
|
||||||
struct peerdist_multiplexer {
|
struct peerdist_multiplexer {
|
||||||
/** Reference count */
|
/** Reference count */
|
||||||
|
@ -65,6 +75,9 @@ struct peerdist_multiplexer {
|
||||||
struct list_head idle;
|
struct list_head idle;
|
||||||
/** Block downloads */
|
/** Block downloads */
|
||||||
struct peerdist_multiplexed_block block[PEERMUX_MAX_BLOCKS];
|
struct peerdist_multiplexed_block block[PEERMUX_MAX_BLOCKS];
|
||||||
|
|
||||||
|
/** Statistics */
|
||||||
|
struct peerdist_statistics stats;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int peermux_filter ( struct interface *xfer, struct interface *info,
|
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 ) {
|
static void peerblk_done ( struct peerdist_block *peerblk, int rc ) {
|
||||||
struct digest_algorithm *digest = peerblk->digest;
|
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];
|
uint8_t hash[digest->digestsize];
|
||||||
unsigned long now = peerblk_timestamp();
|
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,
|
profile_custom ( &peerblk_attempt_success_profiler,
|
||||||
( now - peerblk->attempted ) );
|
( 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 */
|
/* Close download */
|
||||||
peerblk_close ( peerblk, 0 );
|
peerblk_close ( peerblk, 0 );
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -76,6 +76,36 @@ static struct peerdisc_segment * peerdisc_find ( const char *id );
|
||||||
static int peerdisc_discovered ( struct peerdisc_segment *segment,
|
static int peerdisc_discovered ( struct peerdisc_segment *segment,
|
||||||
const char *location );
|
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
|
* Discovery sockets
|
||||||
|
|
|
@ -24,9 +24,11 @@
|
||||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <ipxe/uri.h>
|
#include <ipxe/uri.h>
|
||||||
#include <ipxe/xferbuf.h>
|
#include <ipxe/xferbuf.h>
|
||||||
|
#include <ipxe/job.h>
|
||||||
#include <ipxe/peerblk.h>
|
#include <ipxe/peerblk.h>
|
||||||
#include <ipxe/peermux.h>
|
#include <ipxe/peermux.h>
|
||||||
|
|
||||||
|
@ -74,6 +76,28 @@ static void peermux_close ( struct peerdist_multiplexer *peermux, int rc ) {
|
||||||
intf_shutdown ( &peermux->info, 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
|
* Receive content information
|
||||||
*
|
*
|
||||||
|
@ -274,6 +298,35 @@ peermux_block_buffer ( struct peerdist_multiplexed_block *peermblk ) {
|
||||||
return xfer_buffer ( &peermux->xfer );
|
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
|
* Close multiplexed block download
|
||||||
*
|
*
|
||||||
|
@ -303,6 +356,8 @@ static void peermux_block_close ( struct peerdist_multiplexed_block *peermblk,
|
||||||
|
|
||||||
/** Data transfer interface operations */
|
/** Data transfer interface operations */
|
||||||
static struct interface_operation peermux_xfer_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 ),
|
INTF_OP ( intf_close, struct peerdist_multiplexer *, peermux_close ),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -330,6 +385,8 @@ static struct interface_operation peermux_block_operations[] = {
|
||||||
peermux_block_deliver ),
|
peermux_block_deliver ),
|
||||||
INTF_OP ( xfer_buffer, struct peerdist_multiplexed_block *,
|
INTF_OP ( xfer_buffer, struct peerdist_multiplexed_block *,
|
||||||
peermux_block_buffer ),
|
peermux_block_buffer ),
|
||||||
|
INTF_OP ( peerdisc_stat, struct peerdist_multiplexed_block *,
|
||||||
|
peermux_block_stat ),
|
||||||
INTF_OP ( intf_close, struct peerdist_multiplexed_block *,
|
INTF_OP ( intf_close, struct peerdist_multiplexed_block *,
|
||||||
peermux_block_close ),
|
peermux_block_close ),
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue