]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[peerdist] Gather and report peer statistics during download
authorMichael Brown <mcb30@ipxe.org>
Tue, 5 Sep 2017 21:55:05 +0000 (22:55 +0100)
committerMichael Brown <mcb30@ipxe.org>
Tue, 5 Sep 2017 22:23:22 +0000 (23:23 +0100)
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>
src/include/ipxe/peerdisc.h
src/include/ipxe/peermux.h
src/net/peerblk.c
src/net/peerdisc.c
src/net/peermux.c

index f08ccaae26b2b31f7d4701479231d106e20544f7..45d592e76dfef60913e58489b96c8b5a6719406c 100644 (file)
@@ -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 );
index 44cbdb9d647632536c8d610eba4e5acac2347318..54acbfec938f48849c02b1d4c7c8b1877cae0edf 100644 (file)
@@ -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,
index 9fd52b736572bb8490aaa38df44aa5ec9a188c21..78888d2dbb778e991c8143d2834e959f25bf8850 100644 (file)
@@ -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;
index 4c3cd2ea5ea8bfb7bffa88bf8274464d0f696a09..20ac2427b1d2ff9c43c39fbfe874984d78edffa4 100644 (file)
@@ -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
index 634c699929af77f9c0ed5353543bbc962323ea1f..a391ed37307fb0ed4787a910ce8ac156562963a5 100644 (file)
 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 ),
 };