<commit_before>// Copyright (c) 2006-2008 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/common/net/cookie_monster_sqlite.h"

#include "base/logging.h"
#include "base/ref_counted.h"
#include "base/string_util.h"
#include "base/thread.h"
#include "chrome/common/sqlite_compiled_statement.h"
#include "chrome/common/sqlite_utils.h"

// This class is designed to be shared between any calling threads and the
// database thread.  It batches operations and commits them on a timer.
class SQLitePersistentCookieStore::Backend
    : public base::RefCountedThreadSafe<SQLitePersistentCookieStore::Backend> {
 public:
  // The passed database pointer must be already-initialized. This object will
  // take ownership.
  explicit Backend(sqlite3* db, MessageLoop* loop)
      : db_(db),
        background_loop_(loop),
        cache_(new SqliteStatementCache(db)),
        num_pending_(0) {
    DCHECK(db_) << "Database must exist.";
  }

  // You should call Close() before destructing this object.
  ~Backend() {
    DCHECK(!db_) << "Close should have already been called.";
    DCHECK(num_pending_ == 0 && pending_.empty());
  }

  // Batch a cookie add
  void AddCookie(const std::string& key,
                 const net::CookieMonster::CanonicalCookie& cc);
  // Batch a cookie delete
  void DeleteCookie(const net::CookieMonster::CanonicalCookie& cc);
  // Commit and pending operations and close the database, must be called
  // before the object is destructed.
  void Close();

 private:
  class PendingOperation {
   public:
    typedef enum {
      COOKIE_ADD,
      COOKIE_DELETE,
    } OperationType;

    PendingOperation(OperationType op,
                     const std::string& key,
                     const net::CookieMonster::CanonicalCookie& cc)
        : op_(op), key_(key), cc_(cc) { }

    OperationType op() const { return op_; }
    const std::string& key() const { return key_; }
    const net::CookieMonster::CanonicalCookie& cc() const { return cc_; }

   private:
    OperationType op_;
    std::string key_;  // Only used for OP_ADD
    net::CookieMonster::CanonicalCookie cc_;
  };

 private:
  // Batch a cookie operation (add or delete)
  void BatchOperation(PendingOperation::OperationType op,
                      const std::string& key,
                      const net::CookieMonster::CanonicalCookie& cc);
  // Commit our pending operations to the database.
  void Commit();
  // Close() executed on the background thread.
  void InternalBackgroundClose();

  sqlite3* db_;
  MessageLoop* background_loop_;
  SqliteStatementCache* cache_;

  typedef std::list<PendingOperation*> PendingOperationsList;
  PendingOperationsList pending_;
  PendingOperationsList::size_type num_pending_;
  Lock pending_lock_;  // Guard pending_ and num_pending_

  DISALLOW_EVIL_CONSTRUCTORS(Backend);
};

void SQLitePersistentCookieStore::Backend::AddCookie(
    const std::string& key,
    const net::CookieMonster::CanonicalCookie& cc) {
  BatchOperation(PendingOperation::COOKIE_ADD, key, cc);
}

void SQLitePersistentCookieStore::Backend::DeleteCookie(
    const net::CookieMonster::CanonicalCookie& cc) {
  BatchOperation(PendingOperation::COOKIE_DELETE, std::string(), cc);
}

void SQLitePersistentCookieStore::Backend::BatchOperation(
    PendingOperation::OperationType op,
    const std::string& key,
    const net::CookieMonster::CanonicalCookie& cc) {
  // Commit every 30 seconds.
  static const int kCommitIntervalMs = 30 * 1000;
  // Commit right away if we have more than 512 outstanding operations.
  static const int kCommitAfterBatchSize = 512;
  DCHECK(MessageLoop::current() != background_loop_);

  // We do a full copy of the cookie here, and hopefully just here.
  scoped_ptr<PendingOperation> po(new PendingOperation(op, key, cc));
  CHECK(po.get());

  PendingOperationsList::size_type num_pending;
  {
    AutoLock locked(pending_lock_);
    pending_.push_back(po.release());
    num_pending = ++num_pending_;
  }<commit_msg>Add a missing include and match a constant type better.  From phajdan.jr. Review URL: http://codereview.chromium.org/2922<commit_after>// Copyright (c) 2006-2008 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/common/net/cookie_monster_sqlite.h"

#include <list>

#include "base/basictypes.h"
#include "base/logging.h"
#include "base/ref_counted.h"
#include "base/string_util.h"
#include "base/thread.h"
#include "chrome/common/sqlite_compiled_statement.h"
#include "chrome/common/sqlite_utils.h"

// This class is designed to be shared between any calling threads and the
// database thread.  It batches operations and commits them on a timer.
class SQLitePersistentCookieStore::Backend
    : public base::RefCountedThreadSafe<SQLitePersistentCookieStore::Backend> {
 public:
  // The passed database pointer must be already-initialized. This object will
  // take ownership.
  explicit Backend(sqlite3* db, MessageLoop* loop)
      : db_(db),
        background_loop_(loop),
        cache_(new SqliteStatementCache(db)),
        num_pending_(0) {
    DCHECK(db_) << "Database must exist.";
  }

  // You should call Close() before destructing this object.
  ~Backend() {
    DCHECK(!db_) << "Close should have already been called.";
    DCHECK(num_pending_ == 0 && pending_.empty());
  }

  // Batch a cookie add
  void AddCookie(const std::string& key,
                 const net::CookieMonster::CanonicalCookie& cc);
  // Batch a cookie delete
  void DeleteCookie(const net::CookieMonster::CanonicalCookie& cc);
  // Commit and pending operations and close the database, must be called
  // before the object is destructed.
  void Close();

 private:
  class PendingOperation {
   public:
    typedef enum {
      COOKIE_ADD,
      COOKIE_DELETE,
    } OperationType;

    PendingOperation(OperationType op,
                     const std::string& key,
                     const net::CookieMonster::CanonicalCookie& cc)
        : op_(op), key_(key), cc_(cc) { }

    OperationType op() const { return op_; }
    const std::string& key() const { return key_; }
    const net::CookieMonster::CanonicalCookie& cc() const { return cc_; }

   private:
    OperationType op_;
    std::string key_;  // Only used for OP_ADD
    net::CookieMonster::CanonicalCookie cc_;
  };

 private:
  // Batch a cookie operation (add or delete)
  void BatchOperation(PendingOperation::OperationType op,
                      const std::string& key,
                      const net::CookieMonster::CanonicalCookie& cc);
  // Commit our pending operations to the database.
  void Commit();
  // Close() executed on the background thread.
  void InternalBackgroundClose();

  sqlite3* db_;
  MessageLoop* background_loop_;
  SqliteStatementCache* cache_;

  typedef std::list<PendingOperation*> PendingOperationsList;
  PendingOperationsList pending_;
  PendingOperationsList::size_type num_pending_;
  Lock pending_lock_;  // Guard pending_ and num_pending_

  DISALLOW_EVIL_CONSTRUCTORS(Backend);
};

void SQLitePersistentCookieStore::Backend::AddCookie(
    const std::string& key,
    const net::CookieMonster::CanonicalCookie& cc) {
  BatchOperation(PendingOperation::COOKIE_ADD, key, cc);
}

void SQLitePersistentCookieStore::Backend::DeleteCookie(
    const net::CookieMonster::CanonicalCookie& cc) {
  BatchOperation(PendingOperation::COOKIE_DELETE, std::string(), cc);
}

void SQLitePersistentCookieStore::Backend::BatchOperation(
    PendingOperation::OperationType op,
    const std::string& key,
    const net::CookieMonster::CanonicalCookie& cc) {
  // Commit every 30 seconds.
  static const int kCommitIntervalMs = 30 * 1000;
  // Commit right away if we have more than 512 outstanding operations.
  static const size_t kCommitAfterBatchSize = 512;
  DCHECK(MessageLoop::current() != background_loop_);

  // We do a full copy of the cookie here, and hopefully just here.
  scoped_ptr<PendingOperation> po(new PendingOperation(op, key, cc));
  CHECK(po.get());

  PendingOperationsList::size_type num_pending;
  {
    AutoLock locked(pending_lock_);
    pending_.push_back(po.release());
    num_pending = ++num_pending_;
  }
{'fraction_non_alphanumeric': 0.10337780983291261, 'fraction_numerical': 0.006731578314701286, 'mean_word_length': 3.9085545722713864, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6190372', 'n_tokens_mistral': 2444, 'n_tokens_neox': 2399, 'n_words': 696}