View this PageEdit this PageAttachments to this PageHistory of this PageHomeRecent ChangesSearch the SwikiHelp Guide

MediaBroker


Examples of audio type lattices

Audio Demo Notes

Some Diagrams



The MediaBroker Client API


Graphic Explaining Structure en Route

The MediaBroker Client Dynamic


A MediaBroker client connects to the MediaBroker and then has the power to establish Producer and Consumer entities. A MediaBroker client also has the ability to instantiate threads inside the MediaBroker cluster to provide for complex computation within the MediaBroker cluster.

Two basic dynamics exist for the MediaBroker client. First, the MediaBroker client can instantiate itself as the Producer or Consumer and modify data as necessary. Second, the MediaBroker client can act as a commanding thread spawning off worker threads who will become Producers or Consumers. This second method of operation is very similar to instantiating and controlling Internal Threads.

Examples: en route
First Dynamic:  producer.c  consumer.c
Second Dynamic:  external_producer.c



Connecting


Initially an MB Client must connect to the MediaBroker server. To connect pass the predetermined address and port numbers of the MediaBroker you wish to connect to. Once connected, an mb_connect socket structure is returned to be used in future interactions.
mb_connect_t mb_connect(const char serv_addr, int ds_port, int mb_port);

Once the MB Client has connected it is free to call any of the other system calls.
Any of the read or write calls which access the prod_handle or cons_handle structures must be made from within a D-Stampede thread. By calling spd_thread_create a thread will be started with access to all of the MediaBroker structures. For a better understanding of how this fits into the above dynamics; please look at the above examples.

spd_error_t
spd_thread_create (spd_thread_t              *stid_p,
                   const spd_thread_attr_t   *attr_p,
                   void *                   (*start_routine)(void *),
                   void                      *arg,
                   int                        arg_size,
                   spd_AS_t                   target_AS,
                   spd_time_stamp_t           child_vt);



Producers


There are several important data structures related to Producing into the MediaBroker. First the prod_attr_t structure is what is passed to the init_producer function. It defines what attributes you would like to register for the producer. Next is the prod_handle structure. It defines the working structures for the producer. It holds the Channel and Register objects so that you can read and write to the MediaBroker.
typedef struct _mb_prod_attr_t{
  char *name;
  int type;
  char *sub_type;
  char *location;
  char *type_library;
} mb_prod_attr_t;

typedef struct _mb_prod_handle{
  mb_chan_obj data_channel;
  mb_reg_obj status_register;
  mb_reg_obj feedback_register;
} mb_prod_handle;

In order to initialize a producer the MB Client calls init_producer as defined below.
mb_prod_handle* init_producer(mb_connect_t *connect_id, mb_prod_attr_t *attributes);

Because producers may at times be disjoint from the MB Client, you may wish to call terminate_producer to signal through the MediaBroker to the producer that it should close itself (more explanation on this point coming). The terminate_producer call returns an spd_error_t which signifies the success or failure of the call.
mb_error_t terminate_producer(mb_connect_t *connect_id, mb_prod_handle *handle, mb_prod_attr_t *attributes);



Consumers


There are structures and functions for the consumers very similar to the producers. Below are the Consumer Attribute and the Consumer Handle structures.

typedef struct _mb_cons_attr_t{
  char *name;
  int type;
  char *sub_type;
  char *location;
  char *producer_name;
} mb_cons_attr_t;

typedef struct _mb_cons_handle{
  mb_chan_obj data_channel;
  mb_reg_obj command_register;
  mb_reg_obj status_register;
  type_map_t data_type_map;
} mb_cons_handle;

In order to start a consumer, we will call init_consumer and pass the arguments for the consumer we wish to initialize. We would have previously searched the database for the producer we wished to consume.
mb_cons_handle* init_consumer(mb_connect_t *connect_id, mb_cons_attr_t *cons_attrs, mb_prod_attr_t *prod_attrs);

As with the producer, there might be times when we wish to destroy the producer from within a different context than in which it is currently running.
mb_error_t terminate_consumer(mb_connect_t *connect_id, mb_cons_handle *handle, mb_cons_attr_t *attributes);



Reading and Writing to the MediaBroker


There are four basic calls with which to read and write MediaBroker Channels and Registers. First, to use an mb_chan_obj, the MediaBroker Client API provides mb_write_to_channel and mb_read_to_channel. Both of these calls are supplied with an mb_chan_obj as well as a buffer and buffer_size variable.

mb_error_t mb_write_channel(mb_prod_handle *handle, mb_timestamp ts, int buffer_size, void *buffer);

mb_error_t mb_read_channel(mb_cons_handle *handle, mb_timestamp ts_reqd, mb_timestamp *ts_recvd, int *buffer_size, void **buffer);

Status is communicated to and from the MediaBroker through a set of Stampede registers. By calling mb_producer_read_feedback and mb_producer_write_status the producer can read what should be produced and write what is being produced.
mb_error_t mb_producer_read_feedback(mb_prod_handle *handle, data_t *data);

mb_error_t mb_producer_write_status(mb_prod_handle *handle, data_t *data);

In a similar way, a consumer can call mb_consumer_read_status and mb_consumer_write_command to write what it wants produced and read what is being produced.

mb_error_t mb_consumer_read_status(mb_cons_handle *handle, data_t *data);

mb_error_t mb_consumer_write_command(mb_cons_handle *handle, data_t *data);




Using the Type System


Producers and Consumers both have access to the type maps respective to the data they are producing or consuming. Producers are expected to be linked to their type maps and have a better knowledge of their specific type maps, while consumers receive a type_map with their cons_handle.
The commonly used API calls for use on the type maps are mb_type_map_iterator, mb_type_map_attributes and mb_type_get_attribute. By using these calls, the type_maps can be manually searched for types to be requested.

The type_map_iterator's last searched argument must be initialized to NULL before each iteration.
data_t mb_type_map_iterator(type_map map, data_t last_searched);

mb_type_map_attributes returns a NULL terminated list of string attribute names.
char** mb_type_map_attributes(type_map map);

mb_attr mb_type_get_attribute(data_t node, char* attribute);

mb_attr{
  mb_attr_type type;
  union {
    float f;
    int i;
    char s;
  }
}

mb_attr_type{ 
  FLOAT,
  INT,
  STRING
}

Note: Would a system of calls to generate a set of wanted attributes and then to search the type_map for the closest approximation be appropriate?





Querying the Nameservice


Note: Does the MB Client have an inherent need to query the nameservice?




Internal Threads


en route


Common Defined Enums


mb_timestamp {
  MB_NEXT = -1,  
  MB_LATEST = -2
}

mb_error_t {
  MB_FAILURE = 0,
  MB_SUCCESS
}  

Link to this Page