2015-04-13 04:09:02 -05:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
2015-03-12 09:18:35 -05:00
|
|
|
/*
|
|
|
|
* This file is part of the LibreOffice project.
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2015-05-28 04:53:14 -05:00
|
|
|
#include <cassert>
|
2015-05-28 10:39:05 -05:00
|
|
|
#include <cstdio>
|
2015-03-12 09:18:35 -05:00
|
|
|
#include <fstream>
|
|
|
|
#include <iostream>
|
|
|
|
#include <memory>
|
2015-05-05 06:57:51 -05:00
|
|
|
#include <string>
|
2015-03-12 09:18:35 -05:00
|
|
|
|
2015-05-28 10:39:05 -05:00
|
|
|
#include <Poco/DirectoryIterator.h>
|
2015-03-12 09:18:35 -05:00
|
|
|
#include <Poco/File.h>
|
|
|
|
#include <Poco/Path.h>
|
|
|
|
#include <Poco/SHA1Engine.h>
|
2015-05-28 04:53:14 -05:00
|
|
|
#include <Poco/StringTokenizer.h>
|
|
|
|
#include <Poco/Util/Application.h>
|
2015-03-12 09:18:35 -05:00
|
|
|
|
|
|
|
#include "TileCache.hpp"
|
|
|
|
|
2015-03-12 18:34:42 -05:00
|
|
|
TileCache::TileCache(const std::string& docURL) :
|
|
|
|
_docURL(docURL)
|
|
|
|
{
|
|
|
|
Poco::File dir(cacheDirName());
|
2015-03-12 09:18:35 -05:00
|
|
|
|
2015-04-30 13:09:56 -05:00
|
|
|
// TODO: Actually handle URLs (file: and http:), not file names.
|
2015-03-12 18:34:42 -05:00
|
|
|
if (dir.exists() && dir.isDirectory() && Poco::File(_docURL).exists() && Poco::File(_docURL).isFile())
|
|
|
|
{
|
|
|
|
if (getLastModified() != Poco::File(_docURL).getLastModified())
|
|
|
|
{
|
|
|
|
dir.remove(true);
|
|
|
|
}
|
2015-03-12 09:18:35 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-27 13:24:05 -05:00
|
|
|
std::unique_ptr<std::fstream> TileCache::lookupTile(int part, int width, int height, int tilePosX, int tilePosY, int tileWidth, int tileHeight)
|
2015-03-12 09:18:35 -05:00
|
|
|
{
|
2015-03-12 18:34:42 -05:00
|
|
|
std::string dirName = cacheDirName();
|
|
|
|
|
|
|
|
if (!Poco::File(dirName).exists() || !Poco::File(dirName).isDirectory())
|
|
|
|
return nullptr;
|
2015-03-12 09:18:35 -05:00
|
|
|
|
2015-04-27 13:24:05 -05:00
|
|
|
std::string fileName = dirName + "/" + cacheFileName(part, width, height, tilePosX, tilePosY, tileWidth, tileHeight);
|
2015-03-12 18:34:42 -05:00
|
|
|
|
|
|
|
std::unique_ptr<std::fstream> result(new std::fstream(fileName, std::ios::in));
|
2015-03-12 09:18:35 -05:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2015-04-27 13:24:05 -05:00
|
|
|
void TileCache::saveTile(int part, int width, int height, int tilePosX, int tilePosY, int tileWidth, int tileHeight, const char *data, size_t size)
|
2015-03-12 09:18:35 -05:00
|
|
|
{
|
2015-03-12 18:34:42 -05:00
|
|
|
std::string dirName = cacheDirName();
|
2015-03-12 09:18:35 -05:00
|
|
|
|
2015-03-12 18:34:42 -05:00
|
|
|
Poco::File(dirName).createDirectories();
|
2015-03-12 09:18:35 -05:00
|
|
|
|
2015-04-27 13:24:05 -05:00
|
|
|
std::string fileName = dirName + "/" + cacheFileName(part, width, height, tilePosX, tilePosY, tileWidth, tileHeight);
|
2015-03-13 07:17:51 -05:00
|
|
|
|
2015-03-12 18:34:42 -05:00
|
|
|
std::fstream outStream(fileName, std::ios::out);
|
2015-03-12 09:18:35 -05:00
|
|
|
outStream.write(data, size);
|
|
|
|
outStream.close();
|
2015-03-12 18:34:42 -05:00
|
|
|
|
2015-04-30 13:09:56 -05:00
|
|
|
// TODO: Actually handle URLs (file: and http:), not file names.
|
|
|
|
if (!Poco::File(_docURL).exists() || !Poco::File(_docURL).isFile())
|
|
|
|
return;
|
2015-03-12 18:34:42 -05:00
|
|
|
std::fstream modTimeFile(dirName + "/modtime.txt", std::ios::out);
|
|
|
|
modTimeFile << Poco::File(_docURL).getLastModified().raw() << std::endl;
|
|
|
|
modTimeFile.close();
|
|
|
|
}
|
|
|
|
|
2015-03-13 07:17:51 -05:00
|
|
|
std::string TileCache::getStatus()
|
|
|
|
{
|
|
|
|
std::string dirName = cacheDirName();
|
|
|
|
|
|
|
|
if (!Poco::File(dirName).exists() || !Poco::File(dirName).isDirectory())
|
2015-03-16 14:08:07 -05:00
|
|
|
return "";
|
2015-03-13 07:17:51 -05:00
|
|
|
|
|
|
|
std::string fileName = dirName + "/status.txt";
|
|
|
|
std::fstream statusStream(fileName, std::ios::in);
|
|
|
|
if (!statusStream.is_open())
|
|
|
|
return "";
|
2015-03-16 14:08:07 -05:00
|
|
|
|
2015-03-13 07:17:51 -05:00
|
|
|
std::vector<char> result;
|
|
|
|
statusStream.seekg(0, std::ios_base::end);
|
|
|
|
std::streamsize size = statusStream.tellg();
|
|
|
|
result.resize(size);
|
|
|
|
statusStream.seekg(0, std::ios_base::beg);
|
|
|
|
statusStream.read(result.data(), size);
|
|
|
|
statusStream.close();
|
|
|
|
|
|
|
|
if (result[result.size()-1] == '\n')
|
|
|
|
result.resize(result.size() - 1);
|
2015-03-16 14:08:07 -05:00
|
|
|
|
2015-03-13 07:17:51 -05:00
|
|
|
return std::string(result.data(), result.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
void TileCache::saveStatus(const std::string& status)
|
|
|
|
{
|
|
|
|
std::string dirName = cacheDirName();
|
|
|
|
|
|
|
|
Poco::File(dirName).createDirectories();
|
|
|
|
|
2015-05-28 04:53:14 -05:00
|
|
|
Poco::StringTokenizer tokens(status, " ", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM);
|
|
|
|
|
|
|
|
assert(tokens[0] == "status:");
|
|
|
|
|
2015-03-13 07:17:51 -05:00
|
|
|
std::string fileName = dirName + "/status.txt";
|
|
|
|
std::fstream statusStream(fileName, std::ios::out);
|
2015-03-16 14:08:07 -05:00
|
|
|
|
2015-03-13 07:17:51 -05:00
|
|
|
if (!statusStream.is_open())
|
|
|
|
return;
|
|
|
|
|
|
|
|
statusStream << status << std::endl;
|
|
|
|
statusStream.close();
|
|
|
|
}
|
|
|
|
|
2015-05-28 10:39:05 -05:00
|
|
|
void TileCache::invalidateTiles(int part, int x, int y, int width, int height)
|
|
|
|
{
|
|
|
|
std::string dirName = cacheDirName();
|
|
|
|
|
|
|
|
std::vector<std::string> toBeRemoved;
|
|
|
|
|
|
|
|
for (auto tileIterator = Poco::DirectoryIterator(dirName); tileIterator != Poco::DirectoryIterator(); ++tileIterator)
|
|
|
|
{
|
|
|
|
std::string baseName = tileIterator.path().getBaseName();
|
|
|
|
|
|
|
|
int tilePart, tilePixelWidth, tilePixelHeight, tilePosX, tilePosY, tileWidth, tileHeight;
|
|
|
|
|
|
|
|
if (parseCacheFileName(baseName, tilePart, tilePixelWidth, tilePixelHeight, tilePosX, tilePosY, tileWidth, tileHeight))
|
|
|
|
{
|
|
|
|
std::cout << "Tile " << baseName << " is " << tileWidth << "x" << tileHeight << "@+" << tilePosX << "+" << tilePosY << std::endl;
|
|
|
|
if (tilePart == part &&
|
|
|
|
tilePosX < x + width && tilePosX + tileWidth >= x &&
|
|
|
|
tilePosY < y + height && tilePosY + tileHeight >= y)
|
|
|
|
{
|
|
|
|
std::cout << "Match!" << std::endl;
|
|
|
|
toBeRemoved.push_back(tileIterator.path().toString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto i: toBeRemoved)
|
|
|
|
std::remove(i.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
void TileCache::invalidateTiles(int part, const std::string& tiles)
|
|
|
|
{
|
|
|
|
Poco::StringTokenizer tokens(tiles, " ", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM);
|
|
|
|
|
2015-05-28 15:22:27 -05:00
|
|
|
assert(tokens[0] == "invalidatetiles:");
|
2015-05-28 10:39:05 -05:00
|
|
|
|
|
|
|
if (tokens.count() != 5)
|
|
|
|
return;
|
|
|
|
|
|
|
|
int width(std::stoi(tokens[1]));
|
|
|
|
int height(std::stoi(tokens[2]));
|
|
|
|
int x(std::stoi(tokens[3]));
|
|
|
|
int y(std::stoi(tokens[4]));
|
|
|
|
|
|
|
|
invalidateTiles(part, x, y, width, height);
|
|
|
|
}
|
|
|
|
|
2015-03-12 18:34:42 -05:00
|
|
|
std::string TileCache::cacheDirName()
|
|
|
|
{
|
|
|
|
Poco::SHA1Engine digestEngine;
|
|
|
|
|
|
|
|
digestEngine.update(_docURL.c_str(), _docURL.size());
|
|
|
|
|
|
|
|
return (LOOLWSD_CACHEDIR "/" +
|
|
|
|
Poco::DigestEngine::digestToHex(digestEngine.digest()).insert(3, "/").insert(2, "/").insert(1, "/"));
|
|
|
|
}
|
|
|
|
|
2015-04-27 13:24:05 -05:00
|
|
|
std::string TileCache::cacheFileName(int part, int width, int height, int tilePosX, int tilePosY, int tileWidth, int tileHeight)
|
2015-03-12 18:34:42 -05:00
|
|
|
{
|
2015-04-27 13:24:05 -05:00
|
|
|
return (std::to_string(part) + "_" +
|
|
|
|
std::to_string(width) + "x" + std::to_string(height) + "." +
|
2015-03-12 18:34:42 -05:00
|
|
|
std::to_string(tilePosX) + "," + std::to_string(tilePosY) + "." +
|
|
|
|
std::to_string(tileWidth) + "x" + std::to_string(tileHeight) + ".png");
|
|
|
|
}
|
|
|
|
|
2015-05-28 10:39:05 -05:00
|
|
|
bool TileCache::parseCacheFileName(std::string& fileName, int& part, int& width, int& height, int& tilePosX, int& tilePosY, int& tileWidth, int& tileHeight)
|
|
|
|
{
|
|
|
|
return (std::sscanf(fileName.c_str(), "%d_%dx%d.%d,%d.%dx%d", &part, &width, &height, &tilePosX, &tilePosY, &tileWidth, &tileHeight) == 7);
|
|
|
|
}
|
|
|
|
|
2015-03-12 18:34:42 -05:00
|
|
|
Poco::Timestamp TileCache::getLastModified()
|
|
|
|
{
|
|
|
|
std::fstream modTimeFile(cacheDirName() + "/modtime.txt", std::ios::in);
|
|
|
|
|
|
|
|
if (!modTimeFile.is_open())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
Poco::Timestamp::TimeVal result;
|
|
|
|
modTimeFile >> result;
|
|
|
|
|
|
|
|
modTimeFile.close();
|
|
|
|
return result;
|
2015-03-12 09:18:35 -05:00
|
|
|
}
|
|
|
|
|
2015-03-12 18:34:42 -05:00
|
|
|
|
2015-03-12 09:18:35 -05:00
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|