/*
* File : TRHostTorrentImpl.java
* Created : 26-Oct-2003
* By : stuff
*
* Azureus - a Java Bittorrent client
*
* 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.
*
* 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 ( see the LICENSE file ).
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.gudy.azureus2.core3.tracker.host.impl;
/**
* @author parg
*
*/
import java.util.*;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.core3.tracker.host.*;
import org.gudy.azureus2.core3.tracker.server.*;
import org.gudy.azureus2.core3.torrent.*;
public class
TRHostTorrentHostImpl
implements TRHostTorrent
{
private TRHostImpl host;
private TRTrackerServer server;
private TRTrackerServerTorrent server_torrent;
private TOTorrent torrent;
private long date_added;
private int port;
private List listeners_cow = new ArrayList();
private List removal_listeners = new ArrayList();
private int status = TS_STOPPED;
private boolean persistent;
private boolean passive;
private long sos_uploaded;
private long sos_downloaded;
private long sos_bytes_in;
private long sos_bytes_out;
private long sos_announce;
private long sos_scrape;
private long sos_complete;
private long last_uploaded;
private long last_downloaded;
private long last_bytes_in;
private long last_bytes_out;
private long last_announce;
private long last_scrape;
//average over 10 periods, update every period.
private Average average_uploaded = Average.getInstance(TRHostImpl.STATS_PERIOD_SECS*1000,TRHostImpl.STATS_PERIOD_SECS*10);
private Average average_downloaded = Average.getInstance(TRHostImpl.STATS_PERIOD_SECS*1000,TRHostImpl.STATS_PERIOD_SECS*10);
private Average average_bytes_in = Average.getInstance(TRHostImpl.STATS_PERIOD_SECS*1000,TRHostImpl.STATS_PERIOD_SECS*10);
private Average average_bytes_out = Average.getInstance(TRHostImpl.STATS_PERIOD_SECS*1000,TRHostImpl.STATS_PERIOD_SECS*10);
private Average average_announce = Average.getInstance(TRHostImpl.STATS_PERIOD_SECS*1000,TRHostImpl.STATS_PERIOD_SECS*10);
private Average average_scrape = Average.getInstance(TRHostImpl.STATS_PERIOD_SECS*1000,TRHostImpl.STATS_PERIOD_SECS*10);
private boolean disable_reply_caching;
private HashMap data;
protected AEMonitor this_mon = new AEMonitor( "TRHostTorrentHost" );
protected
TRHostTorrentHostImpl(
TRHostImpl _host,
TRTrackerServer _server,
TOTorrent _torrent,
int _port,
long _date_added )
{
host = _host;
server = _server;
torrent = _torrent;
port = _port;
date_added = _date_added;
}
public int
getPort()
{
return( port );
}
public void
start()
{
// there's a potential deadlock situation if we call the server while holding
// the torrent lock, as the server then calls back to the host and we get
// a torrent -> host monitor chain. We already have a host->torrent chain.
// easiest solution is to delegate call to the host, which will grab the host
// monitor and then call back out to startSupport. Hence the chain is in the
// right direction
host.startTorrent( this );
}
protected void
startSupport()
{
try{
this_mon.enter();
// System.out.println( "TRHostTorrentHostImpl::start");
status = TS_STARTED;
server_torrent = server.permit( "", torrent.getHash(), true);
if ( disable_reply_caching ){
server_torrent.disableCaching();
}
}catch( Throwable e ){
Debug.printStackTrace( e );
}finally{
this_mon.exit();
}
host.hostTorrentStateChange( this );
}
public void
stop()
{
host.stopTorrent( this );
}
protected void
stopSupport()
{
try{
this_mon.enter();
// System.out.println( "TRHostTorrentHostImpl::stop");
status = TS_STOPPED;
server.deny( torrent.getHash(), true);
TRTrackerServerTorrent st = server_torrent;
TRTrackerServerTorrentStats torrent_stats = st==null?null:st.getStats();
if ( torrent_stats != null ){
sos_uploaded = sos_uploaded + torrent_stats.getUploaded();
sos_downloaded = sos_downloaded + torrent_stats.getDownloaded();
sos_bytes_in = sos_bytes_in + torrent_stats.getBytesIn();
sos_bytes_out = sos_bytes_out + torrent_stats.getBytesOut();
sos_announce = sos_announce + torrent_stats.getAnnounceCount();
sos_scrape = sos_scrape + torrent_stats.getScrapeCount();
sos_complete = sos_complete + torrent_stats.getCompletedCount();
torrent_stats = null;
}
last_uploaded = 0;
last_downloaded = 0;
last_bytes_in = 0;
last_bytes_out = 0;
last_announce = 0;
last_scrape = 0;
}catch( Throwable e ){
Debug.printStackTrace( e );
}finally{
this_mon.exit();
}
host.hostTorrentStateChange( this );
}
public void
remove()
throws TRHostTorrentRemovalVetoException
{
canBeRemoved();
stop();
host.remove( this );
}
public boolean
canBeRemoved()
throws TRHostTorrentRemovalVetoException
{
ArrayList listeners_copy;
try{
this_mon.enter();
listeners_copy = new ArrayList( removal_listeners );
}finally{
this_mon.exit();
}
for (int i=0;i<listeners_copy.size();i++){
((TRHostTorrentWillBeRemovedListener)listeners_copy.get(i)).torrentWillBeRemoved( this );
}
return( true );
}
public int
getStatus()
{
return( status );
}
public boolean
isPersistent()
{
return( persistent );
}
protected void
setPersistent(
boolean _persistent )
{
persistent = _persistent;
}
public boolean
isPassive()
{
return( passive );
}
public void
setPassive(
boolean b )
{
passive = b;
}
public long
getDateAdded()
{
return( date_added );
}
public TOTorrent
getTorrent()
{
return( torrent );
}
protected void
setTorrent(
TOTorrent _torrent )
{
torrent = _torrent;
}
public TRTrackerServerTorrent
getTrackerTorrent()
{
return( server_torrent );
}
public TRHostPeer[]
getPeers()
{
try{
TRTrackerServerPeer[] peers = server.getPeers( torrent.getHash());
if ( peers != null ){
TRHostPeer[] res = new TRHostPeer[peers.length];
for (int i=0;i<peers.length;i++){
res[i] = new TRHostPeerHostImpl(peers[i]);
}
return( res );
}
}catch( TOTorrentException e ){
Debug.printStackTrace( e );
}
return( new TRHostPeer[0] );
}
protected TRTrackerServerTorrentStats
getStats()
{
TRTrackerServerTorrent st = server_torrent;
if ( st != null ){
return( st.getStats());
}
return( null );
}
protected void
setStartOfDayValues(
long _date_added,
long completed,
long announces,
long scrapes,
long uploaded,
long downloaded,
long bytes_in,
long bytes_out )
{
date_added = _date_added;
sos_complete = completed;
sos_announce = announces;
sos_scrape = scrapes;
sos_uploaded = uploaded;
sos_downloaded = downloaded;
sos_bytes_in = bytes_in;
sos_bytes_out = bytes_out;
}
public int
getSeedCount()
{
TRTrackerServerTorrentStats stats = getStats();
if ( stats != null ){
return( stats.getSeedCount());
}
return( 0 );
}
public int
getLeecherCount()
{
TRTrackerServerTorrentStats stats = getStats();
if ( stats != null ){
return( stats.getLeecherCount());
}
return( 0 );
}
public int
getBadNATCount()
{
TRTrackerServerTorrentStats stats = getStats();
if ( stats != null ){
return( stats.getBadNATPeerCount());
}
return( 0 );
}
protected void
updateStats()
{
TRTrackerServerTorrentStats stats = getStats();
if ( stats != null ){
long current_uploaded = stats.getUploaded();
long ul_diff = current_uploaded - last_uploaded;
if ( ul_diff < 0 ){
ul_diff = 0;
}
average_uploaded.addValue(ul_diff);
last_uploaded = current_uploaded;
// downloaded
long current_downloaded = stats.getDownloaded();
long dl_diff = current_downloaded - last_downloaded;
if ( dl_diff < 0 ){
dl_diff = 0;
}
average_downloaded.addValue(dl_diff);
last_downloaded = current_downloaded;
// bytes in
long current_bytes_in = stats.getBytesIn();
long bi_diff = current_bytes_in - last_bytes_in;
if ( bi_diff < 0 ){
bi_diff = 0;
}
average_bytes_in.addValue(bi_diff);
last_bytes_in = current_bytes_in;
// bytes out
long current_bytes_out = stats.getBytesOut();
long bo_diff = current_bytes_out - last_bytes_out;
if ( bo_diff < 0 ){
bo_diff = 0;
}
average_bytes_out.addValue(bo_diff);
last_bytes_out = current_bytes_out;
// announce
long current_announce = stats.getAnnounceCount();
long an_diff = current_announce - last_announce;
if ( an_diff < 0 ){
an_diff = 0;
}
average_announce.addValue(an_diff);
last_announce = current_announce;
// scrape
long current_scrape = stats.getScrapeCount();
long sc_diff = current_scrape - last_scrape;
if ( sc_diff < 0 ){
sc_diff = 0;
}
average_scrape.addValue(sc_diff);
last_scrape = current_scrape;
}
}
protected TRTrackerServer
getServer()
{
return( server );
}
public long
getTotalUploaded()
{
TRTrackerServerTorrentStats stats = getStats();
if ( stats != null ){
return( sos_uploaded + stats.getUploaded());
}
return( sos_uploaded );
}
public long
getTotalDownloaded()
{
TRTrackerServerTorrentStats stats = getStats();
if ( stats != null ){
return( sos_downloaded + stats.getDownloaded());
}
return( sos_downloaded );
}
public long
getTotalLeft()
{
TRTrackerServerTorrentStats stats = getStats();
if ( stats != null ){
return( stats.getAmountLeft());
}
return( 0 );
}
public long
getTotalBytesIn()
{
TRTrackerServerTorrentStats stats = getStats();
if ( stats != null ){
return( sos_bytes_in + stats.getBytesIn());
}
return( sos_bytes_in );
}
public long
getTotalBytesOut()
{
TRTrackerServerTorrentStats stats = getStats();
if ( stats != null ){
return( sos_bytes_out + stats.getBytesOut());
}
return( sos_bytes_out );
}
public long
getAnnounceCount()
{
TRTrackerServerTorrentStats stats = getStats();
if ( stats != null ){
return( sos_announce + stats.getAnnounceCount());
}
return( sos_announce );
}
public long
getScrapeCount()
{
TRTrackerServerTorrentStats stats = getStats();
if ( stats != null ){
return( sos_scrape + stats.getScrapeCount());
}
return( sos_scrape );
}
public long
getCompletedCount()
{
TRTrackerServerTorrentStats stats = getStats();
if ( stats != null ){
return( sos_complete + stats.getCompletedCount());
}
return( sos_complete );
}
// averages
public long
getAverageBytesIn()
{
return( average_bytes_in.getAverage());
}
public long
getAverageBytesOut()
{
return( average_bytes_out.getAverage() );
}
public long
getAverageUploaded()
{
return( average_uploaded.getAverage() );
}
public long
getAverageDownloaded()
{
return( average_downloaded.getAverage() );
}
public long
getAverageAnnounceCount()
{
return( average_announce.getAverage());
}
public long
getAverageScrapeCount()
{
return( average_scrape.getAverage());
}
public void
disableReplyCaching()
{
TRTrackerServerTorrent st = server_torrent;
disable_reply_caching = true;
if ( st != null ){
st.disableCaching();
}
}
protected void
preProcess(
TRHostTorrentRequest req )
throws TRHostException
{
List listeners_ref = listeners_cow;
for (int i=0;i<listeners_ref.size();i++){
try{
((TRHostTorrentListener)listeners_ref.get(i)).preProcess(req);
}catch( TRHostException e ){
throw( e );
}catch( Throwable e ){
Debug.printStackTrace(e);
}
}
}
protected void
postProcess(
TRHostTorrentRequest req )
throws TRHostException
{
List listeners_ref = listeners_cow;
for (int i=0;i<listeners_ref.size();i++){
try{
((TRHostTorrentListener)listeners_ref.get(i)).postProcess(req);
}catch( TRHostException e ){
throw( e );
}catch( Throwable e ){
Debug.printStackTrace(e);
}
}
}
public void
addListener(
TRHostTorrentListener l )
{
try{
this_mon.enter();
List new_listeners = new ArrayList( listeners_cow );
new_listeners.add(l);
listeners_cow = new_listeners;
}finally{
this_mon.exit();
}
host.torrentListenerRegistered();
}
public void
removeListener(
TRHostTorrentListener l )
{
try{
this_mon.enter();
List new_listeners = new ArrayList( listeners_cow );
new_listeners.remove(l);
listeners_cow = new_listeners;
}finally{
this_mon.exit();
}
}
public void
addRemovalListener(
TRHostTorrentWillBeRemovedListener l )
{
try{
this_mon.enter();
removal_listeners.add(l);
}finally{
this_mon.exit();
}
}
public void
removeRemovalListener(
TRHostTorrentWillBeRemovedListener l )
{
try{
this_mon.enter();
removal_listeners.remove(l);
}finally{
this_mon.exit();
}
}
/** To retreive arbitrary objects against this object. */
public Object getData (String key) {
if (data == null) return null;
return data.get(key);
}
/** To store arbitrary objects against this object. */
public void setData (String key, Object value) {
try{
this_mon.enter();
if (data == null) {
data = new HashMap();
}
if (value == null) {
if (data.containsKey(key))
data.remove(key);
} else {
data.put(key, value);
}
}finally{
this_mon.exit();
}
}
}