/* sweeper.cc
****************************************************************************************************************
****************************************************************************************************************

    Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2020, 2021, 2026 Askar
    Almatov

    This file is part of Trafficmeter.

    Trafficmeter 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 3 of the License, or (at your
    option) any later version.

    Trafficmeter 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 Trafficmeter. If not, see
    <http://www.gnu.org/licenses/>.
*/

#include <cassert>
#include <iostream>
#include <libiclass/time>
#include <unistd.h>

#include "flowwriter.h"
#include "flow2writer.h"
#include "now.h"
#include "packetwriter.h"
#include "statwriter.h"
#include "sweeper.h"
#include "tmdefs.h"

using namespace iclass;
using namespace trafficmeter;

using std::cout;
using std::endl;
using std::string;
using std::vector;

constexpr const int     IDLE_DURATION_          = 100000;   // microseconds
constexpr const int     REMOVING_IDLE_DURATION_ = 1000;     // microseconds

/**************************************************************************************************************/
Sweeper::~Sweeper()
{
    this->lock();

    assert( removedFiles_c_.empty() );
}

/**************************************************************************************************************/
void
Sweeper::attach( Directory* directory )
{
    directories_.push_back( directory );
}

/**************************************************************************************************************/
vector<Path>
Sweeper::removedFiles()
{
    this->lock();

    vector<Path>    files( std::move(removedFiles_c_) );

    this->unlock();

    return std::move( files );
}

/**************************************************************************************************************/
void
Sweeper::routine()
{
    cout << Now() << "tid=" << tid() << " sweeper started" << endl;

    for ( Directory* dir : directories_ )
    {
        dir->load();
        usleep( 1000 );
    }

    while ( !stopped() )
    {
        if ( !fileQueue_.empty() )
        {
            removeFile_();
            usleep( REMOVING_IDLE_DURATION_ );
            continue;
        }

        usleep( IDLE_DURATION_ );

        for ( Directory* dir : directories_ )
        {
            for ( const auto& file : dir->deletingFiles() )
            {
                fileQueue_.push( file );
            }
        }
    }

    for ( Directory* dir : directories_ )
    {
        dir->loadCancel();
    }

    cout << Now() << "tid=" << tid() << " sweeper finished" << endl;
}

/**************************************************************************************************************/
void
Sweeper::removeFile_()
{
    Path&&  path( fileQueue_.front().path() );

    unlink( path.c_str() );
    fileQueue_.front().removeSize();
    fileQueue_.pop();

    this->lock();

    removedFiles_c_.push_back( path );

    this->unlock();
}

