forked from organicmaps/organicmaps
[alohalytics] Fixed code comments.
This commit is contained in:
parent
451d1b6420
commit
eb1b15ba2b
7 changed files with 23 additions and 44 deletions
|
@ -36,8 +36,7 @@
|
|||
// or in application:willFinishLaunchingWithOptions:
|
||||
+ (void)setup:(NSString *)serverUrl withLaunchOptions:(NSDictionary *)options;
|
||||
// Alternative to the previous setup method if you integrated Alohalytics after initial release
|
||||
// and don't want to count app upgrades as new installs (and definitely know that it's an already existing
|
||||
// user).
|
||||
// and don't want to count app upgrades as new installs (and definitely know that it's an already existing user).
|
||||
+ (void)setup:(NSString *)serverUrl andFirstLaunch:(BOOL)isFirstLaunch withLaunchOptions:(NSDictionary *)options;
|
||||
+ (void)forceUpload;
|
||||
+ (void)logEvent:(NSString *)event;
|
||||
|
|
|
@ -87,7 +87,7 @@ void Stats::GzipAndArchiveFileInTheQueue(const std::string & in_file, const std:
|
|||
fo.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
fo.open(out_archive, std::ofstream::out | std::ofstream::binary | std::ofstream::trunc);
|
||||
const std::string gzipped_buffer = Gzip(buffer);
|
||||
std::string().swap(buffer); // Free memory.
|
||||
std::string().swap(buffer); // Free memory.
|
||||
fo.write(gzipped_buffer.data(), gzipped_buffer.size());
|
||||
}
|
||||
} catch (const std::exception & ex) {
|
||||
|
|
|
@ -36,8 +36,7 @@ struct FileManager {
|
|||
// Initialized separately for each platform.
|
||||
static const char kDirectorySeparator;
|
||||
|
||||
// Checks and appends if necessary platform-dependent slash at the end of the
|
||||
// path.
|
||||
// Checks and appends if necessary platform-dependent slash at the end of the path.
|
||||
static void AppendDirectorySlash(std::string & directory) {
|
||||
// Fix missing slash if necessary.
|
||||
if (!directory.empty() && directory.back() != kDirectorySeparator) {
|
||||
|
@ -81,8 +80,7 @@ struct FileManager {
|
|||
return std::string();
|
||||
}
|
||||
|
||||
// Executes lambda for each regular file in the directory and stops
|
||||
// immediately if lambda returns false.
|
||||
// Executes lambda for each regular file in the directory and stops immediately if lambda returns false.
|
||||
static void ForEachFileInDir(std::string directory, std::function<bool(const std::string & full_path)> lambda);
|
||||
|
||||
// Returns negative value on error and if full_path_to_file is a directory.
|
||||
|
|
|
@ -43,8 +43,7 @@ namespace alohalytics {
|
|||
// Archiver function, should process first parameter's file, remove it and store result in the second parameter.
|
||||
typedef std::function<void(const std::string & file_to_archive, const std::string & archived_file)> TFileArchiver;
|
||||
// Processor should return true if file was processed successfully.
|
||||
// If file_name_in_content is true, then second parameter is a full path to a
|
||||
// file instead of a buffer.
|
||||
// If file_name_in_content is true, then second parameter is a full path to a file instead of a buffer.
|
||||
typedef std::function<bool(bool file_name_in_content, const std::string & content)> TArchivedFileProcessor;
|
||||
enum class ProcessingResult { EProcessedSuccessfully, EProcessingError, ENothingToProcess };
|
||||
typedef std::function<void(ProcessingResult)> TFileProcessingFinishedCallback;
|
||||
|
@ -55,10 +54,8 @@ constexpr char kArchivedFilesExtension[] = ".archived";
|
|||
|
||||
class MessagesQueue final {
|
||||
public:
|
||||
// Size limit (before gzip) when we archive "current" file and create a new
|
||||
// one for appending.
|
||||
// Optimal size is the one which (gzipped) can be POSTed to the server as one
|
||||
// HTTP request.
|
||||
// Size limit (before gzip) when we archive "current" file and create a new one for appending.
|
||||
// Optimal size is the one which (gzipped) can be POSTed to the server as one HTTP request.
|
||||
const std::ofstream::pos_type kMaxFileSizeInBytes = 100 * 1024;
|
||||
|
||||
// Default archiving simply renames original file without any additional processing.
|
||||
|
@ -87,8 +84,7 @@ class MessagesQueue final {
|
|||
commands_queue_.push_back(std::bind(&MessagesQueue::ProcessInitializeStorageCommand, this, directory));
|
||||
condition_variable_.notify_all();
|
||||
}
|
||||
// Stores message into a file archive (if SetStorageDirectory was called with
|
||||
// a valid directory),
|
||||
// Stores message into a file archive (if SetStorageDirectory was called with a valid directory),
|
||||
// otherwise stores messages in-memory.
|
||||
// Executed on the WorkerThread.
|
||||
void PushMessage(const std::string & message) {
|
||||
|
@ -98,8 +94,7 @@ class MessagesQueue final {
|
|||
condition_variable_.notify_all();
|
||||
}
|
||||
|
||||
// Processor should return true if file was successfully processed (e.g.
|
||||
// uploaded to a server, etc.).
|
||||
// Processor should return true if file was successfully processed (e.g. uploaded to a server, etc.).
|
||||
// File is deleted if processor has returned true.
|
||||
// Processing stops if processor returns false.
|
||||
// Optional callback is called when all files are processed.
|
||||
|
@ -155,8 +150,7 @@ class MessagesQueue final {
|
|||
} else {
|
||||
storage_directory_ = directory;
|
||||
current_file_ = std::move(new_current_file);
|
||||
// Also check if there are any messages in the memory storage, and save them
|
||||
// to file.
|
||||
// Also check if there are any messages in the memory storage, and save them to file.
|
||||
if (!messages_storage_.empty()) {
|
||||
StoreMessages(messages_storage_);
|
||||
messages_storage_.clear();
|
||||
|
@ -177,25 +171,20 @@ class MessagesQueue final {
|
|||
}
|
||||
}
|
||||
|
||||
// If there is no file storage directory set, it should also process messages
|
||||
// from the memory buffer.
|
||||
// If there is no file storage directory set, it should also process messages from the memory buffer.
|
||||
void ProcessArchivedFilesCommand(TArchivedFileProcessor processor, TFileProcessingFinishedCallback callback) {
|
||||
ProcessingResult result = ProcessingResult::ENothingToProcess;
|
||||
// Process in-memory messages, if any.
|
||||
// TODO(AlexZ): Append user ID to every bunch of data sent to processor.
|
||||
if (!messages_storage_.empty()) {
|
||||
// TODO(AlexZ): gzip it before processing.
|
||||
if (processor(false /* in-memory buffer */, messages_storage_)) {
|
||||
messages_storage_.clear();
|
||||
result = ProcessingResult::EProcessedSuccessfully;
|
||||
} else {
|
||||
result = ProcessingResult::EProcessingError;
|
||||
}
|
||||
// If in-memory storage is used, then file storage directory was not set
|
||||
// and we can't process files.
|
||||
// If in-memory storage is used, then file storage directory was not set and we can't process files.
|
||||
// So here we notify callback and return.
|
||||
// TODO(AlexZ): Do we need to use in-memory storage if storage is
|
||||
// initialized but full/not accessible?
|
||||
// TODO(AlexZ): Do we need to use in-memory storage if storage is initialized but full/not accessible?
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
|
@ -232,9 +221,8 @@ class MessagesQueue final {
|
|||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
condition_variable_.wait(lock, [this] { return !commands_queue_.empty() || worker_thread_should_exit_; });
|
||||
if (worker_thread_should_exit_) {
|
||||
// TODO(AlexZ): Should we execute commands (if any) on exit? What if
|
||||
// they will be too long (e.g.
|
||||
// network connection)?
|
||||
// TODO(AlexZ): Should we execute commands (if any) on exit?
|
||||
// What if they will be too long (e.g. network connection)?
|
||||
return;
|
||||
}
|
||||
command_to_execute = commands_queue_.front();
|
||||
|
@ -248,8 +236,7 @@ class MessagesQueue final {
|
|||
TFileArchiver file_archiver_;
|
||||
// Synchronized buffer to pass messages between threads.
|
||||
std::string messages_buffer_;
|
||||
// Directory with a slash at the end, where we store "current" file and
|
||||
// archived files.
|
||||
// Directory with a slash at the end, where we store "current" file and archived files.
|
||||
std::string storage_directory_;
|
||||
// Used as an in-memory storage if storage_dir_ was not set.
|
||||
std::string messages_storage_;
|
||||
|
@ -261,8 +248,7 @@ class MessagesQueue final {
|
|||
std::condition_variable condition_variable_;
|
||||
// Only WorkerThread accesses this variable.
|
||||
std::unique_ptr<std::ofstream> current_file_;
|
||||
// Should be the last member of the class to initialize after all other
|
||||
// members.
|
||||
// Should be the last member of the class to initialize after all other members.
|
||||
std::thread worker_thread_ = std::thread(&MessagesQueue::WorkerThread, this);
|
||||
};
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|||
SOFTWARE.
|
||||
*******************************************************************************/
|
||||
|
||||
// POSIX implementations for FileManager
|
||||
// POSIX implementations for FileManager.
|
||||
#include "../file_manager.h"
|
||||
|
||||
#include <dirent.h>
|
||||
|
|
|
@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|||
SOFTWARE.
|
||||
*******************************************************************************/
|
||||
|
||||
// Windows implementations for FileManager
|
||||
// Windows implementations for FileManager.
|
||||
#include <windows.h>
|
||||
#include <direct.h>
|
||||
#include <stdio.h>
|
||||
|
@ -47,8 +47,7 @@ void FileManager::ForEachFileInDir(std::string directory, std::function<bool(con
|
|||
return;
|
||||
}
|
||||
AppendDirectorySlash(directory);
|
||||
// TODO(AlexZ): Do we need to use *W functions (and wstrings) for files
|
||||
// processing?
|
||||
// TODO(AlexZ): Do we need to use *W functions (and wstrings) for files processing?
|
||||
WIN32_FIND_DATAA find_data;
|
||||
HANDLE handle = ::FindFirstFileA((directory + "*.*").c_str(), &find_data);
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
|
|
|
@ -371,8 +371,7 @@ void Test_MessagesQueue_SwitchFromInMemoryToFile_and_OfflineEmulation() {
|
|||
second_archived_file = full_file_path;
|
||||
archive2_processed = true;
|
||||
}
|
||||
return true; // Archives should be deleted by queue after successful
|
||||
// processing.
|
||||
return true; // Archives should be deleted by queue after successful processing.
|
||||
}, std::bind(&FinishedCallback, std::placeholders::_1, std::ref(finish_task)));
|
||||
TEST_EQUAL(ProcessingResult::EProcessedSuccessfully, finish_task.get());
|
||||
TEST_EQUAL(true, archive1_processed);
|
||||
|
@ -419,8 +418,7 @@ void Test_MessagesQueue_CreateArchiveOnSizeLimitHit() {
|
|||
|
||||
void Test_MessagesQueue_HighLoadAndIntegrity() {
|
||||
// TODO(AlexZ): This test can be improved by generating really a lot of data
|
||||
// so many archives will be created. But it will make everything much more
|
||||
// complex now.
|
||||
// so many archives will be created. But it will make everything much more complex now.
|
||||
const std::string tmpdir = FileManager::GetDirectoryFromFilePath(GenerateTemporaryFileName());
|
||||
CleanUpQueueFiles(tmpdir);
|
||||
ScopedRemoveFile remover(tmpdir + alohalytics::kCurrentFileName);
|
||||
|
@ -435,8 +433,7 @@ void Test_MessagesQueue_HighLoadAndIntegrity() {
|
|||
char c = dis(gen);
|
||||
total_size += static_cast<size_t>(c);
|
||||
if (i == kMaxThreads / 2) {
|
||||
// At first, messages go into the in-memory queue. Then we initialize
|
||||
// files storage.
|
||||
// At first, messages go into the in-memory queue. Then we initialize files storage.
|
||||
q.SetStorageDirectory(tmpdir);
|
||||
}
|
||||
std::thread worker([&generator, c]() { generator(c); });
|
||||
|
|
Loading…
Add table
Reference in a new issue