• No se han encontrado resultados

CAPÍTULO I: ANTECEDENTES Y ESTADO DE LA CUESTIÓN

I.2. Antecedentes sobre la toma de apuntes

I.2.1. Concepciones sobre la toma de apuntes

The source code for the entire server takes only a few lines:

#include <time.h> #include <iostream.h> #include "timeS.hh"

class Time_impl : public virtual POA_Time { public:

virtual TimeOfDay get_gmt() throw(CORBA::SystemException); };

TimeOfDay Time_impl::

get_gmt() throw(CORBA::SystemException) {

time_t time_now = time(0);

struct tm * time_p = gmtime(&time_now); TimeOfDay tod; tod.hour = time_p->tm_hour; tod.minute = time_p->tm_min; tod.second = time_p->tm_sec; return tod; } int

main(int argc, char * argv[]) {

try {

// Initialize orb

CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);

// Get reference to Root POA. CORBA::Object_var obj

= orb->resolve_initial_references("RootPOA"); PortableServer::POA_var poa

= PortableServer::POA::_narrow(obj);

// Activate POA manager

PortableServer::POAManager_var mgr = poa->the_POAManager(); mgr->activate(); // Create an object Time_impl time_servant;

// Write its stringified reference to stdout Time_var tm = time_servant._this(); CORBA::String_var str = orb->object_to_string(tm); cout < str < endl; // Accept requests orb->run(); }

catch (const CORBA::Exception &) {

cerr < "Uncaught CORBA exception" < endl; return 1;

}

return 0; }

The server implements one Time object. The timeS.hh header file contains an abstract base class called POA_Time. Its definition looks like this (tidied up a little to get rid of code that is irrelevant to the application):

// In file timeS.hh: class POA_Time :

public:

virtual ~POA_Time(); Time_ptr _this(); virtual TimeOfDay get_gmt()

throw(CORBA::SystemException) = 0; };

Note that this class contains a get_gmt pure virtual method. To create an implementation object that clients can call, we must derive a concrete class from

POA_Time that provides an implementation for the get_gmt method. This means that the first few lines of our server program look like this:

#include <time.h> #include <iostream.h> #include "timeS.hh"

class Time_impl : public virtual POA_Time { public:

virtual TimeOfDay get_gmt() throw(CORBA::SystemException); };

Here, we define a class Time_impl that inherits from POA_Time. This class provides a concrete implementation of a Time object that clients actually can communicate with. Our implementation class is very simple. It has only the single method get_gmt (which is not pure virtual because we require a concrete class that can actually be instantiated). The next step is to implement the get_gmt method of Time_impl. For now, we are ignoring error conditions. If the call to time fails with a return value of -1, get_gmt

returns a garbage time value instead of raising an exception. (We discuss how to deal with errors in Chapters 7 and 9.)

TimeOfDay Time_impl::

get_gmt() throw(CORBA::SystemException) {

time_t time_now = time(0);

struct tm * time_p = gmtime(&time_now); TimeOfDay tod; tod.hour = time_p->tm_hour; tod.minute = time_p->tm_min; tod.second = time_p->tm_sec; return tod; }

This completes the object implementation. What remains is to provide a main function for the server. The first few lines are identical for most servers and initialize the server- side ORB run time:

main(int argc, char * argv[]) {

try {

// Initialize orb

CORBA::ORB_var orb = CORBA::ORB_init(argc, argv); // Get reference to Root POA.

CORBA::Object_var obj

= orb->resolve_initial_references("RootPOA"); PortableServer::POA_var poa

= PortableServer::POA::_narrow(obj); // Activate POA manager

PortableServer::POAManager_var mgr = poa->the_POAManager();

mgr->activate();

Do not be concerned about the details of this code for the moment—we will discuss its precise purpose in later chapters.

The next step is to provide an actual servant for a Time object so that clients can send invocations to it. We do this by creating an instance of the Time_impl servant class:

// Create a Time object Time_impl time_servant;

For the client to be able to access the object, the client requires an object reference. In this simple example, we provide that reference by writing it as a string to stdout. Of course, this is not a distributed solution, but it will suffice for now:

// Write a stringified reference // for the Time object to stdout Time_var tm = time_servant._this();

CORBA::String_var str = orb->object_to_string(tm); cout < str < endl;

The call to _this creates an object reference for the object, and object_to_string

converts that reference into a printable string.

At this point we have a concrete implementation of a Time object whose reference is available to the client. The server is now ready to accept requests, something that it indicates to the ORB run time by calling run:

// Accept requests orb->run();

The remainder of the server source code sets an exception handler that prints an error message if anything goes wrong and terminates main. (The closing curly brace at the start of this code fragment completes the try block we opened at the beginning of main.)

}

catch (const CORBA::Exception &) {

cerr < "Uncaught CORBA exception" < endl; return 1;

}

return 0; }

This completes the server source code. In this short example, most of the source code is boilerplate that you will find in every server. In a more realistic application, most of the server source code consists of the actual operation implementations.

We are now ready to compile and link the server code. The exact compile and link commands you use depend on your compiler and ORB. For example, include paths differ from vendor to vendor, and you may have to add various preprocessor or compiler options. However, the basic idea is the same for all ORBs: you compile the generated stub file (timeC.cc), the generated skeleton file (timeS.cc), and the server source code you have written, which we assume is in the file myserver.cc. Simple compilation commands could look like this:

$ CC -c -I/opt/myORB/include timeC.cc $ CC -c -I/opt/myORB/include timeS.cc $ CC -c -I/opt/myORB/include myserver.cc

Assuming that there are no errors, this produces three object files that we can link into an executable. Again, the exact link command you use depends on your C++ compiler and ORB vendor. Also, the name and location of the ORB run-time libraries you link with will differ for each vendor. A simple link command is

$ CC -o myserver timeC.o timeS.o myserver.o \ > -L/opt/myORB/lib -lorb

Here, we assume that the ORB run-time library is called liborb. Assuming that there are no errors, we now have a complete executable we can run from the command line. On start-up, the server prints a reference to its Time object on stdout. The server then waits indefinitely for client requests. (To stop the server, we must kill it by sending it a signal.) $ ./myserver IOR:000000000000000d49444c3a54696d653a312e300000000000000001000000 00000000f000010100000000066d6572676500060b000000d7030231310c000016 7e0000175d360aed118143582d466163653a20457348795e426e5851664e527333 3d4d7268787b72643b4b4c4e59295a526a4c3a39564628296e4345633637533d6a 2c77245879727c7b6371752b7434567d61383b3422535e514a2b48322e772f354f

245e573e69512b6b24717a412f7822265c2172772d577d303927537d5e715c5757 70784a2734385832694f3e7433483753276f4825305a2858382e4a30667577487b 3647343e3e7e5b554b21643d67613c6d367a4e784d414f7a7658606d214a45677e 272f737756642420000000000000