この付録では、console、contactsおよびhellogridのC++を例にして、サンプル・コードを紹介します。
hellogridのサンプルを実行した後は、そのコードを調べることをお薦めします。各サンプルには、examplesの下に対応するディレクトリがあります。ここには、サンプル固有のソースが含まれています。また、すべてのサンプルで使用されるソースを含む、commonディレクトリもあります。
例A-1は、hellogrid.cppサンプルのソース・コードで、基本的なキャッシュ・アクセスを示しています。
例A-1 HelloGridサンプル・アプリケーションのコード
#include "coherence/lang.ns"
#include "coherence/net/cache/ContinuousQueryCache.hpp"
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 "VerboseMapListener.hpp"
#include <iostream>
using namespace coherence::lang;
using coherence::examples::VerboseMapListener;
using coherence::net::cache::ContinuousQueryCache;
sing 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 matchingcache contents, incrementing each
// value by the minimum 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));
// disconnect from the grid
CacheFactory::shutdown();
}
catch (const std::exception& e)
{
std::cerr << "error: " << e.what() << std::endl;
return 1;
}
return 0;
}
consoleのサンプルを実行した後は、そのコードを調べることをお薦めします。各サンプルには、examplesの下に対応するディレクトリがあります。ここには、サンプル固有のソースが含まれています。また、すべてのサンプルで使用されるソースを含む、commonディレクトリもあります。
例A-2は、簡単なコマンドでキャッシュとの対話を可能にする、console.cppコマンドライン・アプリケーションのソース・コードを示しています。
例A-2 Consoleサンプル・アプリケーションのコード
#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;
}
}
}
contactsのサンプルを実行した後は、そのコードを調べることをお薦めします。各サンプルには、examplesの下に対応するディレクトリがあります。ここには、サンプル固有のソースが含まれています。また、すべてのサンプルで使用されるソースを含む、commonディレクトリもあります。
例A-3は、contactsサンプルのソース・コードで、既存の(つまり、Coherenceではない)C++クラスをグリッド内に格納する方法を示しています。
例A-3 ContactInfoサンプル・アプリケーションのヘッダー・コード
#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);
// ----- 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;
};
// ----- free functions -----------------------------------------------------
/**
* 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);
/*** Perform an equality test on two ContactInfo objects** @param infoA the first ContactInfo* @param infoB the second ContactInfo** @return true if the objects are equal*/bool operator==(const ContactInfo& infoA, const ContactInfo& infoB); /*** Return the has for the ContactInfo.** @param info the ContactInfo to hash** @return the hash for the ContactInfo*/size_t hash_value(const ContactInfo& info);
#endif // COH_EXAMPLES_CONTACT_INFO_HPP
例A-4 ContactInfoサンプル・アプリケーションのC++コード
#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;
}
// ----- free functions -----------------------------------------------------
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;
}
bool operator==(const ContactInfo& infoA, const ContactInfo& infoB)
{
return infoA.getName() == infoB.getName() &&
infoA.getStreet() == infoB.getStreet() &&
infoA.getCity() == infoB.getCity() &&
infoA.getState() == infoB.getState() &&
infoA.getZip() == infoB.getZip();
}
size_t hash_value(const ContactInfo& info)
{
return size_t(&info); // identity hash (note: not suitable for cache keys)
}
例A-5 PortableContactInfoアプリケーションのC++コード
/**
* This file defines serializers for the ContactInfo class and registers its
* managed form (Managed<ContactInfo>) with Coherence.
*/
#include "coherence/lang.ns"
#include "coherence/io/pof/PofWriter.hpp"
#include "coherence/io/pof/PofReader.hpp"
#include "coherence/io/pof/SystemPofContext.hpp"
#include "ContactInfo.hpp"
#include <string>
using namespace coherence::lang;
using coherence::io::pof::PofReader;
using coherence::io::pof::PofWriter;
COH_REGISTER_MANAGED_CLASS(1001, ContactInfo);
template<> void serialize<ContactInfo>(PofWriter::Handle hOut, const ContactInfo& info)
{
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());
}
template<> ContactInfo deserialize<ContactInfo>(PofReader::Handle hIn)
{
std::string sName = hIn->readString(0);
std::string sStreet = hIn->readString(1);
std::string sCity = hIn->readString(2);
std::string sState = hIn->readString(3);
std::string sZip = hIn->readString(4);
return ContactInfo(sName, sStreet, sCity, sState, sZip);
}
例A-6 ContactInfoデータ・オブジェクトのコード
#include "coherence/lang.ns"
#include "coherence/net/CacheFactory.hpp"
#include "coherence/net/NamedCache.hpp"
#include "ContactInfo.hpp"
#include <iostream>
#include <sstream>
using namespace coherence::lang;
using coherence::net::CacheFactory;
using coherence::net::NamedCache;
// ----- function 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);
if (std::cin.fail())
{
std::cin.clear();
continue;
}
std::stringstream ssInput(achInput);
// process input
std::string sCmd;
ssInput >> sCmd;
if (sCmd == "")
{
continue;
}
else if (sCmd == "bye")
{
// quit
CacheFactory::shutdown();
return 0;
}
else if (sCmd == "create")
{
ContactInfo ci = readContact();
std::cout << "storing: " << ci << std::endl;
hCache->put(String::create(ci.getName().c_str()),
Managed<ContactInfo>::create(ci));
}
else if (sCmd == "find")
{
std::string sPart;
ssInput >> sPart;
std::cout << "Name: " << std::flush;
std::cin.getline(achInput, 256);
String::View vsName = achInput;
Managed<ContactInfo>::View vInfo =
cast<Managed<ContactInfo>::View>(hCache->get(vsName));
if (NULL == vInfo)
{
std::cout << vsName << " not found" << std::endl;
continue;
}
if (sPart == "" || sPart == "all")
{
std::cout << vInfo << std::endl;
}
else if (sPart == "street")
{
std::cout << vInfo->getStreet() << std::endl;
}
else if (sPart == "city")
{
std::cout << vInfo->getCity() << std::endl;
}
else if (sPart == "state")
{
std::cout << vInfo->getState() << std::endl;
}
else if (sPart == "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);
}