int
main (int argc, char **argv)
{
  kogmo_rtdb_handle_t *dbc;
  kogmo_rtdb_connect_info_t dbinfo;
  kogmo_rtdb_obj_info_t demoobj_info;
  kogmo_rtdb_obj_c3_ints256_t demoobj;
  kogmo_rtdb_objid_t oid;
  kogmo_rtdb_objsize_t olen;
  int err;

  // Verbindung zur Datenbank aufbauen, unsere Zykluszeit is 33 ms
  err = kogmo_rtdb_connect_initinfo (&dbinfo, "", "demo_object_reader", 0.033); DIEonERR(err);
  oid = kogmo_rtdb_connect (&dbc, &dbinfo); DIEonERR(oid);

  // Auf Demo-Objekt warten
  oid = kogmo_rtdb_obj_searchinfo_wait (dbc, "demo_object",
    KOGMO_RTDB_OBJTYPE_C3_INTS, 0, 0); DIEonERR(oid);

  // Infoblock des Objektes holen (wenn Metadaten benoetigt werden)
  err = kogmo_rtdb_obj_readinfo (dbc, oid, 0, &demoobj_info); DIEonERR(err);

  // Objekt erstmalig holen (initialer Timestamp)
  err = kogmo_rtdb_obj_readdata_waitnext (dbc, oid, 0, &demoobj, sizeof(demoobj)); DIEonERR(err);

  while (1)
    {
      kogmo_timestamp_string_t timestring;
      olen = kogmo_rtdb_obj_readdata_waitnext (dbc, oid, demoobj.base.committed_ts, &demoobj, sizeof(demoobj)); DIEonERR(olen);
      if ( olen != sizeof(demoobj) )
        continue; // object to small (shouldn't happen - ask the object-writer!)
      kogmo_timestamp_to_string(demoobj.base.data_ts, timestring);
      printf("%s: i[0]=%i, ...\n", timestring, demoobj.ints.intval[0]);
    }

  err = kogmo_rtdb_disconnect(dbc, NULL); DIEonERR(err);

  return 0;
}
kogmo_rtdb_objid_t
kogmo_rtdb_obj_c3_process_getprocessinfo (kogmo_rtdb_handle_t *db_h,
                                          kogmo_rtdb_objid_t proc_oid,
                                          kogmo_timestamp_t ts,
                                          kogmo_rtdb_obj_c3_process_info_t str)
{
  int err;
  kogmo_rtdb_obj_info_t om;
  kogmo_rtdb_obj_c3_process_t po;
  kogmo_rtdb_objid_t oid;

  memset(str, 0, sizeof(kogmo_rtdb_obj_c3_process_info_t));
  strcpy(str, "?");

  oid = kogmo_rtdb_obj_c3_process_searchprocessobj (db_h, ts, proc_oid);

  if ( oid < 0 )
    return oid;

  err = kogmo_rtdb_obj_readinfo ( db_h, oid, ts, &om);
  if ( err < 0 )
    return err;

  err = kogmo_rtdb_obj_readdata (db_h, oid, ts, &po, sizeof (po) );
  if ( err < 0 )
    return err;

  sprintf(str, "%s%s(%lli)", om.deleted_ts ? "D!":"", om.name,
               (long long int) om.oid);

  //sprintf(str, "%s%s [OID %lli, PID %i]", om.deleted_ts ? "D!":"", om.name,
  //             (long long int) om.oid,
  //             po.process.pid);

  return oid;
}
int
kogmo_rtdb_objmeta_purge_procs (kogmo_rtdb_handle_t *db_h)
{
  int i;
  kogmo_rtdb_objid_t err;

  CHK_DBH("kogmo_rtdb_objmeta_purge_procs",db_h,0);

  for(i=0;i<KOGMO_RTDB_PROC_MAX;i++)
    {
      if(db_h->ipc_h.shm_p->proc[i].proc_oid != 0 )
        {
          err = kill ( db_h->ipc_h.shm_p->proc[i].pid , 0);
          if ( err == -1 && errno == ESRCH )
            {
              kogmo_rtdb_obj_info_t used_objmeta;
              kogmo_rtdb_objid_list_t objlist;
              int j, immediately_delete;
              kogmo_rtdb_objid_t err;

              immediately_delete = db_h->ipc_h.shm_p->proc[i].flags & KOGMO_RTDB_CONNECT_FLAGS_IMMEDIATELYDELETE;

              DBGL(DBGL_APP,"DEAD PROCESS: %s [OID %lli, PID %i]",
                      db_h->ipc_h.shm_p->proc[i].name,
                      (long long int)db_h->ipc_h.shm_p->proc[i].proc_oid,
                      db_h->ipc_h.shm_p->proc[i].pid);

              err = kogmo_rtdb_obj_searchinfo_deleted (db_h, "", 0, 0,
                        db_h->ipc_h.shm_p->proc[i].proc_oid, 0, objlist, 0);
              if (err < 0 )
                {
                  DBGL(DBGL_APP,"search for objectlist failed: %d",err);
                }
              else
                {
                  DBGL(DBGL_APP,"dead process has %i objects to%s delete",err,
                       immediately_delete ? " immediately":"");
                  for (j=0; objlist[j] != 0; j++ )
                    {
                      err = kogmo_rtdb_obj_readinfo (db_h, objlist[j], 0, &used_objmeta );
                      if ( err >= 0 && used_objmeta.flags.persistent )
                        {
                          DBGL(DBGL_APP,"keeping persistent object '%s'",used_objmeta.name);
                          continue;
                        }
                       else
                         {
                           used_objmeta.oid = objlist[j]; // enough for delete
                         }
                        kogmo_rtdb_obj_delete_imm(db_h, &used_objmeta, immediately_delete);
                    }
                }

              kogmo_rtdb_ipc_mutex_lock (&db_h->ipc_h.shm_p->proc_lock);
              memset(&db_h->ipc_h.shm_p->proc[i],0,sizeof(struct kogmo_rtdb_ipc_process_t));
              db_h->ipc_h.shm_p->proc_free++;
              kogmo_rtdb_ipc_mutex_unlock (&db_h->ipc_h.shm_p->proc_lock);
            }
        }
    }
  return 0;
}