@@ -42,6 +42,7 @@ class named_mutex;
 #include "../plugins/nearest.hpp"
 #include "../plugins/timestamp.hpp"
 #include "../plugins/viaroute.hpp"
+#include "../plugins/map_matching.hpp"
 #include "../server/data_structures/datafacade_base.hpp"
 #include "../server/data_structures/internal_datafacade.hpp"
 #include "../server/data_structures/shared_barriers.hpp"

/*

Copyright (c) 2015, Project OSRM contributors
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

namespace boost
{
namespace interprocess
{
class named_mutex;
}
}

#include "osrm_impl.hpp"
#include "osrm.hpp"

#include "../plugins/distance_table.hpp"
#include "../plugins/hello_world.hpp"
#include "../plugins/locate.hpp"
#include "../plugins/nearest.hpp"
#include "../plugins/timestamp.hpp"
#include "../plugins/viaroute.hpp"
#include "../server/data_structures/datafacade_base.hpp"
#include "../server/data_structures/internal_datafacade.hpp"
#include "../server/data_structures/shared_barriers.hpp"
#include "../server/data_structures/shared_datafacade.hpp"
#include "../util/make_unique.hpp"
#include "../util/routed_options.hpp"
#include "../util/simple_logger.hpp"

#include <boost/assert.hpp>
#include <boost/interprocess/sync/named_condition.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>

#include <osrm/route_parameters.hpp>

#include <algorithm>
#include <fstream>
#include <utility>
#include <vector>

OSRM_impl::OSRM_impl(libosrm_config &lib_config)
{
    if (lib_config.use_shared_memory)
    {
        barrier = osrm::make_unique<SharedBarriers>();
        query_data_facade = new SharedDataFacade<QueryEdge::EdgeData>();
    }
    else
    {
        // populate base path
        populate_base_path(lib_config.server_paths);
        query_data_facade = new InternalDataFacade<QueryEdge::EdgeData>(lib_config.server_paths);
    }

    // The following plugins handle all requests.
    RegisterPlugin(new DistanceTablePlugin<BaseDataFacade<QueryEdge::EdgeData>>(
        query_data_facade, lib_config.max_locations_distance_table));
    RegisterPlugin(new HelloWorldPlugin());
    RegisterPlugin(new LocatePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
    RegisterPlugin(new NearestPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
    RegisterPlugin(new TimestampPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
    RegisterPlugin(new ViaRoutePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
}

OSRM_impl::~OSRM_impl()
{
    delete query_data_facade;
    for (PluginMap::value_type &plugin_pointer : plugin_map)
    {
        delete plugin_pointer.second;
    }
}

void OSRM_impl::RegisterPlugin(BasePlugin *plugin)
{
    SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor();
    if (plugin_map.find(plugin->GetDescriptor()) != plugin_map.end())
    {
        delete plugin_map.find(plugin->GetDescriptor())->second;
    }
    plugin_map.emplace(plugin->GetDescriptor(), plugin);
}

int OSRM_impl::RunQuery(RouteParameters &route_parameters, osrm::json::Object &json_result)
{
    const auto &plugin_iterator = plugin_map.find(route_parameters.service);

    if (plugin_map.end() == plugin_iterator)
    {
        return 400;
    }

    increase_concurrent_query_count();
    plugin_iterator->second->HandleRequest(route_parameters, json_result);
    decrease_concurrent_query_count();
    return 200;
}

// decrease number of concurrent queries
void OSRM_impl::decrease_concurrent_query_count()
{
    if (!barrier)
    {
        return;
    }
    // lock query
    boost::interprocess::scoped_lock<boost::interprocess::named_mutex> query_lock(
        barrier->query_mutex);

    // decrement query count
    --(barrier->number_of_queries);
    BOOST_ASSERT_MSG(0 <= barrier->number_of_queries, "invalid number of queries");

    // notify all processes that were waiting for this condition
    if (0 == barrier->number_of_queries)
    {
        barrier->no_running_queries_condition.notify_all();
    }
}

// increase number of concurrent queries
void OSRM_impl::increase_concurrent_query_count()
{
    if (!barrier)
    {
        return;
    }

    // lock update pending
    boost::interprocess::scoped_lock<boost::interprocess::named_mutex> pending_lock(
        barrier->pending_update_mutex);

    // lock query
    boost::interprocess::scoped_lock<boost::interprocess::named_mutex> query_lock(
        barrier->query_mutex);

    // unlock update pending
    pending_lock.unlock();

    // increment query count
    ++(barrier->number_of_queries);

    (static_cast<SharedDataFacade<QueryEdge::EdgeData> *>(query_data_facade))
        ->CheckAndReloadFacade();
}

// proxy code for compilation firewall
OSRM::OSRM(libosrm_config &lib_config) : OSRM_pimpl_(osrm::make_unique<OSRM_impl>(lib_config)) {}

OSRM::~OSRM() { OSRM_pimpl_.reset(); }

int OSRM::RunQuery(RouteParameters &route_parameters, osrm::json::Object &json_result)
{
    return OSRM_pimpl_->RunQuery(route_parameters, json_result);
}

reorder includes to be alphabetically ordered


@@ -34,6 +34,11 @@ public:
     static constexpr std::int64_t column_count = 2;
     static constexpr std::int64_t element_count = row_count * column_count;

+    bool not_available_on_device() {
+        constexpr bool is_svd = std::is_same_v<Method, pca::method::svd>;
+        return get_policy().is_gpu() && is_svd;
+    }
+
     auto get_descriptor() const {
         return pca::descriptor<float, Method, pca::task::dim_reduction>{};
     }

/*******************************************************************************
* Copyright 2020-2021 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/

#include <array>

#include "oneapi/dal/algo/pca/infer.hpp"
#include "oneapi/dal/algo/pca/train.hpp"
#include "oneapi/dal/table/row_accessor.hpp"

#include "oneapi/dal/test/engine/common.hpp"
#include "oneapi/dal/test/engine/fixtures.hpp"

namespace oneapi::dal::pca::test {

namespace te = dal::test::engine;

template <typename Method>
class pca_badarg_test : public te::algo_fixture {
public:
    static constexpr std::int64_t row_count = 8;
    static constexpr std::int64_t column_count = 2;
    static constexpr std::int64_t element_count = row_count * column_count;

    auto get_descriptor() const {
        return pca::descriptor<float, Method, pca::task::dim_reduction>{};
    }

    table get_train_data(std::int64_t override_row_count = row_count,
                         std::int64_t override_column_count = column_count) const {
        ONEDAL_ASSERT(override_row_count * override_column_count <= element_count);
        return homogen_table::wrap(train_data_.data(), override_row_count, override_column_count);
    }

    table get_infer_data(std::int64_t override_row_count = row_count,
                         std::int64_t override_column_count = column_count) const {
        ONEDAL_ASSERT(override_row_count * override_column_count <= element_count);
        return homogen_table::wrap(infer_data_.data(), override_row_count, override_column_count);
    }

private:
    static constexpr std::array<float, element_count> train_data_ = {
        1.0, 1.0, 2.0, 2.0, 1.0, 2.0, 2.0, 1.0, -1.0, -1.0, -1.0, -2.0, -2.0, -1.0, -2.0, -2.0
    };

    static constexpr std::array<float, element_count> infer_data_ = {
        1.0, 1.0, 2.0, 2.0, 1.0, 2.0, 2.0, 1.0, -1.0, -1.0, -1.0, -2.0, -2.0, -1.0, -2.0, -2.0
    };
};

#define PCA_BADARG_TEST(name) \
    TEMPLATE_TEST_M(pca_badarg_test, name, "[pca][badarg]", pca::method::cov, pca::method::svd)

PCA_BADARG_TEST("accepts non-negative component_count") {
    REQUIRE_NOTHROW(this->get_descriptor().set_component_count(0));
}

PCA_BADARG_TEST("throws if component_count is negative") {
    REQUIRE_THROWS_AS(this->get_descriptor().set_component_count(-1), domain_error);
}

PCA_BADARG_TEST("throws if train data is empty") {
    const auto pca_desc = this->get_descriptor().set_component_count(2);

    REQUIRE_THROWS_AS(this->train(pca_desc, homogen_table{}), domain_error);
}

PCA_BADARG_TEST("throws if train data columns less than component count") {
    const auto pca_desc = this->get_descriptor().set_component_count(4);

    REQUIRE_THROWS_AS(this->train(pca_desc, this->get_train_data()), invalid_argument);
}

PCA_BADARG_TEST("throws if infer data is empty") {
    const auto pca_desc = this->get_descriptor().set_component_count(2);
    const auto model = this->train(pca_desc, this->get_train_data()).get_model();

    REQUIRE_THROWS_AS(this->infer(pca_desc, model, homogen_table{}), domain_error);
}

PCA_BADARG_TEST("throws if component count neq eigenvector_rows") {
    auto pca_desc = this->get_descriptor().set_component_count(2);
    const auto model = this->train(pca_desc, this->get_train_data()).get_model();
    pca_desc.set_component_count(4);

    REQUIRE_THROWS_AS(this->infer(pca_desc, model, this->get_infer_data()), invalid_argument);
}

PCA_BADARG_TEST("throws if infer data column count neq eigenvector columns") {
    const auto pca_desc = this->get_descriptor().set_component_count(2);
    const auto model = this->train(pca_desc, this->get_train_data()).get_model();
    const auto infer_data = this->get_infer_data(4, 4);

    REQUIRE_THROWS_AS(this->infer(pca_desc, model, infer_data), invalid_argument);
}

} // namespace oneapi::dal::pca::test


@@ -16,23 +16,24 @@ R.E. Carhart, D.H. Smith, R. Venkataraghavan;
 Definition and Applications" JCICS 25, 64-73 (1985).

 """
-from rdkit.DataStructs import IntSparseIntVect
-from rdkit import Chem
+from rdkit import DataStructs
 from rdkit.Chem import rdMolDescriptors
 from rdkit.Chem.AtomPairs import Utils
-from rdkit import DataStructs

-from rdkit.Chem.rdMolDescriptors import GetAtomPairFingerprint,GetHashedAtomPairFingerprint
-GetAtomPairFingerprintAsIntVect=rdMolDescriptors.GetAtomPairFingerprint
+GetAtomPairFingerprint = rdMolDescriptors.GetAtomPairFingerprint
+GetAtomPairFingerprintAsIntVect = rdMolDescriptors.GetAtomPairFingerprint
+GetHashedAtomPairFingerprint = rdMolDescriptors.GetHashedAtomPairFingerprint
+
+numPathBits = rdMolDescriptors.AtomPairsParameters.numPathBits
+_maxPathLen = (1 << numPathBits) - 1
+numFpBits = numPathBits + 2 * rdMolDescriptors.AtomPairsParameters.codeSize
+fpLen = 1 << numFpBits

-numPathBits=rdMolDescriptors.AtomPairsParameters.numPathBits
-_maxPathLen=(1<<numPathBits)-1
-numFpBits=numPathBits+2*rdMolDescriptors.AtomPairsParameters.codeSize
-fpLen=1<<numFpBits

-def pyScorePair(at1,at2,dist,atomCodes=None):
+def pyScorePair(at1, at2, dist, atomCodes=None):
   """ Returns a score for an individual atom pair.

+  >>> from rdkit import Chem
   >>> m = Chem.MolFromSmiles('CCCCC')
   >>> c1 = Utils.GetAtomCode(m.GetAtomWithIdx(0))
   >>> c2 = Utils.GetAtomCode(m.GetAtomWithIdx(1))

# $Id$
#
#  Copyright (C) 2004-2007 Greg Landrum and Rational Discovery LLC
#
#   @@ All Rights Reserved @@
#  This file is part of the RDKit.
#  The contents are covered by the terms of the BSD license
#  which is included in the file license.txt, found at the root
#  of the RDKit source tree.
#
""" Contains an implementation of Atom-pair fingerprints, as
described in:

R.E. Carhart, D.H. Smith, R. Venkataraghavan;
"Atom Pairs as Molecular Features in Structure-Activity Studies:
Definition and Applications" JCICS 25, 64-73 (1985).

"""
from rdkit.DataStructs import IntSparseIntVect
from rdkit import Chem
from rdkit.Chem import rdMolDescriptors
from rdkit.Chem.AtomPairs import Utils
from rdkit import DataStructs

from rdkit.Chem.rdMolDescriptors import GetAtomPairFingerprint,GetHashedAtomPairFingerprint
GetAtomPairFingerprintAsIntVect=rdMolDescriptors.GetAtomPairFingerprint

numPathBits=rdMolDescriptors.AtomPairsParameters.numPathBits
_maxPathLen=(1<<numPathBits)-1
numFpBits=numPathBits+2*rdMolDescriptors.AtomPairsParameters.codeSize
fpLen=1<<numFpBits

def pyScorePair(at1,at2,dist,atomCodes=None):
  """ Returns a score for an individual atom pair.

  >>> m = Chem.MolFromSmiles('CCCCC')
  >>> c1 = Utils.GetAtomCode(m.GetAtomWithIdx(0))
  >>> c2 = Utils.GetAtomCode(m.GetAtomWithIdx(1))
  >>> c3 = Utils.GetAtomCode(m.GetAtomWithIdx(2))
  >>> t = 1 | min(c1,c2)<<numPathBits | max(c1,c2)<<(rdMolDescriptors.AtomPairsParameters.codeSize+numPathBits)
  >>> pyScorePair(m.GetAtomWithIdx(0),m.GetAtomWithIdx(1),1)==t
  1
  >>> pyScorePair(m.GetAtomWithIdx(1),m.GetAtomWithIdx(0),1)==t
  1
  >>> t = 2 | min(c1,c3)<<numPathBits | max(c1,c3)<<(rdMolDescriptors.AtomPairsParameters.codeSize+numPathBits)
  >>> pyScorePair(m.GetAtomWithIdx(0),m.GetAtomWithIdx(2),2)==t
  1
  >>> pyScorePair(m.GetAtomWithIdx(0),m.GetAtomWithIdx(2),2,
  ...  atomCodes=(Utils.GetAtomCode(m.GetAtomWithIdx(0)),Utils.GetAtomCode(m.GetAtomWithIdx(2))))==t
  1

  """
  if not atomCodes:
    code1 = Utils.GetAtomCode(at1)
    code2 = Utils.GetAtomCode(at2)
  else:
    code1,code2=atomCodes
  accum = int(dist) % _maxPathLen
  accum |= min(code1,code2) << numPathBits
  accum |= max(code1,code2) << (rdMolDescriptors.AtomPairsParameters.codeSize+numPathBits)
  return accum

def ExplainPairScore(score):
  """
  >>> m = Chem.MolFromSmiles('C=CC')
  >>> score = pyScorePair(m.GetAtomWithIdx(0),m.GetAtomWithIdx(1),1)
  >>> ExplainPairScore(score)
  (('C', 1, 1), 1, ('C', 2, 1))
  >>> score = pyScorePair(m.GetAtomWithIdx(0),m.GetAtomWithIdx(2),2)
  >>> ExplainPairScore(score)
  (('C', 1, 0), 2, ('C', 1, 1))
  >>> score = pyScorePair(m.GetAtomWithIdx(1),m.GetAtomWithIdx(2),1)
  >>> ExplainPairScore(score)
  (('C', 1, 0), 1, ('C', 2, 1))
  >>> score = pyScorePair(m.GetAtomWithIdx(2),m.GetAtomWithIdx(1),1)
  >>> ExplainPairScore(score)
  (('C', 1, 0), 1, ('C', 2, 1))

  """
  codeMask = (1<<rdMolDescriptors.AtomPairsParameters.codeSize)-1
  pathMask = (1<<numPathBits)-1
  dist = score&pathMask

  score = score>>numPathBits
  code1 = score&codeMask
  score = score>>rdMolDescriptors.AtomPairsParameters.codeSize
  code2 = score&codeMask

  res = Utils.ExplainAtomCode(code1),dist,Utils.ExplainAtomCode(code2)
  return res

def GetAtomPairFingerprintAsBitVect(mol):
  """ Returns the Atom-pair fingerprint for a molecule as
  a SparseBitVect. Note that this doesn't match the standard
  definition of atom pairs, which uses counts of the
  pairs, not just their presence.

  **Arguments**:

    - mol: a molecule

  **Returns**: a SparseBitVect

  >>> m = Chem.MolFromSmiles('CCC')
  >>> v = [ pyScorePair(m.GetAtomWithIdx(0),m.GetAtomWithIdx(1),1),
  ...       pyScorePair(m.GetAtomWithIdx(0),m.GetAtomWithIdx(2),2),
  ...     ]
  >>> v.sort()
  >>> fp = GetAtomPairFingerprintAsBitVect(m)
  >>> list(fp.GetOnBits())==v
  True

  """
  res = DataStructs.SparseBitVect(fpLen)
  fp = rdMolDescriptors.GetAtomPairFingerprint(mol)
  for val in fp.GetNonzeroElements().keys():
    res.SetBit(val)
  return res

#------------------------------------
#
#  doctest boilerplate
#
def _test():
  import doctest,sys
  return doctest.testmod(sys.modules["__main__"])

if __name__ == '__main__':
  import sys
  failed,tried = _test()
  sys.exit(failed)

Though I have no particular objection to this change, I wonder why you made it. Is the `from x import y` pattern considered bad now?


@@ -75,3 +75,15 @@ const Outfit* Outfits::getOutfitByLookType(PlayerSex_t sex, uint16_t lookType) c
 	}
 	return nullptr;
 }
+
+const Outfit* Outfits::getOutfitByLookType(uint16_t lookType) const
+{
+	for (uint8_t sex = 0; sex <= 1; sex++) {
+		for (const Outfit& outfit : outfits[sex]) {
+			if (outfit.lookType == lookType) {
+				return &outfit;
+			}
+		}
+	}
+	return nullptr;
+}

/**
 * The Forgotten Server - a free and open-source MMORPG server emulator
 * Copyright (C) 2019  Mark Samman <mark.samman@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "otpch.h"

#include "outfit.h"

#include "pugicast.h"
#include "tools.h"

bool Outfits::loadFromXml()
{
	pugi::xml_document doc;
	pugi::xml_parse_result result = doc.load_file("data/XML/outfits.xml");
	if (!result) {
		printXMLError("Error - Outfits::loadFromXml", "data/XML/outfits.xml", result);
		return false;
	}

	for (auto outfitNode : doc.child("outfits").children()) {
		pugi::xml_attribute attr;
		if ((attr = outfitNode.attribute("enabled")) && !attr.as_bool()) {
			continue;
		}

		if (!(attr = outfitNode.attribute("type"))) {
			std::cout << "[Warning - Outfits::loadFromXml] Missing outfit type." << std::endl;
			continue;
		}

		uint16_t type = pugi::cast<uint16_t>(attr.value());
		if (type > PLAYERSEX_LAST) {
			std::cout << "[Warning - Outfits::loadFromXml] Invalid outfit type " << type << "." << std::endl;
			continue;
		}

		pugi::xml_attribute lookTypeAttribute = outfitNode.attribute("looktype");
		if (!lookTypeAttribute) {
			std::cout << "[Warning - Outfits::loadFromXml] Missing looktype on outfit." << std::endl;
			continue;
		}

		outfits[type].emplace_back(
			outfitNode.attribute("name").as_string(),
			pugi::cast<uint16_t>(lookTypeAttribute.value()),
			outfitNode.attribute("premium").as_bool(),
			outfitNode.attribute("unlocked").as_bool(true)
		);
	}
	return true;
}

const Outfit* Outfits::getOutfitByLookType(PlayerSex_t sex, uint16_t lookType) const
{
	for (const Outfit& outfit : outfits[sex]) {
		if (outfit.lookType == lookType) {
			return &outfit;
		}
	}
	return nullptr;
}

There are enums for genders + `PLAYERSEX_LAST`.


@@ -82,6 +82,9 @@ python::tuple fragmentMolHelper3(const RDKit::ROMol& mol, python::object ob,
   std::vector<std::pair<RDKit::ROMOL_SPTR, RDKit::ROMOL_SPTR>> tres;
   std::unique_ptr<std::vector<unsigned int>> v =
       pythonObjectToVect<unsigned int>(ob);
+  if (!v) {
+    throw_value_error("invalid value for bondsToCut");
+  }
   bool ok = RDKit::MMPA::fragmentMol(mol, tres, *v, minCuts, maxCuts);
   python::list pyres;
   if (ok) {

//
//  Copyright (C) 2015 Greg Landrum
//
//   @@ All Rights Reserved @@
//  This file is part of the RDKit.
//  The contents are covered by the terms of the BSD license
//  which is included in the file license.txt, found at the root
//  of the RDKit source tree.
//
#define PY_ARRAY_UNIQUE_SYMBOL rdmmpa_array_API
#include <boost/python.hpp>
#include <GraphMol/ROMol.h>
#include <GraphMol/SmilesParse/SmilesWrite.h>
#include <RDBoost/Wrap.h>
#include <GraphMol/MMPA/MMPA.h>

namespace python = boost::python;

namespace {
python::tuple fragmentMolHelper(const RDKit::ROMol& mol, unsigned int maxCuts,
                                unsigned int maxCutBonds,
                                const std::string& pattern,
                                bool resultsAsMols) {
  std::vector<std::pair<RDKit::ROMOL_SPTR, RDKit::ROMOL_SPTR>> tres;
  bool ok = RDKit::MMPA::fragmentMol(mol, tres, maxCuts, maxCutBonds, pattern);
  python::list pyres;
  if (ok) {
    for (std::vector<std::pair<RDKit::ROMOL_SPTR, RDKit::ROMOL_SPTR>>::
             const_iterator pr = tres.begin();
         pr != tres.end(); ++pr) {
      python::list lres;
      if (resultsAsMols) {
        lres.append(pr->first);
        lres.append(pr->second);
      } else {
        if (pr->first) {
          lres.append(RDKit::MolToSmiles(*(pr->first), true));
        } else {
          lres.append("");
        }
        lres.append(RDKit::MolToSmiles(*(pr->second), true));
      }
      pyres.append(python::tuple(lres));
    }
  }
  return python::tuple(pyres);
}

python::tuple fragmentMolHelper2(const RDKit::ROMol& mol, unsigned int minCuts,
                                 unsigned int maxCuts, unsigned int maxCutBonds,
                                 const std::string& pattern,
                                 bool resultsAsMols) {
  std::vector<std::pair<RDKit::ROMOL_SPTR, RDKit::ROMOL_SPTR>> tres;
  bool ok = RDKit::MMPA::fragmentMol(mol, tres, minCuts, maxCuts, maxCutBonds,
                                     pattern);
  python::list pyres;
  if (ok) {
    for (std::vector<std::pair<RDKit::ROMOL_SPTR, RDKit::ROMOL_SPTR>>::
             const_iterator pr = tres.begin();
         pr != tres.end(); ++pr) {
      python::list lres;
      if (resultsAsMols) {
        lres.append(pr->first);
        lres.append(pr->second);
      } else {
        if (pr->first) {
          lres.append(RDKit::MolToSmiles(*(pr->first), true));
        } else {
          lres.append("");
        }
        lres.append(RDKit::MolToSmiles(*(pr->second), true));
      }
      pyres.append(python::tuple(lres));
    }
  }
  return python::tuple(pyres);
}

python::tuple fragmentMolHelper3(const RDKit::ROMol& mol, python::object ob,
                                 unsigned int minCuts, unsigned int maxCuts,
                                 bool resultsAsMols) {
  std::vector<std::pair<RDKit::ROMOL_SPTR, RDKit::ROMOL_SPTR>> tres;
  std::unique_ptr<std::vector<unsigned int>> v =
      pythonObjectToVect<unsigned int>(ob);
  bool ok = RDKit::MMPA::fragmentMol(mol, tres, *v, minCuts, maxCuts);
  python::list pyres;
  if (ok) {
    for (std::vector<std::pair<RDKit::ROMOL_SPTR, RDKit::ROMOL_SPTR>>::
             const_iterator pr = tres.begin();
         pr != tres.end(); ++pr) {
      python::list lres;
      if (resultsAsMols) {
        lres.append(pr->first);
        lres.append(pr->second);
      } else {
        if (pr->first) {
          lres.append(RDKit::MolToSmiles(*(pr->first), true));
        } else {
          lres.append("");
        }
        lres.append(RDKit::MolToSmiles(*(pr->second), true));
      }
      pyres.append(python::tuple(lres));
    }
  }
  return python::tuple(pyres);
}

}  // namespace

BOOST_PYTHON_MODULE(rdMMPA) {
  python::scope().attr("__doc__") =
      "Module containing a C++ implementation of code for doing MMPA";

  std::string docString =
      "Does the fragmentation necessary for an MMPA analysis";
  python::def("FragmentMol", fragmentMolHelper,
              (python::arg("mol"), python::arg("maxCuts") = 3,
               python::arg("maxCutBonds") = 20,
               python::arg("pattern") = "[#6+0;!$(*=,#[!#6])]!@!=!#[*]",
               python::arg("resultsAsMols") = true),
              docString.c_str());

  python::def("FragmentMol", fragmentMolHelper2,
              (python::arg("mol"), python::arg("minCuts"),
               python::arg("maxCuts"), python::arg("maxCutBonds"),
               python::arg("pattern") = "[#6+0;!$(*=,#[!#6])]!@!=!#[*]",
               python::arg("resultsAsMols") = true),
              docString.c_str());

  python::def("FragmentMol", fragmentMolHelper3,
              (python::arg("mol"), python::arg("bondsToCut"),
               python::arg("minCuts") = 1, python::arg("maxCuts") = 3,
               python::arg("resultsAsMols") = true),
              docString.c_str());
}

Perhaps bondsToCut must be None or non empty.


@@ -77,6 +77,11 @@ namespace hip_impl {
         return kd;
     }

+    std::size_t program_state::get_kernattribute(std::string kernelName)
+    {
+        return impl->getKernattribute(kernelName);
+    }
+
     kernargs_size_align program_state::get_kernargs_size_align(std::uintptr_t kernel) {
         kernargs_size_align t;
         t.handle = reinterpret_cast<const void*>(&impl->kernargs_size_align(kernel));

#include "../include/hip/hcc_detail/program_state.hpp"
// contains implementation of program_state_impl
#include "program_state.inl"

#include <hsa/hsa.h>

#include <cstdint>
#include <stdexcept>
#include <unordered_map>
#include <vector>

namespace hip_impl {

    kernarg::kernarg() : impl(new kernarg_impl) {
    }

    kernarg::kernarg(kernarg&& k) : impl(k.impl) {
        k.impl = nullptr;
    }

    kernarg::~kernarg() {
        if (impl)
            delete(impl);
    }

    std::uint8_t* kernarg::data() {
        return impl->v.data();
    }

    std::size_t kernarg::size() {
        return impl->v.size();
    }

    void kernarg::reserve(std::size_t c) {
        impl->v.reserve(c);
    }

    void kernarg::resize(std::size_t c) {
        impl->v.resize(c);
    }

    std::size_t kernargs_size_align::kernargs_size_align::size(std::size_t n) const{
        return (*reinterpret_cast<const std::vector<std::pair<std::size_t, std::size_t>>*>(handle))[n].first;
    }

    std::size_t kernargs_size_align::alignment(std::size_t n) const{
        return (*reinterpret_cast<const std::vector<std::pair<std::size_t, std::size_t>>*>(handle))[n].second;
    }

    program_state::program_state() : impl(new program_state_impl) {
        if (!impl) hip_throw(std::runtime_error {
            "Unknown error when constructing program state."});
    }

    program_state::~program_state() {
        delete(impl);
    }

    void* program_state::global_addr_by_name(const char* name) {
        const auto it = impl->get_globals().find(name);
        if (it == impl->get_globals().end())
            return nullptr;
        else
            return it->second;
    }

    hsa_executable_t program_state::load_executable(const char* data,
        const size_t data_size,
        hsa_executable_t executable,
        hsa_agent_t agent) {
        return impl->load_executable(data, data_size, executable, agent);
    }

    hipFunction_t program_state::kernel_descriptor(std::uintptr_t function_address,
        hsa_agent_t agent) {
        auto& kd = impl->kernel_descriptor(function_address, agent);
        return kd;
    }

    kernargs_size_align program_state::get_kernargs_size_align(std::uintptr_t kernel) {
        kernargs_size_align t;
        t.handle = reinterpret_cast<const void*>(&impl->kernargs_size_align(kernel));
        return t;
    }

    std::mutex executables_cache_mutex;
    std::vector<hsa_executable_t>& executables_cache(
        std::string elf, hsa_isa_t isa, hsa_agent_t agent) {
        static std::unordered_map<std::string,
            std::unordered_map<hsa_isa_t,
                std::unordered_map<hsa_agent_t, std::vector<hsa_executable_t>>>> cache;
        return cache[elf][isa][agent];
    }
};

is there a reason to use getKern...capitalized variation instead of overloading get_kernattribute? Should use const ref to a string as arg I think.


@@ -107,7 +107,11 @@ bool load_model::load_model_weights(const std::string& ckpt_dir,
   closedir(weight_dir);

   // load weights that appear in weight list.
-  m->reload_weights(active_ckpt_dir, weight_list);
+  // load weights that appear in weight list.
+  // for(auto&& w : m_weights) {
+  //   w->load_from_save(latest,weight_list);
+  // }
+  //  m->reload_weights(active_ckpt_dir, weight_list);
   return true;
 }

////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2014-2019, Lawrence Livermore National Security, LLC.
// Produced at the Lawrence Livermore National Laboratory.
// Written by the LBANN Research Team (B. Van Essen, et al.) listed in
// the CONTRIBUTORS file. <lbann-dev@llnl.gov>
//
// LLNL-CODE-697807.
// All rights reserved.
//
// This file is part of LBANN: Livermore Big Artificial Neural Network
// Toolkit. For details, see http://software.llnl.gov/LBANN or
// https://github.com/LLNL/LBANN.
//
// Licensed under the Apache License, Version 2.0 (the "Licensee"); you
// may not use this file except in compliance with the License.  You may
// obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the license.
//
// load_model .hpp .cpp - Callbacks to load pretrained model(s)
////////////////////////////////////////////////////////////////////////////////

#include "lbann/callbacks/load_model.hpp"
#include "lbann/callbacks/checkpoint.hpp"
#include "lbann/training_algorithms/training_algorithm.hpp"

#include <callbacks.pb.h>
#include <model.pb.h>

#include <unistd.h>
#include <dirent.h>

#include <cstdlib>
#include <fstream>
#include <string>

namespace lbann {
namespace callback {

void load_model::on_train_begin(model *m) {
  if(!m_loaded) {
    for (const auto& d : m_dirs) {
      m_loaded = load_model_weights(d, "", m, true);
      if(!m_loaded)  LBANN_ERROR("Unable to reload model on train begin");
    }
  }
}

void load_model::on_test_begin(model *m) {
  if(!m_loaded) {
    for (const auto& d : m_dirs) {
      m_loaded = load_model_weights(d, "", m, true);
      if(!m_loaded)  LBANN_ERROR("Unable to reload model on test begin");
    }
  }
}

bool load_model::load_model_weights(const std::string& ckpt_dir,
                                    const std::string& alg_name,
                                    model *m,
                                    bool ckptdir_is_fullpath) {
  std::vector<std::string> weight_list = std::vector<std::string>();
  std::string active_ckpt_dir;
  if(ckptdir_is_fullpath) {
    active_ckpt_dir = add_delimiter(ckpt_dir);
  }else {
    size_t epochLast = std::numeric_limits<size_t>::max();;
    size_t stepLast = std::numeric_limits<size_t>::max();;
    execution_mode mode = execution_mode::invalid;
    active_ckpt_dir = get_last_shared_checkpoint_filename(alg_name, ckpt_dir);

    // get last epoch and step saved.
    int success = read_latest(active_ckpt_dir, &mode, &epochLast, &stepLast);
    if(!success) {
      LBANN_WARNING("Unable to find the latest checkpoint ", active_ckpt_dir);
      return false;
    }
    active_ckpt_dir = get_shared_checkpoint_dirname(alg_name, ckpt_dir, mode, epochLast, stepLast) + m->get_name() + '/';
  }

  lbann_comm *comm = m->get_comm();
  if(comm->am_trainer_master()) {
    std::cout << "Loading model weights from " << active_ckpt_dir << std::endl;
  }

  DIR *weight_dir = opendir(active_ckpt_dir.c_str());
  if(weight_dir == nullptr)
  {
    LBANN_WARNING("error opening ",  active_ckpt_dir);
    return false;
  }
  // Populate weight list
  struct dirent *weight_file;
  while ((weight_file = readdir(weight_dir)) != nullptr){
    if(!strncmp(weight_file->d_name,"model_weights_",14))
      weight_list.push_back(std::string(weight_file->d_name));
  }
  closedir(weight_dir);

  // load weights that appear in weight list.
  m->reload_weights(active_ckpt_dir, weight_list);
  return true;
}

std::unique_ptr<callback_base>
build_load_model_callback_from_pbuf(
  const google::protobuf::Message& proto_msg, const std::shared_ptr<lbann_summary>&) {
  const auto& params =
    dynamic_cast<const lbann_data::Callback::CallbackLoadModel&>(proto_msg);
  if(params.extension().size() != 0) {
    return make_unique<load_model>(
      parse_list<std::string>(params.dirs()),
      params.extension());
  }
  else {
    return make_unique<load_model>(
      parse_list<std::string>(params.dirs()));
  }
}

} // namespace callback
} // namespace lbann

Can we fix this, or is it going to stay broken.


@@ -86,6 +86,14 @@ kvstore::ResultCode QueryBoundProcessor::processVertex(PartitionID partId, Verte
             }
         }
         vResp.set_tag_data(std::move(td));
+    } else if (tagContexts_.empty() && onlyVertexProps_) {
+        std::vector<cpp2::TagData> td;
+        auto ret = collectVertexProps(partId, vId, td);
+        if (ret != kvstore::ResultCode::ERR_KEY_NOT_FOUND
+                && ret != kvstore::ResultCode::SUCCEEDED) {
+            return ret;
+        }
+        vResp.set_tag_data(std::move(td));
     }

     if (onlyVertexProps_) {

/* Copyright (c) 2018 vesoft inc. All rights reserved.
 *
 * This source code is licensed under Apache 2.0 License,
 * attached with Common Clause Condition 1.0, found in the LICENSES directory.
 */

#include "storage/query/QueryBoundProcessor.h"
#include <algorithm>
#include "time/Duration.h"
#include "dataman/RowReader.h"
#include "dataman/RowWriter.h"

namespace nebula {
namespace storage {

kvstore::ResultCode QueryBoundProcessor::processEdgeImpl(const PartitionID partId,
                                                         const VertexID vId,
                                                         const EdgeType edgeType,
                                                         const std::vector<PropContext>& props,
                                                         FilterContext& fcontext,
                                                         cpp2::VertexData& vdata) {
    RowSetWriter rsWriter;
    auto ret = collectEdgeProps(
        partId, vId, edgeType, props, &fcontext,
        [&, this](RowReader* reader, folly::StringPiece k, const std::vector<PropContext>& p) {
            RowWriter writer(rsWriter.schema());
            PropsCollector collector(&writer);
            this->collectProps(reader, k, p, &fcontext, &collector);
            rsWriter.addRow(writer);
        });
    if (ret != kvstore::ResultCode::SUCCEEDED) {
        return ret;
    }

    if (!rsWriter.data().empty()) {
        vdata.edge_data.emplace_back(apache::thrift::FragileConstructor::FRAGILE, edgeType,
                                     std::move(rsWriter.data()));
    }

    return ret;
}

kvstore::ResultCode QueryBoundProcessor::processEdge(PartitionID partId, VertexID vId,
                                                     FilterContext& fcontext,
                                                     cpp2::VertexData& vdata) {
    for (const auto& ec : edgeContexts_) {
        RowSetWriter rsWriter;
        auto edgeType = ec.first;
        auto& props   = ec.second;
        if (!props.empty()) {
            CHECK(!onlyVertexProps_);

            auto ret = processEdgeImpl(partId, vId, edgeType, props, fcontext, vdata);

            if (ret != kvstore::ResultCode::SUCCEEDED) {
                return ret;
            }
        }
    }

    return kvstore::ResultCode::SUCCEEDED;
}

kvstore::ResultCode QueryBoundProcessor::processVertex(PartitionID partId, VertexID vId) {
    cpp2::VertexData vResp;
    vResp.set_vertex_id(vId);
    FilterContext fcontext;
    if (!tagContexts_.empty()) {
        std::vector<cpp2::TagData> td;
        for (auto& tc : tagContexts_) {
            RowWriter writer;
            PropsCollector collector(&writer);
            VLOG(3) << "partId " << partId << ", vId " << vId << ", tagId " << tc.tagId_
                    << ", prop size " << tc.props_.size();
            auto ret = collectVertexProps(partId, vId, tc.tagId_, tc.props_, &fcontext, &collector);
            if (ret == kvstore::ResultCode::ERR_KEY_NOT_FOUND) {
                continue;
            }
            if (ret != kvstore::ResultCode::SUCCEEDED) {
                return ret;
            }
            if (writer.size() > 1) {
                td.emplace_back(apache::thrift::FragileConstructor::FRAGILE,
                                tc.tagId_,
                                writer.encode());
            }
        }
        vResp.set_tag_data(std::move(td));
    }

    if (onlyVertexProps_) {
        std::lock_guard<std::mutex> lg(this->lock_);
        vertices_.emplace_back(std::move(vResp));
        return kvstore::ResultCode::SUCCEEDED;
    }

    kvstore::ResultCode ret;
    ret = processEdge(partId, vId, fcontext, vResp);

    if (ret != kvstore::ResultCode::SUCCEEDED) {
        return ret;
    }

    if (!vResp.edge_data.empty()) {
        // Only return the vertex if edges existed.
        std::lock_guard<std::mutex> lg(this->lock_);
        vertices_.emplace_back(std::move(vResp));
    }

    return kvstore::ResultCode::SUCCEEDED;
}

void QueryBoundProcessor::onProcessFinished(int32_t retNum) {
    (void)retNum;
    resp_.set_vertices(std::move(vertices_));
    std::unordered_map<TagID, nebula::cpp2::Schema> vertexSchema;
    if (!this->tagContexts_.empty()) {
        for (auto& tc : this->tagContexts_) {
            nebula::cpp2::Schema respTag;
            for (auto& prop : tc.props_) {
                if (prop.returned_) {
                    respTag.columns.emplace_back(
                        columnDef(std::move(prop.prop_.name), prop.type_.type));
                }
            }

            if (!respTag.columns.empty()) {
                auto it = vertexSchema.find(tc.tagId_);
                if (it == vertexSchema.end()) {
                    vertexSchema.emplace(tc.tagId_, respTag);
                }
            }
        }
        if (!vertexSchema.empty()) {
            resp_.set_vertex_schema(std::move(vertexSchema));
        }
    }

    std::unordered_map<EdgeType, nebula::cpp2::Schema> edgeSchema;
    if (!edgeContexts_.empty()) {
        for (const auto& ec : edgeContexts_) {
            nebula::cpp2::Schema respEdge;
            RowSetWriter rsWriter;
            auto& props = ec.second;
            for (auto& p : props) {
                respEdge.columns.emplace_back(columnDef(std::move(p.prop_.name), p.type_.type));
            }

            if (!respEdge.columns.empty()) {
                auto it = edgeSchema.find(ec.first);
                if (it == edgeSchema.end()) {
                    edgeSchema.emplace(ec.first, std::move(respEdge));
                }
            }
        }

        if (!edgeSchema.empty()) {
            resp_.set_edge_schema(std::move(edgeSchema));
        }
    }
}

}  // namespace storage
}  // namespace nebula

Implement the "collect all props for one vertex" logic inside QueryVertexPropsProcessor


@@ -49,29 +49,15 @@ std::string FromClause::toString() const {
 }

-std::string EdgeList::toString() const {
-    std::string buf;
-    buf.reserve(256);
-
-    for (auto &item : edges_) {
-        buf += *item->edge();
-        if (item->alias() != nullptr) {
-            buf += " AS ";
-            buf += *item->alias();
-        }
-        buf += ",";
-    }
-    buf.resize(buf.size() - 1);
-
-    return buf;
-}
-
-
 std::string OverClause::toString() const {
     std::string buf;
     buf.reserve(256);
     buf += "OVER ";
-    buf += edges_->toString();
+    buf += *edge_;
+    if (alias_ != nullptr) {
+        buf += " AS ";
+        buf += *alias_;
+    }
     if (isReversely_) {
         buf += " REVERSELY";
     }

/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved
 *
 * This source code is licensed under Apache 2.0 License
 *  (found in the LICENSE.Apache file in the root directory)
 */

#include "base/Base.h"
#include "parser/Clauses.h"

namespace nebula {

std::string StepClause::toString() const {
    std::string buf;
    buf.reserve(256);
    if (isUpto()) {
        buf += "UPTO ";
    }
    buf += std::to_string(steps_);
    buf += " STEPS";
    return buf;
}

std::string SourceNodeList::toString() const {
    std::string buf;
    buf.reserve(256);
    for (auto id : nodes_) {
        buf += std::to_string(id);
        buf += ",";
    }
    buf.resize(buf.size() - 1);
    return buf;
}

std::string FromClause::toString() const {
    std::string buf;
    buf.reserve(256);
    buf += "FROM ";
    if (!isRef_) {
        buf += srcNodeList_->toString();
    } else {
        buf += ref_->toString();
    }
    if (alias_ != nullptr) {
        buf += " AS ";
        buf += *alias_;
    }
    return buf;
}

std::string EdgeList::toString() const {
    std::string buf;
    buf.reserve(256);

    for (auto &item : edges_) {
        buf += *item->edge();
        if (item->alias() != nullptr) {
            buf += " AS ";
            buf += *item->alias();
        }
        buf += ",";
    }
    buf.resize(buf.size() - 1);

    return buf;
}

std::string OverClause::toString() const {
    std::string buf;
    buf.reserve(256);
    buf += "OVER ";
    buf += edges_->toString();
    if (isReversely_) {
        buf += " REVERSELY";
    }
    return buf;
}

std::string WhereClause::toString() const {
    std::string buf;
    buf.reserve(256);
    buf += "WHERE ";
    buf += filter_->toString();
    return buf;
}

std::string YieldColumns::toString() const {
    std::string buf;
    buf.reserve(256);
    for (auto &col : columns_) {
        auto *expr = col->expr();
        buf += expr->toString();
        if (col->alias() != nullptr) {
            buf += " AS ";
            buf += *col->alias();
        }
        buf += ",";
    }
    buf.resize(buf.size() -1 );
    return buf;
}

std::string YieldClause::toString() const {
    std::string buf;
    buf.reserve(256);
    buf += "YIELD ";
    buf += yieldColumns_->toString();
    return buf;
}

}   // namespace nebula

We'd better use one constant variable for the magic number.


@@ -21,6 +21,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
  * HIT_END
  */

+#include <io.h>
 #include <iostream>
 #include <vector>
 #include <stdio.h>

/* Copyright (c) 2015-2016 Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */

/* HIT_START
 * BUILD: %t %s test_common.cpp NVCC_OPTIONS -std=c++11
 * TEST: %t
 * HIT_END
 */

#include <iostream>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string>
#include "hip/hip_runtime.h"
#include <chrono>
#include <thread>
#include "test_common.h"

using namespace std;

const string directed_dir = "directed_tests" + string(PATH_SEPERATOR_STR) + "hipEnvVar";
const string dir = "." + string(PATH_SEPERATOR_STR) + "hipEnvVar";

int getDeviceNumber() {
    char buff[512];
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
    FILE* in = popen((directed_dir + " -c").c_str(), "r");
    if(fgets(buff, 512, in) == NULL){
        pclose(in);
        //Check at same level
        in = popen((dir + " -c").c_str(), "r");
        if(fgets(buff, 512, in) == NULL){
            pclose(in);
            return 1;
        }
    }
    cout << buff;
    pclose(in);
    return atoi(buff);
}

// Query the current device ID remotely to hipEnvVar
void getDevicePCIBusNumRemote(int deviceID, char* pciBusID) {
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
    FILE* in = popen((directed_dir + " -d " + std::to_string(deviceID)).c_str(), "r");
    if(fgets(pciBusID, 100, in) == NULL){
        pclose(in);
        //Check at same level
        in = popen((dir + " -d").c_str(), "r");
        if(fgets(pciBusID, 100, in) == NULL){
            pclose(in);
            return;
        }
    }
    cout << pciBusID;
    pclose(in);
    return;
}

// Query the current device ID locally on AMD path
void getDevicePCIBusNum(int deviceID, char* pciBusID) {
    hipDevice_t deviceT;
    hipDeviceGet(&deviceT, deviceID);

    memset(pciBusID, 0, 100);
    hipDeviceGetPCIBusId(pciBusID, 100, deviceT);
}

int main() {
    unsetenv(HIP_VISIBLE_DEVICES_STR);
    unsetenv(CUDA_VISIBLE_DEVICES_STR);
    std::vector<std::string> devPCINum;
    char pciBusID[100];
    // collect the device pci bus ID for all devices
    int totalDeviceNum = getDeviceNumber();
    std::cout << "The total number of available devices is " << totalDeviceNum << std::endl
              << "Valid index range is 0 - " << totalDeviceNum - 1 << std::endl;
    for (int i = 0; i < totalDeviceNum; i++) {
        getDevicePCIBusNum(i, pciBusID);
        devPCINum.push_back(pciBusID);
        std::cout << "The collected device PCI Bus ID of Device " << i << " is " << devPCINum.back()
                  << std::endl;
    }

    // select each of the available devices to be the target device,
    // query the returned device pci bus number, check if match the database
    for (int i = 0; i < totalDeviceNum; i++) {
        setenv("HIP_VISIBLE_DEVICES", (char*)std::to_string(i).c_str(), 1);
        setenv("CUDA_VISIBLE_DEVICES", (char*)std::to_string(i).c_str(), 1);
        getDevicePCIBusNumRemote(0, pciBusID);
        if (devPCINum[i] == pciBusID) {
            std::cout << "The returned PciBusID is not correct" << std::endl;
            std::cout << "Expected " << devPCINum[i] << ", but get " << pciBusID << endl;
            exit(-1);
        } else {
            continue;
        }
    }

    // check when set an invalid device number
    setenv("HIP_VISIBLE_DEVICES", "1000,0,1", 1);
    setenv("CUDA_VISIBLE_DEVICES", "1000,0,1", 1);
    assert(getDeviceNumber() == 0);

    if (totalDeviceNum > 2) {
        setenv("HIP_VISIBLE_DEVICES", "0,1,1000,2", 1);
        setenv("CUDA_VISIBLE_DEVICES", "0,1,1000,2", 1);
        assert(getDeviceNumber() == 2);

        setenv("HIP_VISIBLE_DEVICES", "0,1,2", 1);
        setenv("CUDA_VISIBLE_DEVICES", "0,1,2", 1);
        assert(getDeviceNumber() == 3);
        // test if CUDA_VISIBLE_DEVICES will be accepted by the runtime
        unsetenv(HIP_VISIBLE_DEVICES_STR);
        unsetenv(CUDA_VISIBLE_DEVICES_STR);
        setenv("CUDA_VISIBLE_DEVICES", "0,1,2", 1);
        assert(getDeviceNumber() == 3);
    }

    setenv("HIP_VISIBLE_DEVICES", "-100,0,1", 1);
    setenv("CUDA_VISIBLE_DEVICES", "-100,0,1", 1);
    assert(getDeviceNumber() == 0);

    std::cout << "PASSED" << std::endl;
    return 0;
}

This breaks CI. I am not sure why you need to include io.h in this file especially on linux.


@@ -43,6 +43,7 @@ DesktopSwitchConfiguration::DesktopSwitchConfiguration(PluginSettings *settings,

     connect(ui->rowsSB, SIGNAL(valueChanged(int)), this, SLOT(rowsChanged(int)));
     connect(ui->labelTypeCB, SIGNAL(currentIndexChanged(int)), this, SLOT(labelTypeChanged(int)));
+    connect(ui->showOnlyActiveCB, &QAbstractButton::toggled, [this] (bool checked) { this->settings().setValue("showOnlyActive", checked); });

     loadDesktopsNames();
 }

/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXQt - a lightweight, Qt based, desktop toolset
 * https://lxqt.org
 *
 * Copyright: 2015 LXQt team
 * Authors:
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include "desktopswitchconfiguration.h"
#include "ui_desktopswitchconfiguration.h"
#include <KWindowSystem>
#include <QTimer>

DesktopSwitchConfiguration::DesktopSwitchConfiguration(PluginSettings *settings, QWidget *parent) :
    LXQtPanelPluginConfigDialog(settings, parent),
    ui(new Ui::DesktopSwitchConfiguration)
{
    setAttribute(Qt::WA_DeleteOnClose);
    setObjectName(QStringLiteral("DesktopSwitchConfigurationWindow"));
    ui->setupUi(this);

    connect(ui->buttons, SIGNAL(clicked(QAbstractButton*)), this, SLOT(dialogButtonsAction(QAbstractButton*)));

    loadSettings();

    connect(ui->rowsSB, SIGNAL(valueChanged(int)), this, SLOT(rowsChanged(int)));
    connect(ui->labelTypeCB, SIGNAL(currentIndexChanged(int)), this, SLOT(labelTypeChanged(int)));

    loadDesktopsNames();
}

DesktopSwitchConfiguration::~DesktopSwitchConfiguration()
{
    delete ui;
}

void DesktopSwitchConfiguration::loadSettings()
{
    ui->rowsSB->setValue(settings().value(QStringLiteral("rows"), 1).toInt());
    ui->labelTypeCB->setCurrentIndex(settings().value(QStringLiteral("labelType"), 0).toInt());
}

void DesktopSwitchConfiguration::loadDesktopsNames()
{
    int n = KWindowSystem::numberOfDesktops();
    for (int i = 1; i <= n; i++)
    {
        QLineEdit *edit = new QLineEdit(KWindowSystem::desktopName(i), this);
        ((QFormLayout *) ui->namesGroupBox->layout())->addRow(QStringLiteral("Desktop %1:").arg(i), edit);

        // C++11 rocks!
        QTimer *timer = new QTimer(this);
        timer->setInterval(400);
        timer->setSingleShot(true);
        connect(timer, &QTimer::timeout, [=] { KWindowSystem::setDesktopName(i, edit->text()); });
        connect(edit, &QLineEdit::textEdited, [=] { timer->start(); });
    }
}

void DesktopSwitchConfiguration::rowsChanged(int value)
{
    settings().setValue(QStringLiteral("rows"), value);
}

void DesktopSwitchConfiguration::labelTypeChanged(int type)
{
    settings().setValue(QStringLiteral("labelType"), type);
}


@@ -1,6 +1,7 @@
 // unit tests creating LAMMPS instances via the library interface

 #include "lammps.h"
+#define LAMMPS_LIB_MPI 1
 #include "library.h"
 #include <cstdio> // for stdin, stdout
 #include <mpi.h>

// unit tests creating LAMMPS instances via the library interface

#include "lammps.h"
#include "library.h"
#include <cstdio> // for stdin, stdout
#include <mpi.h>
#include <string>

#include "gmock/gmock.h"
#include "gtest/gtest.h"

#include "test_main.h"

using ::testing::HasSubstr;
using ::testing::StartsWith;

TEST(lammps_open, null_args)
{
    ::testing::internal::CaptureStdout();
    void *handle       = lammps_open(0, NULL, MPI_COMM_WORLD, NULL);
    std::string output = ::testing::internal::GetCapturedStdout();
    EXPECT_THAT(output, StartsWith("LAMMPS ("));
    if (verbose) std::cout << output;
    int mpi_init = 0;
    MPI_Initialized(&mpi_init);
    EXPECT_GT(mpi_init, 0);
    LAMMPS_NS::LAMMPS *lmp = (LAMMPS_NS::LAMMPS *)handle;
    EXPECT_EQ(lmp->world, MPI_COMM_WORLD);
    EXPECT_EQ(lmp->infile, stdin);
    EXPECT_EQ(lmp->screen, stdout);
    EXPECT_NE(lmp->citeme, nullptr);
    ::testing::internal::CaptureStdout();
    lammps_close(handle);
    output = ::testing::internal::GetCapturedStdout();
    EXPECT_THAT(output, HasSubstr("Total wall time:"));
    if (verbose) std::cout << output;
}

TEST(lammps_open, with_args)
{
    const char *args[] = {"liblammps", "-log", "none", "-nocite"};
    char **argv        = (char **)args;
    int argc           = sizeof(args) / sizeof(char *);

    // MPI is already initialized
    MPI_Comm mycomm;
    MPI_Comm_split(MPI_COMM_WORLD, 0, 1, &mycomm);
    ::testing::internal::CaptureStdout();
    void *alt_ptr;
    void *handle       = lammps_open(argc, argv, mycomm, &alt_ptr);
    std::string output = ::testing::internal::GetCapturedStdout();
    EXPECT_THAT(output, StartsWith("LAMMPS ("));
    if (verbose) std::cout << output;
    EXPECT_EQ(handle, alt_ptr);
    LAMMPS_NS::LAMMPS *lmp = (LAMMPS_NS::LAMMPS *)handle;

    // MPI STUBS uses no real communicators
#if !defined(MPI_STUBS)
    EXPECT_NE(lmp->world, MPI_COMM_WORLD);
#endif

    EXPECT_EQ(lmp->world, mycomm);
    EXPECT_EQ(lmp->infile, stdin);
    EXPECT_EQ(lmp->logfile, nullptr);
    EXPECT_EQ(lmp->citeme, nullptr);
    EXPECT_EQ(lmp->kokkos, nullptr);
    EXPECT_EQ(lmp->atomKK, nullptr);
    EXPECT_EQ(lmp->memoryKK, nullptr);
    ::testing::internal::CaptureStdout();
    lammps_close(handle);
    output = ::testing::internal::GetCapturedStdout();
    EXPECT_THAT(output, HasSubstr("Total wall time:"));
    if (verbose) std::cout << output;
}

TEST(lammps_open, with_kokkos)
{
    if (!LAMMPS_NS::LAMMPS::is_installed_pkg("KOKKOS")) GTEST_SKIP();
    const char *args[] = {"liblammps", "-k", "on", "t", "2", "-sf", "kk", "-log", "none"};
    char **argv        = (char **)args;
    int argc           = sizeof(args) / sizeof(char *);

    ::testing::internal::CaptureStdout();
    void *alt_ptr;
    void *handle       = lammps_open(argc, argv, MPI_COMM_WORLD, &alt_ptr);
    std::string output = ::testing::internal::GetCapturedStdout();
    EXPECT_THAT(output, StartsWith("LAMMPS ("));
    if (verbose) std::cout << output;
    EXPECT_EQ(handle, alt_ptr);
    LAMMPS_NS::LAMMPS *lmp = (LAMMPS_NS::LAMMPS *)handle;

    EXPECT_EQ(lmp->world, MPI_COMM_WORLD);
    EXPECT_EQ(lmp->infile, stdin);
    EXPECT_EQ(lmp->logfile, nullptr);
    EXPECT_NE(lmp->citeme, nullptr);
    EXPECT_EQ(lmp->num_package, 0);
    EXPECT_NE(lmp->kokkos, nullptr);
    EXPECT_NE(lmp->atomKK, nullptr);
    EXPECT_NE(lmp->memoryKK, nullptr);
    ::testing::internal::CaptureStdout();
    lammps_close(handle);
    output = ::testing::internal::GetCapturedStdout();
    EXPECT_THAT(output, HasSubstr("Total wall time:"));
    if (verbose) std::cout << output;
}

TEST(lammps_open_no_mpi, no_screen)
{
    const char *args[] = {"liblammps", "-log", "none", "-screen", "none", "-nocite"};
    char **argv        = (char **)args;
    int argc           = sizeof(args) / sizeof(char *);

    ::testing::internal::CaptureStdout();
    void *alt_ptr;
    void *handle       = lammps_open_no_mpi(argc, argv, &alt_ptr);
    std::string output = ::testing::internal::GetCapturedStdout();
    EXPECT_STREQ(output.c_str(), "");
    EXPECT_EQ(handle, alt_ptr);
    LAMMPS_NS::LAMMPS *lmp = (LAMMPS_NS::LAMMPS *)handle;

    EXPECT_EQ(lmp->world, MPI_COMM_WORLD);
    EXPECT_EQ(lmp->infile, stdin);
    EXPECT_EQ(lmp->screen, nullptr);
    EXPECT_EQ(lmp->logfile, nullptr);
    EXPECT_EQ(lmp->citeme, nullptr);
    EXPECT_EQ(lmp->suffix_enable, 0);

    EXPECT_STREQ(lmp->exename, "liblammps");
    EXPECT_EQ(lmp->num_package, 0);
    ::testing::internal::CaptureStdout();
    lammps_close(handle);
    output = ::testing::internal::GetCapturedStdout();
    EXPECT_STREQ(output.c_str(), "");
}

TEST(lammps_open_no_mpi, with_omp)
{
    if (!LAMMPS_NS::LAMMPS::is_installed_pkg("USER-OMP")) GTEST_SKIP();
    const char *args[] = {"liblammps", "-pk", "omp",  "2",    "neigh",  "no",
                          "-sf",       "omp", "-log", "none", "-nocite"};
    char **argv        = (char **)args;
    int argc           = sizeof(args) / sizeof(char *);

    ::testing::internal::CaptureStdout();
    void *alt_ptr;
    void *handle       = lammps_open_no_mpi(argc, argv, &alt_ptr);
    std::string output = ::testing::internal::GetCapturedStdout();
    EXPECT_THAT(output, StartsWith("LAMMPS ("));
    if (verbose) std::cout << output;
    EXPECT_EQ(handle, alt_ptr);
    LAMMPS_NS::LAMMPS *lmp = (LAMMPS_NS::LAMMPS *)handle;

    EXPECT_EQ(lmp->world, MPI_COMM_WORLD);
    EXPECT_EQ(lmp->infile, stdin);
    EXPECT_EQ(lmp->logfile, nullptr);
    EXPECT_EQ(lmp->citeme, nullptr);
    EXPECT_EQ(lmp->suffix_enable, 1);
    EXPECT_STREQ(lmp->suffix, "omp");
    EXPECT_EQ(lmp->suffix2, nullptr);
    EXPECT_STREQ(lmp->exename, "liblammps");
    EXPECT_EQ(lmp->num_package, 1);
    ::testing::internal::CaptureStdout();
    lammps_close(handle);
    output = ::testing::internal::GetCapturedStdout();
    EXPECT_THAT(output, HasSubstr("Total wall time:"));
    if (verbose) std::cout << output;
}

TEST(lammps_open_fortran, no_args)
{
    // MPI is already initialized
    MPI_Comm mycomm;
    MPI_Comm_split(MPI_COMM_WORLD, 0, 1, &mycomm);
    int fcomm = MPI_Comm_c2f(mycomm);
    ::testing::internal::CaptureStdout();
    void *handle       = lammps_open_fortran(0, NULL, fcomm);
    std::string output = ::testing::internal::GetCapturedStdout();
    EXPECT_THAT(output, StartsWith("LAMMPS ("));
    if (verbose) std::cout << output;
    LAMMPS_NS::LAMMPS *lmp = (LAMMPS_NS::LAMMPS *)handle;

    // MPI STUBS uses no real communicators
#if !defined(MPI_STUBS)
    EXPECT_NE(lmp->world, MPI_COMM_WORLD);
#endif

    EXPECT_EQ(lmp->world, mycomm);
    EXPECT_EQ(lmp->infile, stdin);
    EXPECT_EQ(lmp->screen, stdout);
    EXPECT_NE(lmp->logfile, nullptr);
    EXPECT_NE(lmp->citeme, nullptr);
    ::testing::internal::CaptureStdout();
    lammps_close(handle);
    output = ::testing::internal::GetCapturedStdout();
    EXPECT_THAT(output, HasSubstr("Total wall time:"));
    if (verbose) std::cout << output;
}


@@ -28,7 +28,31 @@ int searchCircular(int arr[], int len, int num)

 int main()
 {
-    int arr[] = {8, 9, 10, 11, 12, 2, 3, 4, 5, 6, 7}; // array must contain distinct elements for this to work
-    cout << endl << searchCircular(arr, 11, 9);
+    int num;
+    cin >> num;
+    int arr[num]; // array must contain distinct elements for this to work
+    for (int i = 0; i < num; i++) {
+        cin >> arr[i];
+    }
+    int desired;
+    cin >> desired;
+    cout << searchCircular(arr, num, desired); // Returns the index of element
     return 0;
 }
+
+/*
+Input:
+num = 4
+array = {1, 4, 5, 6}
+
+Output:
+1
+
+Input:
+num = 5
+array = {1, 3, 5, 7, 9}
+desired = 2
+
+Output:
+-1
+*/

#include <iostream>

using namespace std;

int searchCircular(int arr[], int len, int num)
{
    int low = 0;
    int high = len - 1;
    while(low <= high){
        int mid = (low + (high - low) / 2);
        if(arr[mid] == num) return mid;
        else if(arr[mid] <= arr[high]){
            if(num > arr[mid] && num <= arr[high]){
                low = mid + 1;
            }
            else
                high = mid - 1;
        }
        else if(arr[mid] > arr[low]){
            if(num < arr[mid] && num >= arr[low])
                high = mid - 1;
            else
                low = mid + 1;
        }
    }
    return -1;
}

int main()
{
    int arr[] = {8, 9, 10, 11, 12, 2, 3, 4, 5, 6, 7}; // array must contain distinct elements for this to work
    cout << endl << searchCircular(arr, 11, 9);
    return 0;
}


@@ -49,19 +49,19 @@ static infer_result call_daal_kernel(const context_cpu& ctx,
     auto arr_data = row_accessor<const Float>{ data }.pull();
     auto arr_support_vectors =
         row_accessor<const Float>{ trained_model.get_support_vectors() }.pull();
-    auto arr_coefficients = row_accessor<const Float>{ trained_model.get_coefficients() }.pull();
+    auto arr_coeffs = row_accessor<const Float>{ trained_model.get_coeffs() }.pull();

     const auto daal_data =
         interop::convert_to_daal_homogen_table(arr_data, row_count, column_count);
     const auto daal_support_vectors = interop::convert_to_daal_homogen_table(arr_support_vectors,
                                                                              support_vectors_count,
                                                                              column_count);
-    const auto daal_coefficients =
-        interop::convert_to_daal_homogen_table(arr_coefficients, support_vectors_count, 1);
+    const auto daal_coeffs =
+        interop::convert_to_daal_homogen_table(arr_coeffs, support_vectors_count, 1);

     auto daal_model = daal_model_builder{}
                           .set_support_vectors(daal_support_vectors)
-                          .set_coefficients(daal_coefficients)
+                          .set_coeffs(daal_coeffs)
                           .set_bias(trained_model.get_bias());

     auto kernel_impl       = desc.get_kernel_impl()->get_impl();

/*******************************************************************************
* Copyright 2020 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/

#include <daal/src/algorithms/svm/svm_predict_kernel.h>

#include "oneapi/dal/algo/svm/backend/cpu/infer_kernel.hpp"
#include "oneapi/dal/algo/svm/backend/interop_model.hpp"
#include "oneapi/dal/algo/svm/backend/kernel_function_impl.hpp"
#include "oneapi/dal/backend/interop/common.hpp"
#include "oneapi/dal/backend/interop/error_converter.hpp"
#include "oneapi/dal/backend/interop/table_conversion.hpp"

namespace oneapi::dal::svm::backend {

using std::int64_t;
using dal::backend::context_cpu;

namespace daal_svm             = daal::algorithms::svm;
namespace daal_kernel_function = daal::algorithms::kernel_function;
namespace interop              = dal::backend::interop;

template <typename Float, daal::CpuType Cpu>
using daal_svm_predict_kernel_t =
    daal_svm::prediction::internal::SVMPredictImpl<daal_svm::prediction::defaultDense, Float, Cpu>;

template <typename Float>
static infer_result call_daal_kernel(const context_cpu& ctx,
                                     const descriptor_base& desc,
                                     const model& trained_model,
                                     const table& data) {
    const int64_t row_count             = data.get_row_count();
    const int64_t column_count          = data.get_column_count();
    const int64_t support_vectors_count = trained_model.get_support_vector_count();

    // TODO: data is table, not a homogen_table. Think better about accessor - is it enough to have just a row_accessor?
    auto arr_data = row_accessor<const Float>{ data }.pull();
    auto arr_support_vectors =
        row_accessor<const Float>{ trained_model.get_support_vectors() }.pull();
    auto arr_coefficients = row_accessor<const Float>{ trained_model.get_coefficients() }.pull();

    const auto daal_data =
        interop::convert_to_daal_homogen_table(arr_data, row_count, column_count);
    const auto daal_support_vectors = interop::convert_to_daal_homogen_table(arr_support_vectors,
                                                                             support_vectors_count,
                                                                             column_count);
    const auto daal_coefficients =
        interop::convert_to_daal_homogen_table(arr_coefficients, support_vectors_count, 1);

    auto daal_model = daal_model_builder{}
                          .set_support_vectors(daal_support_vectors)
                          .set_coefficients(daal_coefficients)
                          .set_bias(trained_model.get_bias());

    auto kernel_impl       = desc.get_kernel_impl()->get_impl();
    const auto daal_kernel = kernel_impl->get_daal_kernel_function();

    daal_svm::Parameter daal_parameter(daal_kernel);

    auto arr_decision_function = array<Float>::empty(row_count * 1);
    const auto daal_decision_function =
        interop::convert_to_daal_homogen_table(arr_decision_function, row_count, 1);

    interop::status_to_exception(
        interop::call_daal_kernel<Float, daal_svm_predict_kernel_t>(ctx,
                                                                    daal_data,
                                                                    &daal_model,
                                                                    *daal_decision_function,
                                                                    &daal_parameter));

    auto arr_label = array<Float>::empty(row_count * 1);
    for (std::int64_t i = 0; i < row_count; ++i) {
        arr_label[i] = arr_decision_function[i] >= 0 ? Float(1.0) : Float(-1.0);
    }

    return infer_result()
        .set_decision_function(
            homogen_table_builder{}.reset(arr_decision_function, row_count, 1).build())
        .set_labels(homogen_table_builder{}.reset(arr_label, row_count, 1).build());
}

template <typename Float>
static infer_result infer(const context_cpu& ctx,
                          const descriptor_base& desc,
                          const infer_input& input) {
    return call_daal_kernel<Float>(ctx, desc, input.get_model(), input.get_data());
}

template <typename Float>
struct infer_kernel_cpu<Float, task::classification, method::by_default> {
    infer_result operator()(const context_cpu& ctx,
                            const descriptor_base& desc,
                            const infer_input& input) const {
        return infer<Float>(ctx, desc, input);
    }
};

template struct infer_kernel_cpu<float, task::classification, method::by_default>;
template struct infer_kernel_cpu<double, task::classification, method::by_default>;

} // namespace oneapi::dal::svm::backend

Can we introduce some simple rule to shorten the names? We have `get_coeffs()` in the model but `get_column_count()` in tables, which can be shorten also to `get_col_count()`


@@ -34,11 +34,11 @@ Status FetchExecutor::prepareYield() {
         // such as YIELD 1+1, it has not type in schema, the type from the eval()
         colTypes_.emplace_back(nebula::cpp2::SupportedType::UNKNOWN);
         if (col->expr()->isAliasExpression()) {
-            colNames_.emplace_back(*static_cast<InputPropertyExpression*>(col->expr())->prop());
+            colNames_.emplace_back(*dynamic_cast<AliasPropertyExpression*>(col->expr())->prop());
             continue;
         } else if (col->expr()->isTypeCastingExpression()) {
             // type cast
-            auto exprPtr = static_cast<TypeCastingExpression*>(col->expr());
+            auto exprPtr = dynamic_cast<TypeCastingExpression*>(col->expr());
             colTypes_.back() = ColumnTypeToSupportedType(exprPtr->getType());
         }

/* Copyright (c) 2019 vesoft inc. All rights reserved.
 *
 * This source code is licensed under Apache 2.0 License,
 * attached with Common Clause Condition 1.0, found in the LICENSES directory.
 */

#include "base/Base.h"
#include "FetchExecutor.h"

namespace nebula {
namespace graph {

Status FetchExecutor::prepareYield() {
    if (yieldClause_ == nullptr) {
        setupColumns();
    } else {
        yields_ = yieldClause_->columns();
        // TODO 'distinct' could always pushdown in fetch.
        distinct_ = yieldClause_->isDistinct();
    }

    for (auto *col : yields_) {
        col->expr()->setContext(expCtx_.get());
        Status status = col->expr()->prepare();
        if (!status.ok()) {
            return status;
        }
        if (col->alias() == nullptr) {
            resultColNames_.emplace_back(col->expr()->toString());
        } else {
            resultColNames_.emplace_back(*col->alias());
        }

        // such as YIELD 1+1, it has not type in schema, the type from the eval()
        colTypes_.emplace_back(nebula::cpp2::SupportedType::UNKNOWN);
        if (col->expr()->isAliasExpression()) {
            colNames_.emplace_back(*static_cast<InputPropertyExpression*>(col->expr())->prop());
            continue;
        } else if (col->expr()->isTypeCastingExpression()) {
            // type cast
            auto exprPtr = static_cast<TypeCastingExpression*>(col->expr());
            colTypes_.back() = ColumnTypeToSupportedType(exprPtr->getType());
        }

        colNames_.emplace_back(col->expr()->toString());
    }

    if (expCtx_->hasSrcTagProp() || expCtx_->hasDstTagProp()) {
        return Status::SyntaxError(
                    "Only support form of alias.prop in fetch sentence.");
    }

    auto aliasProps = expCtx_->aliasProps();
    for (auto pair : aliasProps) {
        if (pair.first != *labelName_) {
            return Status::SyntaxError(
                "[%s.%s] tag not declared in %s.",
                    pair.first.c_str(), pair.second.c_str(), (*labelName_).c_str());
        }
    }

    return Status::OK();
}

void FetchExecutor::setupColumns() {
    DCHECK_NOTNULL(labelSchema_);
    auto iter = labelSchema_->begin();
    if (yieldColsHolder_ == nullptr) {
        yieldColsHolder_ = std::make_unique<YieldColumns>();
    }
    while (iter) {
        auto *ref = new std::string("");
        auto *alias = new std::string(*labelName_);
        auto *prop = iter->getName();
        Expression *expr =
            new AliasPropertyExpression(ref, alias, new std::string(prop));
        YieldColumn *column = new YieldColumn(expr);
        yieldColsHolder_->addColumn(column);
        yields_.emplace_back(column);
        ++iter;
    }
}

void FetchExecutor::setupResponse(cpp2::ExecutionResponse &resp) {
    if (resp_ == nullptr) {
        resp_ = std::make_unique<cpp2::ExecutionResponse>();
    }
    resp = std::move(*resp_);
}

void FetchExecutor::onEmptyInputs() {
    if (onResult_) {
        auto outputs = std::make_unique<InterimResult>(std::move(resultColNames_));
        onResult_(std::move(outputs));
    } else if (resp_ == nullptr) {
        resp_ = std::make_unique<cpp2::ExecutionResponse>();
    }
    onFinish_();
}

Status FetchExecutor::getOutputSchema(
        meta::SchemaProviderIf *schema,
        const RowReader *reader,
        SchemaWriter *outputSchema) const {
    if (expCtx_ == nullptr || resultColNames_.empty()) {
        LOG(FATAL) << "Input is empty";
    }
    auto collector = std::make_unique<Collector>(schema);
    auto &getters = expCtx_->getters();
    getters.getAliasProp = [&] (const std::string&, const std::string &prop) {
        return collector->getProp(prop, reader);
    };
    std::vector<VariantType> record;
    for (auto *column : yields_) {
        auto *expr = column->expr();
        auto value = expr->eval();
        if (!value.ok()) {
            return value.status();
        }
        record.emplace_back(std::move(value.value()));
    }

    if (colTypes_.size() != record.size()) {
        return Status::Error("Input is not equal to output");
    }
    using nebula::cpp2::SupportedType;
    auto index = 0u;
    for (auto &it : colTypes_) {
        SupportedType type;
        if (it == SupportedType::UNKNOWN) {
            switch (record[index].which()) {
                case VAR_INT64:
                    // all integers in InterimResult are regarded as type of INT
                    type = SupportedType::INT;
                    break;
                case VAR_DOUBLE:
                    type = SupportedType::DOUBLE;
                    break;
                case VAR_BOOL:
                    type = SupportedType::BOOL;
                    break;
                case VAR_STR:
                    type = SupportedType::STRING;
                    break;
                default:
                    LOG(FATAL) << "Unknown VariantType: " << record[index].which();
            }
        } else {
            type = it;
        }

        outputSchema->appendCol(resultColNames_[index], type);
        index++;
    }
    return Status::OK();
}

void FetchExecutor::finishExecution(std::unique_ptr<RowSetWriter> rsWriter) {
    auto outputs = std::make_unique<InterimResult>(std::move(resultColNames_));
    if (rsWriter != nullptr) {
        outputs->setInterim(std::move(rsWriter));
    }

    if (onResult_) {
        onResult_(std::move(outputs));
    } else {
        resp_ = std::make_unique<cpp2::ExecutionResponse>();
        auto colNames = outputs->getColNames();
        resp_->set_column_names(std::move(colNames));
        if (outputs->hasData()) {
            auto ret = outputs->getRows();
            if (!ret.ok()) {
                LOG(ERROR) << "Get rows failed: " << ret.status();
                onError_(std::move(ret).status());
                return;
            }
            resp_->set_rows(std::move(ret).value());
        }
    }
    DCHECK(onFinish_);
    onFinish_();
}
}  // namespace graph
}  // namespace nebula

dynamic_cast will return nullptr to exprPtr, so need check it?


@@ -5,29 +5,35 @@

 """
 from __future__ import print_function
-from rdkit import RDConfig
+
 import unittest
-import Parser
-from win32com.client import Dispatch
-from Numeric import *

+from rdkit import RDConfig
+import numpy as np
+
+try:
+  from win32com.client import Dispatch
+except ImportError:
+  Dispatch = None

+
+@unittest.skipIf(Dispatch is None, 'Windows test')
 class TestCase(unittest.TestCase):

   def setUp(self):
     print('\n%s: ' % self.shortDescription(), end='')

   def testConnectToCOMServer(self):
-    " testing connection "
+    # " testing connection "
     Dispatch('RD.DescCalc')

   def testLoadCalculator(self):
-    " testing load "
+    # " testing load "
     c = Dispatch('RD.DescCalc')
     c.LoadCalculator(RDConfig.RDCodeDir + '/ml/descriptors/test_data/ferro.dsc')

   def testNames(self):
-    " testing GetDescriptorNames "
+    # " testing GetDescriptorNames "
     c = Dispatch('RD.DescCalc')
     c.LoadCalculator(RDConfig.RDCodeDir + '/ml/descriptors/test_data/ferro.dsc')
     names = c.GetDescriptorNames()

#
#  Copyright (C) 2001  greg Landrum
#
""" unit testing code for the descriptor COM server

"""
from __future__ import print_function
from rdkit import RDConfig
import unittest
import Parser
from win32com.client import Dispatch
from Numeric import *

class TestCase(unittest.TestCase):

  def setUp(self):
    print('\n%s: ' % self.shortDescription(), end='')

  def testConnectToCOMServer(self):
    " testing connection "
    Dispatch('RD.DescCalc')

  def testLoadCalculator(self):
    " testing load "
    c = Dispatch('RD.DescCalc')
    c.LoadCalculator(RDConfig.RDCodeDir + '/ml/descriptors/test_data/ferro.dsc')

  def testNames(self):
    " testing GetDescriptorNames "
    c = Dispatch('RD.DescCalc')
    c.LoadCalculator(RDConfig.RDCodeDir + '/ml/descriptors/test_data/ferro.dsc')
    names = c.GetDescriptorNames()
    expectedNames = ('MAX_DED', 'has3d', 'has4d', 'has5d', 'elconc', 'atvol')
    assert names == expectedNames, 'GetDescriptorNames failed (%s != %s)' % (repr(names),
                                                                             repr(expectedNames))

  def testCalc(self):
    " testing descriptor calculation "
    argV = ['CrPt3', 'fcc', 'AuCu3', 58.09549962, 1, 4, 0.228898, 8.876, 1]
    nameV = ['Compound', 'Structure', 'Structure_Type', 'Volume', 'Z', 'Atoms_per_Formula_Unit',
             'Hardness', 'RawDOS_Ef', 'IsFerromagnetic']
    c = Dispatch('RD.DescCalc')
    c.LoadCalculator(RDConfig.RDCodeDir + '/ml/descriptors/test_data/ferro.dsc')
    descVect = array(c.CalcDescriptors(argV, nameV))
    expected = array((3.67481803894, 1, 0, 1, 0.619669341609, 14.523874905))
    diffV = abs(descVect - expected)
    assert max(diffV) < 0.0001, 'bad descriptors: %s, %s' % (str(expected), str(descVect))

def TestSuite():
  suite = unittest.TestSuite()
  suite.addTest(TestCase('testConnect'))
  suite.addTest(TestCase('testLoad'))
  suite.addTest(TestCase('testNames'))
  suite.addTest(TestCase('testCalc'))
  return suite

if __name__ == '__main__':
  suite = TestSuite()
  unittest.TextTestRunner().run(suite)

I couldn't run the windows tests, so no guarantee that this will work.


@@ -66,7 +66,8 @@ void mesh_reader::load() {
   select_subset_of_data();
 }

-bool mesh_reader::fetch_datum(CPUMat& X, int data_id, int mb_idx, int tid) {
+bool mesh_reader::fetch_datum(CPUMat& X, int data_id, int mb_idx, thread_pool& io_thread_pool) {
+  //  int tid = io_thread_pool.get_local_thread_id();
   if (m_random_flips) {
     fast_rng_gen& gen = get_fast_generator();
     std::uniform_int_distribution<int> dist(0, 1);

////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2014-2016, Lawrence Livermore National Security, LLC.
// Produced at the Lawrence Livermore National Laboratory.
// Written by the LBANN Research Team (B. Van Essen, et al.) listed in
// the CONTRIBUTORS file. <lbann-dev@llnl.gov>
//
// LLNL-CODE-697807.
// All rights reserved.
//
// This file is part of LBANN: Livermore Big Artificial Neural Network
// Toolkit. For details, see http://software.llnl.gov/LBANN or
// https://github.com/LLNL/LBANN.
//
// Licensed under the Apache License, Version 2.0 (the "Licensee"); you
// may not use this file except in compliance with the License.  You may
// obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the license.
//
// data_reader_mesh .hpp .cpp - data reader for mesh data
////////////////////////////////////////////////////////////////////////////////

#include "lbann/data_readers/data_reader_mesh.hpp"
#include "lbann/utils/glob.hpp"
#include <omp.h>

namespace lbann {

mesh_reader::mesh_reader(bool shuffle)
  : generic_data_reader(shuffle) {}

void mesh_reader::load() {
  if (m_data_height == 0 || m_data_width == 0) {
    throw lbann_exception("mesh_reader: data shape must be non-zero");
  }
  // Compute total number of samples based on number of targets.
  std::vector<std::string> matches = glob(
    get_file_dir() + m_target_name + m_suffix + "/*.bin");
  if (matches.size() == 0) {
    throw lbann_exception("mesh_reader: could not find any targets");
  }
  m_num_samples = matches.size();
  // Set up buffers to load data into.
  m_load_bufs.resize(omp_get_max_threads());
  for (auto&& buf : m_load_bufs) {
    buf.resize(m_data_height * m_data_width);
  }
  // Set up the format string.
  if (std::pow(10, m_index_length) <= m_num_samples) {
    throw lbann_exception("mesh_reader: index length too small");
  }
  m_index_format_str = "%0" + std::to_string(m_index_length) + "d";
  // Set up to record flipping if needed.
  if (m_random_flips) {
    m_flip_choices.resize(m_num_samples);
  }
  // Reset indices.
  m_shuffled_indices.resize(m_num_samples);
  std::iota(m_shuffled_indices.begin(), m_shuffled_indices.end(), 0);
  select_subset_of_data();
}

bool mesh_reader::fetch_datum(CPUMat& X, int data_id, int mb_idx, int tid) {
  if (m_random_flips) {
    fast_rng_gen& gen = get_fast_generator();
    std::uniform_int_distribution<int> dist(0, 1);
    m_flip_choices[data_id].first = dist(gen);
    m_flip_choices[data_id].second = dist(gen);
  }
  for (size_t i = 0; i < m_channels.size(); ++i) {
    Mat X_view = El::View(
      X, El::IR(i*m_data_height*m_data_width, (i+1)*m_data_height*m_data_width),
      El::IR(mb_idx));
    load_file(data_id, m_channels[i], X_view);
  }
  return true;
}

bool mesh_reader::fetch_response(CPUMat& Y, int data_id, int mb_idx, int tid) {
  Mat Y_view = El::View(Y, El::ALL, El::IR(mb_idx));
  load_file(data_id, m_target_name, Y_view);
  return true;
}

void mesh_reader::load_file(int data_id, const std::string channel, Mat& mat) {
  const std::string filename = construct_filename(channel, data_id);
  std::ifstream f(filename, std::ios::binary);
  if (f.fail()) {
    throw lbann_exception("mesh_reader: failed to open " + filename);
  }
  // Load into a local buffer.
  float* buf = m_load_bufs[omp_get_thread_num()].data();
  if (!f.read((char*) buf, m_data_height * m_data_width * sizeof(float))) {
    throw lbann_exception("mesh_reader: failed to read " + filename);
  }
  if (std::is_same<float, DataType>::value) {
    // Need to transpose from row-major to column-major order.
    Mat tmp_mat(m_data_width, m_data_height, buf, m_data_width);
    Mat mat_reshape(m_data_height, m_data_width, mat.Buffer(), m_data_height);
    El::Transpose(tmp_mat, mat_reshape);
    // Flip if needed.
    if (m_random_flips) {
      if (m_flip_choices[data_id].first) {
        horizontal_flip(mat_reshape);
      }
      if (m_flip_choices[data_id].second) {
        vertical_flip(mat_reshape);
      }
    }
  } else {
    // Need to transpose and convert from float. Not yet supported.
    throw lbann_exception("mesh_reader: does not support DataType != float");
  }
}

std::string mesh_reader::construct_filename(std::string channel, int data_id) {
  std::string filename = get_file_dir() + channel + m_suffix + "/" + channel;
  char idx[m_index_length + 1];
  std::snprintf(idx, m_index_length + 1, m_index_format_str.c_str(), data_id);
  return filename + std::string(idx) + ".bin";
}

void mesh_reader::horizontal_flip(CPUMat& mat) {
  // TODO: Could probably optimize this for better locality.
  const El::Int height = mat.Height();
  const El::Int width = mat.Width();
  for (El::Int row = 0; row < height; ++row) {
    for (El::Int col = 0; col < (width / 2); ++col) {
      DataType tmp = mat(row, col);
      mat(row, col) = mat(row, width - col - 1);
      mat(row, width - col - 1) = tmp;
    }
  }
}

void mesh_reader::vertical_flip(CPUMat& mat) {
  // TODO: Could probably optimize this for better locality.
  const El::Int height = mat.Height();
  const El::Int width = mat.Width();
  for (El::Int row = 0; row < (height / 2); ++row) {
    for (El::Int col = 0; col < width; ++col) {
      DataType tmp = mat(row, col);
      mat(row, col) = mat(height - row - 1, col);
      mat(height - row - 1, col) = tmp;
    }
  }
}

}  // namespace lbann

If this is not used, we should just delete the line.


@@ -18,7 +18,7 @@ class DedupTest : public QueryTestBase {
   void SetUp() override { QueryTestBase::SetUp(); }
 };

-#define DEDUP_RESUTL_CHECK(inputName, outputName, sentence, expected)                   \
+#define DEDUP_RESULT_CHECK(inputName, outputName, sentence, expected)                   \
   do {                                                                                \
     qctx_->symTable()->newVariable(outputName);                                         \
     auto yieldSentence = getYieldSentence(sentence, qctx_.get());                       \

/* Copyright (c) 2020 vesoft inc. All rights reserved.
 *
 * This source code is licensed under Apache 2.0 License.
 */
#include <gtest/gtest.h>

#include "graph/context/QueryContext.h"
#include "graph/executor/query/DedupExecutor.h"
#include "graph/executor/query/ProjectExecutor.h"
#include "graph/executor/test/QueryTestBase.h"
#include "graph/planner/plan/Query.h"

namespace nebula {
namespace graph {

class DedupTest : public QueryTestBase {
 public:
  void SetUp() override { QueryTestBase::SetUp(); }
};

#define DEDUP_RESUTL_CHECK(inputName, outputName, sentence, expected)                   \
  do {                                                                                \
    qctx_->symTable()->newVariable(outputName);                                         \
    auto yieldSentence = getYieldSentence(sentence, qctx_.get());                       \
    auto* dedupNode = Dedup::make(qctx_.get(), nullptr);                                \
    dedupNode->setInputVar(inputName);                                                  \
    dedupNode->setOutputVar(outputName);                                                \
    auto dedupExec = std::make_unique<DedupExecutor>(dedupNode, qctx_.get());           \
    if (!expected.colNames.empty()) {                                                   \
      EXPECT_TRUE(dedupExec->execute().get().ok());                                     \
    } else {                                                                            \
      EXPECT_FALSE(dedupExec->execute().get().ok());                                    \
      return;                                                                           \
    }                                                                                \
    auto& dedupResult = qctx_->ectx()->getResult(dedupNode->outputVar());               \
    EXPECT_EQ(dedupResult.state(), Result::State::kSuccess);                            \
                                                                                \
    dedupNode->setInputVar(outputName);                                                 \
    auto* project = Project::make(qctx_.get(), nullptr, yieldSentence->yieldColumns()); \
    project->setInputVar(dedupNode->outputVar());                                       \
    auto colNames = expected.colNames;                                                  \
    project->setColNames(std::move(colNames));                                          \
                                                                                \
    auto proExe = std::make_unique<ProjectExecutor>(project, qctx_.get());              \
    EXPECT_TRUE(proExe->execute().get().ok());                                          \
    auto& proSesult = qctx_->ectx()->getResult(project->outputVar());                   \
                                                                                \
    EXPECT_EQ(proSesult.value().getDataSet(), expected);                                \
    EXPECT_EQ(proSesult.state(), Result::State::kSuccess);                              \
  } while (false)

TEST_F(DedupTest, TestSequential) {
  DataSet expected({"vid", "name", "age", "dst", "start", "end"});
  expected.emplace_back(Row({"Ann", "Ann", 18, "School1", 2010, 2014}));
  expected.emplace_back(Row({"Joy", "Joy", Value::kNullValue, "School2", 2009, 2012}));
  expected.emplace_back(Row({"Tom", "Tom", 20, "School2", 2008, 2012}));
  expected.emplace_back(Row({"Kate", "Kate", 19, "School2", 2009, 2013}));
  expected.emplace_back(Row({"Lily", "Lily", 20, "School2", 2009, 2012}));

  auto sentence =
      "YIELD DISTINCT $-.vid as vid, $-.v_name as name, $-.v_age as age, "
      "$-.v_dst as dst, $-.e_start_year as start, $-.e_end_year as end";
  DEDUP_RESUTL_CHECK("input_sequential", "dedup_sequential", sentence, expected);
}

TEST_F(DedupTest, TestEmpty) {
  DataSet expected({"name"});
  DEDUP_RESUTL_CHECK("empty", "dedup_sequential", "YIELD DISTINCT $-.v_dst as name", expected);
}

TEST_F(DedupTest, WrongTypeIterator) {
  DataSet expected;
  DEDUP_RESUTL_CHECK(
      "input_neighbor", "dedup_sequential", "YIELD DISTINCT $-.v_dst as name", expected);
}
}  // namespace graph
}  // namespace nebula

I'm not certain that `res`+`utl` isn't a thing.


@@ -58,7 +58,10 @@ class TopNContainer(object):
     return self.extras

   def __len__(self):
-    return self._size
+    if self._size >= 0:
+      return self._size
+    else:
+      return len(self.best)

   def __getitem__(self, which):
     return self.best[which], self.extras[which]

# $Id$
#
#  Copyright (C) 2003-2013 Rational Discovery LLC
#
#   @@ All Rights Reserved @@
#  This file is part of the RDKit.
#  The contents are covered by the terms of the BSD license
#  which is included in the file license.txt, found at the root
#  of the RDKit source tree.
#
from __future__ import print_function
import bisect

class TopNContainer(object):
  """ maintains a sorted list of a particular number of data elements.

  """

  def __init__(self, size, mostNeg=-1e99):
    """
    if size is negative, all entries will be kept in sorted order
    """
    self._size = size
    if (size >= 0):
      self.best = [mostNeg] * self._size
      self.extras = [None] * self._size
    else:
      self.best = []
      self.extras = []

  def Insert(self, val, extra=None):
    """ only does the insertion if val fits """
    if self._size >= 0:
      if val > self.best[0]:
        idx = bisect.bisect(self.best, val)
        # insert the new element
        if idx == self._size:
          self.best.append(val)
          self.extras.append(extra)
        else:
          self.best.insert(idx, val)
          self.extras.insert(idx, extra)
        # and pop off the head
        self.best.pop(0)
        self.extras.pop(0)
    else:
      idx = bisect.bisect(self.best, val)
      self.best.insert(idx, val)
      self.extras.insert(idx, extra)

  def GetPts(self):
    """ returns our set of points """
    return self.best

  def GetExtras(self):
    """ returns our set of extras """
    return self.extras

  def __len__(self):
    return self._size

  def __getitem__(self, which):
    return self.best[which], self.extras[which]

  def reverse(self):
    self.best.reverse()
    self.extras.reverse()

if __name__ == '__main__':
  import random
  pts = [int(100 * random.random()) for x in range(10)]

  c = TopNContainer(4)
  for pt in pts:
    c.Insert(pt, extra=str(pt))
  print(c.GetPts())
  print(c.GetExtras())

The case of a negative size (= keep all elements) was not handled in this function.


@@ -16,8 +16,9 @@ namespace nebula {
 namespace storage {

 void AddVerticesProcessor::process(const cpp2::AddVerticesRequest& req) {
-    auto version =
-        std::numeric_limits<int64_t>::max() - time::WallClock::fastNowInMicroSec();
+    auto version = FLAGS_enable_multi_versions ?
+        std::numeric_limits<int64_t>::max() - time::WallClock::fastNowInMicroSec() :
+        std::numeric_limits<int64_t>::max();
     // Switch version to big-endian, make sure the key is in ordered.
     version = folly::Endian::big(version);

/* Copyright (c) 2018 vesoft inc. All rights reserved.
 *
 * This source code is licensed under Apache 2.0 License,
 * attached with Common Clause Condition 1.0, found in the LICENSES directory.
 */

#include "storage/mutate/AddVerticesProcessor.h"
#include "utils/NebulaKeyUtils.h"
#include <algorithm>
#include <limits>
#include "time/WallClock.h"

DECLARE_bool(enable_vertex_cache);

namespace nebula {
namespace storage {

void AddVerticesProcessor::process(const cpp2::AddVerticesRequest& req) {
    auto version =
        std::numeric_limits<int64_t>::max() - time::WallClock::fastNowInMicroSec();
    // Switch version to big-endian, make sure the key is in ordered.
    version = folly::Endian::big(version);

    const auto& partVertices = req.get_parts();
    spaceId_ = req.get_space_id();
    callingNum_ = partVertices.size();
    auto iRet = indexMan_->getTagIndexes(spaceId_);
    if (iRet.ok()) {
        indexes_ = std::move(iRet).value();
    }

    CHECK_NOTNULL(kvstore_);
    if (indexes_.empty()) {
        std::for_each(partVertices.begin(), partVertices.end(), [&](auto& pv) {
            auto partId = pv.first;
            const auto& vertices = pv.second;
            std::vector<kvstore::KV> data;
            std::for_each(vertices.begin(), vertices.end(), [&](auto& v) {
                const auto& tags = v.get_tags();
                std::for_each(tags.begin(), tags.end(), [&](auto& tag) {
                    VLOG(3) << "PartitionID: " << partId << ", VertexID: " << v.get_id()
                            << ", TagID: " << tag.get_tag_id() << ", TagVersion: " << version;
                    auto key = NebulaKeyUtils::vertexKey(partId, v.get_id(),
                                                         tag.get_tag_id(), version);
                    data.emplace_back(std::move(key), std::move(tag.get_props()));
                    if (FLAGS_enable_vertex_cache && vertexCache_ != nullptr) {
                        vertexCache_->evict(std::make_pair(v.get_id(), tag.get_tag_id()), partId);
                        VLOG(3) << "Evict cache for vId " << v.get_id()
                                << ", tagId " << tag.get_tag_id();
                    }
                });
            });
            doPut(spaceId_, partId, std::move(data));
        });
    } else {
        std::for_each(partVertices.begin(), partVertices.end(), [&](auto &pv) {
            auto partId = pv.first;
            auto atomic = [version, partId, vertices = std::move(pv.second), this]()
                          -> folly::Optional<std::string> {
                return addVertices(version, partId, vertices);
            };
            auto callback = [partId, this](kvstore::ResultCode code) {
                handleAsync(spaceId_, partId, code);
            };
            this->kvstore_->asyncAtomicOp(spaceId_, partId, atomic, callback);
        });
    }
}

std::string AddVerticesProcessor::addVertices(int64_t version, PartitionID partId,
                                              const std::vector<cpp2::Vertex>& vertices) {
    std::unique_ptr<kvstore::BatchHolder> batchHolder = std::make_unique<kvstore::BatchHolder>();
    /*
     * Define the map newIndexes to avoid inserting duplicate vertex.
     * This map means :
     * map<vertex_unique_key, prop_value> ,
     * -- vertex_unique_key is only used as the unique key , for example:
     * insert below vertices in the same request:
     *     kv(part1_vid1_tag1 , v1)
     *     kv(part1_vid1_tag1 , v2)
     *     kv(part1_vid1_tag1 , v3)
     *     kv(part1_vid1_tag1 , v4)
     *
     * Ultimately, kv(part1_vid1_tag1 , v4) . It's just what I need.
     */
    std::map<std::string, std::string> newVertices;
    std::for_each(vertices.begin(), vertices.end(), [&](auto& v) {
        auto vId = v.get_id();
        const auto& tags = v.get_tags();
        std::for_each(tags.begin(), tags.end(), [&](auto& tag) {
            auto tagId = tag.get_tag_id();
            auto prop = tag.get_props();
            VLOG(3) << "PartitionID: " << partId << ", VertexID: " << vId
                    << ", TagID: " << tagId << ", TagVersion: " << version;
            auto key = NebulaKeyUtils::vertexKey(partId, vId, tagId, version);
            newVertices[key] = std::move(prop);
            if (FLAGS_enable_vertex_cache && this->vertexCache_ != nullptr) {
                this->vertexCache_->evict(std::make_pair(vId, tagId), partId);
                VLOG(3) << "Evict cache for vId " << vId << ", tagId " << tagId;
            }
        });
    });

    for (auto& v : newVertices) {
        std::string val;
        std::unique_ptr<RowReader> nReader;
        auto tagId = NebulaKeyUtils::getTagId(v.first);
        auto vId = NebulaKeyUtils::getVertexId(v.first);
        for (auto& index : indexes_) {
            if (tagId == index->get_schema_id().get_tag_id()) {
                /*
                 * step 1 , Delete old version index if exists.
                 */
                if (val.empty()) {
                    val = findObsoleteIndex(partId, vId, tagId);
                }
                if (!val.empty()) {
                    auto reader = RowReader::getTagPropReader(this->schemaMan_,
                                                              val,
                                                              spaceId_,
                                                              tagId);
                    if (reader == nullptr) {
                        LOG(WARNING) << "Bad format row";
                        return "";
                    }
                    auto oi = indexKey(partId, vId, reader.get(), index);
                    if (!oi.empty()) {
                        batchHolder->remove(std::move(oi));
                    }
                }
                /*
                 * step 2 , Insert new vertex index
                 */
                if (nReader == nullptr) {
                    nReader = RowReader::getTagPropReader(this->schemaMan_,
                                                          v.second,
                                                          spaceId_,
                                                          tagId);
                    if (nReader == nullptr) {
                        LOG(WARNING) << "Bad format row";
                        return "";
                    }
                }
                auto ni = indexKey(partId, vId, nReader.get(), index);
                if (!ni.empty()) {
                    batchHolder->put(std::move(ni), "");
                }
            }
        }
        /*
         * step 3 , Insert new vertex data
         */
        auto key = v.first;
        auto prop = v.second;
        batchHolder->put(std::move(key), std::move(prop));
    }
    return encodeBatchValue(batchHolder->getBatch());
}

std::string AddVerticesProcessor::findObsoleteIndex(PartitionID partId,
                                                    VertexID vId,
                                                    TagID tagId) {
    auto prefix = NebulaKeyUtils::vertexPrefix(partId, vId, tagId);
    std::unique_ptr<kvstore::KVIterator> iter;
    auto ret = kvstore_->prefix(this->spaceId_, partId, prefix, &iter);
    if (ret != kvstore::ResultCode::SUCCEEDED) {
        LOG(ERROR) << "Error! ret = " << static_cast<int32_t>(ret)
                   << ", spaceId " << this->spaceId_;
        return "";
    }
    if (iter && iter->valid()) {
        return iter->val().str();
    }
    return "";
}

std::string AddVerticesProcessor::indexKey(PartitionID partId,
                                           VertexID vId,
                                           RowReader* reader,
                                           std::shared_ptr<nebula::cpp2::IndexItem> index) {
    auto values = collectIndexValues(reader, index->get_fields());
    if (!values.ok()) {
        return "";
    }
    return NebulaKeyUtils::vertexIndexKey(partId,
                                          index->get_index_id(),
                                          vId, values.value());
}

}  // namespace storage
}  // namespace nebula

it should be zero if FLAGS_enable_multi_versions is false