<commit_before>#include "models/profile.h"
#include <QDir>
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include "commands/commands.h"
#include "models/site.h"

Profile::Profile()
	: m_settings(nullptr), m_commands(nullptr)
{}
Profile::Profile(QSettings *settings, const QList<Favorite> &favorites, const QStringList &keptForLater, const QString &path)
	: m_path(path), m_settings(settings), m_favorites(favorites), m_keptForLater(keptForLater), m_commands(nullptr)
{}
Profile::Profile(const QString &path)
	: m_path(path)
{
	m_settings = new QSettings(m_path + "/settings.ini", QSettings::IniFormat);

	// Load sources
	QStringList dirs = QDir(m_path + "/sites/").entryList(QDir::Dirs | QDir::NoDotAndDotDot);
	for (const QString &dir : dirs)
	{
		Source *source = new Source(this, m_path + "/sites/" + dir);
		m_sources.insert(source->getName(), source);

		for (Site *site : source->getSites())
			m_sites.insert(site->url(), site);
	}

	// Load favorites
	QSet<QString> unique;
	QFile fileFavorites(m_path + "/favorites.txt");
	if (fileFavorites.open(QFile::ReadOnly | QFile::Text))
	{
		QString favs = fileFavorites.readAll();
		fileFavorites.close();

		QStringList words = favs.split("\n", QString::SkipEmptyParts);
		m_favorites.reserve(words.count());
		for (const QString &word : words)
		{
			Favorite fav = Favorite::fromString(m_path, word);
			if (!unique.contains(fav.getName()))
			{
				unique.insert(fav.getName());
				m_favorites.append(fav);
			}
		}
	}
	QFile fileFavoritesJson(m_path + "/favorites.json");
	if (fileFavoritesJson.open(QFile::ReadOnly | QFile::Text))
	{
		QByteArray data = fileFavoritesJson.readAll();
		QJsonDocument loadDoc = QJsonDocument::fromJson(data);
		QJsonObject object = loadDoc.object();

		QJsonArray favorites = object["favorites"].toArray();
		for (auto favoriteJson : favorites)
		{
			Favorite fav = Favorite::fromJson(m_path, favoriteJson.toObject(), m_sites);
			if (!unique.contains(fav.getName()))
			{
				unique.insert(fav.getName());
				m_favorites.append(fav);
			}
		}
	}

	// Load view it later
	QFile fileKfl(m_path + "/viewitlater.txt");
	if (fileKfl.open(QFile::ReadOnly | QFile::Text))
	{
		QString vil = fileKfl.readAll();
		fileKfl.close();

		m_keptForLater = vil.split("\n", QString::SkipEmptyParts);
	}

	// Load ignored
	QFile fileIgnored(m_path + "/ignore.txt");
	if (fileIgnored.open(QFile::ReadOnly | QFile::Text))
	{
		QString ign = fileIgnored.readAll();
		fileIgnored.close();

		m_ignored = ign.split("\n", QString::SkipEmptyParts);
	}

	// Load MD5s
	QFile fileMD5(m_path + "/md5s.txt");
	if (fileMD5.open(QFile::ReadOnly | QFile::Text))
	{
		QString line;
		while (!(line = fileMD5.readLine()).isEmpty())
			m_md5s.insert(line.left(32), line.mid(32).trimmed());

		fileMD5.close();
	}

	// Load auto-complete
	QFile fileAutoComplete(m_path + "/words.txt");
	if (fileAutoComplete.open(QFile::ReadOnly | QFile::Text))
	{
		QString line;
		while (!(line = fileAutoComplete.readLine()).isEmpty())
			m_autoComplete.append(line.trimmed().split(" ", QString::SkipEmptyParts));

		fileAutoComplete.close();
	}

	// Load custom auto-complete
	QFile fileCustomAutoComplete(m_path + "/wordsc.txt");
	if (fileCustomAutoComplete.open(QFile::ReadOnly | QFile::Text))
	{
		QString line;
		while (!(line = fileCustomAutoComplete.readLine()).isEmpty())
			m_customAutoComplete.append(line.trimmed().split(" ", QString::SkipEmptyParts));

		fileCustomAutoComplete.close();
	}

	m_commands = new Commands(this);

	// Blacklisted tags
	m_blacklistedTags = m_settings->value("blacklistedtags").toString().split(' ', QString::SkipEmptyParts);
}

Profile::~Profile()
{
	sync();

	if (m_settings != nullptr)
		m_settings->deleteLater();

	qDeleteAll(m_sources);
	delete m_commands;
}

void Profile::sync()
{
	if (m_path.isEmpty())
		return;

	syncFavorites();
	syncKeptForLater();
	syncIgnored();

	// MD5s
	QFile fileMD5(m_path + "/md5s.txt");
	if (fileMD5.open(QFile::WriteOnly | QFile::Truncate))
	{
		QStringList md5s = m_md5s.keys();
		QStringList paths = m_md5s.values();
		for (int i = 0; i < md5s.size(); i++)
			fileMD5.write(QString(md5s[i] + paths[i] + "\n").toUtf8());

		fileMD5.close();
	}

	// Custom auto-complete
	QFile fileCustomAutoComplete(m_path + "/wordsc.txt");
	if (fileCustomAutoComplete.open(QFile::WriteOnly | QFile::Text | QFile::Truncate))
	{
		fileCustomAutoComplete.write(m_customAutoComplete.join("\r\n").toUtf8());
		fileCustomAutoComplete.close();
	}

	// Update commands settings
	auto *oldCommands = m_commands;
	auto *newCommands = new Commands(this);
	m_commands = newCommands;
	delete oldCommands;

	// Blacklisted tags
	m_settings->setValue("blacklistedtags", m_blacklistedTags.join(' '));

	// Sync settings
	if (m_settings != nullptr)
		m_settings->sync();
}
void Profile::syncFavorites()
{
	QFile fileFavorites(m_path + "/favorites.json");
	if (fileFavorites.open(QFile::WriteOnly | QFile::Text | QFile::Truncate))
	{
		// Generate JSON array
		QJsonArray favoritesJson;
		for (const Favorite &fav : m_favorites)
		{
			QJsonObject unique;
			fav.toJson(unique);
			favoritesJson.append(unique);
		}

		// Generate result
		QJsonObject full;
		full["version"] = 1;
		full["favorites"] = favoritesJson;

		// Write result
		QJsonDocument saveDoc(full);
		fileFavorites.write(saveDoc.toJson());
		fileFavorites.close();
	}
	QFile::remove(m_path + "/favorites.txt");
}
void Profile::syncKeptForLater()
{
	QFile fileKfl(m_path + "/viewitlater.txt");
	if (fileKfl.open(QFile::WriteOnly | QFile::Text | QFile::Truncate))
	{
		fileKfl.write(m_keptForLater.join("\r\n").toUtf8());
		fileKfl.close();
	}
}
void Profile::syncIgnored()
{
	QFile fileIgnored(m_path + "/ignore.txt");
	if (fileIgnored.open(QFile::WriteOnly | QFile::Text | QFile::Truncate))
	{
		fileIgnored.write(m_ignored.join("\r\n").toUtf8());
		fileIgnored.close();
	}
}

QString Profile::tempPath() const
{
	QString tmp = QDir::tempPath();
	QString subDir = "Grabber";
	QDir(tmp).mkpath(subDir);
	return tmp + QDir::separator() + subDir;
}

void Profile::addFavorite(const Favorite &fav)
{
	m_favorites.removeAll(fav);
	m_favorites.append(fav);

	syncFavorites();
	emit favoritesChanged();
}
void Profile::removeFavorite(const Favorite &fav)
{
	m_favorites.removeAll(fav);

	if (QFile::exists(m_path + "/thumbs/" + fav.getName(true) + ".png"))
		QFile::remove(m_path + "/thumbs/" + fav.getName(true) + ".png");

	syncFavorites();
	emit favoritesChanged();
}
void Profile::emitFavorite()
{
	syncFavorites();
	emit favoritesChanged();
}

void Profile::addKeptForLater(const QString &tag)
{
	m_keptForLater.removeAll(tag);
	m_keptForLater.append(tag);

	syncKeptForLater();
	emit keptForLaterChanged();
}
void Profile::removeKeptForLater(const QString &tag)
{
	m_keptForLater.removeAll(tag);

	syncKeptForLater();
	emit keptForLaterChanged();
}

void Profile::addIgnored(const QString &tag)
{
	m_ignored.removeAll(tag);
	m_ignored.append(tag);

	syncIgnored();
	emit ignoredChanged();
}
void Profile::removeIgnored(const QString &tag)
{
	m_ignored.removeAll(tag);

	syncIgnored();
	emit ignoredChanged();
}

QPair<QString, QString> Profile::md5Action(const QString &md5)
{
	QString action = m_settings->value("Save/md5Duplicates", "save").toString();
	bool keepDeleted = m_settings->value("Save/keepDeletedMd5", false).toBool();

	bool contains = !md5.isEmpty() && m_md5s.contains(md5);
	QString path = contains ? m_md5s[md5] : QString();
	bool exists = contains && QFile::exists(path);

	if (contains && !exists)
	{
		if (!keepDeleted)
		{
			removeMd5(md5);
			path = QString();
		}
		else
		{ action = "ignore"; }
	}

	return QPair<QString, QString>(action, path);
}

/**
 * Check if a file with this md5 already exists;
 * @param	md5		The md5 that needs to be checked.
 * @return			A QString containing the path to the already existing file, an empty QString if the md5 does not already exists.
 */
QString Profile::md5Exists(const QString &md5)
{
	if (m_md5s.contains(md5))
	{
		if (QFile::exists(m_md5s[md5]))
			return m_md5s[md5];

		if (!m_settings->value("Save/keepDeletedMd5", false).toBool())
			removeMd5(md5);
	}
	return QString();
}

/**
 * Adds a md5 to the _md5 map and adds it to the md5 file.
 * @param	md5		The md5 to add.
 * @param	path	The path to the image with this md5.
 */
void Profile::addMd5(const QString &md5, const QString &path)
{
	if (!md5.isEmpty())
	{ m_md5s.insert(md5, path); }
}

/**
 * Set a md5 to the _md5 map changing the file it is pointing to.
 * @param	md5		The md5 to add.
 * @param	path	The path to the image with this md5.
 */
void Profile::setMd5(const QString &md5, const QString &path)
{
	m_md5s[md5] = path;
}

/**
 * Removes a md5 from the _md5 map and removes it from the md5 file.
 * @param	md5		The md5 to remove.
 */
void Profile::removeMd5(const QString &md5)
{
	m_md5s.remove(md5);
}

void Profile::addAutoComplete(const QString &tag)
{
	m_customAutoComplete.append(tag);
}

void Profile::addSite(Site *site)
{
	m_sites.insert(site->url(), site);
	emit sitesChanged();
}

void Profile::removeSite(Site *site)
{
	m_sites.remove(site->url());
	emit siteDeleted(site);
	emit sitesChanged();
}

void Profile::setBlacklistedTags(const QStringList &tags)
{
	m_blacklistedTags = tags;
	emit blacklistChanged();
}

void Profile::addBlacklistedTag(const QString &tag)
{
	m_blacklistedTags.append(tag);
	emit blacklistChanged();
}

void Profile::removeBlacklistedTag(const QString &tag)
{
	m_blacklistedTags.removeAll(tag);
	emit blacklistChanged();
}

QString Profile::getPath() const				{ return m_path;				}
QSettings *Profile::getSettings() const			{ return m_settings;			}
QList<Favorite> &Profile::getFavorites()		{ return m_favorites;			}
QStringList &Profile::getKeptForLater()			{ return m_keptForLater;		}
QStringList &Profile::getIgnored()				{ return m_ignored;				}
Commands &Profile::getCommands()				{ return *m_commands;			}
QStringList &Profile::getAutoComplete()			{ return m_autoComplete;		}
QStringList &Profile::getCustomAutoComplete()	{ return m_customAutoComplete;	}
QStringList &Profile::getBlacklist()			{ return m_blacklistedTags;		}
const QMap<QString, Source*> &Profile::getSources() const	{ return m_sources;	}
const QMap<QString, Site*> &Profile::getSites() const		{ return m_sites;	}

QList<Site*> Profile::getFilteredSites(const QStringList &urls) const
{
	QList<Site*> ret;
	for (const QString &url : urls)
		if (m_sites.contains(url))
			ret.append(m_sites.value(url));
	return ret;
}
<commit_msg>Keep favorites.txt after conversion in case of issues<commit_after>#include "models/profile.h"
#include <QDir>
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include "commands/commands.h"
#include "models/site.h"

Profile::Profile()
	: m_settings(nullptr), m_commands(nullptr)
{}
Profile::Profile(QSettings *settings, const QList<Favorite> &favorites, const QStringList &keptForLater, const QString &path)
	: m_path(path), m_settings(settings), m_favorites(favorites), m_keptForLater(keptForLater), m_commands(nullptr)
{}
Profile::Profile(const QString &path)
	: m_path(path)
{
	m_settings = new QSettings(m_path + "/settings.ini", QSettings::IniFormat);

	// Load sources
	QStringList dirs = QDir(m_path + "/sites/").entryList(QDir::Dirs | QDir::NoDotAndDotDot);
	for (const QString &dir : dirs)
	{
		Source *source = new Source(this, m_path + "/sites/" + dir);
		m_sources.insert(source->getName(), source);

		for (Site *site : source->getSites())
			m_sites.insert(site->url(), site);
	}

	// Load favorites
	QSet<QString> unique;
	QFile fileFavoritesJson(m_path + "/favorites.json");
	if (fileFavoritesJson.open(QFile::ReadOnly | QFile::Text))
	{
		QByteArray data = fileFavoritesJson.readAll();
		QJsonDocument loadDoc = QJsonDocument::fromJson(data);
		QJsonObject object = loadDoc.object();

		QJsonArray favorites = object["favorites"].toArray();
		for (auto favoriteJson : favorites)
		{
			Favorite fav = Favorite::fromJson(m_path, favoriteJson.toObject(), m_sites);
			if (!unique.contains(fav.getName()))
			{
				unique.insert(fav.getName());
				m_favorites.append(fav);
			}
		}
	}
	else
	{
		QFile fileFavorites(m_path + "/favorites.txt");
		if (fileFavorites.open(QFile::ReadOnly | QFile::Text))
		{
			QString favs = fileFavorites.readAll();
			fileFavorites.close();

			QStringList words = favs.split("\n", QString::SkipEmptyParts);
			m_favorites.reserve(words.count());
			for (const QString &word : words)
			{
				Favorite fav = Favorite::fromString(m_path, word);
				if (!unique.contains(fav.getName()))
				{
					unique.insert(fav.getName());
					m_favorites.append(fav);
				}
			}
		}
	}

	// Load view it later
	QFile fileKfl(m_path + "/viewitlater.txt");
	if (fileKfl.open(QFile::ReadOnly | QFile::Text))
	{
		QString vil = fileKfl.readAll();
		fileKfl.close();

		m_keptForLater = vil.split("\n", QString::SkipEmptyParts);
	}

	// Load ignored
	QFile fileIgnored(m_path + "/ignore.txt");
	if (fileIgnored.open(QFile::ReadOnly | QFile::Text))
	{
		QString ign = fileIgnored.readAll();
		fileIgnored.close();

		m_ignored = ign.split("\n", QString::SkipEmptyParts);
	}

	// Load MD5s
	QFile fileMD5(m_path + "/md5s.txt");
	if (fileMD5.open(QFile::ReadOnly | QFile::Text))
	{
		QString line;
		while (!(line = fileMD5.readLine()).isEmpty())
			m_md5s.insert(line.left(32), line.mid(32).trimmed());

		fileMD5.close();
	}

	// Load auto-complete
	QFile fileAutoComplete(m_path + "/words.txt");
	if (fileAutoComplete.open(QFile::ReadOnly | QFile::Text))
	{
		QString line;
		while (!(line = fileAutoComplete.readLine()).isEmpty())
			m_autoComplete.append(line.trimmed().split(" ", QString::SkipEmptyParts));

		fileAutoComplete.close();
	}

	// Load custom auto-complete
	QFile fileCustomAutoComplete(m_path + "/wordsc.txt");
	if (fileCustomAutoComplete.open(QFile::ReadOnly | QFile::Text))
	{
		QString line;
		while (!(line = fileCustomAutoComplete.readLine()).isEmpty())
			m_customAutoComplete.append(line.trimmed().split(" ", QString::SkipEmptyParts));

		fileCustomAutoComplete.close();
	}

	m_commands = new Commands(this);

	// Blacklisted tags
	m_blacklistedTags = m_settings->value("blacklistedtags").toString().split(' ', QString::SkipEmptyParts);
}

Profile::~Profile()
{
	sync();

	if (m_settings != nullptr)
		m_settings->deleteLater();

	qDeleteAll(m_sources);
	delete m_commands;
}

void Profile::sync()
{
	if (m_path.isEmpty())
		return;

	syncFavorites();
	syncKeptForLater();
	syncIgnored();

	// MD5s
	QFile fileMD5(m_path + "/md5s.txt");
	if (fileMD5.open(QFile::WriteOnly | QFile::Truncate))
	{
		QStringList md5s = m_md5s.keys();
		QStringList paths = m_md5s.values();
		for (int i = 0; i < md5s.size(); i++)
			fileMD5.write(QString(md5s[i] + paths[i] + "\n").toUtf8());

		fileMD5.close();
	}

	// Custom auto-complete
	QFile fileCustomAutoComplete(m_path + "/wordsc.txt");
	if (fileCustomAutoComplete.open(QFile::WriteOnly | QFile::Text | QFile::Truncate))
	{
		fileCustomAutoComplete.write(m_customAutoComplete.join("\r\n").toUtf8());
		fileCustomAutoComplete.close();
	}

	// Update commands settings
	auto *oldCommands = m_commands;
	auto *newCommands = new Commands(this);
	m_commands = newCommands;
	delete oldCommands;

	// Blacklisted tags
	m_settings->setValue("blacklistedtags", m_blacklistedTags.join(' '));

	// Sync settings
	if (m_settings != nullptr)
		m_settings->sync();
}
void Profile::syncFavorites()
{
	QFile fileFavorites(m_path + "/favorites.json");
	if (fileFavorites.open(QFile::WriteOnly | QFile::Text | QFile::Truncate))
	{
		// Generate JSON array
		QJsonArray favoritesJson;
		for (const Favorite &fav : m_favorites)
		{
			QJsonObject unique;
			fav.toJson(unique);
			favoritesJson.append(unique);
		}

		// Generate result
		QJsonObject full;
		full["version"] = 1;
		full["favorites"] = favoritesJson;

		// Write result
		QJsonDocument saveDoc(full);
		fileFavorites.write(saveDoc.toJson());
		fileFavorites.close();
	}
}
void Profile::syncKeptForLater()
{
	QFile fileKfl(m_path + "/viewitlater.txt");
	if (fileKfl.open(QFile::WriteOnly | QFile::Text | QFile::Truncate))
	{
		fileKfl.write(m_keptForLater.join("\r\n").toUtf8());
		fileKfl.close();
	}
}
void Profile::syncIgnored()
{
	QFile fileIgnored(m_path + "/ignore.txt");
	if (fileIgnored.open(QFile::WriteOnly | QFile::Text | QFile::Truncate))
	{
		fileIgnored.write(m_ignored.join("\r\n").toUtf8());
		fileIgnored.close();
	}
}

QString Profile::tempPath() const
{
	QString tmp = QDir::tempPath();
	QString subDir = "Grabber";
	QDir(tmp).mkpath(subDir);
	return tmp + QDir::separator() + subDir;
}

void Profile::addFavorite(const Favorite &fav)
{
	m_favorites.removeAll(fav);
	m_favorites.append(fav);

	syncFavorites();
	emit favoritesChanged();
}
void Profile::removeFavorite(const Favorite &fav)
{
	m_favorites.removeAll(fav);

	if (QFile::exists(m_path + "/thumbs/" + fav.getName(true) + ".png"))
		QFile::remove(m_path + "/thumbs/" + fav.getName(true) + ".png");

	syncFavorites();
	emit favoritesChanged();
}
void Profile::emitFavorite()
{
	syncFavorites();
	emit favoritesChanged();
}

void Profile::addKeptForLater(const QString &tag)
{
	m_keptForLater.removeAll(tag);
	m_keptForLater.append(tag);

	syncKeptForLater();
	emit keptForLaterChanged();
}
void Profile::removeKeptForLater(const QString &tag)
{
	m_keptForLater.removeAll(tag);

	syncKeptForLater();
	emit keptForLaterChanged();
}

void Profile::addIgnored(const QString &tag)
{
	m_ignored.removeAll(tag);
	m_ignored.append(tag);

	syncIgnored();
	emit ignoredChanged();
}
void Profile::removeIgnored(const QString &tag)
{
	m_ignored.removeAll(tag);

	syncIgnored();
	emit ignoredChanged();
}

QPair<QString, QString> Profile::md5Action(const QString &md5)
{
	QString action = m_settings->value("Save/md5Duplicates", "save").toString();
	bool keepDeleted = m_settings->value("Save/keepDeletedMd5", false).toBool();

	bool contains = !md5.isEmpty() && m_md5s.contains(md5);
	QString path = contains ? m_md5s[md5] : QString();
	bool exists = contains && QFile::exists(path);

	if (contains && !exists)
	{
		if (!keepDeleted)
		{
			removeMd5(md5);
			path = QString();
		}
		else
		{ action = "ignore"; }
	}

	return QPair<QString, QString>(action, path);
}

/**
 * Check if a file with this md5 already exists;
 * @param	md5		The md5 that needs to be checked.
 * @return			A QString containing the path to the already existing file, an empty QString if the md5 does not already exists.
 */
QString Profile::md5Exists(const QString &md5)
{
	if (m_md5s.contains(md5))
	{
		if (QFile::exists(m_md5s[md5]))
			return m_md5s[md5];

		if (!m_settings->value("Save/keepDeletedMd5", false).toBool())
			removeMd5(md5);
	}
	return QString();
}

/**
 * Adds a md5 to the _md5 map and adds it to the md5 file.
 * @param	md5		The md5 to add.
 * @param	path	The path to the image with this md5.
 */
void Profile::addMd5(const QString &md5, const QString &path)
{
	if (!md5.isEmpty())
	{ m_md5s.insert(md5, path); }
}

/**
 * Set a md5 to the _md5 map changing the file it is pointing to.
 * @param	md5		The md5 to add.
 * @param	path	The path to the image with this md5.
 */
void Profile::setMd5(const QString &md5, const QString &path)
{
	m_md5s[md5] = path;
}

/**
 * Removes a md5 from the _md5 map and removes it from the md5 file.
 * @param	md5		The md5 to remove.
 */
void Profile::removeMd5(const QString &md5)
{
	m_md5s.remove(md5);
}

void Profile::addAutoComplete(const QString &tag)
{
	m_customAutoComplete.append(tag);
}

void Profile::addSite(Site *site)
{
	m_sites.insert(site->url(), site);
	emit sitesChanged();
}

void Profile::removeSite(Site *site)
{
	m_sites.remove(site->url());
	emit siteDeleted(site);
	emit sitesChanged();
}

void Profile::setBlacklistedTags(const QStringList &tags)
{
	m_blacklistedTags = tags;
	emit blacklistChanged();
}

void Profile::addBlacklistedTag(const QString &tag)
{
	m_blacklistedTags.append(tag);
	emit blacklistChanged();
}

void Profile::removeBlacklistedTag(const QString &tag)
{
	m_blacklistedTags.removeAll(tag);
	emit blacklistChanged();
}

QString Profile::getPath() const				{ return m_path;				}
QSettings *Profile::getSettings() const			{ return m_settings;			}
QList<Favorite> &Profile::getFavorites()		{ return m_favorites;			}
QStringList &Profile::getKeptForLater()			{ return m_keptForLater;		}
QStringList &Profile::getIgnored()				{ return m_ignored;				}
Commands &Profile::getCommands()				{ return *m_commands;			}
QStringList &Profile::getAutoComplete()			{ return m_autoComplete;		}
QStringList &Profile::getCustomAutoComplete()	{ return m_customAutoComplete;	}
QStringList &Profile::getBlacklist()			{ return m_blacklistedTags;		}
const QMap<QString, Source*> &Profile::getSources() const	{ return m_sources;	}
const QMap<QString, Site*> &Profile::getSites() const		{ return m_sites;	}

QList<Site*> Profile::getFilteredSites(const QStringList &urls) const
{
	QList<Site*> ret;
	for (const QString &url : urls)
		if (m_sites.contains(url))
			ret.append(m_sites.value(url));
	return ret;
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/js_modal_dialog.h"

#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "ipc/ipc_message.h"

JavaScriptAppModalDialog::JavaScriptAppModalDialog(
    JavaScriptMessageBoxClient* client,
    const std::wstring& title,
    int dialog_flags,
    const std::wstring& message_text,
    const std::wstring& default_prompt_text,
    bool display_suppress_checkbox,
    bool is_before_unload_dialog,
    IPC::Message* reply_msg)
    : AppModalDialog(client->AsTabContents(), title),
      client_(client),
      extension_host_(client->AsExtensionHost()),
      dialog_flags_(dialog_flags),
      message_text_(message_text),
      default_prompt_text_(default_prompt_text),
      display_suppress_checkbox_(display_suppress_checkbox),
      is_before_unload_dialog_(is_before_unload_dialog),
      reply_msg_(reply_msg) {
  DCHECK((tab_contents_ != NULL) != (extension_host_ != NULL));
}

JavaScriptAppModalDialog::~JavaScriptAppModalDialog() {
}

void JavaScriptAppModalDialog::Observe(NotificationType type,
                                       const NotificationSource& source,
                                       const NotificationDetails& details) {
  if (skip_this_dialog_)
    return;

  if (NotificationType::EXTENSION_HOST_DESTROYED == type &&
      Details<ExtensionHost>(extension_host_) != details)
    return;

  // If we reach here, we know the notification is relevant to us, either
  // because we're only observing applicable sources or because we passed the
  // check above. Both of those indicate that we should ignore this dialog.
  // Also clear the client, since it's now invalid.
  skip_this_dialog_ = true;
  client_ = NULL;
  CloseModalDialog();
}

void JavaScriptAppModalDialog::InitNotifications() {
  // Make sure we get relevant navigation notifications so we know when our
  // parent contents will disappear or navigate to a different page.
  if (tab_contents_) {
    registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED,
                   Source<NavigationController>(&tab_contents_->controller()));
    registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED,
                   Source<TabContents>(tab_contents_));
  } else if (extension_host_) {
    // EXTENSION_HOST_DESTROYED uses the Profile as its source, but we care
    // about the ExtensionHost (which is passed in the details).
    registrar_.Add(this, NotificationType::EXTENSION_HOST_DESTROYED,
                   NotificationService::AllSources());
  } else {
    NOTREACHED();
  }
}

void JavaScriptAppModalDialog::OnCancel() {
  // We need to do this before WM_DESTROY (WindowClosing()) as any parent frame
  // will receive its activation messages before this dialog receives
  // WM_DESTROY. The parent frame would then try to activate any modal dialogs
  // that were still open in the ModalDialogQueue, which would send activation
  // back to this one. The framework should be improved to handle this, so this
  // is a temporary workaround.
  CompleteDialog();

  if (!skip_this_dialog_) {
    client_->OnMessageBoxClosed(reply_msg_, false, std::wstring());
  }

  Cleanup();
}

void JavaScriptAppModalDialog::OnAccept(const std::wstring& prompt_text,
                                        bool suppress_js_messages) {
  CompleteDialog();

  if (!skip_this_dialog_) {
    client_->OnMessageBoxClosed(reply_msg_, true, prompt_text);
    if (suppress_js_messages)
      client_->SetSuppressMessageBoxes(true);
  }

  Cleanup();
}

void JavaScriptAppModalDialog::OnClose() {
  Cleanup();
}

void JavaScriptAppModalDialog::Cleanup() {
  if (skip_this_dialog_) {
    // We can't use the client_, because we might be in the process of
    // destroying it.
    if (tab_contents_)
      tab_contents_->OnMessageBoxClosed(reply_msg_, false, L"");
// The extension_host_ will always be a dirty pointer on OS X because the alert
// window will cause the extension popup to close since it is resigning its key
// state, destroying the host. http://crbug.com/29355
#if !defined(OS_MACOSX)
    else if (extension_host_)
      extension_host_->OnMessageBoxClosed(reply_msg_, false, L"");
    else
      NOTREACHED();
#endif
  }
  AppModalDialog::Cleanup();
}

<commit_msg>Fixed regression due to refactoring change from http://codereview.chromium.org/560030/show<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/js_modal_dialog.h"

#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "ipc/ipc_message.h"

JavaScriptAppModalDialog::JavaScriptAppModalDialog(
    JavaScriptMessageBoxClient* client,
    const std::wstring& title,
    int dialog_flags,
    const std::wstring& message_text,
    const std::wstring& default_prompt_text,
    bool display_suppress_checkbox,
    bool is_before_unload_dialog,
    IPC::Message* reply_msg)
    : AppModalDialog(client->AsTabContents(), title),
      client_(client),
      extension_host_(client->AsExtensionHost()),
      dialog_flags_(dialog_flags),
      message_text_(message_text),
      default_prompt_text_(default_prompt_text),
      display_suppress_checkbox_(display_suppress_checkbox),
      is_before_unload_dialog_(is_before_unload_dialog),
      reply_msg_(reply_msg) {
  DCHECK((tab_contents_ != NULL) != (extension_host_ != NULL));
  InitNotifications();
}

JavaScriptAppModalDialog::~JavaScriptAppModalDialog() {
}

void JavaScriptAppModalDialog::Observe(NotificationType type,
                                       const NotificationSource& source,
                                       const NotificationDetails& details) {
  if (skip_this_dialog_)
    return;

  if (NotificationType::EXTENSION_HOST_DESTROYED == type &&
      Details<ExtensionHost>(extension_host_) != details)
    return;

  // If we reach here, we know the notification is relevant to us, either
  // because we're only observing applicable sources or because we passed the
  // check above. Both of those indicate that we should ignore this dialog.
  // Also clear the client, since it's now invalid.
  skip_this_dialog_ = true;
  client_ = NULL;
  CloseModalDialog();
}

void JavaScriptAppModalDialog::InitNotifications() {
  // Make sure we get relevant navigation notifications so we know when our
  // parent contents will disappear or navigate to a different page.
  if (tab_contents_) {
    registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED,
                   Source<NavigationController>(&tab_contents_->controller()));
    registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED,
                   Source<TabContents>(tab_contents_));
  } else if (extension_host_) {
    // EXTENSION_HOST_DESTROYED uses the Profile as its source, but we care
    // about the ExtensionHost (which is passed in the details).
    registrar_.Add(this, NotificationType::EXTENSION_HOST_DESTROYED,
                   NotificationService::AllSources());
  } else {
    NOTREACHED();
  }
}

void JavaScriptAppModalDialog::OnCancel() {
  // We need to do this before WM_DESTROY (WindowClosing()) as any parent frame
  // will receive its activation messages before this dialog receives
  // WM_DESTROY. The parent frame would then try to activate any modal dialogs
  // that were still open in the ModalDialogQueue, which would send activation
  // back to this one. The framework should be improved to handle this, so this
  // is a temporary workaround.
  CompleteDialog();

  if (!skip_this_dialog_) {
    client_->OnMessageBoxClosed(reply_msg_, false, std::wstring());
  }

  Cleanup();
}

void JavaScriptAppModalDialog::OnAccept(const std::wstring& prompt_text,
                                        bool suppress_js_messages) {
  CompleteDialog();

  if (!skip_this_dialog_) {
    client_->OnMessageBoxClosed(reply_msg_, true, prompt_text);
    if (suppress_js_messages)
      client_->SetSuppressMessageBoxes(true);
  }

  Cleanup();
}

void JavaScriptAppModalDialog::OnClose() {
  Cleanup();
}

void JavaScriptAppModalDialog::Cleanup() {
  if (skip_this_dialog_) {
    // We can't use the client_, because we might be in the process of
    // destroying it.
    if (tab_contents_)
      tab_contents_->OnMessageBoxClosed(reply_msg_, false, L"");
// The extension_host_ will always be a dirty pointer on OS X because the alert
// window will cause the extension popup to close since it is resigning its key
// state, destroying the host. http://crbug.com/29355
#if !defined(OS_MACOSX)
    else if (extension_host_)
      extension_host_->OnMessageBoxClosed(reply_msg_, false, L"");
    else
      NOTREACHED();
#endif
  }
  AppModalDialog::Cleanup();
}

<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/net/url_fetcher.h"

#include "base/compiler_specific.h"
#include "base/string_util.h"
#include "base/thread.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/net/url_request_context_getter.h"
#include "googleurl/src/gurl.h"
#include "net/base/load_flags.h"
#include "net/base/io_buffer.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"

static const int kBufferSize = 4096;

bool URLFetcher::g_interception_enabled = false;

class URLFetcher::Core
    : public base::RefCountedThreadSafe<URLFetcher::Core>,
      public URLRequest::Delegate {
 public:
  // For POST requests, set |content_type| to the MIME type of the content
  // and set |content| to the data to upload.  |flags| are flags to apply to
  // the load operation--these should be one or more of the LOAD_* flags
  // defined in url_request.h.
  Core(URLFetcher* fetcher,
       const GURL& original_url,
       RequestType request_type,
       URLFetcher::Delegate* d);

  // Starts the load.  It's important that this not happen in the constructor
  // because it causes the IO thread to begin AddRef()ing and Release()ing
  // us.  If our caller hasn't had time to fully construct us and take a
  // reference, the IO thread could interrupt things, run a task, Release()
  // us, and destroy us, leaving the caller with an already-destroyed object
  // when construction finishes.
  void Start();

  // Stops any in-progress load and ensures no callback will happen.  It is
  // safe to call this multiple times.
  void Stop();

  // URLRequest::Delegate implementations
  virtual void OnResponseStarted(URLRequest* request);
  virtual void OnReadCompleted(URLRequest* request, int bytes_read);

  URLFetcher::Delegate* delegate() const { return delegate_; }

 private:
  friend class base::RefCountedThreadSafe<URLFetcher::Core>;

  ~Core() {}

  // Wrapper functions that allow us to ensure actions happen on the right
  // thread.
  void StartURLRequest();
  void CancelURLRequest();
  void OnCompletedURLRequest(const URLRequestStatus& status);

  URLFetcher* fetcher_;              // Corresponding fetcher object
  GURL original_url_;                // The URL we were asked to fetch
  GURL url_;                         // The URL we eventually wound up at
  RequestType request_type_;         // What type of request is this?
  URLFetcher::Delegate* delegate_;   // Object to notify on completion
  MessageLoop* delegate_loop_;       // Message loop of the creating thread
  URLRequest* request_;              // The actual request this wraps
  int load_flags_;                   // Flags for the load operation
  int response_code_;                // HTTP status code for the request
  std::string data_;                 // Results of the request
  scoped_refptr<net::IOBuffer> buffer_;
                                     // Read buffer
  scoped_refptr<URLRequestContextGetter> request_context_getter_;
                                     // Cookie/cache info for the request
  ResponseCookies cookies_;          // Response cookies
  std::string extra_request_headers_;// Extra headers for the request, if any
  scoped_refptr<net::HttpResponseHeaders> response_headers_;

  std::string upload_content_;       // HTTP POST payload
  std::string upload_content_type_;  // MIME type of POST payload

  // The overload protection entry for this URL.  This is used to
  // incrementally back off how rapidly we'll send requests to a particular
  // URL, to avoid placing too much demand on the remote resource.  We update
  // this with the status of all requests as they return, and in turn use it
  // to determine how long to wait before making another request.
  URLFetcherProtectEntry* protect_entry_;
  // |num_retries_| indicates how many times we've failed to successfully
  // fetch this URL.  Once this value exceeds the maximum number of retries
  // specified by the protection manager, we'll give up.
  int num_retries_;

  friend class URLFetcher;
  DISALLOW_COPY_AND_ASSIGN(Core);
};

// static
URLFetcher::Factory* URLFetcher::factory_ = NULL;

URLFetcher::URLFetcher(const GURL& url,
                       RequestType request_type,
                       Delegate* d)
    : ALLOW_THIS_IN_INITIALIZER_LIST(
      core_(new Core(this, url, request_type, d))) {
}

URLFetcher::~URLFetcher() {
  core_->Stop();
}

// static
URLFetcher* URLFetcher::Create(int id, const GURL& url,
                               RequestType request_type, Delegate* d) {
  return factory_ ? factory_->CreateURLFetcher(id, url, request_type, d) :
                    new URLFetcher(url, request_type, d);
}

URLFetcher::Core::Core(URLFetcher* fetcher,
                       const GURL& original_url,
                       RequestType request_type,
                       URLFetcher::Delegate* d)
    : fetcher_(fetcher),
      original_url_(original_url),
      request_type_(request_type),
      delegate_(d),
      delegate_loop_(MessageLoop::current()),
      request_(NULL),
      load_flags_(net::LOAD_NORMAL),
      response_code_(-1),
      buffer_(new net::IOBuffer(kBufferSize)),
      protect_entry_(URLFetcherProtectManager::GetInstance()->Register(
          original_url_.host())),
      num_retries_(0) {
}

void URLFetcher::Core::Start() {
  DCHECK(delegate_loop_);
  DCHECK(request_context_getter_) << "We need an URLRequestContext!";
  ChromeThread::PostDelayedTask(
      ChromeThread::IO, FROM_HERE,
      NewRunnableMethod(this, &Core::StartURLRequest),
          protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SEND));
}

void URLFetcher::Core::Stop() {
  DCHECK_EQ(MessageLoop::current(), delegate_loop_);
  delegate_ = NULL;
  ChromeThread::PostTask(
      ChromeThread::IO, FROM_HERE,
      NewRunnableMethod(this, &Core::CancelURLRequest));
}

void URLFetcher::Core::OnResponseStarted(URLRequest* request) {
  DCHECK(request == request_);
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
  if (request_->status().is_success()) {
    response_code_ = request_->GetResponseCode();
    response_headers_ = request_->response_headers();
  }

  int bytes_read = 0;
  // Some servers may treat HEAD requests as GET requests.  To free up the
  // network connection as soon as possible, signal that the request has
  // completed immediately, without trying to read any data back (all we care
  // about is the response code and headers, which we already have).
  if (request_->status().is_success() && (request_type_ != HEAD))
    request_->Read(buffer_, kBufferSize, &bytes_read);
  OnReadCompleted(request_, bytes_read);
}

void URLFetcher::Core::OnReadCompleted(URLRequest* request, int bytes_read) {
  DCHECK(request == request_);
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));

  url_ = request->url();

  do {
    if (!request_->status().is_success() || bytes_read <= 0)
      break;
    data_.append(buffer_->data(), bytes_read);
  } while (request_->Read(buffer_, kBufferSize, &bytes_read));

  if (request_->status().is_success())
    request_->GetResponseCookies(&cookies_);

  // See comments re: HEAD requests in OnResponseStarted().
  if (!request_->status().is_io_pending() || (request_type_ == HEAD)) {
    delegate_loop_->PostTask(FROM_HERE, NewRunnableMethod(
        this, &Core::OnCompletedURLRequest, request_->status()));
    delete request_;
    request_ = NULL;
  }
}

void URLFetcher::Core::StartURLRequest() {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
  DCHECK(!request_);

  request_ = new URLRequest(original_url_, this);
  int flags = request_->load_flags() | load_flags_;
  if (!g_interception_enabled) {
    flags = flags | net::LOAD_DISABLE_INTERCEPT;
  }
  request_->set_load_flags(flags);
  request_->set_context(request_context_getter_->GetURLRequestContext());

  switch (request_type_) {
    case GET:
      break;

    case POST:
      DCHECK(!upload_content_.empty());
      DCHECK(!upload_content_type_.empty());

      request_->set_method("POST");
      if (!extra_request_headers_.empty())
        extra_request_headers_ += "\r\n";
      StringAppendF(&extra_request_headers_,
                    "Content-Type: %s", upload_content_type_.c_str());
      request_->AppendBytesToUpload(upload_content_.data(),
                                    static_cast<int>(upload_content_.size()));
      break;

    case HEAD:
      request_->set_method("HEAD");
      break;

    default:
      NOTREACHED();
  }

  if (!extra_request_headers_.empty())
    request_->SetExtraRequestHeaders(extra_request_headers_);

  request_->Start();
}

void URLFetcher::Core::CancelURLRequest() {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
  if (request_) {
    request_->Cancel();
    delete request_;
    request_ = NULL;
  }
  // Release the reference to the request context. There could be multiple
  // references to URLFetcher::Core at this point so it may take a while to
  // delete the object, but we cannot delay the destruction of the request
  // context.
  request_context_getter_ = NULL;
}

void URLFetcher::Core::OnCompletedURLRequest(const URLRequestStatus& status) {
  DCHECK(MessageLoop::current() == delegate_loop_);

  // Checks the response from server.
  if (response_code_ >= 500) {
    // When encountering a server error, we will send the request again
    // after backoff time.
    const int64 wait =
        protect_entry_->UpdateBackoff(URLFetcherProtectEntry::FAILURE);
    ++num_retries_;
    // Restarts the request if we still need to notify the delegate.
    if (delegate_) {
      if (num_retries_ <= protect_entry_->max_retries()) {
        ChromeThread::PostDelayedTask(
            ChromeThread::IO, FROM_HERE,
            NewRunnableMethod(this, &Core::StartURLRequest), wait);
      } else {
        delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_,
                                      cookies_, data_);
      }
    }
  } else {
    protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SUCCESS);
    if (delegate_)
      delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_,
                                    cookies_, data_);
  }
}

void URLFetcher::set_upload_data(const std::string& upload_content_type,
                     const std::string& upload_content) {
  core_->upload_content_type_ = upload_content_type;
  core_->upload_content_ = upload_content;
}

void URLFetcher::set_load_flags(int load_flags) {
  core_->load_flags_ = load_flags;
}

int URLFetcher::load_flags() const {
  return core_->load_flags_;
}

void URLFetcher::set_extra_request_headers(
    const std::string& extra_request_headers) {
  core_->extra_request_headers_ = extra_request_headers;
}

void URLFetcher::set_request_context(
    URLRequestContextGetter* request_context_getter) {
  core_->request_context_getter_ = request_context_getter;
}

net::HttpResponseHeaders* URLFetcher::response_headers() const {
  return core_->response_headers_;
}

void URLFetcher::Start() {
  core_->Start();
}

const GURL& URLFetcher::url() const {
  return core_->url_;
}

URLFetcher::Delegate* URLFetcher::delegate() const {
  return core_->delegate();
}
<commit_msg>Add instrumentation to track down a crash.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/net/url_fetcher.h"

#include "base/compiler_specific.h"
#include "base/string_util.h"
#include "base/thread.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/net/url_request_context_getter.h"
#include "googleurl/src/gurl.h"
#include "net/base/load_flags.h"
#include "net/base/io_buffer.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"

static const int kBufferSize = 4096;

bool URLFetcher::g_interception_enabled = false;

class URLFetcher::Core
    : public base::RefCountedThreadSafe<URLFetcher::Core>,
      public URLRequest::Delegate {
 public:
  // For POST requests, set |content_type| to the MIME type of the content
  // and set |content| to the data to upload.  |flags| are flags to apply to
  // the load operation--these should be one or more of the LOAD_* flags
  // defined in url_request.h.
  Core(URLFetcher* fetcher,
       const GURL& original_url,
       RequestType request_type,
       URLFetcher::Delegate* d);

  // Starts the load.  It's important that this not happen in the constructor
  // because it causes the IO thread to begin AddRef()ing and Release()ing
  // us.  If our caller hasn't had time to fully construct us and take a
  // reference, the IO thread could interrupt things, run a task, Release()
  // us, and destroy us, leaving the caller with an already-destroyed object
  // when construction finishes.
  void Start();

  // Stops any in-progress load and ensures no callback will happen.  It is
  // safe to call this multiple times.
  void Stop();

  // URLRequest::Delegate implementations
  virtual void OnResponseStarted(URLRequest* request);
  virtual void OnReadCompleted(URLRequest* request, int bytes_read);

  URLFetcher::Delegate* delegate() const { return delegate_; }

 private:
  friend class base::RefCountedThreadSafe<URLFetcher::Core>;

  ~Core() {}

  // Wrapper functions that allow us to ensure actions happen on the right
  // thread.
  void StartURLRequest();
  void CancelURLRequest();
  void OnCompletedURLRequest(const URLRequestStatus& status);

  URLFetcher* fetcher_;              // Corresponding fetcher object
  GURL original_url_;                // The URL we were asked to fetch
  GURL url_;                         // The URL we eventually wound up at
  RequestType request_type_;         // What type of request is this?
  URLFetcher::Delegate* delegate_;   // Object to notify on completion
  MessageLoop* delegate_loop_;       // Message loop of the creating thread
  URLRequest* request_;              // The actual request this wraps
  int load_flags_;                   // Flags for the load operation
  int response_code_;                // HTTP status code for the request
  std::string data_;                 // Results of the request
  scoped_refptr<net::IOBuffer> buffer_;
                                     // Read buffer
  scoped_refptr<URLRequestContextGetter> request_context_getter_;
                                     // Cookie/cache info for the request
  ResponseCookies cookies_;          // Response cookies
  std::string extra_request_headers_;// Extra headers for the request, if any
  scoped_refptr<net::HttpResponseHeaders> response_headers_;

  std::string upload_content_;       // HTTP POST payload
  std::string upload_content_type_;  // MIME type of POST payload

  // The overload protection entry for this URL.  This is used to
  // incrementally back off how rapidly we'll send requests to a particular
  // URL, to avoid placing too much demand on the remote resource.  We update
  // this with the status of all requests as they return, and in turn use it
  // to determine how long to wait before making another request.
  URLFetcherProtectEntry* protect_entry_;
  // |num_retries_| indicates how many times we've failed to successfully
  // fetch this URL.  Once this value exceeds the maximum number of retries
  // specified by the protection manager, we'll give up.
  int num_retries_;

  // Temporary member variable to test whether requests are being started
  // after they have already been cancelled.
  // TODO(eroman): Remove this after done investigating 27074.
  bool was_cancelled_;

  friend class URLFetcher;
  DISALLOW_COPY_AND_ASSIGN(Core);
};

// static
URLFetcher::Factory* URLFetcher::factory_ = NULL;

URLFetcher::URLFetcher(const GURL& url,
                       RequestType request_type,
                       Delegate* d)
    : ALLOW_THIS_IN_INITIALIZER_LIST(
      core_(new Core(this, url, request_type, d))) {
}

URLFetcher::~URLFetcher() {
  core_->Stop();
}

// static
URLFetcher* URLFetcher::Create(int id, const GURL& url,
                               RequestType request_type, Delegate* d) {
  return factory_ ? factory_->CreateURLFetcher(id, url, request_type, d) :
                    new URLFetcher(url, request_type, d);
}

URLFetcher::Core::Core(URLFetcher* fetcher,
                       const GURL& original_url,
                       RequestType request_type,
                       URLFetcher::Delegate* d)
    : fetcher_(fetcher),
      original_url_(original_url),
      request_type_(request_type),
      delegate_(d),
      delegate_loop_(MessageLoop::current()),
      request_(NULL),
      load_flags_(net::LOAD_NORMAL),
      response_code_(-1),
      buffer_(new net::IOBuffer(kBufferSize)),
      protect_entry_(URLFetcherProtectManager::GetInstance()->Register(
          original_url_.host())),
      num_retries_(0),
      was_cancelled_(false) {
}

void URLFetcher::Core::Start() {
  DCHECK(delegate_loop_);
  CHECK(request_context_getter_) << "We need an URLRequestContext!";
  ChromeThread::PostDelayedTask(
      ChromeThread::IO, FROM_HERE,
      NewRunnableMethod(this, &Core::StartURLRequest),
          protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SEND));
}

void URLFetcher::Core::Stop() {
  DCHECK_EQ(MessageLoop::current(), delegate_loop_);
  delegate_ = NULL;
  ChromeThread::PostTask(
      ChromeThread::IO, FROM_HERE,
      NewRunnableMethod(this, &Core::CancelURLRequest));
}

void URLFetcher::Core::OnResponseStarted(URLRequest* request) {
  DCHECK(request == request_);
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
  if (request_->status().is_success()) {
    response_code_ = request_->GetResponseCode();
    response_headers_ = request_->response_headers();
  }

  int bytes_read = 0;
  // Some servers may treat HEAD requests as GET requests.  To free up the
  // network connection as soon as possible, signal that the request has
  // completed immediately, without trying to read any data back (all we care
  // about is the response code and headers, which we already have).
  if (request_->status().is_success() && (request_type_ != HEAD))
    request_->Read(buffer_, kBufferSize, &bytes_read);
  OnReadCompleted(request_, bytes_read);
}

void URLFetcher::Core::OnReadCompleted(URLRequest* request, int bytes_read) {
  DCHECK(request == request_);
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));

  url_ = request->url();

  do {
    if (!request_->status().is_success() || bytes_read <= 0)
      break;
    data_.append(buffer_->data(), bytes_read);
  } while (request_->Read(buffer_, kBufferSize, &bytes_read));

  if (request_->status().is_success())
    request_->GetResponseCookies(&cookies_);

  // See comments re: HEAD requests in OnResponseStarted().
  if (!request_->status().is_io_pending() || (request_type_ == HEAD)) {
    delegate_loop_->PostTask(FROM_HERE, NewRunnableMethod(
        this, &Core::OnCompletedURLRequest, request_->status()));
    delete request_;
    request_ = NULL;
  }
}

void URLFetcher::Core::StartURLRequest() {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
  CHECK(!was_cancelled_);
  CHECK(request_context_getter_);
  CHECK(!request_);

  request_ = new URLRequest(original_url_, this);
  int flags = request_->load_flags() | load_flags_;
  if (!g_interception_enabled) {
    flags = flags | net::LOAD_DISABLE_INTERCEPT;
  }
  request_->set_load_flags(flags);
  request_->set_context(request_context_getter_->GetURLRequestContext());

  switch (request_type_) {
    case GET:
      break;

    case POST:
      DCHECK(!upload_content_.empty());
      DCHECK(!upload_content_type_.empty());

      request_->set_method("POST");
      if (!extra_request_headers_.empty())
        extra_request_headers_ += "\r\n";
      StringAppendF(&extra_request_headers_,
                    "Content-Type: %s", upload_content_type_.c_str());
      request_->AppendBytesToUpload(upload_content_.data(),
                                    static_cast<int>(upload_content_.size()));
      break;

    case HEAD:
      request_->set_method("HEAD");
      break;

    default:
      NOTREACHED();
  }

  if (!extra_request_headers_.empty())
    request_->SetExtraRequestHeaders(extra_request_headers_);

  request_->Start();
}

void URLFetcher::Core::CancelURLRequest() {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
  if (request_) {
    request_->Cancel();
    delete request_;
    request_ = NULL;
  }
  // Release the reference to the request context. There could be multiple
  // references to URLFetcher::Core at this point so it may take a while to
  // delete the object, but we cannot delay the destruction of the request
  // context.
  request_context_getter_ = NULL;
  was_cancelled_ = true;
}

void URLFetcher::Core::OnCompletedURLRequest(const URLRequestStatus& status) {
  DCHECK(MessageLoop::current() == delegate_loop_);

  // Checks the response from server.
  if (response_code_ >= 500) {
    // When encountering a server error, we will send the request again
    // after backoff time.
    const int64 wait =
        protect_entry_->UpdateBackoff(URLFetcherProtectEntry::FAILURE);
    ++num_retries_;
    // Restarts the request if we still need to notify the delegate.
    if (delegate_) {
      if (num_retries_ <= protect_entry_->max_retries()) {
        ChromeThread::PostDelayedTask(
            ChromeThread::IO, FROM_HERE,
            NewRunnableMethod(this, &Core::StartURLRequest), wait);
      } else {
        delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_,
                                      cookies_, data_);
      }
    }
  } else {
    protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SUCCESS);
    if (delegate_)
      delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_,
                                    cookies_, data_);
  }
}

void URLFetcher::set_upload_data(const std::string& upload_content_type,
                     const std::string& upload_content) {
  core_->upload_content_type_ = upload_content_type;
  core_->upload_content_ = upload_content;
}

void URLFetcher::set_load_flags(int load_flags) {
  core_->load_flags_ = load_flags;
}

int URLFetcher::load_flags() const {
  return core_->load_flags_;
}

void URLFetcher::set_extra_request_headers(
    const std::string& extra_request_headers) {
  core_->extra_request_headers_ = extra_request_headers;
}

void URLFetcher::set_request_context(
    URLRequestContextGetter* request_context_getter) {
  core_->request_context_getter_ = request_context_getter;
}

net::HttpResponseHeaders* URLFetcher::response_headers() const {
  return core_->response_headers_;
}

void URLFetcher::Start() {
  core_->Start();
}

const GURL& URLFetcher::url() const {
  return core_->url_;
}

URLFetcher::Delegate* URLFetcher::delegate() const {
  return core_->delegate();
}
<|endoftext|>


<commit_before>/*=========================================================================

Program:   Insight Segmentation & Registration Toolkit
Module:    itkGoodnessOfFitMixtureModelCostFunctionTest.cxx
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) 2002 Insight Consortium. All rights reserved.
See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "itkWin32Header.h"

#include <fstream>

#include "itkPoint.h"
#include "itkPointSet.h"
#include "itkArray.h"

#include "itkPointSetToListAdaptor.h"
#include "itkHistogram.h"
#include "itkSubsample.h"
#include "itkListSampleToHistogramFilter.h"
#include "itkGaussianGoodnessOfFitComponent.h"
#include "itkLogLikelihoodGoodnessOfFitFunction.h"
#include "itkNormalVariateGenerator.h"
#include "itkOnePlusOneEvolutionaryOptimizer.h"
#include "itkGoodnessOfFitMixtureModelCostFunction.h"

#define NO_OF_DIMENSIONS 2
typedef double ValueType ;

int itkGoodnessOfFitMixtureModelCostFunctionTest(int argc, char** argv)
{
  namespace stat = itk::Statistics ;

  if (argc < 2)
    {
      std::cout << "ERROR: data file name argument missing."
                << std::endl ;
      return EXIT_FAILURE;
    }

  int i ;
  char* dataFileName = argv[1] ;
  double minStandardDeviation =28.54746 ;

  std::vector< double > trueParams(6) ;
  trueParams[0] = 99.261 ;
  trueParams[1] = 100.078 ;
  trueParams[2] = 28.59448 ;
  trueParams[3] = 200.1 ;
  trueParams[4] = 201.3 ;
  trueParams[5] = 29.32210 ;

  std::vector< double > initialParams(6) ;
  initialParams[0] = 90.0 ;
  initialParams[1] = 90.0 ;
  initialParams[2] = 28.59448 ;
  //initialParams[2] = 15 ;
  initialParams[3] = 190.0 ;
  initialParams[4] = 190.0;
  initialParams[5] = 29.32210 ;
  //initialParams[5] = 15 ;

  std::vector< double > standardDeviations ;
  int maxIteration = 400 ;
  int dataSize = 2000 ;
  double histogramOverlap = 0.75 ;
  double histogramExtent = 1.5 ;
  double histogramUseEquiProbableBins = true ;
  float minimumGoodnessOfFitValue = -40 ;
  int numberOfClasses = 2 ;

  /* Loading point data */
  typedef itk::PointSet< double, 2 > PointSetType ;
  PointSetType::Pointer pointSet = PointSetType::New() ;
  PointSetType::PointsContainerPointer pointsContainer =
    PointSetType::PointsContainer::New() ;
  pointsContainer->Reserve(dataSize) ;
  pointSet->SetPoints(pointsContainer.GetPointer()) ;

  PointSetType::PointsContainerIterator p_iter = pointsContainer->Begin() ;
  PointSetType::PointType point ;
  double temp ;
  std::ifstream dataStream(dataFileName) ;
  if ( !dataStream )
    {
      std::cout << "ERROR: fail to open the data file." << std::endl ;
      return EXIT_FAILURE ;
    }

  while (p_iter != pointsContainer->End())
    {
      for ( i = 0 ; i < PointSetType::PointDimension ; i++)
        {
          dataStream >> temp ;
          point[i] = temp ;
        }
      p_iter.Value() = point ;
      ++p_iter ;
    }

  dataStream.close() ;

  /* Importing the point set to the sample */
  typedef stat::PointSetToListAdaptor< PointSetType >
    DataSampleType;

  DataSampleType::Pointer sample =
    DataSampleType::New() ;

  sample->SetPointSet(pointSet);

  /* =============================================== */
  typedef stat::GoodnessOfFitMixtureModelCostFunction< DataSampleType >
    CostFunctionType ;

  CostFunctionType::Pointer costFunction = CostFunctionType::New() ;

  //  costFunction->SetInputSample(histogram.GetPointer()) ;

  typedef stat::GaussianGoodnessOfFitComponent< DataSampleType >
    ComponentType ;

  std::vector< ComponentType::Pointer > components(numberOfClasses) ;

  for (int i = 0 ; i < numberOfClasses ; i++)
    {
      components[i] = ComponentType::New() ;
      components[i]->SetHistogramNumberOfBins(6) ;
      components[i]->SetHistogramExtent(histogramExtent) ;
      components[i]->SetInputSample(sample) ;

      costFunction->AddComponent(components[i].GetPointer()) ;
    }

  /* Initializing the goodness of fit function */
  typedef ComponentType::HistogramType ObservedHistogramType ;

  typedef stat::LogLikelihoodGoodnessOfFitFunction< ComponentType::HistogramType > FunctionType ;

  FunctionType::Pointer function = FunctionType::New() ;

  costFunction->SetFunction(function.GetPointer()) ;

  typedef stat::NormalVariateGenerator
    RandomVariateGeneratorType ;
  RandomVariateGeneratorType::Pointer randomGenerator =
    RandomVariateGeneratorType::New() ;
  randomGenerator->Initialize(3024) ;

  typedef itk::OnePlusOneEvolutionaryOptimizer
    OptimizerType ;

  unsigned int paramSize = costFunction->GetNumberOfParameters() ;
  CostFunctionType::ParametersType params(paramSize) ;

  for ( int i = 0 ; i < paramSize ; i++ )
    {
      params[i] = initialParams[i] ;
    }

  double initStepSize = 1.02 ;
  double grow = 1.05 ;
  double shrink = pow(grow, -0.25) ;
  OptimizerType::ScalesType scales(paramSize) ;
  scales.Fill(1.0) ;
  for ( int i = 0 ; i < paramSize ; i++)
    {
      if ( i % (NO_OF_DIMENSIONS + 1) == 2 )
        {
          scales[i] = 100.0 ;
        }
    }

  OptimizerType::Pointer optimizer = OptimizerType::New() ;
  optimizer->SetCostFunction(costFunction.GetPointer()) ;
  optimizer->Initialize(initStepSize, grow, shrink) ;
  optimizer->SetMaximumIteration(maxIteration) ;
  optimizer->SetNormalVariateGenerator(randomGenerator.GetPointer()) ;
  optimizer->SetInitialPosition(params) ;
  optimizer->SetScales(scales) ;
  optimizer->SetEpsilon(1.0e-6) ;

  /* Optimizing */
  optimizer->StartOptimization() ;

  std::cout << "DEBUG: current iteration = "
            << optimizer->GetCurrentIteration() << std::endl ;

  bool passed = true ;
  double displacement ;
  int paramIndex = 0 ;
  for (unsigned int i = 0 ; i < numberOfClasses ; i++)
    {
      std::cout << "Cluster[" << i << "]" << std::endl ;
      std::cout << "    Parameters:" << std::endl ;
      std::cout << "         " << (components[i])->GetFullParameters() << std::endl ;
      displacement = 0.0 ;
      for (unsigned int j = 0 ; j < DataSampleType::MeasurementVectorSize ;
           j++)
        {
          temp = (components[i])->GetFullParameters()[j] - trueParams[paramIndex] ;
          displacement += (temp * temp) ;
          paramIndex++ ;
        }
      paramIndex++ ;
      displacement = sqrt(displacement) ;
      std::cout << "    Mean displacement: " << std::endl ;
      std::cout << "        " << displacement
                << std::endl << std::endl ;
      if ( displacement > (minStandardDeviation / 100.0) * 10 )
        {
          passed = false ;
        }
    }

  if( !passed )
    {
      std::cout << "Test failed." << std::endl;
      return EXIT_FAILURE;
    }

  std::cout << "Test passed." << std::endl;
  return EXIT_SUCCESS;
}
<commit_msg><commit_after>/*=========================================================================

Program:   Insight Segmentation & Registration Toolkit
Module:    itkGoodnessOfFitMixtureModelCostFunctionTest.cxx
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) 2002 Insight Consortium. All rights reserved.
See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "itkWin32Header.h"

#include <fstream>

#include "itkPoint.h"
#include "itkPointSet.h"
#include "itkArray.h"

#include "itkPointSetToListAdaptor.h"
#include "itkHistogram.h"
#include "itkSubsample.h"
#include "itkListSampleToHistogramFilter.h"
#include "itkGaussianGoodnessOfFitComponent.h"
#include "itkLogLikelihoodGoodnessOfFitFunction.h"
#include "itkNormalVariateGenerator.h"
#include "itkOnePlusOneEvolutionaryOptimizer.h"
#include "itkGoodnessOfFitMixtureModelCostFunction.h"

#define NO_OF_DIMENSIONS 2
typedef double ValueType ;

int itkGoodnessOfFitMixtureModelCostFunctionTest(int argc, char** argv)
{
  namespace stat = itk::Statistics ;

  if (argc < 2)
    {
      std::cout << "ERROR: data file name argument missing."
                << std::endl ;
      return EXIT_FAILURE;
    }

  unsigned int i, j ;
  char* dataFileName = argv[1] ;
  double minStandardDeviation =28.54746 ;

  std::vector< double > trueParams(6) ;
  trueParams[0] = 99.261 ;
  trueParams[1] = 100.078 ;
  trueParams[2] = 28.59448 ;
  trueParams[3] = 200.1 ;
  trueParams[4] = 201.3 ;
  trueParams[5] = 29.32210 ;

  std::vector< double > initialParams(6) ;
  initialParams[0] = 90.0 ;
  initialParams[1] = 90.0 ;
  initialParams[2] = 28.59448 ;
  //initialParams[2] = 15 ;
  initialParams[3] = 190.0 ;
  initialParams[4] = 190.0;
  initialParams[5] = 29.32210 ;
  //initialParams[5] = 15 ;

  std::vector< double > standardDeviations ;
  int maxIteration = 400 ;
  int dataSize = 2000 ;
  double histogramOverlap = 0.75 ;
  unsigned int numberOfClasses = 2 ;

  /* Loading point data */
  typedef itk::PointSet< double, 2 > PointSetType ;
  PointSetType::Pointer pointSet = PointSetType::New() ;
  PointSetType::PointsContainerPointer pointsContainer =
    PointSetType::PointsContainer::New() ;
  pointsContainer->Reserve(dataSize) ;
  pointSet->SetPoints(pointsContainer.GetPointer()) ;

  PointSetType::PointsContainerIterator p_iter = pointsContainer->Begin() ;
  PointSetType::PointType point ;
  double temp ;
  std::ifstream dataStream(dataFileName) ;
  if ( !dataStream )
    {
      std::cout << "ERROR: fail to open the data file." << std::endl ;
      return EXIT_FAILURE ;
    }

  while (p_iter != pointsContainer->End())
    {
      for ( i = 0 ; i < PointSetType::PointDimension ; i++)
        {
          dataStream >> temp ;
          point[i] = temp ;
        }
      p_iter.Value() = point ;
      ++p_iter ;
    }

  dataStream.close() ;

  /* Importing the point set to the sample */
  typedef stat::PointSetToListAdaptor< PointSetType >
    DataSampleType;

  DataSampleType::Pointer sample =
    DataSampleType::New() ;

  sample->SetPointSet(pointSet);

  /* =============================================== */
  typedef stat::GoodnessOfFitMixtureModelCostFunction< DataSampleType >
    CostFunctionType ;

  CostFunctionType::Pointer costFunction = CostFunctionType::New() ;

  //  costFunction->SetInputSample(histogram.GetPointer()) ;

  typedef stat::GaussianGoodnessOfFitComponent< DataSampleType >
    ComponentType ;

  std::vector< ComponentType::Pointer > components(numberOfClasses) ;

  for (int i = 0 ; i < numberOfClasses ; i++)
    {
      components[i] = ComponentType::New() ;
      components[i]->SetHistogramNumberOfBins(6) ;
      components[i]->SetHistogramExtent(histogramExtent) ;
      components[i]->SetInputSample(sample) ;

      costFunction->AddComponent(components[i].GetPointer()) ;
    }

  /* Initializing the goodness of fit function */
  typedef ComponentType::HistogramType ObservedHistogramType ;

  typedef stat::LogLikelihoodGoodnessOfFitFunction< ComponentType::HistogramType > FunctionType ;

  FunctionType::Pointer function = FunctionType::New() ;

  costFunction->SetFunction(function.GetPointer()) ;

  typedef stat::NormalVariateGenerator
    RandomVariateGeneratorType ;
  RandomVariateGeneratorType::Pointer randomGenerator =
    RandomVariateGeneratorType::New() ;
  randomGenerator->Initialize(3024) ;

  typedef itk::OnePlusOneEvolutionaryOptimizer
    OptimizerType ;

  unsigned int paramSize = costFunction->GetNumberOfParameters() ;
  CostFunctionType::ParametersType params(paramSize) ;

  for ( i = 0 ; i < paramSize ; i++ )
    {
      params[i] = initialParams[i] ;
    }

  double initStepSize = 1.02 ;
  double grow = 1.05 ;
  double shrink = pow(grow, -0.25) ;
  OptimizerType::ScalesType scales(paramSize) ;
  scales.Fill(1.0) ;
  for ( i = 0 ; i < paramSize ; i++)
    {
      if ( i % (NO_OF_DIMENSIONS + 1) == 2 )
        {
          scales[i] = 100.0 ;
        }
    }

  OptimizerType::Pointer optimizer = OptimizerType::New() ;
  optimizer->SetCostFunction(costFunction.GetPointer()) ;
  optimizer->Initialize(initStepSize, grow, shrink) ;
  optimizer->SetMaximumIteration(maxIteration) ;
  optimizer->SetNormalVariateGenerator(randomGenerator.GetPointer()) ;
  optimizer->SetInitialPosition(params) ;
  optimizer->SetScales(scales) ;
  optimizer->SetEpsilon(1.0e-6) ;

  /* Optimizing */
  optimizer->StartOptimization() ;

  std::cout << "DEBUG: current iteration = "
            << optimizer->GetCurrentIteration() << std::endl ;

  bool passed = true ;
  double displacement ;
  int paramIndex = 0 ;
  for ( i = 0 ; i < numberOfClasses ; i++)
    {
      std::cout << "Cluster[" << i << "]" << std::endl ;
      std::cout << "    Parameters:" << std::endl ;
      std::cout << "         " << (components[i])->GetFullParameters() << std::endl ;
      displacement = 0.0 ;
      for ( j = 0 ; j < DataSampleType::MeasurementVectorSize ;
           j++)
        {
          temp = (components[i])->GetFullParameters()[j] - trueParams[paramIndex] ;
          displacement += (temp * temp) ;
          paramIndex++ ;
        }
      paramIndex++ ;
      displacement = sqrt(displacement) ;
      std::cout << "    Mean displacement: " << std::endl ;
      std::cout << "        " << displacement
                << std::endl << std::endl ;
      if ( displacement > (minStandardDeviation / 100.0) * 10 )
        {
          passed = false ;
        }
    }

  if( !passed )
    {
      std::cout << "Test failed." << std::endl;
      return EXIT_FAILURE;
    }

  std::cout << "Test passed." << std::endl;
  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/core/framework/allocator.h"

#include "tensorflow/core/framework/allocator_registry.h"
#include "tensorflow/core/framework/log_memory.h"
#include "tensorflow/core/framework/tracking_allocator.h"
#include "tensorflow/core/lib/strings/stringprintf.h"
#include "tensorflow/core/platform/mem.h"
#include "tensorflow/core/platform/mutex.h"
#include "tensorflow/core/platform/types.h"

namespace tensorflow {

void AllocatorStats::Clear() {
  this->num_allocs = 0;
  this->bytes_in_use = 0;
  this->max_bytes_in_use = 0;
  this->max_alloc_size = 0;
  this->bytes_limit = 0;
}

string AllocatorStats::DebugString() const {
  return strings::Printf(
      "Limit:        %20lld\n"
      "InUse:        %20lld\n"
      "MaxInUse:     %20lld\n"
      "NumAllocs:    %20lld\n"
      "MaxAllocSize: %20lld\n",
      this->bytes_limit, this->bytes_in_use, this->max_bytes_in_use,
      this->num_allocs, this->max_alloc_size);
}

constexpr size_t Allocator::kAllocatorAlignment;

Allocator::~Allocator() {}

void RunResourceCtor(ResourceHandle* p, size_t n) {
  for (size_t i = 0; i < n; ++p, ++i) new (p) ResourceHandle();
}

void RunResourceDtor(ResourceHandle* p, size_t n) {
  for (size_t i = 0; i < n; ++p, ++i) p->~ResourceHandle();
}

// If true, cpu allocator collects more stats.
static bool cpu_allocator_collect_stats = false;
// If true, cpu allocator collects full stats.
static bool cpu_allocator_collect_full_stats = false;

void EnableCPUAllocatorStats(bool enable) {
  cpu_allocator_collect_stats = enable;
}
void EnableCPUAllocatorFullStats(bool enable) {
  cpu_allocator_collect_full_stats = enable;
}

class CPUAllocator : public Allocator {
 public:
  CPUAllocator() {}

  ~CPUAllocator() override {}

  string Name() override { return "cpu"; }

  void* AllocateRaw(size_t alignment, size_t num_bytes) override {
    void* p = port::AlignedMalloc(num_bytes, alignment);
    if (cpu_allocator_collect_stats) {
      const std::size_t alloc_size = port::MallocExtension_GetAllocatedSize(p);
      mutex_lock l(mu_);
      ++stats_.num_allocs;
      stats_.bytes_in_use += alloc_size;
      stats_.max_bytes_in_use =
          std::max<int64>(stats_.max_bytes_in_use, stats_.bytes_in_use);
      stats_.max_alloc_size =
          std::max<int64>(stats_.max_alloc_size, alloc_size);
    }
    return p;
  }

  void DeallocateRaw(void* ptr) override {
    if (cpu_allocator_collect_stats) {
      const std::size_t alloc_size =
          port::MallocExtension_GetAllocatedSize(ptr);
      mutex_lock l(mu_);
      stats_.bytes_in_use -= alloc_size;
    }
    port::AlignedFree(ptr);
  }

  void GetStats(AllocatorStats* stats) override {
    mutex_lock l(mu_);
    *stats = stats_;
  }

  size_t AllocatedSizeSlow(void* ptr) override {
    return port::MallocExtension_GetAllocatedSize(ptr);
  }

 private:
  mutex mu_;
  AllocatorStats stats_ GUARDED_BY(mu_);

  TF_DISALLOW_COPY_AND_ASSIGN(CPUAllocator);
};

namespace {
Allocator* MakeCpuAllocator() {
  Allocator* allocator = new CPUAllocator;
  if (cpu_allocator_collect_full_stats || LogMemory::IsEnabled()) {
    allocator = new TrackingAllocator(allocator, true);
  }
  return allocator;
}
}  // namespace

Allocator* cpu_allocator() {
  static Allocator* cpu_alloc = AllocatorRegistry::Global()->GetAllocator();
  if (cpu_allocator_collect_full_stats && !cpu_alloc->TracksAllocationSizes()) {
    cpu_alloc = new TrackingAllocator(cpu_alloc, true);
  }
  return cpu_alloc;
}

REGISTER_MEM_ALLOCATOR("DefaultCPUAllocator", 100, CPUAllocator);

}  // namespace tensorflow
<commit_msg>remove unused cpu allocator factory<commit_after>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/core/framework/allocator.h"

#include "tensorflow/core/framework/allocator_registry.h"
#include "tensorflow/core/framework/log_memory.h"
#include "tensorflow/core/framework/tracking_allocator.h"
#include "tensorflow/core/lib/strings/stringprintf.h"
#include "tensorflow/core/platform/mem.h"
#include "tensorflow/core/platform/mutex.h"
#include "tensorflow/core/platform/types.h"

namespace tensorflow {

void AllocatorStats::Clear() {
  this->num_allocs = 0;
  this->bytes_in_use = 0;
  this->max_bytes_in_use = 0;
  this->max_alloc_size = 0;
  this->bytes_limit = 0;
}

string AllocatorStats::DebugString() const {
  return strings::Printf(
      "Limit:        %20lld\n"
      "InUse:        %20lld\n"
      "MaxInUse:     %20lld\n"
      "NumAllocs:    %20lld\n"
      "MaxAllocSize: %20lld\n",
      this->bytes_limit, this->bytes_in_use, this->max_bytes_in_use,
      this->num_allocs, this->max_alloc_size);
}

constexpr size_t Allocator::kAllocatorAlignment;

Allocator::~Allocator() {}

void RunResourceCtor(ResourceHandle* p, size_t n) {
  for (size_t i = 0; i < n; ++p, ++i) new (p) ResourceHandle();
}

void RunResourceDtor(ResourceHandle* p, size_t n) {
  for (size_t i = 0; i < n; ++p, ++i) p->~ResourceHandle();
}

// If true, cpu allocator collects more stats.
static bool cpu_allocator_collect_stats = false;
// If true, cpu allocator collects full stats.
static bool cpu_allocator_collect_full_stats = false;

void EnableCPUAllocatorStats(bool enable) {
  cpu_allocator_collect_stats = enable;
}
void EnableCPUAllocatorFullStats(bool enable) {
  cpu_allocator_collect_full_stats = enable;
}

class CPUAllocator : public Allocator {
 public:
  CPUAllocator() {}

  ~CPUAllocator() override {}

  string Name() override { return "cpu"; }

  void* AllocateRaw(size_t alignment, size_t num_bytes) override {
    void* p = port::AlignedMalloc(num_bytes, alignment);
    if (cpu_allocator_collect_stats) {
      const std::size_t alloc_size = port::MallocExtension_GetAllocatedSize(p);
      mutex_lock l(mu_);
      ++stats_.num_allocs;
      stats_.bytes_in_use += alloc_size;
      stats_.max_bytes_in_use =
          std::max<int64>(stats_.max_bytes_in_use, stats_.bytes_in_use);
      stats_.max_alloc_size =
          std::max<int64>(stats_.max_alloc_size, alloc_size);
    }
    return p;
  }

  void DeallocateRaw(void* ptr) override {
    if (cpu_allocator_collect_stats) {
      const std::size_t alloc_size =
          port::MallocExtension_GetAllocatedSize(ptr);
      mutex_lock l(mu_);
      stats_.bytes_in_use -= alloc_size;
    }
    port::AlignedFree(ptr);
  }

  void GetStats(AllocatorStats* stats) override {
    mutex_lock l(mu_);
    *stats = stats_;
  }

  size_t AllocatedSizeSlow(void* ptr) override {
    return port::MallocExtension_GetAllocatedSize(ptr);
  }

 private:
  mutex mu_;
  AllocatorStats stats_ GUARDED_BY(mu_);

  TF_DISALLOW_COPY_AND_ASSIGN(CPUAllocator);
};

Allocator* cpu_allocator() {
  static Allocator* cpu_alloc = AllocatorRegistry::Global()->GetAllocator();
  if (cpu_allocator_collect_full_stats && !cpu_alloc->TracksAllocationSizes()) {
    cpu_alloc = new TrackingAllocator(cpu_alloc, true);
  }
  return cpu_alloc;
}

REGISTER_MEM_ALLOCATOR("DefaultCPUAllocator", 100, CPUAllocator);

}  // namespace tensorflow
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#if defined(OS_WIN)
#include <windows.h>
#endif

#include "chrome/gpu/gpu_watchdog_thread.h"

#include "base/compiler_specific.h"
#include "build/build_config.h"

namespace {
const int64 kCheckPeriod = 2000;

void DoNothing() {
}
}

GpuWatchdogThread::GpuWatchdogThread(int timeout)
    : base::Thread("Watchdog"),
      watched_message_loop_(MessageLoop::current()),
      timeout_(timeout),
      armed_(false),
#if defined(OS_WIN)
      watched_thread_handle_(0),
      arm_time_(0),
#endif
      ALLOW_THIS_IN_INITIALIZER_LIST(task_observer_(this)) {
  DCHECK(timeout >= 0);

#if defined(OS_WIN)
  // GetCurrentThread returns a pseudo-handle that cannot be used by one thread
  // to identify another. DuplicateHandle creates a "real" handle that can be
  // used for this purpose.
  BOOL result = DuplicateHandle(GetCurrentProcess(),
                                GetCurrentThread(),
                                GetCurrentProcess(),
                                &watched_thread_handle_,
                                THREAD_QUERY_INFORMATION,
                                FALSE,
                                0);
  DCHECK(result);
#endif

  watched_message_loop_->AddTaskObserver(&task_observer_);
}

GpuWatchdogThread::~GpuWatchdogThread() {
  // Verify that the thread was explicitly stopped. If the thread is stopped
  // implicitly by the destructor, CleanUp() will not be called.
  DCHECK(!method_factory_.get());

#if defined(OS_WIN)
  CloseHandle(watched_thread_handle_);
#endif

  watched_message_loop_->RemoveTaskObserver(&task_observer_);
}

void GpuWatchdogThread::PostAcknowledge() {
  // Called on the monitored thread. Responds with OnAcknowledge. Cannot use
  // the method factory. Rely on reference counting instead.
  message_loop()->PostTask(
      FROM_HERE,
      NewRunnableMethod(this, &GpuWatchdogThread::OnAcknowledge));
}

void GpuWatchdogThread::Init() {
  // The method factory must be created on the watchdog thread.
  method_factory_.reset(new MethodFactory(this));

  // Schedule the first check.
  OnCheck();
}

void GpuWatchdogThread::CleanUp() {
  // The method factory must be destroyed on the watchdog thread.
  method_factory_->RevokeAll();
  method_factory_.reset();
}

GpuWatchdogThread::GpuWatchdogTaskObserver::GpuWatchdogTaskObserver(
    GpuWatchdogThread* watchdog)
  : watchdog_(watchdog) {
}

GpuWatchdogThread::GpuWatchdogTaskObserver::~GpuWatchdogTaskObserver() {
}

void GpuWatchdogThread::GpuWatchdogTaskObserver::WillProcessTask(
    const Task* task)
{
  CheckArmed();
}

void GpuWatchdogThread::GpuWatchdogTaskObserver::DidProcessTask(
    const Task* task)
{
  CheckArmed();
}

void GpuWatchdogThread::GpuWatchdogTaskObserver::CheckArmed()
{
  // Acknowledge the watchdog if it has armed itself. The watchdog will not
  // change its armed state until it is acknowledged.
  if (watchdog_->armed()) {
    watchdog_->PostAcknowledge();
  }
}

void GpuWatchdogThread::OnAcknowledge() {
  // The check has already been acknowledged and another has already been
  // scheduled by a previous call to OnAcknowledge. It is normal for a
  // watched thread to see armed_ being true multiple times before
  // the OnAcknowledge task is run on the watchdog thread.
  if (!armed_)
    return;

  // Revoke any pending OnExit.
  method_factory_->RevokeAll();
  armed_ = false;

  // The monitored thread has responded. Post a task to check it again.
  message_loop()->PostDelayedTask(
      FROM_HERE,
      method_factory_->NewRunnableMethod(&GpuWatchdogThread::OnCheck),
      kCheckPeriod);
}

#if defined(OS_WIN)
int64 GpuWatchdogThread::GetWatchedThreadTime() {
  FILETIME creation_time;
  FILETIME exit_time;
  FILETIME user_time;
  FILETIME kernel_time;
  BOOL result = GetThreadTimes(watched_thread_handle_,
                               &creation_time,
                               &exit_time,
                               &kernel_time,
                               &user_time);
  DCHECK(result);

  ULARGE_INTEGER user_time64;
  user_time64.HighPart = user_time.dwHighDateTime;
  user_time64.LowPart = user_time.dwLowDateTime;

  ULARGE_INTEGER kernel_time64;
  kernel_time64.HighPart = kernel_time.dwHighDateTime;
  kernel_time64.LowPart = kernel_time.dwLowDateTime;

  // Time is reported in units of 100 nanoseconds. Kernel and user time are
  // summed to deal with to kinds of hangs. One is where the GPU process is
  // stuck in user level, never calling into the kernel and kernel time is
  // not increasing. The other is where either the kernel hangs and never
  // returns to user level or where user level code
  // calls into kernel level repeatedly, giving up its quanta before it is
  // tracked, for example a loop that repeatedly Sleeps.
  return static_cast<int64>(
      (user_time64.QuadPart + kernel_time64.QuadPart) / 10000);
}
#endif

void GpuWatchdogThread::OnCheck() {
  if (armed_)
    return;

  // Must set armed before posting the task. This task might be the only task
  // that will activate the TaskObserver on the watched thread and it must not
  // miss the false -> true transition.
  armed_ = true;

#if defined(OS_WIN)
  arm_time_ = GetWatchedThreadTime();
#endif

  // Post a task to the monitored thread that does nothing but wake up the
  // TaskObserver. Any other tasks that are pending on the watched thread will
  // also wake up the observer. This simply ensures there is at least one.
  watched_message_loop_->PostTask(
      FROM_HERE,
      NewRunnableFunction(DoNothing));

  // Post a task to the watchdog thread to exit if the monitored thread does
  // not respond in time.
  message_loop()->PostDelayedTask(
      FROM_HERE,
      method_factory_->NewRunnableMethod(&GpuWatchdogThread::OnExit),
      timeout_);
}

// Use the --disable-gpu-watchdog command line switch to disable this.
void GpuWatchdogThread::OnExit() {
#if defined(OS_WIN)
  // Defer termination until a certain amount of user time has elapsed.
  int64 time_since_arm = GetWatchedThreadTime() - arm_time_;
  if (time_since_arm < timeout_) {
    message_loop()->PostDelayedTask(
        FROM_HERE,
        method_factory_->NewRunnableMethod(&GpuWatchdogThread::OnExit),
        timeout_ - time_since_arm);
    return;
  }
#endif

  // Make sure the timeout period is on the stack before crashing.
  volatile int timeout = timeout_;

  // For minimal developer annoyance, don't keep crashing.
  static bool crashed = false;
  if (crashed)
    return;

#if defined(OS_WIN)
  if (IsDebuggerPresent())
    return;
#endif

  LOG(ERROR) << "The GPU process hung. Restarting after "
             << timeout_ << " seconds.";

  volatile int* null_pointer = NULL;
  *null_pointer = timeout;

  crashed = true;
}
<commit_msg>Corrected GPU watchdog termination error message.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#if defined(OS_WIN)
#include <windows.h>
#endif

#include "chrome/gpu/gpu_watchdog_thread.h"

#include "base/compiler_specific.h"
#include "build/build_config.h"

namespace {
const int64 kCheckPeriod = 2000;

void DoNothing() {
}
}

GpuWatchdogThread::GpuWatchdogThread(int timeout)
    : base::Thread("Watchdog"),
      watched_message_loop_(MessageLoop::current()),
      timeout_(timeout),
      armed_(false),
#if defined(OS_WIN)
      watched_thread_handle_(0),
      arm_time_(0),
#endif
      ALLOW_THIS_IN_INITIALIZER_LIST(task_observer_(this)) {
  DCHECK(timeout >= 0);

#if defined(OS_WIN)
  // GetCurrentThread returns a pseudo-handle that cannot be used by one thread
  // to identify another. DuplicateHandle creates a "real" handle that can be
  // used for this purpose.
  BOOL result = DuplicateHandle(GetCurrentProcess(),
                                GetCurrentThread(),
                                GetCurrentProcess(),
                                &watched_thread_handle_,
                                THREAD_QUERY_INFORMATION,
                                FALSE,
                                0);
  DCHECK(result);
#endif

  watched_message_loop_->AddTaskObserver(&task_observer_);
}

GpuWatchdogThread::~GpuWatchdogThread() {
  // Verify that the thread was explicitly stopped. If the thread is stopped
  // implicitly by the destructor, CleanUp() will not be called.
  DCHECK(!method_factory_.get());

#if defined(OS_WIN)
  CloseHandle(watched_thread_handle_);
#endif

  watched_message_loop_->RemoveTaskObserver(&task_observer_);
}

void GpuWatchdogThread::PostAcknowledge() {
  // Called on the monitored thread. Responds with OnAcknowledge. Cannot use
  // the method factory. Rely on reference counting instead.
  message_loop()->PostTask(
      FROM_HERE,
      NewRunnableMethod(this, &GpuWatchdogThread::OnAcknowledge));
}

void GpuWatchdogThread::Init() {
  // The method factory must be created on the watchdog thread.
  method_factory_.reset(new MethodFactory(this));

  // Schedule the first check.
  OnCheck();
}

void GpuWatchdogThread::CleanUp() {
  // The method factory must be destroyed on the watchdog thread.
  method_factory_->RevokeAll();
  method_factory_.reset();
}

GpuWatchdogThread::GpuWatchdogTaskObserver::GpuWatchdogTaskObserver(
    GpuWatchdogThread* watchdog)
  : watchdog_(watchdog) {
}

GpuWatchdogThread::GpuWatchdogTaskObserver::~GpuWatchdogTaskObserver() {
}

void GpuWatchdogThread::GpuWatchdogTaskObserver::WillProcessTask(
    const Task* task)
{
  CheckArmed();
}

void GpuWatchdogThread::GpuWatchdogTaskObserver::DidProcessTask(
    const Task* task)
{
  CheckArmed();
}

void GpuWatchdogThread::GpuWatchdogTaskObserver::CheckArmed()
{
  // Acknowledge the watchdog if it has armed itself. The watchdog will not
  // change its armed state until it is acknowledged.
  if (watchdog_->armed()) {
    watchdog_->PostAcknowledge();
  }
}

void GpuWatchdogThread::OnAcknowledge() {
  // The check has already been acknowledged and another has already been
  // scheduled by a previous call to OnAcknowledge. It is normal for a
  // watched thread to see armed_ being true multiple times before
  // the OnAcknowledge task is run on the watchdog thread.
  if (!armed_)
    return;

  // Revoke any pending OnExit.
  method_factory_->RevokeAll();
  armed_ = false;

  // The monitored thread has responded. Post a task to check it again.
  message_loop()->PostDelayedTask(
      FROM_HERE,
      method_factory_->NewRunnableMethod(&GpuWatchdogThread::OnCheck),
      kCheckPeriod);
}

#if defined(OS_WIN)
int64 GpuWatchdogThread::GetWatchedThreadTime() {
  FILETIME creation_time;
  FILETIME exit_time;
  FILETIME user_time;
  FILETIME kernel_time;
  BOOL result = GetThreadTimes(watched_thread_handle_,
                               &creation_time,
                               &exit_time,
                               &kernel_time,
                               &user_time);
  DCHECK(result);

  ULARGE_INTEGER user_time64;
  user_time64.HighPart = user_time.dwHighDateTime;
  user_time64.LowPart = user_time.dwLowDateTime;

  ULARGE_INTEGER kernel_time64;
  kernel_time64.HighPart = kernel_time.dwHighDateTime;
  kernel_time64.LowPart = kernel_time.dwLowDateTime;

  // Time is reported in units of 100 nanoseconds. Kernel and user time are
  // summed to deal with to kinds of hangs. One is where the GPU process is
  // stuck in user level, never calling into the kernel and kernel time is
  // not increasing. The other is where either the kernel hangs and never
  // returns to user level or where user level code
  // calls into kernel level repeatedly, giving up its quanta before it is
  // tracked, for example a loop that repeatedly Sleeps.
  return static_cast<int64>(
      (user_time64.QuadPart + kernel_time64.QuadPart) / 10000);
}
#endif

void GpuWatchdogThread::OnCheck() {
  if (armed_)
    return;

  // Must set armed before posting the task. This task might be the only task
  // that will activate the TaskObserver on the watched thread and it must not
  // miss the false -> true transition.
  armed_ = true;

#if defined(OS_WIN)
  arm_time_ = GetWatchedThreadTime();
#endif

  // Post a task to the monitored thread that does nothing but wake up the
  // TaskObserver. Any other tasks that are pending on the watched thread will
  // also wake up the observer. This simply ensures there is at least one.
  watched_message_loop_->PostTask(
      FROM_HERE,
      NewRunnableFunction(DoNothing));

  // Post a task to the watchdog thread to exit if the monitored thread does
  // not respond in time.
  message_loop()->PostDelayedTask(
      FROM_HERE,
      method_factory_->NewRunnableMethod(&GpuWatchdogThread::OnExit),
      timeout_);
}

// Use the --disable-gpu-watchdog command line switch to disable this.
void GpuWatchdogThread::OnExit() {
#if defined(OS_WIN)
  // Defer termination until a certain amount of user time has elapsed.
  int64 time_since_arm = GetWatchedThreadTime() - arm_time_;
  if (time_since_arm < timeout_) {
    message_loop()->PostDelayedTask(
        FROM_HERE,
        method_factory_->NewRunnableMethod(&GpuWatchdogThread::OnExit),
        timeout_ - time_since_arm);
    return;
  }
#endif

  // Make sure the timeout period is on the stack before crashing.
  volatile int timeout = timeout_;

  // For minimal developer annoyance, don't keep crashing.
  static bool crashed = false;
  if (crashed)
    return;

#if defined(OS_WIN)
  if (IsDebuggerPresent())
    return;
#endif

  LOG(ERROR) << "The GPU process hung. Terminating after "
             << timeout_ << " ms.";

  volatile int* null_pointer = NULL;
  *null_pointer = timeout;

  crashed = true;
}
<|endoftext|>


<commit_before>// MaxDelaySensor.cc

#include "lib.h"
#include "MaxDelaySensor.h"
#include "DelaySensor.h"
#include "CommandOutput.h"
#include "StateSensor.h"

using namespace std;

MaxDelaySensor::MaxDelaySensor(DelaySensor * newDelay, StateSensor * newState,
        MinDelaySensor *newminDelay)
  : maximum(0, 0.01)
  , delay(newDelay)
  , state(newState)
  , mindelay(newminDelay)
{
}

void MaxDelaySensor::localSend(PacketInfo *)
{
}

void MaxDelaySensor::localAck(PacketInfo * packet)
{
  int current = delay->getLastDelay();
  /*
   * We assume that the minimum delay is transmission delay plus the
   * propagation delay. Thus, any additional time is from queueing.
   * Thus, queueingDelay = maxDelay - minDelay
   * BUT - the latency we feed to dummynet is the whole time spend in the
   * dummynet queue, so we have to include the 'forward' part of the min delay
   * in our calculation.
   */
  int minimumDelay = mindelay->getMinDelay();
  int queueingDelay = current - (minimumDelay/2);
  logWrite(SENSOR, "current=%d,min=%d,queueing=%d,saturated=%d", current,
           minimumDelay, queueingDelay, state->isSaturated());
  if (queueingDelay < 0) {
    logWrite(ERROR,"Queueing delay is less than zero!");
  }
  if (queueingDelay > maximum && current != 0) && state->isSaturated())
  {
    ostringstream buffer;
    buffer << "MAXINQ=" << queueingDelay;
    maximum.reset(queueingDelay);
    global::output->eventMessage(buffer.str(), packet->elab);
  }
  else
  {
    maximum.decay();
  }
}
<commit_msg>Fix a syntax error. I don't know how I let that one slip in!<commit_after>// MaxDelaySensor.cc

#include "lib.h"
#include "MaxDelaySensor.h"
#include "DelaySensor.h"
#include "CommandOutput.h"
#include "StateSensor.h"

using namespace std;

MaxDelaySensor::MaxDelaySensor(DelaySensor * newDelay, StateSensor * newState,
        MinDelaySensor *newminDelay)
  : maximum(0, 0.01)
  , delay(newDelay)
  , state(newState)
  , mindelay(newminDelay)
{
}

void MaxDelaySensor::localSend(PacketInfo *)
{
}

void MaxDelaySensor::localAck(PacketInfo * packet)
{
  int current = delay->getLastDelay();
  /*
   * We assume that the minimum delay is transmission delay plus the
   * propagation delay. Thus, any additional time is from queueing.
   * Thus, queueingDelay = maxDelay - minDelay
   * BUT - the latency we feed to dummynet is the whole time spend in the
   * dummynet queue, so we have to include the 'forward' part of the min delay
   * in our calculation.
   */
  int minimumDelay = mindelay->getMinDelay();
  int queueingDelay = current - (minimumDelay/2);
  logWrite(SENSOR, "current=%d,min=%d,queueing=%d,saturated=%d", current,
           minimumDelay, queueingDelay, state->isSaturated());
  if (queueingDelay < 0) {
    logWrite(ERROR,"Queueing delay is less than zero!");
  }
  if ((queueingDelay > maximum) && (current != 0) && state->isSaturated())
  {
    ostringstream buffer;
    buffer << "MAXINQ=" << queueingDelay;
    maximum.reset(queueingDelay);
    global::output->eventMessage(buffer.str(), packet->elab);
  }
  else
  {
    maximum.decay();
  }
}
<|endoftext|>