Share Library (C++)
File detail
Source code
/**
* @file sharectl.cpp
* @brief Command-line utility manipulating with shared segment
* @author Kamil Dudka, xdudka00@gmail.com
* @date 2007-05-15
* @ingroup sharectl
*/
#include "sharectl.h"
#include "SharedSegment.h"
#include "SegmentHeader.h"
#include <iostream>
#include <sstream>
using namespace Share;
int main (int argc, char *argv[])
{
try {
SharedSegmentWrapper segment;
// Parse command line arguments
ArgParser parser (argc, argv);
if (parser.action() == ArgParser::HELP) {
std::cout <<
"sharectl SEGMENT_NAME [SWITCH] [...]\n"
" --create Create new shared segment of specified size.\n"
" --create-and-wait Create new shared segment of specified size and wait until key pressed.\n"
" --notify-attach Increase internal reference counter.\n"
" --notify-detach Decrease internal reference counter.\n"
" --unlink Mark segment to be destroyed.\n"
" --force-destroy Destroy segment immediately.\n"
" --alloc Allocate block of specified size inside shared segment.\n"
" --free Free block identified by relative pointer (number)\n";
return 0;
}
// Create shared segment or attach to an existing one
if (parser.isNewSegment())
segment.create (parser.name(), parser.size());
else
segment.attach (parser.name());
// Obtaing attached segment address
SegmentDebuger debuger (segment.atAddr());
// Handle cmd-line action switch
switch (parser.action()) {
case ArgParser::FORCE_DESTORY:
segment.destroy();
break;
case ArgParser::ALLOC:
debuger.alloc(parser.size());
std::cout << debuger;
break;
case ArgParser::FREE:
debuger.free(parser.size());
std::cout << debuger;
break;
case ArgParser::CREATE_AND_WAIT: {
std::cout << "Shared segment created.\n Waiting. Pres any key to abort.\n";
char tmp;
std::cin.read (&tmp, sizeof(char));
std::cout << debuger;
}
break;
case ArgParser::NOTIFY_ATTACH:
case ArgParser::NOTIFY_DETACH:
case ArgParser::UNLINK:
debuger.refCountAction (parser.action());
// Print statistics after operation
case ArgParser::CREATE:
case ArgParser::NONE:
std::cout << debuger;
if (debuger.shouldBeDestroyed())
segment.destroy ();
break;
default:
throw ShareException("internal exception");
}
}
catch (ShareException e) {
std::cerr << "sharectl: " << e.message() << std::endl;
return 1;
}
}
// TODO: Comand-line arguments documentation
ArgParser::ArgParser (int, char *argv[]) throw (ShareException):
size_(0),
action_(NONE)
{
ArgSwitchChecker switchChecker;
// Scan all arguments in loop
for (char **current = argv + 1; *current; current++) {
// Obtain current argument
const char *str = *current;
// Check for --switch
Action act = switchChecker.checkSwitch (str);
if (act != NONE) {
// Accept switch argument
if (action_ != NONE)
throw ShareException ("ArgParser: More then one switch - not implemented yet");
action_ = act;
continue;
}
if (str[0] == '-') {
// Decline switch argument
std::ostringstream stream;
stream << "ArgParser: Unknown switch: " << str;
throw ShareException (stream.str().c_str());
}
// Read size argument
size_t size;
std::istringstream stream (str);
if (stream >> size) {
if (size_)
throw ShareException ("ArgParser: More then one numeric argument - not implemented yet");
size_ = size;
continue;
}
if (!name_.empty())
throw ShareException ("ArgParser: More then one string argument - not implemented yet");
// Read name argument
name_ = str;
}
switch (action_) {
case HELP:
break;
case CREATE:
case CREATE_AND_WAIT:
case ALLOC:
case FREE:
if (!size_)
throw ShareException ("ArgParser: Size argument must be given!");
default:
if (name_.empty())
throw ShareException ("ArgParser: Name of shared segment must be given!");
}
}
bool ArgParser::isNewSegment()
{
return
action_ == CREATE ||
action_ == CREATE_AND_WAIT;
}
const char* ArgParser::name()
{
return name_.c_str();
}
size_t ArgParser::size()
{
return size_;
}
ArgParser::Action ArgParser::action()
{
return action_;
}
ArgSwitchChecker::ArgSwitchChecker()
{
// Build map
map_ ["--help"] = ArgParser::HELP;
map_ ["--usage"] = ArgParser::HELP;
map_ ["--create"] = ArgParser::CREATE;
map_ ["--create-and-wait"] = ArgParser::CREATE_AND_WAIT;
map_ ["--notify-attach"] = ArgParser::NOTIFY_ATTACH;
map_ ["--notify-detach"] = ArgParser::NOTIFY_DETACH;
map_ ["--unlink"] = ArgParser::UNLINK;
map_ ["--force-destroy"] = ArgParser::FORCE_DESTORY;
map_ ["--alloc"] = ArgParser::ALLOC;
map_ ["--free"] = ArgParser::FREE;
}
ArgSwitchChecker::TAction ArgSwitchChecker::checkSwitch (std::string stringToCheck)
{
// Map look-up
TMap::const_iterator i = map_.find (stringToCheck);
if (i == map_.end())
return ArgParser::NONE;
else
return i->second;
}
SharedSegmentWrapper::SharedSegmentWrapper():
segment_(0)
{
}
SharedSegmentWrapper::~SharedSegmentWrapper()
{
delete segment_;
}
void SharedSegmentWrapper::create (const char *name, size_t size) throw (ShareException)
{
if (segment_)
throw ShareException("internal exception");
try {
segment_ = new SharedSegment (name, size);
ShareManager::instance()-> initDebugMode (segment_);
void *atAddr = segment_ -> atAddress();
new (atAddr) SegmentHeader (name, size);
}
catch (ShareException e) {
std::cerr << e.message() << std::endl;
std::ostringstream stream;
stream << "Unable to create shared segment '" << name << "' of size " << size;
throw ShareException (stream.str().c_str());
}
}
void SharedSegmentWrapper::attach (const char *name) throw (ShareException)
{
if (segment_)
throw ShareException("internal exception");
try {
segment_ = new SharedSegment (name);
ShareManager::instance()-> initDebugMode (segment_);
}
catch (ShareException e) {
std::cerr << e.message() << std::endl;
std::ostringstream stream;
stream << "Unable to attach shared segment '" << name << "'";
throw ShareException (stream.str().c_str());
}
}
SegmentHeader* SharedSegmentWrapper::atAddr() throw (ShareException)
{
if (0 == segment_)
throw ShareException("internal exception");
return static_cast<SegmentHeader *> (segment_ -> atAddress());
}
void SharedSegmentWrapper::destroy()
{
std::cout << "Attempting to destroy shared segment '" << segment_->name() << "'" << std::endl;
//segment_ -> destroy();
ShareManager::instance()-> destroySegment();
}
SegmentDebuger::SegmentDebuger (SegmentHeader *segmentManager):
segmentManager_ (segmentManager)
{
}
std::ostream& Share::operator<< (std::ostream &stream, SegmentDebuger &m)
{
stream << "Shared segment statistics:" << std::endl;
stream << " Size: " << m.segmentManager_ -> size() << std::endl;
stream << " Available: " << m.segmentManager_ -> available() << std::endl;
stream << " Current RefCount: " << m.segmentManager_ -> refCount() << std::endl;
stream << " Unlinked: " << m.segmentManager_ -> isUnlinked() << std::endl;
return stream;
}
void SegmentDebuger::refCountAction (ArgParser::Action action)
{
switch (action) {
case ArgParser::NOTIFY_ATTACH:
std::cout << "Calling SegmentHeader::notifyAttach()" << std::endl;
segmentManager_ -> notifyAttach();
break;
case ArgParser::NOTIFY_DETACH:
std::cout << "Calling SegmentHeader::notifyDetach()" << std::endl;
segmentManager_ -> notifyDetach();
break;
case ArgParser::UNLINK:
std::cout << "Calling SegmentHeader::unlink()" << std::endl;
segmentManager_ -> unlink();
break;
default:
throw ShareException("internal exception");
}
}
bool SegmentDebuger::shouldBeDestroyed()
{
return segmentManager_ -> shouldBeDestroyed();
}
void SegmentDebuger::alloc (size_t size)
{
std::cout << "Attempting to allocate block of size " << size << std::endl;
RelocPtr<void> addr = segmentManager_ -> alloc (size);
std::cout << "Relative address of allocated block is " << addr.toRel() << std::endl;
}
void SegmentDebuger::free (size_t relativePointer)
{
std::cout << "Attempting to free block at relative address " << relativePointer << std::endl;
typedef RelocPtr<void> TPointer;
TPointer addr = TPointer::fromRel (relativePointer);
segmentManager_ -> free (addr);
}