FEI C++ Interface Examples

FEI Versions 3.2.0
Last update on October 25, 2001
Send questions, comments and corrections to MDMS



Introduction

C++ example programs that use the FEI API come with the distribution and are located in the directory ~Fei/Examples/Cpp/. The following programs are includes


Note: Before running any of the programs, you must first obtain a valid Kerberos ticket and have configured the FEI environment. (See the Client Installation Guide if you need assistance with this.)

Note: In the following sections, numbers in [square brackets] refer to listing line numbers for the program under discussion.




Making The C++ Examples

Copy the files from $FEI_ROOT/examples/cpp to get your own set of examples. You'll need the capability to get, add, replace and delete files on some file type in order to run the examples. For our testing we'll use file types like image. Substitute your own file type for the ones mentioned in the examples.

The syntax to compile and link an example program is: make <program name>. For example:

% make example1

If a program does not compile and link properly, try the command:

% make clean

and then try again.

The Makefile is supplied along with the examples. Look at the definitions section of the Makefile to confirm the the macro definitions are setup properly for your environment. If you're having trouble finding files or linking with shared libraries, make sure your environment was installed correctly.




example1

Example1 will add a set of files to FEI. Then it will get the files. Once a file has been gotten, it it deleted in FEI. In the file already exists in your local directory, the current file will be made a version of the file being gotten. This is done by appending a uniquue number (time stamp) to the file's name.

An example run, we will add the example programs from your /examples directory and then get them in a directory named /test which is below /examples.

The syntax for the command is: example1 <fileType> <file name expression>:

The following example assumes that you start in your /examples directory.

% mkdir test
% cd test
% feiKinit <your Kerberos principal name>
SunOS (milano)
Kerberos Initialization for "me"
Password: <your Kerberos password>
% ../example1 image ../*.cpp

Connected to Fei for file type "image".
added example1.cpp.
added example2.cpp.
added example3.cpp.
got file example1.cpp.
deleted file example1.cpp.
got file example2.cpp.
deleted file example2.cpp.
got file example3.cpp.
deleted file example3.cpp.
Disconnecting from Fei.


If you run the command again, the files you got the first time should turn into versions of the files you get the second time.

The following comments explain what happened. Select the link for example1 to see the code with line numbers.

[46-47] An Fei object is created and used to connect to an FEI server with the supplied file type's name.

[49-50] An error message is created and sent to the FeiMsg object. Notice that we never create this object; we just start using it. There is only one such object per program, and it is used by all of the FEI threads as well as your program, which is the main thread. The single instance is created automatically for you. The method to record a message takes two arguments, a message buffer, which we defined at line [30] and an FEI message status. The message status values can be found in the file FeiGlobal.h. This file is included whenever you include another FEI ".h" file.

[58] Files are represented by FeiProfile objects. We need a pointer to an object of that type so we can handle each one as it retrieve it.

[61] The add member function is used to queue a transaction.

[69] A while loop is used to get all of the results from the result queue. Since the result () member function has no parameter, it blocks until the results of the posted transaction are returned.

[71] We get the status of a profile record. If its FEI_OK, the file was added. Otherwise an error occurred. In that case, the ,FEI object will have written an error message using FeiMsg.

[81] Once we are done with the profile object, we must delete it.

[91] The Fei member function setOptions () is used to turn on file versioning before we get the files so we won't overwrite the local copies of the files already present.

[94, 103] For each file added, we queue two transactions; the first to get the file and the second to remove, or delete, it in the FEI server.

[115] Since we have queued two transactions, we use the Fei member function transactions () to test for the completion of both transactions before we get the next file.

[122-129] The profile object contains information about the file it represents. This information is obtained using a set of get... member functions. In this case we get the command associated with the profile and use it to format a message.

[135] Again, we delete each profile objects once we done with it.

[145] We don't have to disconnect from FEI in this case, because the Fei object's destructor will do it for use. But there are times when you do want to disconnect explicitly - possibly to connect later when you need FEI resources again.




example2

In example2 we list all of the files for file type image that match the file type expression 'file*'. The expression is quoted so the shell won't expand the string - the string should be passed on to the FEI server. The prompt is a string returned by each list profile object. It's composed of the FEI file modification time, the size of the file in bytes and the file's name. The file's content in each case is not very impressive, just the name of the file again.

We must first add, or replace, some files in FEI so we have some test data present. Use the FEI utility FileMaker for this purpose. Once three or four files have been added, stop the program with <control-c>, and then run the example. (If you don't have a Kerberos ticket, get one before running this example. Example1 shows how to do this.)

% feiFileMaker image for replace delay 1
Connect to "image".
   1. added "file1", transaction took 0.010 seconds.
   2. added "file2", transaction took 0.000 seconds.
   3. added "file3", transaction took 0.000 seconds.
   4. added "file4", transaction took 0.000 seconds.
^C
Normal shut down.

% example2 image 'file*'

Respond with the letter 'g' to display the
contents of the listed file. Press <enter> or <return> to skip the file.

1997-223T16:55:08.286,            6, file1 :
1997-223T16:55:13.300,            6, file2 :g
file2

1997-223T16:55:18.296,            6, file3 :g
file3

1997-223T16:56:13.273,            6, file4 :
Disconnecting from Fei.



[48-54] Example2 begins much as example1 did, but this time we use two connections.

[56] The list member function uses a file expression fileNameExpr, so we have the potential to get back any number of profile objects describing files.

[65] This while loop retrieves the profile record of each file found for the list command. A prompt to the user is built from profile information returned as a string by the FeiProfile member function getProfileString () [75].

[83-84] If the user responded with 'g', the the function getFile is called. The file name passed as the second argument to getFile is provided by the profile object returned by list.

[106] Normally when we get a file it's written to disk using the localPath argument, but in this case the localPath is supplied the special value FEI_IN_MEMORY which causes the content of the file to be returned along with the profile object. The memory needed to contain the file's contents is allocated by by the Fei object get.

[116] We get the address of the file's content buffer and the size of the buffer and write the content to stdout.

[120] When we delete the profile, the buffer containing the file's content is deleted as well. If we want to keep the buffer, we supply the parameter FEI_RETAIN to getAddress ():


profile->getAddress (FEI_RETAIN)


After that, it's the caller's responsibility to delete the buffer. Note: The buffer containing the file is not terminated in any special way. The size of file value returned with the address of the memory location of the file's contents, is the size of the file.




example3

Example3 implements a subscription session, and is a little more complicated than the earlier examples. This is not because the FEI interface is more involved in this case, but because you must handle more conditions:

  1. Since subscription sessions often run in the background, we'll use a log file to capture messages. We use the file type argument to create the name of the log file: <file type>.log.
  2. If the subscription sessions is interrupted for any reason, we'll want to restart it at the place if left off. We use a restart file for that. Again we use the file type to create the restart file's name: <file type<>.restart. There are two conditions where we must restart:
    1. Our program stops. In that case we supply the word "restart" in place of the program's file type argument.
    2. A network or server interruption occurs. In that case we continue to run and attempt to restart at intervals. Once successful, we continue on.

  3. Since a subscription session can run a long time, it's often convenient to get reports on what's happened from time to time. We report files delivered and error messages via email.
  4. Since a subscription session just continues to run, we need a way to stop the program with a signal. And when it stops, we must take care of any information in the result queue before exiting.

For this example, we'll need two programs; the example which subscribes and another program to add files to the FEI server. Use one of the command line utilities like Add, Replace or FileMake for that task. In the following example, files are added with FileMaker:

To run this example, you will need three terminal windows. In the first window change to your examples directory and type a command like this:

% example3 image ./test 'jake@milano' '17:37 17:40'
FEI Information on 1997-268T17:36:25
PID 19761: subscribing to file type "image".


This starts the example3's subscription session. The parameters to the command call for the following actions:

  1. image Subscribe to the "image" file type.
  2. ./test Files are written to the subdirectory /test
  3. 'jake@milano' All messages and reports are sent to this email address.
  4. '17:37 17:40' Reports are sent at these times. (Note: For times, both hours and minutes must have two digits, like this: '08:05'.) The times you use should be just a couple minutes later than the current time.

Notice that the program's PID was displayed after example3 started. We'll use this later to stop the program.

Now, in a second terminal window, add some files to the same file type we're subscribing to. When the test is done, stop this program with <control-c>. Use the standard FEI utility FileMaker for this job.

% feiFileMake image for replace delay 20
Connect to "image".
   1. added "file1", transaction took 0.010 seconds.
   2. added "file2", transaction took 0.000 seconds.
   3. added "file3", transaction took 0.000 seconds.
   4. added "file4", transaction took 0.000 seconds.
   5. added "file5", transaction took 0.000 seconds.
   6. added "file6", transaction took 0.000 seconds.
   7. added "file7", transaction took 0.000 seconds.
   8. added "file8", transaction took 0.000 seconds.
   9. added "file9", transaction took 0.000 seconds.
   ^C
Normal shut down.


In your first window, you should start seeing new file messages appear that look something like this:

FEI Information on 1997-268T17:36:30
1997-268T17:36:30.653,            7, file1
FEI Information on 1997-268T17:36:50
1997-268T17:36:50.333,            7, file2
FEI Information on 1997-268T17:37:10
1997-268T17:37:10.336,            7, file3
FEI Information on 1997-268T17:37:30
1997-268T17:37:30.323,            7, file4
FEI Information on 1997-268T17:37:50
1997-268T17:37:50.343,            7, file5
FEI Information on 1997-268T17:38:10
1997-268T17:38:10.333,            7, file6
FEI Information on 1997-268T17:38:20
Normal program termination.


Once you have passed the first report time you entered, you can stop example3 from the third window like this:

% kill 19761

We could also have used <control-c> from the window in which we ran example3.

Now look at your mail, you should have two messages: one sent at the report time and a second sent when example3 was stopped. The messages look something like this:

Date: Thu, 25 Sep 1997 17:37:00 -0700
From: jake@milano.jpl.nasa.gov (Jake Lamata)
To: jake@milano.jpl.nasa.gov
Subject: Re: FEI subscription session for "image"

1997-268T17:36:30.653,            7, file1
1997-268T17:36:50.333,            7, file2


Date: Thu, 25 Sep 1997 17:38:20 -0700
From: jake@milano.jpl.nasa.gov (Jake Lamata)
To: jake@milano.jpl.nasa.gov
Subject: Re: FEI subscription session for "image"


1997-268T17:37:10.336,            7, file3

1997-268T17:37:30.323,            7, file4

1997-268T17:37:50.343,            7, file5

1997-268T17:38:10.333,            7, file6

Final report.


Example3 has several functions. We'll describe the function of each one so you have an idea of the structure of the program. Serveral of the functions carry out standard programming tasks, so we won't go into those in detail. There documented in the code and their workings should be easy to understand.


In the following discussion, we describe sections of code used to implement a subscription session.

[72] If an email address and a string containing a set of restart times is supplied, then we create an FeiMailReport object and pass it the email address and a subject line that's used for each report generated. Next [78], we pass the string containing the report times to the report object. This starts a scheduler thread within the object. The scheduler thread will create a report and mail it at the prescribed times each day as long as the program runs. (See the FeiMailReport reference page for more information.)

[88, 330] Install a signal handler that will assign "true" to shutDown when it is called. The subscription session loop exits when shutDown becomes "true". Also, notice that the programs PID is record once the program starts [132]. Since subscription sessions often run in the background, it's important that the operator have easy access to this information. Since FeiMsg is used to record this message, it appears in the log file automatically.

[102-130] Configure FeiMsg so that it sends messages to a log file and email, but not to stderr.

[136] Create a restart file using the file type name followed by the extension "restart". This name is used to create the restart file and to access the file later if we need to restart the sesssion from within the program. The name simply follows a convention. Any name can be used.

[147, 166] Call the function connectToFei to connect to the file type. If the file type value is "restart", the restart member function is called with the name of the restart file [179]. Otherwise a new subscription session is started and we subscribe with a new restart file.

[132, 205] Once a connection is established, main calls the subscription session function, session. The program remains there until it's terminated.

[205] The session function has a main loop that continues as long as it's not time to shut down. Within the loop, four important activities are performed.





example4