<commit_before>/**
 * Copyright (c) 2015 - The CM Authors <<EMAIL>>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include "stx/protobuf/msg.h"
#include "zbase/docdb/DocumentDB.h"

using namespace stx;

namespace zbase {

DocumentDB::DocumentDB(const String& path) {
  mdb::MDBOptions mdb_opts;
  mdb_opts.data_filename = "docdb.db",
  mdb_opts.lock_filename = "docdb.db.lck";
  mdb_opts.duplicate_keys = false;

  db_ = mdb::MDB::open(path, mdb_opts);
}

void DocumentDB::listDocuments(
    const String& db_namespace,
    const String& userid,
    Function<bool (const Document& doc)> fn) const {
  auto namespace_prefix = db_namespace + "~d~";

  Buffer key;
  Buffer value;

  auto txn = db_->startTransaction(true);
  txn->autoAbort();

  auto cursor = txn->getCursor();
  key.append(namespace_prefix);
  if (!cursor->getFirstOrGreater(&key, &value)) {
    return;
  }

  do {
    if (!StringUtil::beginsWith(key.toString(), namespace_prefix)) {
      break;
    }

    auto doc = msg::decode<Document>(value);
    if (!isDocumentReadableForUser(doc, userid)) {
      continue;
    }

    if (!fn(doc)) {
      break;
    }
  } while (cursor->getNext(&key, &value));

  cursor->close();
}

void DocumentDB::createDocument(
    const String& db_namespace,
    const Document& document) {
  auto db_key = StringUtil::format("$0~d~$1", db_namespace, document.<KEY>
  auto buf = msg::encode(document);

  auto txn = db_->startTransaction(false);
  txn->autoAbort();
  txn->insert(db_key.data(), db_key.size(), buf->data(), buf->size());
  txn->commit();
}

bool DocumentDB::fetchDocument(
    const String& db_namespace,
    const String& userid,
    const SHA1Hash& uuid,
    Document* document) {
  auto db_key = StringUtil::format("$0~d~$1", db_namespace, uuid.toString());

  void* data;
  size_t data_size;
  auto txn = db_->startTransaction(true);
  txn->autoAbort();

  if (txn->get(db_key.data(), db_key.size(), &data, &data_size)) {
    auto doc = msg::decode<Document>(data, data_size);

    if (isDocumentReadableForUser(doc, userid)) {
      *document = doc;
    } else {
      RAISE(kAccessDeniedError, "access denied");
    }

    return true;
  } else {
    return false;
  }
}

void DocumentDB::updateDocument(
      const String& db_namespace,
      const SHA1Hash& uuid,
      Function<void (Document* doc)> fn) {
  auto db_key = StringUtil::format("$0~d~$1", db_namespace, uuid.toString());

  auto txn = db_->startTransaction(false);
  txn->autoAbort();

  void* data;
  size_t data_size;
  if (!txn->get(db_key.data(), db_key.size(), &data, &data_size)) {
    RAISE(kNotFoundError, "document not found");
  }

  auto doc = msg::decode<Document>(data, data_size);
  fn(&doc);

  auto doc_buf = msg::encode<Document>(doc);
  txn->update(db_key.data(), db_key.size(), doc_buf->data(), doc_buf->size());
  txn->commit();
}

void DocumentDB::updateDocumentContent(<commit_msg>set mtime<commit_after>/**
 * Copyright (c) 2015 - The CM Authors <<EMAIL>>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include "stx/protobuf/msg.h"
#include "stx/wallclock.h"
#include "zbase/docdb/DocumentDB.h"

using namespace stx;

namespace zbase {

DocumentDB::DocumentDB(const String& path) {
  mdb::MDBOptions mdb_opts;
  mdb_opts.data_filename = "docdb.db",
  mdb_opts.lock_filename = "docdb.db.lck";
  mdb_opts.duplicate_keys = false;

  db_ = mdb::MDB::open(path, mdb_opts);
}

void DocumentDB::listDocuments(
    const String& db_namespace,
    const String& userid,
    Function<bool (const Document& doc)> fn) const {
  auto namespace_prefix = db_namespace + "~d~";

  Buffer key;
  Buffer value;

  auto txn = db_->startTransaction(true);
  txn->autoAbort();

  auto cursor = txn->getCursor();
  key.append(namespace_prefix);
  if (!cursor->getFirstOrGreater(&key, &value)) {
    return;
  }

  do {
    if (!StringUtil::beginsWith(key.toString(), namespace_prefix)) {
      break;
    }

    auto doc = msg::decode<Document>(value);
    if (!isDocumentReadableForUser(doc, userid)) {
      continue;
    }

    if (!fn(doc)) {
      break;
    }
  } while (cursor->getNext(&key, &value));

  cursor->close();
}

void DocumentDB::createDocument(
    const String& db_namespace,
    const Document& document) {
  auto db_key = StringUtil::format("$0~d~$1", db_namespace, document.uuid());
  auto buf = msg::encode(document);

  auto txn = db_->startTransaction(false);
  txn->autoAbort();
  txn->insert(db_key.data(), db_key.size(), buf->data(), buf->size());
  txn->commit();
}

bool DocumentDB::fetchDocument(
    const String& db_namespace,
    const String& userid,
    const SHA1Hash& uuid,
    Document* document) {
  auto db_key = StringUtil::format("$0~d~$1", db_namespace, uuid.toString());

  void* data;
  size_t data_size;
  auto txn = db_->startTransaction(true);
  txn->autoAbort();

  if (txn->get(db_key.data(), db_key.size(), &data, &data_size)) {
    auto doc = msg::decode<Document>(data, data_size);

    if (isDocumentReadableForUser(doc, userid)) {
      *document = doc;
    } else {
      RAISE(kAccessDeniedError, "access denied");
    }

    return true;
  } else {
    return false;
  }
}

void DocumentDB::updateDocument(
      const String& db_namespace,
      const SHA1Hash& uuid,
      Function<void (Document* doc)> fn) {
  auto db_key = StringUtil::format("$0~d~$1", db_namespace, uuid.toString());

  auto txn = db_->startTransaction(false);
  txn->autoAbort();

  void* data;
  size_t data_size;
  if (!txn->get(db_key.data(), db_key.size(), &data, &data_size)) {
    RAISE(kNotFoundError, "document not found");
  }

  auto doc = msg::decode<Document>(data, data_size);
  fn(&doc);
  doc.set_mtime(WallClock::unixMicros());

  auto doc_buf = msg::encode<Document>(doc);
  txn->update(db_key.data(), db_key.size(), doc_buf->data(), doc_buf->size());
  txn->commit();
}

void DocumentDB::updateDocumentContent(
{'fraction_non_alphanumeric': 0.155, 'fraction_numerical': 0.003870967741935484, 'mean_word_length': 4.033279220779221, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 64, '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': '4486659', 'n_tokens_mistral': 2156, 'n_tokens_neox': 2110, 'n_words': 471}