MIDAS - The Multiple Instance Data Acquisition System

Tape Server - Shared Data Area

The Tape Server holds the most recent fully constructed data buffers in shared memory where they are available for access by data analysis programs (e.g. MTsort). The data buffers include the standard 24 byte block header.
The shared memory is accessed using a name (SunOS shm_open - default value /SHM_110205 or Win32 CreateFileMapping - default value SHM_110205) or key (Linux shmget -default value 110205).
In non default cases simply replace 10205 with the ID used when you start the Tape Server.
The shared memory area can only be access in Read mode.


//    Structure of the Shared Data Area Header

#define NBLOCKS 64                     /*  current number of buffers used - must be 2**n */
#define MAX_BUFFERS 128                /*  unchangeable maximum because of header structure */

typedef struct s_buffer_header {
    int buffer_offset;                 //    offset to first buffer
    int buffer_number;                 //    number of buffers
    int buffer_length;                 //    length of buffers
    int buffer_next;                   //    next buffer to be written
    int buffer_max;                    //    MAX_BUFFERS
    int buffer_spare1;
    int buffer_spare2;
    int buffer_spare3;
    long long buffer_currentage;       //  
    long long buffer_age[MAX_BUFFERS];
    int buffer_status[MAX_BUFFERS];
}  BUFFER_HEADER;  

A sample program demonstrating access to the shared buffer area.
This is available as the program peek in the Tape Server distribution.

#ifdef WIN32
#include <windows.h>
#endif

#ifdef LINUX
#include <sys/types.h>
#include <sys/shm.h>
#endif

#ifdef SOLARIS
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#endif

#include <stdio.h>

#include <stdlib.h>

/*    format of the data buffer area header   */

#define NBLOCKS 64                     /*  current number of buffers used - must be 2**n */
#define MAX_BUFFERS 128                /*  unchangeable maximum because of header structure */

typedef struct s_buffer_header {
    int buffer_offset;                 /*    offset to first buffer */
    int buffer_number;                 /*    number of buffers */
    int buffer_length;                 /*    length of buffers */
    int buffer_next;                   /*    next buffer to be written */
    int buffer_max;                    /*    MAX_BUFFERS */
    int buffer_spare1;
    int buffer_spare2;
    int buffer_spare3;
#ifdef WIN32
    long buffer_currentage;
    long padding1;
    long buffer_age[MAX_BUFFERS];
    long padding2[MAX_BUFFERS];
#else
    long long buffer_currentage;
    long long buffer_age[MAX_BUFFERS];
#endif
}  BUFFER_HEADER;  


#ifdef WIN32
void ReportError (char * s) {

  LPVOID lpMsgBuf;
  DWORD ErrNo;
  
       ErrNo = GetLastError();
       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                      NULL,
                      ErrNo,
                      0,
                      (LPTSTR) &lpMsgBuf,
                      0,
                      NULL
                      );
                      
       printf("%s: error %d - %s\n", s, ErrNo, lpMsgBuf);
       LocalFree (lpMsgBuf);
}
#endif

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

    int offset, number, length, next, max;
    int i, j;
    
#ifdef WIN32
    unsigned long cage, age;
#else
    unsigned long long cage, age;
#endif

#ifndef LINUX
char object_name[16];
#endif
    
#ifdef LINUX
   int shmid;
   key_t shmkey = 110205;
#endif

#ifdef SOLARIS
   int shmid;
   int shmkey = 110205;
#endif

#ifdef WIN32
   HANDLE shmid;
   int shmkey = 110205;
#endif


    short * shm_bufferarea;
    BUFFER_HEADER * baseaddress;
    short * bufferaddress;
    
#ifdef SOLARIS

/*    create a file mapped object (MASTER) or obtain ID of existing object */

    sprintf(object_name,"/SHM_%d", shmkey);

    shmid = shm_open(object_name, O_RDONLY, (mode_t) 0);
    if (shmid == -1)  {
        perror("shm_open");
        exit(1);
    }

#endif

#ifdef LINUX

    shmid = shmget(shmkey, 0, SHM_R);
    if (shmid == -1) {perror("shmget"); exit(1);}
    
#endif

#ifdef WIN32

/*    create a file mapped object */

    sprintf(object_name,"SHM_%d", shmkey);

    shmid = CreateFileMapping( (HANDLE) INVALID_HANDLE_VALUE, NULL,
                               PAGE_READONLY,
                               (DWORD) 0,
                               (DWORD) 1,
                               object_name);

    if (!shmid)  {

/*    give up! */

             ReportError("CreatFileMapping");
             ExitProcess(1);
    }
#endif

#ifdef SOLARIS

/*    attach the memory segment */

    shm_bufferarea = mmap((caddr_t) NULL, (size_t) 0x400000, PROT_READ, MAP_SHARED, shmid, (off_t) 0);
    if (shm_bufferarea == (void *) MAP_FAILED) {
        perror("mmap");
        exit(1);
    }

    close(shmid);

#endif

#ifdef LINUX

    shm_bufferarea = shmat(shmid, (void *) 0, SHM_RDONLY);
    if (shm_bufferarea == (void *) -1) {perror("shmat"); exit(1);}
    
#endif

#ifdef WIN32

/*    map a view of the file mapped object */

    shm_bufferarea = MapViewOfFile(shmid,
                                 FILE_MAP_READ,
                                 0, 0, 0);

    if (shm_bufferarea == NULL) {
    
        ReportError("MapViewOfFile");
        ExitProcess(1);
    }

#endif

    printf("Shared buffer area located at 0x%x\n", shm_bufferarea);

    baseaddress = (BUFFER_HEADER *) shm_bufferarea;

    offset = baseaddress->buffer_offset;
    number = baseaddress->buffer_number;
    length = baseaddress->buffer_length;
    next = baseaddress->buffer_next;
    max = baseaddress->buffer_max;
    cage = baseaddress->buffer_currentage;

    printf ("current control information\n");
#ifndef WIN32
    printf ("offset=%d number=%d length=%d next=%d max=%d age=%lld\n", offset, number, length, next, max, cage);
#else
    printf ("offset=%d number=%d length=%d next=%d max=%d age=%d\n", offset, number, length, next, max, cage);
#endif

    for (i = 0; i < number; i++) {
        age = baseaddress->buffer_age[i];
#ifndef WIN32
        printf(" %lld", age);
#else
        printf(" %d", age);
#endif
    }
    printf("\n");

    i = (next - 1) & (number -1);

    if (baseaddress->buffer_age[i] != 0) {
    
    /*    print out start of lastest data block  */

        bufferaddress = (short *) ((char *)shm_bufferarea + offset + (length * i));
#ifndef WIN32
        printf ("buffer %d, age %lld, address 0x%x\n", i, baseaddress->buffer_age[i], bufferaddress);
#else
        printf ("buffer %d, age %d, address 0x%x\n", i, baseaddress->buffer_age[i], bufferaddress);
#endif

        for (i = 0; i < 64; i++) {
          for (j = 0; j < 16; j++) {
            printf(" 0x%04x", (*bufferaddress & 0x0000ffff));
            bufferaddress++;
          }
          printf ("\n");
        }
        printf ("\n");
    }

#ifdef WIN32
    ExitProcess(0);
#else
   exit(0);
#endif

}

Back to documentation index documentation index


© 2011 NPG - STFC