Main Page   Packages   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Search  

C:/temp/src/j2k/QNX4/ResMgr1.c

Go to the documentation of this file.
00001 // Resource Manager Template
00002 
00003 #include <j2k/Fred/Basic.hpp>
00004 #include <j2k/Fred/System.hpp>
00005 #include <j2k/Fred/Boolean.hpp>
00006 #include <j2k/Fred/StdTypes.hpp>
00007 
00008 #include <sys/fd.h>
00009 #include <sys/prfx.h>
00010 #include <sys/io_msg.h>
00011 
00012 #define  DEBUG_ON
00013 
00014 char* progname = "ResMgr.c";
00015 char* prefix   = "/sample";
00016 
00017 // A union of all message type that we are going to handle
00018 typedef union {
00019   USHORT                   type;
00020   USHORT                   status;
00021   struct _io_open          open;
00022   struct _io_open_reply    open_reply;
00023   struct _io_close         close; 
00024   struct _io_close_reply   close_reply;
00025   struct _io_read          read;
00026   struct _io_read_reply    read_reply;
00027   struct _io_write         write;
00028   struct _io_write_reply   write_reply;
00029 } ResMsg_t;
00030 
00031 /*
00032 
00033  The OCB
00034 
00035  In our case, we've kept it very simple.
00036  Simply the current position into the resource.
00037  This would be a great place to add any per-open
00038  data that you want to store.
00039 
00040 */
00041 
00042 typedef struct {
00043   off_t  offset;
00044 } ResOCB_t;
00045 
00046 /* With a "real" resource manager, you'd set this dynamically based on a
00047  * command-line argument or grow the arrays as necessary while running... */
00048 
00049 // Maximum number of sessions
00050 #define MAX_OCBS  16
00051 
00052 ResMsg_t   msg;                  // The message structure
00053 void*      fd_ctrl;              // The kernel file descriptor interface
00054 int        in_use[ MAX_OCBS ];   // Flags indicating "ocbs" availability
00055 ResOCB_t*  ocbs[   MAX_OCBS ];   // Array of ocbs, by kernel fd index
00056 
00057 /*
00058 
00059 Resource Manager Section
00060 
00061 These functions, up to the 'Connect and I/O functions' header,
00062 are responsible for the ResMgr impl. details.
00063 
00064 */
00065 
00066 int main() {
00067   int devno;
00068 
00069   // Attach a major device number
00070   if ( (devno = qnx_device_attach()) == -1 ) {
00071     fprintf( stderr,
00072              "%s: couldn't qnx_device_attach() %s, errno %d \n",
00073              progname, prefix, errno );
00074 
00075     perror( NULL );
00076     exit( EXIT_FAILURE );
00077   }
00078 
00079   // Register our prefix
00080   if ( qnx_prefix_attach( prefix, NULL, devno ) == -1 ) {
00081     fprintf( stderr,
00082              "%s: couldn't qnx_prefix_attach() %s, errno %d \n",
00083              progname, prefix, errno );
00084 
00085     perror( NULL );
00086     exit( EXIT_FAILURE );
00087   }
00088 
00089   // Initialize the kernel fd interface
00090   if ( (fd_ctrl = __init_fd( getpid() )) == NULL ) {
00091     fprintf( stderr,
00092              "%s: couldn't register kernel fd I/F \n",
00093              progname );
00094 
00095     perror( NULL );
00096     exit( EXIT_FAILURE );
00097   }
00098 
00099   in_use[0] = 1;   // Mark 0 as in use, since it's not valid !
00100 
00101   printf("%s successfully attached as device #%d \n", prefix, devno );
00102   serviceRequests();
00103 
00104   // Shouldn't get here
00105   return ( EXIT_SUCCESS );
00106 }
00107 
00108 void serviceRequests() {
00109   pid_t  pid;
00110   int    replyAction;
00111   int    index;
00112 
00113   for(;;) {
00114     pid = Receive( 0, &msg, sizeof( msg ) );
00115     printf( "Got a message of type 0x%04X from PID %d\n", msg.type, pid );
00116 
00117     switch( msg.type ) {
00118       // Connect Message
00119       case _IO_OPEN :
00120         replyAction = io_open( &msg, pid );
00121         break;
00122 
00123       // I/O Message
00124       case _IO_READ :
00125         if ( (index = __get_fd( pid, msg.read.fd, fd_ctrl ) ) == -1 ) {
00126           msg.status = EBADF;
00127           replyAction = sizeof( msg.read_reply );
00128         } else {
00129           replyAction = io_read( &msg, ocbs[index] );
00130         }
00131         break;
00132 
00133       case _IO_WRITE :
00134         if ( (index = __get_fd( pid, msg.write.fd, fd_ctrl ) ) == -1 ) {
00135           msg.status = EBADF;
00136           replyAction = sizeof( msg.write_reply );
00137         } else {
00138           replyAction = io_write( &msg, ocbs[index] );
00139         }
00140         break;
00141 
00142       case _IO_CLOSE :
00143         if ( (index = __get_fd( pid, msg.close.fd, fd_ctrl ) ) == -1 ) {
00144           msg.status = EBADF;
00145           replyAction = sizeof( msg.close_reply );
00146         } else {
00147           replyAction = io_close( &msg, ocbs[index] );
00148 
00149           // Remove it from the internal tables
00150           in_use[ index ] = 0;
00151           ocbs[   index ] = NULL;
00152 
00153           // Release it from the kernel's fd table
00154           qnx_fd_attach( pid, msg.close.fd, 0, 0, 0, 0 );
00155         }
00156         break;
00157 
00158       // add others as required.
00159 
00160       // Print an error for ones we didn't know what to do
00161       // Return ENOSYS so that the client knows that we didn't handle it.
00162       default :
00163         printf( "Got an unimplemented message of type 0x%04X from PID %d\n",
00164                 msg.type, pid );
00165 
00166         msg.status = ENOSYS;
00167         replyAction = sizeof( msg.status );
00168         break;
00169     }
00170 
00171     // Didn't reply yet ?
00172     if ( replyAction > 0 ) {
00173       Reply( pid, &msg, replyAction );
00174     }
00175   }
00176 }
00177 
00178 /*
00179 
00180  Connect and I/O functions
00181 
00182  The philosophy for these functions is that they should know as little as
00183  possible about the details of the resource manager interface, and should
00184  instead focus as much as possible on the client specific information.
00185 
00186 */
00187 
00188 /*
00189  io_open()
00190 
00191  Our io_open handler prints out the information that we got from the
00192  _IO_OPEN message, allocates space for an OCB, initialize the OCB
00193  for later usage, and binds the OCb into the "ocbs" data structure
00194  and the kernel's "fd" table.
00195 
00196  Upon completion, it return an "EOK"  message to the client.
00197 */
00198 
00199 int io_open( ResMsg_t* msg, pid_t pid ) {
00200  ResOCB_t* ocb;
00201  int index;
00202 
00203  // Print out the information we got from the _IO_OPEN message
00204  printf( "Got an _IO_OPEN message \n" );
00205  printf( "  type:          0x%04X \n", msg->open.type  );
00206  printf( "  fd:            %d     \n", msg->open.fd    );
00207  printf( "  unit:          %d     \n", msg->open.unit  );
00208  printf( "  version_cycle: %d     \n", msg->open.version_cycle );
00209  printf( "  eflag:         0x%02X \n", msg->open.eflag );
00210  printf( "  nid:           %d     \n", msg->open.nid   );
00211  printf( "  pid:           %d     \n", msg->open.pid   );
00212  printf( "  sflag:         0x%02X \n", msg->open.sflag );
00213  printf( "  oflag:         0x%02X \n", msg->open.oflag );
00214  printf( "  mode:          %d     \n", msg->open.mode  );
00215  printf( "  path:          %d     \n", msg->open.path  );
00216 
00217  // Allocate space for the OCB (and clear)
00218  if ( (ocb = calloc( sizeof(*ocb), 1 )) == NULL ) {
00219    msg->open_reply.status = ENOMEM;
00220    return ( sizeof( msg->open_reply ) );
00221  }
00222 
00223  // Initialize any OCB fields
00224  for( index = 0; index < MAX_OCBS; index++ ) {
00225    if ( in_use[index] == 0 ) {
00226      if ( qnx_fd_attach( pid, msg->open.fd, 0,0,0,0, index ) == -1 ) {
00227 
00228     fprintf( stderr,
00229              "%s: couldn't attach fd \n",
00230              progname );
00231 
00232     perror( NULL );
00233     exit( EXIT_FAILURE );
00234     }
00235 
00236     // Bind OCB into table, mark as "in use"
00237     ocbs[index] = ocb;
00238     in_use[index] = 1;
00239     break;
00240    }
00241  }
00242 
00243  // If OCB table is full, then error msg
00244  if ( index == MAX_OCBS ) {
00245    free( ocb );
00246    msg->open_reply.status = EAGAIN;  // Try later
00247    return ( sizeof( msg->open_reply ) );
00248  }
00249 
00250  // Tell the client that everything is fine
00251  msg->open_reply.status = EOK;
00252  return ( sizeof( msg->open_reply ) );
00253 }
00254 
00255 /*
00256  io_read()
00257 
00258  Our io_read handler functions just like /dev/null
00259  It returns EOF. =(
00260 */
00261 
00262 int io_read( ResMsg_t* msg, ResOCB_t* ocb ) {
00263 
00264  // Print out the information we got from the _IO_READ message
00265  printf( "Got an _IO_READ message \n" );
00266  printf( "  type:          0x%04X \n", msg->read.type   );
00267  printf( "  fd:            %d     \n", msg->read.fd     );
00268  printf( "  nbytes:        %d     \n", msg->read.nbytes );
00269 
00270  // Setup the return portion to the client
00271  // Tell him that 0 bytes are available for reading
00272  msg->read_reply.nbytes = 0;
00273  msg->read_reply.status = EOK;
00274  msg->read_reply.zero   = 0;    // Reserved, MUST be 0
00275 
00276  return ( sizeof( msg->read_reply ) );
00277 }
00278 
00279 /*
00280  io_write()
00281 
00282  Our io_write handler functions just like /dev/null
00283  We tell him that all bytes where written, in fact, no where. =(
00284 */
00285 
00286 int io_write( ResMsg_t* msg, ResOCB_t* ocb ) {
00287 
00288  // Print out the information we got from the _IO_WRITE message
00289  printf( "Got an _IO_WRITE message \n" );
00290  printf( "  type:          0x%04X \n", msg->write.type   );
00291  printf( "  fd:            %d     \n", msg->write.fd     );
00292  printf( "  nbytes:        %d     \n", msg->write.nbytes );
00293                                                  
00294  // Setup the return portion to the client
00295  // Tell him that all bytes were written.
00296  msg->write_reply.nbytes = msg->write.nbytes;
00297  msg->write_reply.status = EOK;
00298  msg->write_reply.zero   = 0;    // Reserved, MUST be 0
00299 
00300  return ( sizeof( msg->write_reply ) );
00301 }
00302 
00303 /*
00304  io_close()
00305 
00306  Doesn't do much from the client's perspective except to return EOK.
00307 
00308  From the ResMgr perspective, the message causes the OCB storage area,
00309  ocb/in_use tables, and kernel fd area to be deleted.
00310 
00311  However, the ocbs/in_use and kernel fd area work is done in the calling
00312  routine above !
00313 */
00314 
00315 int io_close( ResMsg_t* msg, ResOCB_t* ocb ) {
00316 
00317  // Print out the information we got from the _IO_CLOSE message
00318  printf( "Got an _IO_CLOSE message \n" );
00319  printf( "  type:          0x%04X \n", msg->close.type   );
00320  printf( "  fd:            %d     \n", msg->close.fd     );
00321                                                  
00322  // Setup the return portion to the client
00323  // Close was successful
00324  msg->write_reply.status = EOK;
00325 
00326  free( ocb );
00327 
00328  return ( sizeof( msg->close_reply ) );
00329 }

Generated on Sun Oct 14 18:46:42 2001 for Standard J2K Library by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001