ARPDAS_QNX6 1.0
DG_data.cc
Go to the documentation of this file.
00001 // Include DG_data.h first here to make sure our definition of
00002 // IOFUNC_ATTR_T gets used in this file
00003 #include "DG_data.h"
00004 #include <unistd.h>
00005 #include <errno.h>
00006 #include <sys/types.h>
00007 #include <sys/stat.h>
00008 #include <fcntl.h>
00009 #include <string.h>
00010 #include <ctype.h>
00011 #include <limits.h>
00012 #include <stdlib.h>
00013 #include "nortlib.h"
00014 #include "nl_assert.h"
00015 #include "tm.h"
00016 
00017 resmgr_connect_funcs_t DG_data::connect_funcs;
00018 resmgr_io_funcs_t DG_data::io_funcs;
00019 bool DG_data::funcs_initialized = false;
00020 bool DG_data::quitting = false;
00021 
00022 extern "C" {
00023   static struct data_dev_ocb *ocb_calloc(resmgr_context_t *ctp,
00024                 data_dev_attr *device);
00025   static void ocb_free(struct data_dev_ocb *ocb);
00026 }
00027 
00028 static iofunc_funcs_t ocb_funcs = {
00029   _IOFUNC_NFUNCS,
00030   ocb_calloc,
00031   ocb_free
00032 };
00033 
00034 static iofunc_mount_t DGdata_mountpoint = { 0, 0, 0, 0, &ocb_funcs };
00035 
00036 static struct data_dev_ocb *ocb_calloc(resmgr_context_t *ctp,
00037               data_dev_attr *device) {
00038   struct data_dev_ocb *ocb =
00039     (struct data_dev_ocb *)
00040       malloc(sizeof(struct data_dev_ocb));
00041   ocb->rcvid = 0;
00042   ocb->msgsize = 0;
00043   return ocb;
00044 }
00045 
00046 static void ocb_free(struct data_dev_ocb *ocb) {
00047   free(ocb);
00048 }
00049 
00050 
00051 
00052 
00053 DG_data::DG_data(DG_dispatch *dispatch, const char *name_in, void *data,
00054          int data_size, int synch)
00055     : DG_dispatch_client() {
00056 
00057   dispatch_t *dpp = dispatch->dpp;
00058   name = name_in;
00059   dptr = data;
00060   dsize = data_size;
00061   synched = synch;
00062   stale_count = 0;
00063   data_attr.written = false;
00064  
00065   // This is our write-only command interface
00066   resmgr_attr_t resmgr_attr;
00067   memset(&resmgr_attr, 0, sizeof(resmgr_attr));
00068   resmgr_attr.nparts_max = 1;
00069   resmgr_attr.msg_max_size = data_size;
00070   data_attr.DGd = this;
00071 
00072   // io_funcs and connect_funcs are static, so we only need ot do this once,
00073   // but it won't hurt to do it more than once
00074   if ( !funcs_initialized ) {
00075     iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &connect_funcs,
00076         _RESMGR_IO_NFUNCS, &io_funcs );
00077     io_funcs.write = DG_data_io_write;
00078     io_funcs.notify = DG_data_io_notify;
00079     io_funcs.close_ocb = DG_data_io_close_ocb;
00080     //io_funcs.unblock = DG_data_io_unblock;
00081     funcs_initialized = true;
00082   }
00083   
00084   iofunc_attr_init( &data_attr.attr, S_IFNAM | 0222, 0, 0 ); // write-only
00085   data_attr.attr.mount = &DGdata_mountpoint;
00086   IOFUNC_NOTIFY_INIT( data_attr.notify );
00087   char tbuf[80];
00088   snprintf(tbuf, 79, "DG/data/%s", name);
00089   const char *wr_devname = tm_dev_name( tbuf );
00090   dev_id = resmgr_attach( dpp, &resmgr_attr, wr_devname, _FTYPE_ANY, 0,
00091                     &connect_funcs, &io_funcs, &data_attr );
00092   if ( dev_id == -1 )
00093     nl_error( 3, "Unable to attach name %s: errno %d", wr_devname, errno );
00094   
00095   attach(dispatch); // Now get in on the quit loop
00096 }
00097 
00098 DG_data::~DG_data() {}
00099 
00100 // The semantics of write are a bit non-standard. I use blocking I/O
00101 // purely as a synchronization technique. In all contexts, a write
00102 // that gets here is immediately processed, but depending on
00103 // the synchronization flag (set in the TMC source) and the nonblock
00104 // value (set by the client), we may not reply immediately to the
00105 // client.
00106 int DG_data::io_write( resmgr_context_t *ctp, IOFUNC_OCB_T *ocb,
00107                           int nonblock ) {
00108   int msgsize = quitting ? 0 :
00109       resmgr_msgread( ctp, dptr, dsize, sizeof(io_write_t) );
00110   data_attr.written = synched;
00111   if (!quitting && synched && !nonblock) {
00112     if (blocked && blocked != ocb)
00113       return EBUSY;
00114     ocb->rcvid = ctp->rcvid;
00115     ocb->msgsize = msgsize;
00116     blocked = ocb;
00117     return _RESMGR_NOREPLY;
00118   }
00119   _IO_SET_WRITE_NBYTES( ctp, msgsize );
00120   stale_count = 0;
00121   return EOK;
00122 }
00123 
00124 void DG_data::synch() {
00125   data_attr.written = false;
00126   if (blocked) {
00127     MsgReply(blocked->rcvid, blocked->msgsize, 0, 0);
00128     blocked = 0;
00129   }
00130   if (IOFUNC_NOTIFY_OUTPUT_CHECK( data_attr.notify, 1 ) )
00131     iofunc_notify_trigger(data_attr.notify, 1, IOFUNC_NOTIFY_OUTPUT);
00132 }
00133 
00134 int DG_data::stale(int max_stale) {
00135   int rv = stale_count;
00136   if ( stale_count < INT_MAX ) ++stale_count;
00137   if ( rv > max_stale ) rv = max_stale;
00138   return rv;
00139 }
00140 
00141 int DG_data_io_write( resmgr_context_t *ctp,
00142          io_write_t *msg, IOFUNC_OCB_T *ocb ) {
00143   int status, nonblock;
00144 
00145   status = iofunc_write_verify(ctp, msg, (iofunc_ocb_t *)ocb, &nonblock);
00146   if ( status != EOK )
00147     return status;
00148 
00149   if ((msg->i.xtype &_IO_XTYPE_MASK) != _IO_XTYPE_NONE )
00150     return ENOSYS;
00151 
00152   return ocb->hdr.attr->DGd->io_write(ctp, ocb, nonblock);
00153 }
00154 
00155 int DG_data_io_notify( resmgr_context_t *ctp,
00156          io_notify_t *msg, IOFUNC_OCB_T *ocb ) {
00157   IOFUNC_ATTR_T *wr_attr = ocb->hdr.attr;
00158   int trig = 0;
00159   if (!wr_attr->written) trig |= _NOTIFY_COND_OUTPUT;
00160   return(iofunc_notify(ctp, msg, wr_attr->notify, trig, NULL, NULL ));
00161 }
00162 
00163 int DG_data_io_close_ocb(resmgr_context_t *ctp, void *rsvd,
00164                           IOFUNC_OCB_T *ocb) {
00165   IOFUNC_ATTR_T *wr_attr = ocb->hdr.attr;
00166   iofunc_notify_remove(ctp, wr_attr->notify);
00167   return(iofunc_close_ocb_default(ctp, rsvd, &ocb->hdr));
00168 }
00169 
00170 /** DG_data::ready_to_quit() returns true if we are ready to terminate. For DG/data, that means all writers
00171   have closed their connections and we have detached the device.
00172 */
00173 int DG_data::ready_to_quit() {
00174   // unlink the name
00175   quitting = true;
00176   if ( dev_id != -1 ) {
00177     int rc = resmgr_detach( dispatch->dpp, dev_id, _RESMGR_DETACH_PATHNAME );
00178     if ( rc == -1 )
00179       nl_error( 2, "Error returned from resmgr_detach: %d", errno );
00180     dev_id = -1;
00181   }
00182   if ( data_attr.attr.count )
00183     nl_error( -2, "Still waiting for DG/data/%s", name );
00184   return data_attr.attr.count == 0;
00185 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines