This appendix provides the sample code for the console
, contacts
, and hellogrid
C++ examples.
Now that you've run the console example, you are encouraged to have a look at the code. Each sample has a corresponding directory under examples which contains its sample specific source. There is also a common directory which contains source used in all samples.
Example A-1 illustrates the source code for the console.cpp
command line application that enables you to interact with the cache using simple commands.
Example A-1 Code for the Console Sample Application
#include "coherence/lang.ns" #include "coherence/io/pof/SystemPofContext.hpp" #include "coherence/net/CacheFactory.hpp" #include "coherence/net/NamedCache.hpp" #include "coherence/util/Iterator.hpp" #include "coherence/util/Map.hpp" #include "coherence/util/Set.hpp" #include "StreamParser.hpp" #include <iostream> #include <sstream> using namespace coherence::lang; using coherence::examples::StreamParser; using coherence::io::pof::SystemPofContext; using coherence::net::CacheFactory; using coherence::net::NamedCache; using coherence::util::Iterator; using coherence::util::Map; using coherence::util::Set; /** * This Coherence for C++ example provides a simple console for playing with * caches from within C++. * * @argc the number of command line arguments (including the process name) * @argv [cache-name] */ int main(int argc, char** argv) { NamedCache::Handle hCache; if (argc > 1) { // load command line specified cache try { hCache = CacheFactory::getCache(argv[1]); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } } while (true) { try { // prompt for input std::cout << "\nMap ("; if (NULL == hCache) { std::cout << '?'; } else { std::cout << hCache->getCacheName(); } std::cout << "): " << std::flush; char achInput[256]; std::cin.getline(achInput, 256); if (std::cin.fail()) { std::cin.clear(); continue; } std::stringstream ssInput(achInput); // process input String::View vsCmd = cast<String::View>(StreamParser::next(ssInput)); if (vsCmd->equals("bye")) { // quit try { CacheFactory::shutdown(); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; return 1; } return 0; } else if (vsCmd->equals("cache")) { // lookup a cache from the CacheFactory String::View vsCacheName = cast<String::View>(StreamParser::next(ssInput)); hCache = CacheFactory::getCache(vsCacheName); } else if (vsCmd->equals("classes")) { // output the SystemClassLoader std::cout << SystemClassLoader::getInstance() << std::endl; } else if (vsCmd->equals("clear")) { // clear the current cache hCache->clear(); } else if (vsCmd->equals("destroy")) { // destroy the current cache CacheFactory::destroyCache(hCache); } else if (vsCmd->equals("get")) { // perform a get operation on the current cache Object::View vKey = StreamParser::next(ssInput); Object::View vValue = hCache->get(vKey); // print the current value std::cout << vValue << std::endl; } else if (vsCmd->equals("list")) { // obtain the entire cache contents Set::View vSetEntries = hCache->entrySet(); // print key value pairs for (Iterator::Handle hIter = vSetEntries->iterator(); hIter->hasNext(); ) { Map::Entry::View vEntry = cast<Map::Entry::View>(hIter->next()); std::cout << vEntry->getKey() << " = " << vEntry->getValue() << std::endl; } } else if (vsCmd->equals("memory")) { // print information about allocated objects HeapAnalyzer::View vAnalyzer = System::getHeapAnalyzer(); if (NULL == vAnalyzer) { std::cout << "analysis disabled" << std::endl; } else if (cast<String::View>(StreamParser::next(ssInput))-> equals("delta")) { static HeapAnalyzer::Snapshot::View vMark; // compare current against the heap mark std::cout << (NULL == vMark ? vAnalyzer->capture() : vAnalyzer->delta(vMark)) << std::endl; // reset to mark based on the current heap useage vMark = NULL; vMark = vAnalyzer->capture(); } else { // output the current heap useage std::cout << vAnalyzer << std::endl; } } else if (vsCmd->equals("pof")) { // output the SystemPofContext std::cout << SystemPofContext::getInstance() << std::endl; } else if (vsCmd->equals("put")) { // perform a put operation on the current cache Object::View vKey = StreamParser::next(ssInput); Object::View vValue = StreamParser::next(ssInput); Object::View vPrev = hCache->put(vKey, vValue); // print the old value std::cout << vPrev << std::endl; } else if (vsCmd->equals("remove")) { // perform a remove operation on the current cache Object::View vKey = StreamParser::next(ssInput); Object::View vPrev = hCache->remove(vKey); // print the removed value std::cout << vPrev << std::endl; } else if (vsCmd->equals("release")) { // release the current cache CacheFactory::releaseCache(hCache); } else if (vsCmd->equals("size")) { // print the size of the current cache size32_t cElements = hCache->size(); std::cout << cElements << std::endl; } else if (vsCmd->equals("threads")) { // print a stack trace for all threads related to coherence Thread::dumpStacks(std::cout); } else if (vsCmd->equals("")) { continue; } else if (vsCmd->equals("help")) { // print help std::cout << "The commands are:" << std::endl << " bye" << std::endl << " cache <name>" << std::endl << " classes" << std::endl << " clear" << std::endl << " destroy" << std::endl << " get <key>" << std::endl << " help" << std::endl << " list" << std::endl << " memory [delta]" << std::endl << " pof" << std::endl << " put <key> <value>" << std::endl << " release" << std::endl << " remove <key>" << std::endl << " size" << std::endl << " threads" << std::endl; } else { std::cout << "Unknown command: \"" << vsCmd << "\"\n" << "Entry \"help\" for command list" << std::endl; } } catch (const NullPointerException::Throwable& e) { if (NULL == hCache) { std::cerr << "Please specify a cache using the \"cache\" " << "command." << std::endl; } else { std::cerr << e << std::endl; } } catch (const std::exception& e) { std::cerr << "Error: " << e.what() << std::endl; } } }
Now that you've run the contacts example, you are encouraged to have a look at the code. Each sample has a corresponding directory under examples which contains its sample specific source. There is also a common directory which contains source used in all samples.
Example A-2 illustrates the source code for the contacts example, and demonstrates how to store pre-existing (that is, non-Coherence) C++ classes in the grid.
Example A-2 Header Code for the ContactInfo Sample Application
#ifndef COH_EXAMPLES_CONTACT_INFO_HPP #define COH_EXAMPLES_CONTACT_INFO_HPP #include <ostream> #include <string> /** * The ContactInfo class encapsulates common contact information for a person. * * This serves as an example data object which does not have direct knowledge * of Coherence but can be stored in the data grid. */ class ContactInfo { // ----- constructors --------------------------------------------------- public: /** * Create a new ContactInfo object. * * @param sName the name of the person * @param sStreet the street on which the person lives * @param sCity the city where the person lives * @param sState the state where the person lives * @param sZip the zip code of the city where the person lives */ ContactInfo(const std::string& sName, const std::string& sStreet, const std::string& sCity, const std::string& sState, const std::string& sZip); /** * Copy constructor. */ ContactInfo(const ContactInfo& that); protected: /** * Default constructor. */ ContactInfo(); // ----- accessors ------------------------------------------------------ public: /** * Determine the name of the person for which this ContactInfo object * contains contact information. * * @return the person's name */ std::string getName() const; /** * Configure the name of the person for which this ContactInfo object * contains contact information. * * @param sName the person's name */ void setName(const std::string& sName); /** * Determine the street on which the person lives. * * @return the street name */ std::string getStreet() const; /** * Configure the street on which the person lives. * * @param sStreet the street name */ void setStreet(const std::string& sStreet); /** * Determine the city in which the person lives. * * @return the city name */ std::string getCity() const; /** * Configure the city in which the person lives. * * @param sCity the city name */ void setCity(const std::string& sCity); /** * Determine the state in which the person lives. * * @return the state name */ std::string getState() const; /** * Configure the state in which the person lives. * * @param sState the state name */ void setState(const std::string& sState); /** * Determine the zip code of the city in which the person lives. * * @return the zip code */ std::string getZip() const; /** * Configure the zip code of the city in which the person lives. * * @param sZip the city's zip code */ void setZip(const std::string& sZip); // ----- operators ------------------------------------------------------ public: /** * Compare two ContactInfo objects for equality * * @param that the ContactInfo to compare against * * @return true if this referenced contact is equal to this contact */ bool operator==(const ContactInfo& that) const; // ----- data members --------------------------------------------------- private: /** * The person's name. */ std::string m_sName; /** * The street on which the person lives. */ std::string m_sStreet; /** * The city in which the person lives. */ std::string m_sCity; /** * The state in which the person lives. */ std::string m_sState; /** * The zip code of the city in which the person lives. */ std::string m_sZip; }; /** * Output this ContactInfo to the stream * * @param out the stream to output to * * @return the stream */ std::ostream& operator<<(std::ostream& out, const ContactInfo& info); #endif // COH_EXAMPLES_CONTACT_INFO_HPP
Example A-3 C++ Code for the ContactInfo Sample Application
#include "ContactInfo.hpp" // ----- constructors ------------------------------------------------------- ContactInfo::ContactInfo(const std::string& sName, const std::string& sStreet, const std::string& sCity, const std::string& sState, const std::string& sZip) { setName(sName); setStreet(sStreet); setCity(sCity); setState(sState); setZip(sZip); } ContactInfo::ContactInfo(const ContactInfo& that) { setName(that.getName()); setStreet(that.getStreet()); setCity(that.getCity()); setState(that.getState()); setZip(that.getZip()); } ContactInfo::ContactInfo() { } // ----- accessors ---------------------------------------------------------- std::string ContactInfo::getName() const { return m_sName; } void ContactInfo::setName(const std::string& sName) { m_sName = sName; } std::string ContactInfo::getStreet() const { return m_sStreet; } void ContactInfo::setStreet(const std::string& sStreet) { m_sStreet = sStreet; } std::string ContactInfo::getCity() const { return m_sCity; } void ContactInfo::setCity(const std::string& sCity) { m_sCity = sCity; } std::string ContactInfo::getState() const { return m_sState; } void ContactInfo::setState(const std::string& sState) { m_sState = sState; } std::string ContactInfo::getZip() const { return m_sZip; } void ContactInfo::setZip(const std::string& sZip) { m_sZip = sZip; } // ----- operators ---------------------------------------------------------- bool ContactInfo::operator==(const ContactInfo& that) const { return getName() == that.getName() && getStreet() == that.getStreet() && getCity() == that.getCity() && getState() == that.getState() && getZip() == that.getZip(); } std::ostream& operator<<(std::ostream& out, const ContactInfo& info) { out << "ContactInfo(" << "Name=" << info.getName() << ", Street=" << info.getStreet() << ", City=" << info.getCity() << ", State=" << info.getState() << ", Zip=" << info.getZip() << ')'; return out; }
Example A-4 Header Code for the PortableContactInfo Applications
#ifndef COH_EXAMPLES_PORTABLE_CONTACT_INFO_HPP #define COH_EXAMPLES_PORTABLE_CONTACT_INFO_HPP // This set of functions add support for storing ContactInfo objects in // Coherence without introducing knowledge of Coherence to the ContactInfo // class. This portable version of ClassInfo can be referred to as // Portable<ContactInfo> #include "ContactInfo.hpp" #include "coherence/io/pof/PofWriter.hpp" #include "coherence/io/pof/PofReader.hpp" #include "coherence/io/pof/Portable.hpp" /** * The POF type id for Portable<ContactInfo> */ #define POF_CONTACT_INFO_ID 1001 /** * Serialize a ContactInfo object to a POF stream. * * @param info the ContactInfo to seralize * @param hOut the PofWritter to write to */ void serialize(const ContactInfo& info, coherence::io::pof::PofWriter::Handle hOut); /** * Deserialize a ContactInfo object from a POF stream. * * @param info the ContactInfo to seralize * @param hIn the PofReader to read from */ void deserialize(ContactInfo& info, coherence::io::pof::PofReader::Handle hIn); /** * Return a hashcode code for a ContactInfo object. */ coherence::lang::size32_t hash(const ContactInfo& info); #endif // COH_EXAMPLES_PORTABLE_CONTACT_INFO_HPP
Example A-5 C++ Code for the PortableContactInfo Application
#include "PortableContactInfo.hpp" #include "coherence/lang.ns" #include "coherence/io/pof/PofWriter.hpp" #include "coherence/io/pof/PofReader.hpp" #include "coherence/io/pof/Portable.hpp" #include "coherence/io/pof/SystemPofContext.hpp" using namespace coherence::lang; // register Portable<ContactInfo> with the SystemPofContext COH_REGISTER_PORTABLE_CLASS(POF_CONTACT_INFO_ID, coherence::io::pof::Portable<ContactInfo>); void serialize(const ContactInfo& info, coherence::io::pof::PofWriter::Handle hOut) { hOut->writeString(0, info.getName()); hOut->writeString(1, info.getStreet()); hOut->writeString(2, info.getCity()); hOut->writeString(3, info.getState()); hOut->writeString(4, info.getZip()); } void deserialize(ContactInfo& info, coherence::io::pof::PofReader::Handle hIn) { info.setName (hIn->readString(0)); info.setStreet(hIn->readString(1)); info.setCity (hIn->readString(2)); info.setState (hIn->readString(3)); info.setZip (hIn->readString(4)); } size32_t hash(const ContactInfo& info) { // ContactInfo is not used as a key, use identity hash return size32_t(size_t(&info)); }
Example A-6 Code for the ContactInfo Data Object
#include "coherence/lang.ns" #include "coherence/io/pof/Portable.hpp" #include "coherence/net/CacheFactory.hpp" #include "coherence/net/NamedCache.hpp" #include "ContactInfo.hpp" #include "PortableContactInfo.hpp" #include "StreamParser.hpp" #include <iostream> #include <sstream> using namespace coherence::lang; using coherence::examples::StreamParser; using coherence::io::pof::Portable; using coherence::net::CacheFactory; using coherence::net::NamedCache; // ----- prototypes --------------------------------------------------------- /** * Create a contact from stdin. * * @return the contact */ ContactInfo readContact(); /** * This Coherence for C++ example illustrates how to use non-Coherence data * objects in the grid. This example operates on the ContactInfo class which * is not Coherence aware. * * To run this against a remote cache, the proxy node must have the * corresponding Java ContactInfo.class in its classpath. * * @argc the number of command line arguments (including the process name) * @argv [cache-name] */ int main(int argc, char** argv) { try { String::View vsCacheName = argc > 1 ? argv[1] : "dist-contacts"; NamedCache::Handle hCache = CacheFactory::getCache(vsCacheName); while (true) { // prompt for input std::cout << "contacts> " << std::flush; char achInput[256]; std::cin.getline(achInput, 256); std::stringstream ssInput(achInput); // process input String::View vsCmd = cast<String::View>( StreamParser::next(ssInput)); if (vsCmd->equals("bye")) { // quit CacheFactory::shutdown(); return 0; } else if (vsCmd->equals("create")) { ContactInfo ci = readContact(); std::cout << "storing: " << ci << std::endl; hCache->put(String::create(ci.getName().c_str()), Portable<ContactInfo>::create(ci)); } else if (vsCmd->equals("find")) { String::View vsPart = cast<String::View>( StreamParser::next(ssInput)); std::cout << "Name: " << std::flush; std::cin.getline(achInput, 256); String::View vsName = achInput; Portable<ContactInfo>::View vInfo = cast<Portable<ContactInfo>::View>(hCache->get(vsName)); if (NULL == vInfo) { std::cout << vsName << " not found" << std::endl; continue; } if (vsPart->equals("all") || vsPart->equals("")) { std::cout << vInfo << std::endl; } else if (vsPart->equals("street")) { std::cout << vInfo->getStreet() << std::endl; } else if (vsPart->equals("city")) { std::cout << vInfo->getCity() << std::endl; } else if (vsPart->equals("state")) { std::cout << vInfo->getState() << std::endl; } else if (vsPart->equals("zip")) { std::cout << vInfo->getZip() << std::endl; } else { std::cerr << "find must be followed by, street, city, " << "state, or zip" << std::endl; } } else // output help { std::cout << "commands are:" << std::endl << "bye" << std::endl << "create" << std::endl << "find <street | city | state | zip | all>" << std::endl; } } } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } } ContactInfo readContact() { char achInput[256]; std::cout << "Name: " << std::flush; std::cin.getline(achInput, 256); std::string sName(achInput); std::cout << "Street: " << std::flush; std::cin.getline(achInput, 256); std::string sStreet(achInput); std::cout << "City: " << std::flush; std::cin.getline(achInput, 256); std::string sCity(achInput); std::cout << "State: " << std::flush; std::cin.getline(achInput, 256); std::string sState(achInput); std::cout << "Zip: " << std::flush; std::cin.getline(achInput, 256); std::string sZip(achInput); return ContactInfo(sName, sStreet, sCity, sState, sZip); }
Now that you've run the hellogrid samples, you are encouraged to have a look at the code. Each sample has a corresponding directory under examples which contains its sample specific source. There is also a common directory which contains source used in all samples.
Example A-7 illustrates the source code for the hellogrid.cpp
example, and demonstrates basic cache access.
Example A-7 Code for the HelloGrid Sample Application
#include "coherence/lang.ns" #include "coherence/net/CacheFactory.hpp" #include "coherence/net/NamedCache.hpp" #include "coherence/stl/boxing_map.hpp" #include "coherence/util/aggregator/ComparableMin.hpp" #include "coherence/util/extractor/IdentityExtractor.hpp" #include "coherence/util/filter/GreaterFilter.hpp" #include "coherence/util/processor/NumberIncrementor.hpp" #include "coherence/util/Iterator.hpp" #include "coherence/util/Filter.hpp" #include "coherence/util/Set.hpp" #include "coherence/util/ValueExtractor.hpp" #include "coherence/util/ValueManipulator.hpp" #include <iostream> using namespace coherence::lang; using coherence::net::CacheFactory; using coherence::net::NamedCache; using coherence::stl::boxing_map; using coherence::util::aggregator::ComparableMin; using coherence::util::extractor::IdentityExtractor; using coherence::util::filter::GreaterFilter; using coherence::util::processor::NumberIncrementor; using coherence::util::Iterator; using coherence::util::Filter; using coherence::util::Set; using coherence::util::ValueExtractor; using coherence::util::ValueManipulator; /** * This example demonstrates the basics of accessing a cache by using the * Coherence C++ API. * * @argc the number of command line arguments (including the process name) * @argv [cache-name] */ int main(int argc, char** argv) { try {
// read optional cache name from command line String::View vsCacheName = argc > 1 ? argv[1] : "dist-hello"; // retrieve the named cache NamedCache::Handle hCache = CacheFactory::getCache(vsCacheName); std::cout << "retrieved cache \"" << hCache->getCacheName() << "\" containing " << hCache->size() << " entries" << std::endl; // create a key, and value String::View vsKey = "hello"; String::View vsValue = "grid"; // insert the pair into the cache hCache->put(vsKey, vsValue); std::cout << "\tput: " << vsKey << " = " << vsValue << std::endl; // read back the value, casting to the expected value type String::View vsGet = cast<String::View>(hCache->get(vsKey)); std::cout << "\tget: " << vsKey << " = " << vsGet << std::endl; // read a non-existent entry from the cache; result will be NULL String::View vsKeyDummy = "dummy"; Object::View vDummy = hCache->get(vsKeyDummy); std::cout << "\tget: " << vsKeyDummy << " = " << vDummy << std::endl; // work with non-string data types hCache->put(Integer32::valueOf(12345), Float64::valueOf(6.7)); hCache->put(Integer32::valueOf(23456), Float64::valueOf(7.8)); hCache->put(Integer32::valueOf(34567), Float64::valueOf(8.9)); // iterate and print the cache contents, treating contents abstractly std::cout << "entire cache contents:" << std::endl; for (Iterator::Handle hIter = hCache->entrySet()->iterator(); hIter->hasNext(); ) { Map::Entry::View vEntry = cast<Map::Entry::View>(hIter->next()); Object::View vKey = vEntry->getKey(); Object::View vValue = vEntry->getValue(); std::cout << '\t' << vKey << " = " << vValue << std::endl; } // remove strings to make the cache contents uniform hCache->remove(vsKey);
// caches may also be wrapped with an STL-like map adapter typedef boxing_map<Integer32, Float64> float_cache; float_cache cache(hCache); cache[45678] = 9.1; std::cout << "updated cache contents:" << std::endl; for (float_cache::iterator i = cache.begin(), e = cache.end(); i != e; ++i) { std::cout << '\t' << i->first << " = " << i->second << std::endl; }
// perform aggregation, and print the results ValueExtractor::View vExtractor = IdentityExtractor::getInstance(); Float64::View vFlMin = cast<Float64::View>( hCache->aggregate((Filter::View) NULL, ComparableMin::create(vExtractor))); std::cout << "minimum: " << vFlMin << std::endl;
// query the cache, and print the results Filter::View vFilter = GreaterFilter::create(vExtractor, Float64::valueOf(7.0)); Set::View vSetResult = hCache->entrySet(vFilter); std::cout << "filtered cache contents by " << vFilter << std::endl; for (Iterator::Handle hIter = vSetResult->iterator(); hIter->hasNext(); ) { Map::Entry::View vEntry = cast<Map::Entry::View>(hIter->next()); Object::View vKey = vEntry->getKey(); Object::View vValue = vEntry->getValue(); std::cout << '\t' << vKey << " = " << vValue << std::endl; }
// present a real-time filtered view of the cache NamedCache::Handle hCacheCqc = ContinuousQueryCache::create(hCache, vFilter); std::cout << "ContinuousQueryCache filtered view: " << std::endl; for (Iterator::Handle hIter = hCacheCqc->entrySet()->iterator(); hIter->hasNext(); ) { Map::Entry::View vEntry = cast<Map::Entry::View>(hIter->next()); Object::View vKey = vEntry->getKey(); Object::View vValue = vEntry->getValue(); std::cout << '\t' << vKey << " = " << vValue << std::endl; } // register MapListener to print changes to stdout std::cout << "start listening to events..." << std::endl; hCache->addFilterListener(VerboseMapListener::create());
// invoke entry processor on matching cache contents, incrementing each value Float64::Handle vFlIncr = Float64::valueOf(1.0); std::cout << "increment results by " << vFlIncr << std::endl; hCacheCqc->invokeAll((Filter::View) NULL, NumberIncrementor::create( (ValueManipulator::View) NULL, vFlIncr, /*fPost*/ true)); // stop the CQC event queue thread and remove listeners hCacheCqc->release(); // disconnect from the grid CacheFactory::shutdown(); } catch (const std::exception& e) { std::cerr << "error: " << e.what() << std::endl; return 1; } return 0; }