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;
}