Esempio n. 1
0
void User::IncrCredits(const std::string& section, long long kBytes)
{
  auto doIncrement = [section, kBytes](acl::UserID uid)
    {
      NoErrorConnection conn;
      auto updateExisting = [&]() -> bool
        {
          auto query = BSON("uid" << uid << 
                            "credits" << BSON("$elemMatch" << BSON("section" << section)));
                            
          auto update = BSON("$inc" << BSON("credits.$.value" << kBytes));
                            
          auto cmd = BSON("findandmodify" << "users" <<
                          "query" << query <<
                          "update" << update);
                          
          mongo::BSONObj result;
          return conn.RunCommand(cmd, result) && 
                 result["value"].type() != mongo::jstNULL;
        };

      auto doInsert = [&]() -> bool
      {
        auto query = QUERY("uid" << uid << "credits" << BSON("$not" << 
                           BSON("$elemMatch" << BSON("section" << section))));
        auto update = BSON("$push" << BSON("credits" << BSON("section" << section << "value" << kBytes)));
        return conn.Update("users", query, update, false) > 0;
      };
      
      if (updateExisting()) return;
      if (doInsert()) return;
      if (updateExisting()) return;

      logs::Database("Unable to increment credits for UID %1%%2%", uid,
                     !section.empty() ? " in section " + section : 
                     std::string(""));
    };
  
  asyncTasks.Assign(std::async(std::launch::async, doIncrement, user.id));
}