diff options
Diffstat (limited to 'dom/system/gonk/mozstumbler/WriteStumbleOnThread.cpp')
-rw-r--r-- | dom/system/gonk/mozstumbler/WriteStumbleOnThread.cpp | 321 |
1 files changed, 0 insertions, 321 deletions
diff --git a/dom/system/gonk/mozstumbler/WriteStumbleOnThread.cpp b/dom/system/gonk/mozstumbler/WriteStumbleOnThread.cpp deleted file mode 100644 index e58e771c4d..0000000000 --- a/dom/system/gonk/mozstumbler/WriteStumbleOnThread.cpp +++ /dev/null @@ -1,321 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* 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 "WriteStumbleOnThread.h" -#include "StumblerLogging.h" -#include "UploadStumbleRunnable.h" -#include "nsDumpUtils.h" -#include "nsGZFileWriter.h" -#include "nsIFileStreams.h" -#include "nsIInputStream.h" -#include "nsPrintfCString.h" - -#define MAXFILESIZE_KB (15 * 1024) -#define ONEDAY_IN_MSEC (24 * 60 * 60 * 1000) -#define MAX_UPLOAD_ATTEMPTS 20 - -mozilla::Atomic<bool> WriteStumbleOnThread::sIsFileWaitingForUpload(false); -mozilla::Atomic<bool> WriteStumbleOnThread::sIsAlreadyRunning(false); -WriteStumbleOnThread::UploadFreqGuard WriteStumbleOnThread::sUploadFreqGuard = {0}; - -#define FILENAME_INPROGRESS NS_LITERAL_CSTRING("stumbles.json.gz") -#define FILENAME_COMPLETED NS_LITERAL_CSTRING("stumbles.done.json.gz") -#define OUTPUT_DIR NS_LITERAL_CSTRING("mozstumbler") - -class DeleteRunnable : public Runnable -{ - public: - DeleteRunnable() {} - - NS_IMETHOD - Run() override - { - nsCOMPtr<nsIFile> tmpFile; - nsresult rv = nsDumpUtils::OpenTempFile(FILENAME_COMPLETED, - getter_AddRefs(tmpFile), - OUTPUT_DIR, - nsDumpUtils::CREATE); - if (NS_SUCCEEDED(rv)) { - tmpFile->Remove(true); - } - // critically, this sets this flag to false so writing can happen again - WriteStumbleOnThread::sIsAlreadyRunning = false; - WriteStumbleOnThread::sIsFileWaitingForUpload = false; - return NS_OK; - } - - private: - ~DeleteRunnable() {} -}; - -bool -WriteStumbleOnThread::IsFileWaitingForUpload() -{ - return sIsFileWaitingForUpload; -} - -void -WriteStumbleOnThread::UploadEnded(bool deleteUploadFile) -{ - if (!deleteUploadFile) { - sIsAlreadyRunning = false; - return; - } - - nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID); - MOZ_ASSERT(target); - nsCOMPtr<nsIRunnable> event = new DeleteRunnable(); - target->Dispatch(event, NS_DISPATCH_NORMAL); -} - -void -WriteStumbleOnThread::WriteJSON(Partition aPart) -{ - MOZ_ASSERT(!NS_IsMainThread()); - - nsCOMPtr<nsIFile> tmpFile; - nsresult rv; - rv = nsDumpUtils::OpenTempFile(FILENAME_INPROGRESS, getter_AddRefs(tmpFile), - OUTPUT_DIR, nsDumpUtils::CREATE); - if (NS_WARN_IF(NS_FAILED(rv))) { - STUMBLER_ERR("Open a file for stumble failed"); - return; - } - - RefPtr<nsGZFileWriter> gzWriter = new nsGZFileWriter(nsGZFileWriter::Append); - rv = gzWriter->Init(tmpFile); - if (NS_WARN_IF(NS_FAILED(rv))) { - STUMBLER_ERR("gzWriter init failed"); - return; - } - - /* - The json format is like below. - {items:[ - {item}, - {item}, - {item} - ]} - */ - - // Need to add "]}" after the last item - if (aPart == Partition::End) { - rv = gzWriter->Write("]}"); - if (NS_WARN_IF(NS_FAILED(rv))) { - STUMBLER_ERR("gzWriter Write failed"); - } - - rv = gzWriter->Finish(); - if (NS_WARN_IF(NS_FAILED(rv))) { - STUMBLER_ERR("ostream finish failed"); - } - - nsCOMPtr<nsIFile> targetFile; - nsresult rv = nsDumpUtils::OpenTempFile(FILENAME_COMPLETED, getter_AddRefs(targetFile), - OUTPUT_DIR, nsDumpUtils::CREATE); - nsAutoString targetFilename; - rv = targetFile->GetLeafName(targetFilename); - if (NS_WARN_IF(NS_FAILED(rv))) { - STUMBLER_ERR("Get Filename failed"); - return; - } - rv = targetFile->Remove(true); - if (NS_WARN_IF(NS_FAILED(rv))) { - STUMBLER_ERR("Remove File failed"); - return; - } - // Rename tmpfile - rv = tmpFile->MoveTo(/* directory */ nullptr, targetFilename); - if (NS_WARN_IF(NS_FAILED(rv))) { - STUMBLER_ERR("Rename File failed"); - return; - } - return; - } - - // Need to add "{items:[" before the first item - if (aPart == Partition::Begining) { - rv = gzWriter->Write("{\"items\":[{"); - if (NS_WARN_IF(NS_FAILED(rv))) { - STUMBLER_ERR("ostream write begining failed"); - } - } else if (aPart == Partition::Middle) { - rv = gzWriter->Write(",{"); - if (NS_WARN_IF(NS_FAILED(rv))) { - STUMBLER_ERR("ostream write middle failed"); - } - } - rv = gzWriter->Write(mDesc.get()); - if (NS_WARN_IF(NS_FAILED(rv))) { - STUMBLER_ERR("ostream write mDesc failed"); - } - // one item is ended with '}' (e.g. {item}) - rv = gzWriter->Write("}"); - if (NS_WARN_IF(NS_FAILED(rv))) { - STUMBLER_ERR("ostream write end failed"); - } - - rv = gzWriter->Finish(); - if (NS_WARN_IF(NS_FAILED(rv))) { - STUMBLER_ERR("ostream finish failed"); - } - - // check if it is the end of this file - int64_t fileSize = 0; - rv = tmpFile->GetFileSize(&fileSize); - if (NS_WARN_IF(NS_FAILED(rv))) { - STUMBLER_ERR("GetFileSize failed"); - return; - } - if (fileSize >= MAXFILESIZE_KB) { - WriteJSON(Partition::End); - return; - } -} - -WriteStumbleOnThread::Partition -WriteStumbleOnThread::GetWritePosition() -{ - MOZ_ASSERT(!NS_IsMainThread()); - - nsCOMPtr<nsIFile> tmpFile; - nsresult rv = nsDumpUtils::OpenTempFile(FILENAME_INPROGRESS, getter_AddRefs(tmpFile), - OUTPUT_DIR, nsDumpUtils::CREATE); - if (NS_WARN_IF(NS_FAILED(rv))) { - STUMBLER_ERR("Open a file for stumble failed"); - return Partition::Unknown; - } - - int64_t fileSize = 0; - rv = tmpFile->GetFileSize(&fileSize); - if (NS_WARN_IF(NS_FAILED(rv))) { - STUMBLER_ERR("GetFileSize failed"); - return Partition::Unknown; - } - - if (fileSize == 0) { - return Partition::Begining; - } else if (fileSize >= MAXFILESIZE_KB) { - return Partition::End; - } else { - return Partition::Middle; - } -} - -NS_IMETHODIMP -WriteStumbleOnThread::Run() -{ - MOZ_ASSERT(!NS_IsMainThread()); - - bool b = sIsAlreadyRunning.exchange(true); - if (b) { - return NS_OK; - } - - UploadFileStatus status = GetUploadFileStatus(); - - if (UploadFileStatus::NoFile != status) { - if (UploadFileStatus::ExistsAndReadyToUpload == status) { - sIsFileWaitingForUpload = true; - Upload(); - return NS_OK; - } - } else { - Partition partition = GetWritePosition(); - if (partition == Partition::Unknown) { - STUMBLER_ERR("GetWritePosition failed, skip once"); - } else { - WriteJSON(partition); - } - } - - sIsFileWaitingForUpload = false; - sIsAlreadyRunning = false; - return NS_OK; -} - - -/* - If the upload file exists, then check if it is one day old. - • if it is a day old -> ExistsAndReadyToUpload - • if it is less than the current day old -> Exists - • otherwise -> NoFile - - The Exists case means that the upload and the stumbling is rate limited - per-day to the size of the one file. - */ -WriteStumbleOnThread::UploadFileStatus -WriteStumbleOnThread::GetUploadFileStatus() -{ - nsCOMPtr<nsIFile> tmpFile; - nsresult rv = nsDumpUtils::OpenTempFile(FILENAME_COMPLETED, getter_AddRefs(tmpFile), - OUTPUT_DIR, nsDumpUtils::CREATE); - int64_t fileSize; - rv = tmpFile->GetFileSize(&fileSize); - if (NS_WARN_IF(NS_FAILED(rv))) { - STUMBLER_ERR("GetFileSize failed"); - return UploadFileStatus::NoFile; - } - if (fileSize <= 0) { - tmpFile->Remove(true); - return UploadFileStatus::NoFile; - } - - PRTime lastModifiedTime; - tmpFile->GetLastModifiedTime(&lastModifiedTime); - if ((PR_Now() / PR_USEC_PER_MSEC) - lastModifiedTime >= ONEDAY_IN_MSEC) { - return UploadFileStatus::ExistsAndReadyToUpload; - } - return UploadFileStatus::Exists; -} - -void -WriteStumbleOnThread::Upload() -{ - MOZ_ASSERT(!NS_IsMainThread()); - - time_t seconds = time(0); - int day = seconds / (60 * 60 * 24); - - if (sUploadFreqGuard.daySinceEpoch < day) { - sUploadFreqGuard.daySinceEpoch = day; - sUploadFreqGuard.attempts = 0; - } - - sUploadFreqGuard.attempts++; - if (sUploadFreqGuard.attempts > MAX_UPLOAD_ATTEMPTS) { - STUMBLER_ERR("Too many upload attempts today"); - sIsAlreadyRunning = false; - return; - } - - nsCOMPtr<nsIFile> tmpFile; - nsresult rv = nsDumpUtils::OpenTempFile(FILENAME_COMPLETED, getter_AddRefs(tmpFile), - OUTPUT_DIR, nsDumpUtils::CREATE); - int64_t fileSize; - rv = tmpFile->GetFileSize(&fileSize); - if (NS_WARN_IF(NS_FAILED(rv))) { - STUMBLER_ERR("GetFileSize failed"); - sIsAlreadyRunning = false; - return; - } - - if (fileSize <= 0) { - sIsAlreadyRunning = false; - return; - } - - // prepare json into nsIInputStream - nsCOMPtr<nsIInputStream> inStream; - rv = NS_NewLocalFileInputStream(getter_AddRefs(inStream), tmpFile); - if (NS_FAILED(rv)) { - sIsAlreadyRunning = false; - return; - } - - RefPtr<nsIRunnable> uploader = new UploadStumbleRunnable(inStream); - NS_DispatchToMainThread(uploader); -} |