Namespace refactor and documentation in the separate buffer files.

This commit is contained in:
Erik Zandvliet 2013-03-28 15:42:46 +01:00
parent 9b41a07c2f
commit 1e2f1602f8
3 changed files with 376 additions and 332 deletions

View file

@ -4,11 +4,13 @@
#include "buffer_stream.h" #include "buffer_stream.h"
#include <mist/timing.h> #include <mist/timing.h>
/// Stores the globally equal reference. namespace Buffer {
Buffer::Stream * Buffer::Stream::ref = 0; ///\brief Stores the singleton reference.
Stream * Stream::ref = 0;
/// Returns a globally equal reference to this class. ///\brief Returns a reference to the singleton instance of this class.
Buffer::Stream * Buffer::Stream::get(){ ///\return A reference to the class.
Stream * Stream::get(){
static tthread::mutex creator; static tthread::mutex creator;
if (ref == 0){ if (ref == 0){
//prevent creating two at the same time //prevent creating two at the same time
@ -21,15 +23,15 @@ Buffer::Stream * Buffer::Stream::get(){
return ref; return ref;
} }
/// Creates a new DTSC::Stream object, private function so only one instance can exist. ///\brief Creates a new DTSC::Stream object, private function so only one instance can exist.
Buffer::Stream::Stream(){ Stream::Stream(){
Strm = new DTSC::Stream(5); Strm = new DTSC::Stream(5);
readers = 0; readers = 0;
writers = 0; writers = 0;
} }
/// Do cleanup on delete. ///\brief Do cleanup on delete.
Buffer::Stream::~Stream(){ Stream::~Stream(){
tthread::lock_guard<tthread::mutex> guard(stats_mutex); tthread::lock_guard<tthread::mutex> guard(stats_mutex);
for (usersIt = users.begin(); usersIt != users.end(); usersIt++){ for (usersIt = users.begin(); usersIt != users.end(); usersIt++){
if (( * *usersIt).S.connected()){ if (( * *usersIt).S.connected()){
@ -40,8 +42,9 @@ Buffer::Stream::~Stream(){
delete Strm; delete Strm;
} }
/// Calculate and return the current statistics in JSON format. ///\brief Calculate and return the current statistics.
std::string & Buffer::Stream::getStats(){ ///\return The current statistics in JSON format.
std::string & Stream::getStats(){
static std::string ret; static std::string ret;
long long int now = Util::epoch(); long long int now = Util::epoch();
unsigned int tot_up = 0, tot_down = 0, tot_count = 0; unsigned int tot_up = 0, tot_down = 0, tot_count = 0;
@ -70,28 +73,34 @@ std::string & Buffer::Stream::getStats(){
return ret; return ret;
} }
/// Get a new DTSC::Ring object for a user. ///\brief Get a new DTSC::Ring object for a user.
DTSC::Ring * Buffer::Stream::getRing(){ ///\return A new DTSC::Ring object.
DTSC::Ring * Stream::getRing(){
return Strm->getRing(); return Strm->getRing();
} }
/// Drop a DTSC::Ring object. ///\brief Drop a DTSC::Ring object.
void Buffer::Stream::dropRing(DTSC::Ring * ring){ ///\param ring The DTSC::Ring to be invalidated.
void Stream::dropRing(DTSC::Ring * ring){
Strm->dropRing(ring); Strm->dropRing(ring);
} }
/// Get the (constant) header data of this stream. ///\brief Get the (constant) header data of this stream.
std::string & Buffer::Stream::getHeader(){ ///\return A reference to the header data of the stream.
std::string & Stream::getHeader(){
return Strm->outHeader(); return Strm->outHeader();
} }
/// Set the IP address to accept push data from. ///\brief Set the IP address to accept push data from.
void Buffer::Stream::setWaitingIP(std::string ip){ ///\param ip The new IP to accept push data from.
void Stream::setWaitingIP(std::string ip){
waiting_ip = ip; waiting_ip = ip;
} }
/// Check if this is the IP address to accept push data from. ///\brief Check if this is the IP address to accept push data from.
bool Buffer::Stream::checkWaitingIP(std::string ip){ ///\param ip The IP address to check.
///\return True if it is the correct address, false otherwise.
bool Stream::checkWaitingIP(std::string ip){
if (ip == waiting_ip || ip == "::ffff:" + waiting_ip){ if (ip == waiting_ip || ip == "::ffff:" + waiting_ip){
return true; return true;
}else{ }else{
@ -100,8 +109,10 @@ bool Buffer::Stream::checkWaitingIP(std::string ip){
} }
} }
/// Sets the current socket for push data. ///\brief Sets the current socket for push data.
bool Buffer::Stream::setInput(Socket::Connection S){ ///\param S The new socket for accepting push data.
///\return True if succesful, false otherwise.
bool Stream::setInput(Socket::Connection S){
if (ip_input.connected()){ if (ip_input.connected()){
return false; return false;
}else{ }else{
@ -110,13 +121,16 @@ bool Buffer::Stream::setInput(Socket::Connection S){
} }
} }
/// Gets the current socket for push data. ///\brief Gets the current socket for push data.
Socket::Connection & Buffer::Stream::getIPInput(){ ///\return A reference to the push socket.
Socket::Connection & Stream::getIPInput(){
return ip_input; return ip_input;
} }
/// Stores intermediate statistics. ///\brief Stores intermediate statistics.
void Buffer::Stream::saveStats(std::string username, Stats & stats){ ///\param username The name of the user.
///\param stats The final statistics to store.
void Stream::saveStats(std::string username, Stats & stats){
tthread::lock_guard<tthread::mutex> guard(stats_mutex); tthread::lock_guard<tthread::mutex> guard(stats_mutex);
Storage["curr"][username]["connector"] = stats.connector; Storage["curr"][username]["connector"] = stats.connector;
Storage["curr"][username]["up"] = stats.up; Storage["curr"][username]["up"] = stats.up;
@ -126,8 +140,11 @@ void Buffer::Stream::saveStats(std::string username, Stats & stats){
Storage["curr"][username]["start"] = Util::epoch() - stats.conntime; Storage["curr"][username]["start"] = Util::epoch() - stats.conntime;
} }
/// Stores final statistics. ///\brief Stores final statistics.
void Buffer::Stream::clearStats(std::string username, Stats & stats, std::string reason){ ///\param username The name of the user.
///\param stats The final statistics to store.
///\param reason The reason for disconnecting.
void Stream::clearStats(std::string username, Stats & stats, std::string reason){
tthread::lock_guard<tthread::mutex> guard(stats_mutex); tthread::lock_guard<tthread::mutex> guard(stats_mutex);
if (Storage["curr"].isMember(username)){ if (Storage["curr"].isMember(username)){
Storage["curr"].removeMember(username); Storage["curr"].removeMember(username);
@ -144,8 +161,8 @@ void Buffer::Stream::clearStats(std::string username, Stats & stats, std::string
Storage["log"][username]["start"] = Util::epoch() - stats.conntime; Storage["log"][username]["start"] = Util::epoch() - stats.conntime;
} }
/// Cleans up broken connections ///\brief Clean up broken connections
void Buffer::Stream::cleanUsers(){ void Stream::cleanUsers(){
bool repeat = false; bool repeat = false;
tthread::lock_guard<tthread::mutex> guard(stats_mutex); tthread::lock_guard<tthread::mutex> guard(stats_mutex);
do{ do{
@ -171,8 +188,10 @@ void Buffer::Stream::cleanUsers(){
}while (repeat); }while (repeat);
} }
///\brief Ask to obtain a write lock.
///
/// Blocks until writing is safe. /// Blocks until writing is safe.
void Buffer::Stream::getWriteLock(){ void Stream::getWriteLock(){
rw_mutex.lock(); rw_mutex.lock();
writers++; writers++;
while (writers != 1 && readers != 0){ while (writers != 1 && readers != 0){
@ -181,9 +200,10 @@ void Buffer::Stream::getWriteLock(){
rw_mutex.unlock(); rw_mutex.unlock();
} }
/// Drops a previously gotten write lock. ///\brief Drops a previously obtained write lock.
void Buffer::Stream::dropWriteLock(bool newpackets_available){ ///\param newPacketsAvailable Whether new packets are available to update the index.
if (newpackets_available){ void Stream::dropWriteLock(bool newPacketsAvailable){
if (newPacketsAvailable){
if (Strm->getPacket(0).isMember("keyframe")){ if (Strm->getPacket(0).isMember("keyframe")){
stats_mutex.lock(); stats_mutex.lock();
Strm->updateHeaders(); Strm->updateHeaders();
@ -194,13 +214,15 @@ void Buffer::Stream::dropWriteLock(bool newpackets_available){
writers--; writers--;
rw_mutex.unlock(); rw_mutex.unlock();
rw_change.notify_all(); rw_change.notify_all();
if (newpackets_available){ if (newPacketsAvailable){
moreData.notify_all(); moreData.notify_all();
} }
} }
///\brief Ask to obtain a read lock.
///
///Blocks until reading is safe. ///Blocks until reading is safe.
void Buffer::Stream::getReadLock(){ void Stream::getReadLock(){
rw_mutex.lock(); rw_mutex.lock();
while (writers > 0){ while (writers > 0){
rw_change.wait(rw_mutex); rw_change.wait(rw_mutex);
@ -209,32 +231,36 @@ void Buffer::Stream::getReadLock(){
rw_mutex.unlock(); rw_mutex.unlock();
} }
/// Drops a previously gotten read lock. ///\brief Drops a previously obtained read lock.
void Buffer::Stream::dropReadLock(){ void Stream::dropReadLock(){
rw_mutex.lock(); rw_mutex.lock();
readers--; readers--;
rw_mutex.unlock(); rw_mutex.unlock();
rw_change.notify_all(); rw_change.notify_all();
} }
/// Retrieves a reference to the DTSC::Stream ///\brief Retrieves a reference to the DTSC::Stream
DTSC::Stream * Buffer::Stream::getStream(){ ///\return A reference to the used DTSC::Stream
DTSC::Stream * Stream::getStream(){
return Strm; return Strm;
} }
/// Sets the buffer name. ///\brief Sets the buffer name.
void Buffer::Stream::setName(std::string n){ ///\param n The new name of the buffer.
void Stream::setName(std::string n){
name = n; name = n;
} }
/// Add a user to the userlist. ///\brief Add a user to the userlist.
void Buffer::Stream::addUser(user * new_user){ ///\param newUser The user to be added.
void Stream::addUser(user * newUser){
tthread::lock_guard<tthread::mutex> guard(stats_mutex); tthread::lock_guard<tthread::mutex> guard(stats_mutex);
users.push_back(new_user); users.push_back(newUser);
} }
/// Blocks the thread until new data is available. ///\brief Blocks the thread until new data is available.
void Buffer::Stream::waitForData(){ void Stream::waitForData(){
tthread::lock_guard<tthread::mutex> guard(stats_mutex); tthread::lock_guard<tthread::mutex> guard(stats_mutex);
moreData.wait(stats_mutex); moreData.wait(stats_mutex);
} }
}

View file

@ -50,7 +50,7 @@ namespace Buffer {
/// Sets the buffer name. /// Sets the buffer name.
void setName(std::string n); void setName(std::string n);
/// Add a user to the userlist. /// Add a user to the userlist.
void addUser(user * new_user); void addUser(user * newUser);
/// Blocks the thread until new data is available. /// Blocks the thread until new data is available.
void waitForData(); void waitForData();
/// Cleanup function /// Cleanup function

View file

@ -1,15 +1,19 @@
/// \file buffer_user.cpp /// \file buffer_user.cpp
/// Contains code for buffer users. /// Contains code for buffer users.
#include "buffer_user.h" #include "buffer_user.h"
#include "buffer_stream.h" #include "buffer_stream.h"
#include <sstream>
#include <stdlib.h> //for atoi and friends
int Buffer::user::UserCount = 0;
/// Creates a new user from a newly connected socket. #include <sstream>
#include <stdlib.h>
namespace Buffer {
int user::UserCount = 0;
///\brief Creates a new user from a newly connected socket.
///
///Also prints "User connected" text to stdout. ///Also prints "User connected" text to stdout.
Buffer::user::user(Socket::Connection fd){ ///\param fd A connection to the user.
user::user(Socket::Connection fd){
S = fd; S = fd;
MyNum = UserCount++; MyNum = UserCount++;
std::stringstream st; std::stringstream st;
@ -24,23 +28,29 @@ Buffer::user::user(Socket::Connection fd){
lastpointer = 0; lastpointer = 0;
} //constructor } //constructor
/// Drops held DTSC::Ring class, if one is held. ///\brief Drops held DTSC::Ring class, if one is held.
Buffer::user::~user(){ user::~user(){
Stream::get()->dropRing(myRing); Stream::get()->dropRing(myRing);
} //destructor } //destructor
/// Disconnects the current user. Doesn't do anything if already disconnected. ///\brief Disconnects the current user. Doesn't do anything if already disconnected.
///
///Prints "Disconnected user" to stdout if disconnect took place. ///Prints "Disconnected user" to stdout if disconnect took place.
void Buffer::user::Disconnect(std::string reason){ ///\param reason The reason for disconnecting the user.
void user::Disconnect(std::string reason){
if (S.connected()){ if (S.connected()){
S.close(); S.close();
} }
Stream::get()->clearStats(MyStr, lastStats, reason); Stream::get()->clearStats(MyStr, lastStats, reason);
} //Disconnect } //Disconnect
/// Tries to send the current buffer, returns true if success, false otherwise. ///\brief Tries to send data to the user.
///
///Has a side effect of dropping the connection if send will never complete. ///Has a side effect of dropping the connection if send will never complete.
bool Buffer::user::doSend(const char * ptr, int len){ ///\param ptr A pointer to the data that is to be sent.
///\param len The amount of bytes to be sent from this pointer.
///\return True if len bytes are sent, false otherwise.
bool user::doSend(const char * ptr, int len){
if ( !len){ if ( !len){
return true; return true;
} //do not do empty sends } //do not do empty sends
@ -56,8 +66,10 @@ bool Buffer::user::doSend(const char * ptr, int len){
return (currsend == len); return (currsend == len);
} //doSend } //doSend
/// Try to send data to this user. Disconnects if any problems occur. ///\brief Try to send the current buffer.
bool Buffer::user::Send(){ ///
///\return True if the send was succesful, false otherwise.
bool user::Send(){
if ( !myRing){ if ( !myRing){
return false; return false;
} //no ring! } //no ring!
@ -116,15 +128,20 @@ bool Buffer::user::Send(){
return true; return true;
} //send } //send
/// Default constructor - should not be in use. ///\brief Default stats constructor.
Buffer::Stats::Stats(){ ///
///Should not be used.
Stats::Stats(){
up = 0; up = 0;
down = 0; down = 0;
conntime = 0; conntime = 0;
} }
///\brief Stats constructor reading a string.
///
///Reads a stats string and parses it to the internal representation. ///Reads a stats string and parses it to the internal representation.
Buffer::Stats::Stats(std::string s){ ///\param s The string of stats.
Stats::Stats(std::string s){
size_t f = s.find(' '); size_t f = s.find(' ');
if (f != std::string::npos){ if (f != std::string::npos){
host = s.substr(0, f); host = s.substr(0, f);
@ -147,3 +164,4 @@ Buffer::Stats::Stats(std::string s){
down = atoi(s.c_str()); down = atoi(s.c_str());
} }
} }
}