Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
[pool] Add a generic concept of a pooled connection
Signed-off-by: Michael Brown <mcb30@ipxe.org>
- Loading branch information
Showing
2 changed files
with
241 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/* | ||
* Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>. | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License as | ||
* published by the Free Software Foundation; either version 2 of the | ||
* License, or any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, but | ||
* WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program; if not, write to the Free Software | ||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
* 02110-1301, USA. | ||
* | ||
* You can also choose to distribute this program under the terms of | ||
* the Unmodified Binary Distribution Licence (as given in the file | ||
* COPYING.UBDL), provided that you have satisfied its requirements. | ||
*/ | ||
|
||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); | ||
|
||
/** | ||
* @file | ||
* | ||
* Pooled connections | ||
* | ||
*/ | ||
|
||
#include <assert.h> | ||
#include <ipxe/pool.h> | ||
|
||
/** | ||
* Recycle this connection after closing | ||
* | ||
* @v intf Data transfer interface | ||
*/ | ||
void pool_recycle ( struct interface *intf ) { | ||
|
||
intf_poke ( intf, pool_recycle ); | ||
} | ||
|
||
/** | ||
* Reopen a defunct connection | ||
* | ||
* @v intf Data transfer interface | ||
*/ | ||
void pool_reopen ( struct interface *intf ) { | ||
|
||
intf_poke ( intf, pool_reopen ); | ||
} | ||
|
||
/** | ||
* Add connection to pool | ||
* | ||
* @v pool Pooled connection | ||
* @v list List of pooled connections | ||
* @v expiry Expiry time | ||
*/ | ||
void pool_add ( struct pooled_connection *pool, struct list_head *list, | ||
unsigned long expiry ) { | ||
|
||
/* Sanity check */ | ||
assert ( list_empty ( &pool->list ) ); | ||
assert ( ! timer_running ( &pool->timer ) ); | ||
|
||
/* Add to list of pooled connections */ | ||
list_add_tail ( &pool->list, list ); | ||
|
||
/* Start expiry timer */ | ||
start_timer_fixed ( &pool->timer, expiry ); | ||
} | ||
|
||
/** | ||
* Remove connection from pool | ||
* | ||
* @v pool Pooled connection | ||
*/ | ||
void pool_del ( struct pooled_connection *pool ) { | ||
|
||
/* Remove from list of pooled connections */ | ||
list_del ( &pool->list ); | ||
INIT_LIST_HEAD ( &pool->list ); | ||
|
||
/* Stop expiry timer */ | ||
stop_timer ( &pool->timer ); | ||
|
||
/* Mark as a freshly recycled connection */ | ||
pool->flags = POOL_RECYCLED; | ||
} | ||
|
||
/** | ||
* Close expired pooled connection | ||
* | ||
* @v timer Expiry timer | ||
* @v over Failure indicator | ||
*/ | ||
void pool_expired ( struct retry_timer *timer, int over __unused ) { | ||
struct pooled_connection *pool = | ||
container_of ( timer, struct pooled_connection, timer ); | ||
|
||
/* Sanity check */ | ||
assert ( ! list_empty ( &pool->list ) ); | ||
|
||
/* Remove from connection pool */ | ||
list_del ( &pool->list ); | ||
INIT_LIST_HEAD ( &pool->list ); | ||
|
||
/* Close expired connection */ | ||
pool->expired ( pool ); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
#ifndef _IPXE_POOL_H | ||
#define _IPXE_POOL_H | ||
|
||
/** @file | ||
* | ||
* Pooled connections | ||
* | ||
*/ | ||
|
||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); | ||
|
||
#include <ipxe/interface.h> | ||
#include <ipxe/list.h> | ||
#include <ipxe/retry.h> | ||
|
||
/** A pooled connection */ | ||
struct pooled_connection { | ||
/** List of pooled connections | ||
* | ||
* Note that each connecton in the pool has a running expiry | ||
* timer which holds a reference to the connection. We | ||
* therefore do not require the connection pool list to hold a | ||
* reference for each pooled connection. | ||
*/ | ||
struct list_head list; | ||
/** Expiry timer */ | ||
struct retry_timer timer; | ||
/** Close expired pooled connection | ||
* | ||
* @v pool Pooled connection | ||
*/ | ||
void ( * expired ) ( struct pooled_connection *pool ); | ||
/** Flags */ | ||
unsigned int flags; | ||
}; | ||
|
||
/** Pooled connection flags */ | ||
enum pooled_connection_flags { | ||
/** Connection should be recycled after closing */ | ||
POOL_RECYCLABLE = 0x0001, | ||
/** Connection has been recycled */ | ||
POOL_RECYCLED = 0x0002, | ||
/** Connection is known to be alive */ | ||
POOL_ALIVE = 0x0004, | ||
}; | ||
|
||
extern void pool_add ( struct pooled_connection *pool, struct list_head *list, | ||
unsigned long expiry ); | ||
extern void pool_del ( struct pooled_connection *pool ); | ||
extern void pool_expired ( struct retry_timer *timer, int over ); | ||
|
||
/** | ||
* Initialise a pooled connection | ||
* | ||
* @v pool Pooled connection | ||
* @v expired Close expired pooled connection method | ||
* @v refcnt Containing object reference counter | ||
*/ | ||
static inline __attribute__ (( always_inline )) void | ||
pool_init ( struct pooled_connection *pool, | ||
void ( * expired ) ( struct pooled_connection *pool ), | ||
struct refcnt *refcnt ) { | ||
|
||
INIT_LIST_HEAD ( &pool->list ); | ||
timer_init ( &pool->timer, pool_expired, refcnt ); | ||
pool->expired = expired; | ||
} | ||
|
||
/** | ||
* Mark pooled connection as recyclable | ||
* | ||
* @v pool Pooled connection | ||
*/ | ||
static inline __attribute__ (( always_inline )) void | ||
pool_recyclable ( struct pooled_connection *pool ) { | ||
|
||
pool->flags |= POOL_RECYCLABLE; | ||
} | ||
|
||
/** | ||
* Mark pooled connection as alive | ||
* | ||
* @v pool Pooled connection | ||
*/ | ||
static inline __attribute__ (( always_inline )) void | ||
pool_alive ( struct pooled_connection *pool ) { | ||
|
||
pool->flags |= POOL_ALIVE; | ||
} | ||
|
||
/** | ||
* Check if pooled connection is recyclable | ||
* | ||
* @v pool Pooled connection | ||
* @ret recyclable Pooled connection is recyclable | ||
*/ | ||
static inline __attribute__ (( always_inline )) int | ||
pool_is_recyclable ( struct pooled_connection *pool ) { | ||
|
||
return ( pool->flags & POOL_RECYCLABLE ); | ||
} | ||
|
||
/** | ||
* Check if pooled connection is reopenable | ||
* | ||
* @v pool Pooled connection | ||
* @ret reopenable Pooled connection is reopenable | ||
*/ | ||
static inline __attribute__ (( always_inline )) int | ||
pool_is_reopenable ( struct pooled_connection *pool ) { | ||
|
||
/* A connection is reopenable if it has been recycled but is | ||
* not yet known to be alive. | ||
*/ | ||
return ( ( pool->flags & POOL_RECYCLED ) & | ||
( ! ( pool->flags & POOL_ALIVE ) ) ); | ||
} | ||
|
||
extern void pool_recycle ( struct interface *intf ); | ||
#define pool_recycle_TYPE( object_type ) \ | ||
typeof ( void ( object_type ) ) | ||
|
||
extern void pool_reopen ( struct interface *intf ); | ||
#define pool_reopen_TYPE( object_type ) \ | ||
typeof ( void ( object_type ) ) | ||
|
||
#endif /* _IPXE_POOL_H */ |