Commit 2483056b15040fdaef86adf649560fa5d36b60c0

Authored by Grzegorz Jabłoński
1 parent 62dba6f1

Added evictor example

cpp11/Ice/evictor/Client.cpp 0 → 100644
  1 +//
  2 +// Copyright (c) ZeroC, Inc. All rights reserved.
  3 +//
  4 +
  5 +#include <Ice/Ice.h>
  6 +#include <Printer.h>
  7 +#include <stdexcept>
  8 +
  9 +using namespace std;
  10 +using namespace Demo;
  11 +
  12 +int
  13 +main(int argc, char* argv[])
  14 +{
  15 + try
  16 + {
  17 + Ice::CommunicatorHolder ich(argc, argv);
  18 + auto base = ich->stringToProxy("SimplePrinter1:default -p 10000");
  19 + auto printer = Ice::checkedCast<PrinterPrx>(base);
  20 + if(!printer)
  21 + {
  22 + throw std::runtime_error("Invalid proxy");
  23 + }
  24 +
  25 + printer->printString("Hello World!");
  26 +
  27 + auto base2 = ich->stringToProxy("SimplePrinter2:default -p 10000");
  28 + auto printer2 = Ice::checkedCast<PrinterPrx>(base2);
  29 + if(!printer2)
  30 + {
  31 + throw std::runtime_error("Invalid proxy");
  32 + }
  33 +
  34 + printer2->printString("Hello World!");
  35 +
  36 + printer->shutdown();
  37 +
  38 + }
  39 + catch(const std::exception& e)
  40 + {
  41 + cerr << e.what() << endl;
  42 + return 1;
  43 + }
  44 + return 0;
  45 +}
... ...
cpp11/Ice/evictor/EvictorBase.cpp 0 → 100644
  1 +#include <EvictorBase.h>
  2 +
  3 +using namespace std;
  4 +
  5 +EvictorBase::EvictorBase(int size) :
  6 + _size(size)
  7 +{
  8 + if (_size < 0)
  9 + {
  10 + _size = 1000;
  11 + }
  12 +}
  13 +
  14 +shared_ptr<Ice::Object>
  15 +EvictorBase::locate(const Ice::Current& c, shared_ptr<void>& cookie)
  16 +{
  17 + lock_guard<mutex> lk(_mutex);
  18 +
  19 + //
  20 + // Check if we have a servant in the map already.
  21 + //
  22 + shared_ptr<EvictorEntry> entry;
  23 + auto i = _map.find(c.id);
  24 + if(i != _map.end())
  25 + {
  26 + //
  27 + // Got an entry already, dequeue the entry from its current position.
  28 + //
  29 + entry = i->second;
  30 + _queue.erase(entry->queuePos);
  31 + }
  32 + else
  33 + {
  34 + //
  35 + // We do not have an entry. Ask the derived class to
  36 + // instantiate a servant and add a new entry to the map.
  37 + //
  38 + entry = make_shared<EvictorEntry>();
  39 + entry->servant = add(c, entry->userCookie); // Down-call
  40 + if(!entry->servant)
  41 + {
  42 + return 0;
  43 + }
  44 + entry->useCount = 0;
  45 + i = _map.insert(make_pair(c.id, entry)).first;
  46 + }
  47 +
  48 + //
  49 + // Increment the use count of the servant and enqueue
  50 + // the entry at the front, so we get LRU order.
  51 + //
  52 + ++(entry->useCount);
  53 + entry->queuePos = _queue.insert(_queue.begin(), i);
  54 +
  55 + cookie = entry;
  56 +
  57 + return entry->servant;
  58 +}
  59 +
  60 +void
  61 +EvictorBase::finished(const Ice::Current&, const shared_ptr<Ice::Object>&, const shared_ptr<void>& cookie)
  62 +{
  63 + lock_guard<mutex> lk(_mutex);
  64 +
  65 + auto entry = static_pointer_cast<EvictorEntry>(cookie);
  66 +
  67 + //
  68 + // Decrement use count and check if there is something to evict.
  69 + //
  70 + --(entry->useCount);
  71 + evictServants();
  72 +}
  73 +
  74 +void
  75 +EvictorBase::deactivate(const string&)
  76 +{
  77 + lock_guard<mutex> lk(_mutex);
  78 +
  79 + _size = 0;
  80 + evictServants();
  81 +}
  82 +
  83 +void
  84 +EvictorBase::evictServants()
  85 +{
  86 + //
  87 + // If the evictor queue has grown larger than the limit,
  88 + // look at the excess elements to see whether any of them
  89 + // can be evicted.
  90 + //
  91 + auto p = _queue.rbegin();
  92 + auto excessEntries = static_cast<int>(_map.size() - _size);
  93 +
  94 + for(int i = 0; i < excessEntries; ++i)
  95 + {
  96 + auto mapPos = *p;
  97 + if(mapPos->second->useCount == 0)
  98 + {
  99 + evict(mapPos->second->servant, mapPos->second->userCookie); // Down-call
  100 + p = EvictorQueue::reverse_iterator(_queue.erase(mapPos->second->queuePos));
  101 + _map.erase(mapPos);
  102 + }
  103 + else
  104 + {
  105 + ++p;
  106 + }
  107 + }
  108 +}
... ...
cpp11/Ice/evictor/EvictorBase.h 0 → 100644
  1 +#ifndef EVICTORBASE_H
  2 +#define EVICTORBASE_H
  3 +
  4 +#include <Ice/Ice.h>
  5 +#include <map>
  6 +#include <list>
  7 +#include <mutex>
  8 +
  9 +class EvictorBase : public Ice::ServantLocator
  10 +{
  11 +public:
  12 +
  13 + EvictorBase(int size = 1000);
  14 +
  15 + virtual std::shared_ptr<Ice::Object> locate(const Ice::Current&, std::shared_ptr<void>&) override;
  16 + virtual void finished(const Ice::Current&, const std::shared_ptr<Ice::Object>&, const std::shared_ptr<void>&) override;
  17 + virtual void deactivate(const std::string&) override;
  18 +
  19 +protected:
  20 +
  21 + virtual std::shared_ptr<Ice::Object> add(const Ice::Current&, std::shared_ptr<void>&) = 0;
  22 + virtual void evict(const std::shared_ptr<Ice::Object>&, const std::shared_ptr<void>&) = 0;
  23 +
  24 +private:
  25 +
  26 + struct EvictorEntry;
  27 +
  28 + using EvictorMap = std::map<Ice::Identity, std::shared_ptr<EvictorEntry>>;
  29 + using EvictorQueue = std::list<EvictorMap::iterator>;
  30 +
  31 + struct EvictorEntry
  32 + {
  33 + std::shared_ptr<Ice::Object> servant;
  34 + std::shared_ptr<void> userCookie;
  35 + EvictorQueue::iterator queuePos;
  36 + int useCount;
  37 + };
  38 +
  39 + EvictorMap _map;
  40 + EvictorQueue _queue;
  41 + int _size;
  42 +
  43 + std::mutex _mutex;
  44 +
  45 + void evictServants();
  46 +};
  47 +#endif
... ...
cpp11/Ice/evictor/Makefile.mk 0 → 100644
  1 +#
  2 +# Copyright (c) ZeroC, Inc. All rights reserved.
  3 +#
  4 +
  5 +$(demo)_server_sources = Printer.ice EvictorBase.cpp Server.cpp
  6 +
  7 +demos += $(demo)
... ...
cpp11/Ice/evictor/Printer.ice 0 → 100644
  1 +//
  2 +// Copyright (c) ZeroC, Inc. All rights reserved.
  3 +//
  4 +
  5 +#pragma once
  6 +
  7 +module Demo
  8 +{
  9 + interface Printer
  10 + {
  11 + void printString(string s);
  12 + void shutdown();
  13 + }
  14 +}
... ...
cpp11/Ice/evictor/Server.cpp 0 → 100644
  1 +//
  2 +// Copyright (c) ZeroC, Inc. All rights reserved.
  3 +//
  4 +
  5 +#include <Ice/Ice.h>
  6 +#include <Printer.h>
  7 +#include "EvictorBase.h"
  8 +
  9 +using namespace std;
  10 +using namespace Demo;
  11 +
  12 +class PrinterI : public Printer
  13 +{
  14 + std::string name;
  15 +public:
  16 + PrinterI(const std::string& a) : name(a) {};
  17 + virtual void printString(string s, const Ice::Current&) override;
  18 + void shutdown(const Ice::Current& c) override
  19 + {
  20 + cout << "Shutting down..." << endl;
  21 + c.adapter->getCommunicator()->shutdown();
  22 + }
  23 +};
  24 +
  25 +void
  26 +PrinterI::printString(string s, const Ice::Current&)
  27 +{
  28 + cout << name << ":" << s << endl;
  29 +}
  30 +
  31 +
  32 +class myEvictor: public EvictorBase
  33 +{
  34 + virtual std::shared_ptr<Ice::Object> add(const Ice::Current& c, std::shared_ptr<void>&) override
  35 + {
  36 + cout << "Adding new servant" << endl;
  37 + return make_shared<PrinterI>(c.id.name);
  38 + }
  39 +
  40 + virtual void evict(const std::shared_ptr<Ice::Object>&, const std::shared_ptr<void>&) override
  41 + {
  42 +
  43 + }
  44 +
  45 +};
  46 +
  47 +
  48 +int
  49 +main(int argc, char* argv[])
  50 +{
  51 + try
  52 + {
  53 + Ice::CommunicatorHolder ich(argc, argv);
  54 + auto adapter = ich->createObjectAdapterWithEndpoints("SimplePrinterAdapter", "default -p 10000");
  55 + auto evictor = make_shared<myEvictor>();
  56 + adapter->addServantLocator(evictor,"");
  57 + adapter->activate();
  58 +
  59 + ich->waitForShutdown();
  60 + }
  61 + catch(const std::exception& e)
  62 + {
  63 + cerr << e.what() << endl;
  64 + return 1;
  65 + }
  66 + return 0;
  67 +}
... ...