Question

Storing C/C++ structures/objects

Asked by: marcus_carey

Can someone provide a complete example on storing C structures to Berkeley DB?  I having problems with the examples from the SleepyCat website.


int add(void)
{
      size_t len;
      u_int8_t *p, data_buffer[1024];

      DBT data, key;
      DB *dbp;
      int ret;
      long SerialNumber = 1989;

      info.data1 = "Hello World";
      info.data2 = 500;

      memset(&key, 0, sizeof(DBT));
      memset(&data, 0, sizeof(DBT));

      key.data = &SerialNumber;
      key.size = sizeof(SerialNumber);


      p = &data_buffer[0];
      len = strlen(info.data1);
      memcpy(p, &len, sizeof(len));
      p += sizeof(len);
      memcpy(p, info.data1, len);
      p += len;
      memcpy(p, &info.data2, sizeof(info.data2));
      p += sizeof(info.data2);


      data.data = &p;
      data.size = sizeof(p);

      if ((ret = db_create(&dbp, NULL, 0)) != 0)
      {
            fprintf(stderr, "db_create: %s\n", db_strerror(ret));
            return(ret);
      }
      if ((ret = dbp->open(dbp, NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0)
      {
            dbp->err(dbp, ret, "%s", DATABASE);
            return(ret);;
      }

      if ((ret = dbp->put(dbp, NULL, &key, &data, 0)) == 0)
      {
            printf("db: %lu: key stored.\n", *(unsigned long *)key.data);
      }
      else
      {
            dbp->err(dbp, ret, "DB->put");
            return(ret);
      }

      ret = dbp->close(dbp, 0);



      return(ret);


}


int get(void)
{
      size_t len;
      u_int8_t *p, data_buffer[1024];

      DBT data, key;
      DB *dbp;
      int ret;

      long SerialNumber = 1989;



      if ((ret = db_create(&dbp, NULL, 0)) != 0)
      {
            fprintf(stderr, "db_create: %s\n", db_strerror(ret));
            return(ret);
      }
      if ((ret = dbp->open(dbp, NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0)
      {
            dbp->err(dbp, ret, "%s", DATABASE);
            return(ret);;
      }


      memset(&key, 0, sizeof(DBT));
      memset(&data, 0, sizeof(DBT));


      key.data = &SerialNumber;
      key.size = sizeof(SerialNumber);




      if ((ret = dbp->get(dbp, NULL, &key, &data, 0)) == 0)
      {
            printf("db: %lu: key retrieved: data was %s.\n",
                *(unsigned long *)key.data, (char *)data.data);
      }
      else
      {
            //dbp->err(dbp, ret, "DB->get");
            return(ret);

      }

      strcpy(data_buffer,data.data);
      p = &data_buffer[0];
      memcpy(&len, p, sizeof(len));
      p += sizeof(len);
      info.data1 = malloc(len);
      memcpy(info.data1, p, len);
      p += len;
      memcpy(&info.data2, p, sizeof(info.data2));
      p += sizeof(info.data2);


      printf("%s\n",info.data1);

      return(0);

}


The examples do not really show how to store and receive the data structure so I have no way to determine if I am doing it correct.

This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.

Subscribe now for full access to Experts Exchange and get

Instant Access to this Solution

  • Plus...
  • 30 Day FREE access, no risk, no obligation
  • Collaborate with the world's top tech experts
  • Unlimited access to our exclusive solution database
  • Never be left without tech help again

Subscribe Now

Asked On
2004-05-04 at 19:27:28ID20978186
Tags

structure

,

db

,

berkeley

,

Berkeley DB

Topic

Databases Miscellaneous

Participating Experts
1
Points
500
Comments
14

Trusted by hundreds of thousands everyday for fast, accurate and reliable tech support.

  • "The time we save is the biggest benefit of Experts Exchange to Warner Bros. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange." Mike Kapnisakis, Warner Bros.
  • "Our team likes having a resource that is more secure than just using Google and most experts using this service really know their stuff. It's nice to look here first versus using Google." Dayna Sellner, Lockheed Martin
  • "Anytime that I've been stumped with a problem, 9 out of 10 times Experts Exchange has either the accepted solution or an open discussion of the potential solution to the problem." Kenny Red, eBay Inc.

See what Experts Exchange can do for you.

Got a question?

We've got the answer.

Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.

Screenshot of Experts Exchange Knowledgebase

Need individual assistance?

Our experts are ready to help.

If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.

Screenshot of Experts Exchange Knowledgebase

Want to learn from the best?

Read articles from industry experts.

Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.

Screenshot of an Article

Working on a long term project?

Store your work and research.

Save solutions to your questions, answers you’ve discovered through searching plus helpful articles in your personal knowledgebase for easy future access.

Screenshot of Experts Exchange Knowledgebase

Access the answers to your technology questions today.

Subscribe Now

30-day free trial. Register in 60 seconds.

What Makes Experts Exchange Unique?

Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Trusted by the world's most respected brands.

image of each brand's logo

Faithfully serving IT professionals since 1996.

Experts Exchange Logo

Try it out and discover for yourself.

Subscribe Now

30-day free trial. Register in 60 seconds.

Related Solutions

  1. 3D array. How to malloc
    I have an array which is 3d. I used to initialise it by just GLubyte array[256][512][3]; It's for storing pixel colors in gtk. If I want to malloc the size because it may be variable, how can I do it? I tried this, but it didn't work. GLubyte *** array; array = malloc(s...
  2. malloc
    I allocate memory to a pointer using malloc or calloc. And then try to assign a value to this array beyond its limit. It still works. Why? eg, int *ptr; ptr = (int *)malloc(5*sizeof(int)); ptr[100] = 5; The above code works. Will not give a crash. Why? Then what is the ...
  3. sizeof() problem
    Can any one tell me how sizeof() is implemented in Linux libc?? Below is my code,can any one tell me why doesn't the value of 'a' change?? main() { int a=10; int s=sizeof(a=20); printf("a = %d\n",a); } output a=10; So still 'a' is 10 even after reaasignm...
  4. malloc and bus error
    Why would malloc cause a Bus Error? This is some of the code I'm using.... node *item, *temp; //item is the new node int i = 0; if ( (item = (node *)malloc(sizeof(node))) == NULL) //Allocate space { fprintf(stdout,"Unable to allocat...

Free Tech Articles

  1. WARNING: 5 Reasons why you should NEVER fix a computer for free.
    It is in our nature to love the puzzle. We are obsessed. The lot of us. We love puzzles. We love the challenge. We thrive on finding the answer. We hate disarray. It bothers us deep in our soul. W...
  2. SCCM OSD Basic troubleshooting
    SCCM 2007 OSD is a fantastic way to deploy operating systems, however, like most things SCCM issues can sometimes be difficult to resolve due to the sheer volume of logs to sift through and the dispe...
  3. Migrate Small Business Server 2003 to Exchange 2010 and Windows 2008 R2
    This guide is intended to provide step by step instructions on how to migrate from Small Business Server 2003 to Windows 2008 R2 with Exchange 2010. For this migration to work you will need the fo...
  4. Create a Win7 Gadget
    This article shows you how to create a simple "Gadget" -- a sort of mini-application supported by Windows 7 and Vista. Gadgets can be dropped anywhere on the desktop to provide instant information, ...
  5. Outlook continually prompting for username and password
    There have been a lot of questions recently regarding Outlook prompting for a username and password whilst using Exchange 2007. There are a few reasons why this would happen and I will try to cover t...
  6. Backup Exchange 2010 Information Store using Windows Backup
    There seems to be quite a lot of confusion around the ability to backup Exchange 2010 using the built in Windows Backup feature. This stems from the omission of this feature prior to Exchange 2007 s...

Cloud Class Webinars

  1. Avoiding Bugs in Microsoft Access
    Alison Balter takes and in-depth look at avoiding bugs in Access. In this webinar you will learn about using the immediate window to debug your applications, invoking the debugger, using breakpoints to troubleshoot, stepping through code, setting the next statement to execute, ...
  2. Top 10 Best New Features in Visio 2010
    Scott Helmers gives live demonstrations of the top 10 new features in Visio 2010. This webinar will teach you how to create compelling diagrams by adding shapes to the page with a single click, linking the shapes in a diagram to data in Excel (or SQL Server, or SharePoint), ...
  3. IT Consultant Business Secrets Revealed
    Michael Munger, Experts Exchange tech pro and IT consultant, pulls back the curtain on his very successful businesses and answers question on every IT consultant and business owner should know about. He shares secrets on what he did to solve the 5 most common problems in IT, ...
  4. Disaster Recovery and Business Continuity
    Quest CTO, Mike Billon, gives an overview of the steps involved in building a dunamic disaster recovery plan. Through case studies and an examination of software/hardware tooles for monitoring and testing, you'll gain a better understandin of where you are, where you want ...
  5. Organize Your Visio Diagrams with Containers and Lists
    Scott Helmers uses cross functional flowcharts, wireframe diagrams, data graphic legends and seating charts to teach you: how to ustilize all three new structured diagram components in Visio 2010, the best practices for organizeing shapes in previous version of Visio, how to organize ...
  6. How to Us Objects, Properties, Events and Methods in Microsoft Access
    Alison Dalter gives an in-depbth look at objects, properties, events and methods in Microsoft Access. In this webinar you will learn about using the object browser, referring to objects, working with properties and methods, working with object variables, understanding the ...

Join the Community

Give a Little. Get a Lot.

Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.

Join the Community

Answers

 

by: fridomPosted on 2004-05-07 at 00:42:41ID: 11012702

Well I don't know why you have omitted the declaration of info.
Whis is the datastructure you're working on.
I've written this some time ago:
typedef struct st_adr {
      struct st_adr_lpVtbl *lpVtbl;
      struct st_adr_data  *data;
      size_t data_size;
} ST_ADR;



struct st_adr_lpVtbl {
      int (*save)(ST_ADR*);
      int (*clone)(ST_ADR*, ST_ADR*);
      int (*equal) (ST_ADR*, ST_ADR*);
      char * (*get_name) (ST_ADR*);
      char * (*get_first_name) (ST_ADR*);
      char * (*get_street) (ST_ADR *);
      char * (*get_city) (ST_ADR *);
      int  (*get_zip) (ST_ADR*);
      void * (*get_by_idx) (ST_ADR*, int);
      char * (*get_entry_by_idx) (ST_ADR*, int);
      void (*set_entry_by_idx) (ST_ADR*, int, char*);
      void (*set_by_idx) (ST_ADR*, int, void*);
      void (*set_name) (ST_ADR *, char*);
      void (*set_first_name)(ST_ADR *, char*);
      void (*set_street)(ST_ADR *, char*);
      void (*set_city)(ST_ADR *, char*);
      void (*set_zip) (ST_ADR*, int);
      void (*st_test) (char*);
};

extern struct st_adr_lpVtbl st_adr_vtable;

struct st_adr_data {
      char name[NAME_MAX];
      char first_name[NAME_MAX];
      char street[STREET_MAX];
      char city [CITY_MAX];
      int zip;

This are the data-structures I wanted to save. Now the save functions looks like this:
int adr_save_record (ST_ADR *record){

      assert(record);
      DB *hdb = NULL;
      DBT key = {0};
      DBT data = {0};
      int i_rval = 0;

      i_rval = adr_open_db(&hdb);
      if (0 != i_rval ) {
            return FAULT;
      }
      key.data = record->get_name();
      key.size = strlen(record->get_name());
      /* Key is the name field of an Adr structure */
      data.data = record->data;
      data.size = record->data_size;

      i_rval = hdb->put(hdb, NULL,
                               &key, &data, 0);
      if (i_rval > 0){
            hdb->err (hdb, i_rval, "Problems puttting value", NULL);
            i_rval = hdb->close(hdb,0);
            return FAULT;
      }
      i_rval = hdb->close(hdb,0);
      return 0;
}

That's all what is needed to write  structures to the Database.

IMHO it pays of to spend some time in the documentation. I propose to check out the tutorial especially.

Regards
Friedrich

 

by: marcus_careyPosted on 2004-05-07 at 05:08:56ID: 11013862

The example I listed came from the SleepyCat documentation  http://www.sleepycat.com/docs/ref/am_misc/struct.html.  

    - Steve Sarette
            Documentation Engineer
            Sleepycat Software

Mr. Sarette provided the following abreviated example.  However when I added in the database support I could not retrieve the data from the database.  


#include <db.h>
#include <string.h>

#define MAXBUFFER 300
#define MAXSTRING 100

/* Declare our struct */
struct example_structure {
    float myFloat;
    int myInt;
    char *myString;
};
typedef struct example_structure EXAMPLE_STRUCTURE;

/*
 * Program to illustrate marshalling and unmarshalling structures.
 *
 * Marshalling is the process of moving the contents of a structure's
 * fields into a single contiguous memory location. This is done so that
 * the structure can be stored in a Berkeley DB database.
 *
 * Unmarshalling is performed to take data retrieved from a Berkeley DB database
 * and place it back into the structure so that it can be used by the
 * application.
 */
int
main(int argc, char *argv[])
{
    DBT sampleDBT; /* The Berkeley DB data structure that we use to store data
                                     * in a database. Typically there are two of these for
                                     * every database record, one for a key and one for the
                                     * data. In this case, we need only one DBT for
                                     * illustration purposes.
                                     */
    EXAMPLE_STRUCTURE myStruct;  /* The structure we want to store */
    EXAMPLE_STRUCTURE newStruct; /* The structure we want to place data into */
    int buffer_length; /* The amount of data stored in our buffer */
    u_int32_t buffer[MAXBUFFER];  /* The buffer itself */
    u_int32_t *bufferPtr; /* A pointer into the buffer */


    /* First, we fill in our structure's data fields */
    myStruct.myFloat = 3.04;
    myStruct.myInt = 200;
    /* malloc space for the string */
    myStruct.myString = (char *)malloc(MAXSTRING * sizeof(char));
    /* Copy a string into that space. */
    strncpy(myStruct.myString, "My example string.", MAXSTRING * sizeof(char));

    /*
     * In order to store the data for this structure, we must make sure that
     * all its data is lined up in a single contiguous block of memory -- that
     * is, in a single buffer. We also need to know how much data was put into
     * that buffer. To do this, we copy the structure's data into the buffer.
     * This is the actual marshalling process.
     *
     * Note that the order we use to copy the data is not important, except
     * that we have to make sure that we unmarshall in the same order. Here
     * we mix things up a bit in order to illustrate the concept.
     *
     * Notice that we keep track of how much data we've placed in the buffer as
     * we go. Also, take care to copy each new bit of data to the end of the
     * buffer, so as to not overwrite any data previously placed there.
     */

    /* Initialize the buffer */
    memset(&buffer, 0, MAXBUFFER);
    /* Copy the struct's int into the buffer */
    bufferPtr = &buffer[0];
    memcpy(bufferPtr, &(myStruct.myInt), sizeof(int));
    buffer_length = sizeof(int);

    /* Copy the struct's string into the buffer */
    bufferPtr = &buffer[buffer_length];
    memcpy(bufferPtr, myStruct.myString,
       (strlen(myStruct.myString) + 1) * sizeof(char));
    buffer_length += (strlen(myStruct.myString) + 1) * sizeof(char);

    /* Copy the struct's float into the buffer */
    bufferPtr = &buffer[buffer_length];
    memcpy(bufferPtr, &(myStruct.myFloat), sizeof(float));
    buffer_length += sizeof(float);

    /*
     * We now have a buffer that contains all our data. We also have the size of
     * the data contained in that buffer. We can use this buffer with our DBT:
     */

    sampleDBT.data = buffer;
    sampleDBT.size = buffer_length;

    /*
     * We can now pass the data DBT to a DB->put() or DBC->c_put() call for
     * storage in the database. We won't show that here.
     */

    /*
     * Upon retrieval from the database (again, we don't show the actual
     * database get() activity), the DBT's data field is pointing to
     * a void * buffer that contains exactly the data that we marshalled into
     * our buffer above. We now need to only unmarshall that data. To do this,
     * we have to remember the order in which we originally marshalled the
     * data.
     */

    /*
     * Note that we're reusing the same DBT for unmarshalling process as we used
     * to marshall the data. In real-world usage, the two would be different
     * as they would almost certainly be declared in different scopes.
     */

    bufferPtr = sampleDBT.data;

    /* First, find the int (the first bit of data that we stored) */
    newStruct.myInt = *((int *)bufferPtr);
    bufferPtr += sizeof(int);

    /* Next, the string */
    newStruct.myString = (char *)bufferPtr;
    bufferPtr += (strlen(newStruct.myString) + 1) * sizeof(char);

    /* And finally, the float */
    newStruct.myFloat = *((float *)bufferPtr);

    /*
     * Now we can print everything out to prove that the marshalling process
     * worked
     */

    printf("Original structure:\n");
    printf("\tmyInt: %i, \tmyFloat: %f\n", myStruct.myInt, myStruct.myFloat);
    printf("\tmyString: %s\n", myStruct.myString);

    printf("\nNew structure (after marshalling and unmarshalling:\n");
    printf("\tmyInt: %i, \tmyFloat: %f\n", newStruct.myInt, newStruct.myFloat);
    printf("\tmyString: %s\n", newStruct.myString);

    /* Cleanup */
    free(myStruct.myString);
    return(0);
}

 

by: fridomPosted on 2004-05-07 at 07:00:59ID: 11014820

Well what is unclear about the code? The idea is this:
they declare a structure
struct example_structure {
    float myFloat;
    int myInt;
    char *myString;
};

To write the structure they "flatten" it
/* Initialize the buffer */
    memset(&buffer, 0, MAXBUFFER);
    /* Copy the struct's int into the buffer */
    bufferPtr = &buffer[0];
    memcpy(bufferPtr, &(myStruct.myInt), sizeof(int));
    buffer_length = sizeof(int);

    /* Copy the struct's string into the buffer */
    bufferPtr = &buffer[buffer_length];
    memcpy(bufferPtr, myStruct.myString,
       (strlen(myStruct.myString) + 1) * sizeof(char));
    buffer_length += (strlen(myStruct.myString) + 1) * sizeof(char);

    /* Copy the struct's float into the buffer */
    bufferPtr = &buffer[buffer_length];
    memcpy(bufferPtr, &(myStruct.myFloat), sizeof(float));
    buffer_length += sizeof(float);

For that you have to keep book on where you are in the buffer and where to write next this is done here. Of course if you write such stuff to the Database you have to write another function to "re-structure" the flat array. That is shown in the example later.

That's very C-ish and well if you had to write  file for Datastructures you would probably do it like they did. My way is less secure but more convenient. The problems you can encounter while doing it my way:
- every C compiler does padding differently so my size may or may not be the "right" one. The problem was neglacted because I use one special C compiler and do not change anything about the padding.

I suggest you try it my way with a simple structure and after you understood that you can try to make it the Berkeley DB way.

Regards
Friedrich

 

by: fridomPosted on 2004-05-07 at 07:04:57ID: 11014869

Small addition. They omit saving the data to the Database. That is what you have to add otherwiese the Database is simply empty

Regards
Friedrich

 

by: marcus_careyPosted on 2004-05-07 at 07:19:17ID: 11014995

When I added the database routines to this code I get the follow output:


Original structure:
        myInt: 200,     myFloat: 3.040000
        myString: My example string.

New structure (after marshalling and unmarshalling:
        myInt: 200,     myFloat: 0.000000
        myString: My example ²²²²&#9612;&#9787;

Some where the data gets corrupt.  

#include "db.h"
#include <string.h>
#include <stdlib.h>

#define MAXBUFFER 300
#define MAXSTRING 100

void getdata(void);
/* Declare our struct */
struct example_structure {
    float myFloat;
    int myInt;
    char *myString;
};
typedef struct example_structure EXAMPLE_STRUCTURE;

/*
 * Program to illustrate marshalling and unmarshalling structures.
 *
 * Marshalling is the process of moving the contents of a structure's
 * fields into a single contiguous memory location. This is done so that
 * the structure can be stored in a Berkeley DB database.
 *
 * Unmarshalling is performed to take data retrieved from a Berkeley DB database
 * and place it back into the structure so that it can be used by the
 * application.
 */
int
main(int argc, char *argv[])
{
    DBT sampleDBT; /* The Berkeley DB data structure that we use to store data
                                     * in a database. Typically there are two of these for
                                     * every database record, one for a key and one for the
                                     * data. In this case, we need only one DBT for
                                     * illustration purposes.
                                     */

      DB *dbp;
      DBT sampleKEY;
      char *SerialNumber;
      char *Database;
      int ret;

    EXAMPLE_STRUCTURE myStruct;  /* The structure we want to store */
   
    int buffer_length; /* The amount of data stored in our buffer */
    u_int32_t buffer[MAXBUFFER];  /* The buffer itself */
    u_int32_t *bufferPtr; /* A pointer into the buffer */



      memset(&sampleKEY, 0, sizeof(DBT));
      memset(&sampleDBT, 0, sizeof(DBT));



    /* First, we fill in our structure's data fields */
    myStruct.myFloat = 3.04;
    myStruct.myInt = 200;
    /* malloc space for the string */
    myStruct.myString = (char *)malloc(MAXSTRING * sizeof(char));
    /* Copy a string into that space. */
    strncpy(myStruct.myString, "My example string.", MAXSTRING * sizeof(char));

    /*
     * In order to store the data for this structure, we must make sure that
     * all its data is lined up in a single contiguous block of memory -- that
     * is, in a single buffer. We also need to know how much data was put into
     * that buffer. To do this, we copy the structure's data into the buffer.
     * This is the actual marshalling process.
     *
     * Note that the order we use to copy the data is not important, except
     * that we have to make sure that we unmarshall in the same order. Here
     * we mix things up a bit in order to illustrate the concept.
     *
     * Notice that we keep track of how much data we've placed in the buffer as
     * we go. Also, take care to copy each new bit of data to the end of the
     * buffer, so as to not overwrite any data previously placed there.
     */

    /* Initialize the buffer */
    memset(&buffer, 0, MAXBUFFER);
    /* Copy the struct's int into the buffer */
    bufferPtr = &buffer[0];
    memcpy(bufferPtr, &(myStruct.myInt), sizeof(int));
    buffer_length = sizeof(int);

    /* Copy the struct's string into the buffer */
    bufferPtr = &buffer[buffer_length];
    memcpy(bufferPtr, myStruct.myString,
       (strlen(myStruct.myString) + 1) * sizeof(char));
    buffer_length += (strlen(myStruct.myString) + 1) * sizeof(char);

    /* Copy the struct's float into the buffer */
    bufferPtr = &buffer[buffer_length];
    memcpy(bufferPtr, &(myStruct.myFloat), sizeof(float));
    buffer_length += sizeof(float);

    /*
     * We now have a buffer that contains all our data. We also have the size of
     * the data contained in that buffer. We can use this buffer with our DBT:
     */

    sampleDBT.data = buffer;
    sampleDBT.size = buffer_length;

      SerialNumber = "12345";
      sampleKEY.data = SerialNumber;
      sampleKEY.size = sizeof(SerialNumber);


      Database = "sample.db";


      if ((ret = db_create(&dbp, NULL, 0)) != 0)
      {
            fprintf(stderr, "db_create: %s\n", db_strerror(ret));
            return(ret);
      }


      if ((ret = dbp->open(dbp,
                  NULL, Database, NULL, DB_BTREE, DB_CREATE, 0664)) != 0)
      {
            dbp->err(dbp, ret, "%s", Database);
            return(ret);

      }

      if ((ret = dbp->put(dbp, NULL, &sampleKEY, &sampleDBT, 0)) != 0)
      {
            dbp->err(dbp, ret, "%s", Database);
            fprintf(stderr, "db_create: %s\n", db_strerror(ret));
            return(ret);
      }

      //ret = dbp->close(dbp, 0);



    /*
     * We can now pass the data DBT to a DB->put() or DBC->c_put() call for
     * storage in the database. We won't show that here.
     */

    /*
     * Upon retrieval from the database (again, we don't show the actual
     * database get() activity), the DBT's data field is pointing to
     * a void * buffer that contains exactly the data that we marshalled into
     * our buffer above. We now need to only unmarshall that data. To do this,
     * we have to remember the order in which we originally marshalled the
     * data.
     */

    /*
     * Note that we're reusing the same DBT for unmarshalling process as we used
     * to marshall the data. In real-world usage, the two would be different
     * as they would almost certainly be declared in different scopes.
     */


    /*
     * Now we can print everything out to prove that the marshalling process
     * worked
     */

    printf("Original structure:\n");
    printf("\tmyInt: %i, \tmyFloat: %f\n", myStruct.myInt, myStruct.myFloat);
    printf("\tmyString: %s\n", myStruct.myString);


      getdata();

    return(0);
}



void getdata(void)
{
      u_int32_t *bufferPtr; /* A pointer into the buffer */
      EXAMPLE_STRUCTURE newStruct; /* The structure we want to place data into */

      DBT sampleDBT;
      DBT sampleKEY;
      DB *dbp;

      int ret;

      char *SerialNumber;
      char *Database;


      
      memset(&sampleKEY, 0, sizeof(DBT));
      memset(&sampleDBT, 0, sizeof(DBT));

      SerialNumber = "12345";
      sampleKEY.data = SerialNumber;
      sampleKEY.size = sizeof(SerialNumber);



      Database = "sample.db";



      if ((ret = db_create(&dbp, NULL, 0)) != 0)
      {
            fprintf(stderr, "db_create: %s\n", db_strerror(ret));
      }


      if ((ret = dbp->open(dbp,
                  NULL, Database, NULL, DB_BTREE, DB_CREATE, 0664)) != 0)
      {
            dbp->err(dbp, ret, "%s", Database);

      }



      if ((ret = dbp->get(dbp, NULL, &sampleKEY, &sampleDBT, 0)) != 0)
      {
            dbp->err(dbp, ret, "%s", Database);
      }


    bufferPtr = sampleDBT.data;

    /* First, find the int (the first bit of data that we stored) */
    newStruct.myInt = *((int *)bufferPtr);
    bufferPtr += sizeof(int);

    /* Next, the string */
    newStruct.myString = (char *)bufferPtr;
    bufferPtr += (strlen(newStruct.myString) + 1) * sizeof(char);

    /* And finally, the float */
    newStruct.myFloat = *((float *)bufferPtr);



    printf("\nNew structure (after marshalling and unmarshalling:\n");
    printf("\tmyInt: %i, \tmyFloat: %f\n", newStruct.myInt, newStruct.myFloat);

    printf("\tmyString: %s\n", newStruct.myString);

    /* Cleanup */

      ret = dbp->close(dbp, 0);


}




The following struct in your example is unclear to me or I would try it.
struct st_adr_lpVtbl {
     int (*save)(ST_ADR*);
     int (*clone)(ST_ADR*, ST_ADR*);
     int (*equal) (ST_ADR*, ST_ADR*);
     char * (*get_name) (ST_ADR*);
     char * (*get_first_name) (ST_ADR*);
     char * (*get_street) (ST_ADR *);
     char * (*get_city) (ST_ADR *);
     int  (*get_zip) (ST_ADR*);
     void * (*get_by_idx) (ST_ADR*, int);
     char * (*get_entry_by_idx) (ST_ADR*, int);
     void (*set_entry_by_idx) (ST_ADR*, int, char*);
     void (*set_by_idx) (ST_ADR*, int, void*);
     void (*set_name) (ST_ADR *, char*);
     void (*set_first_name)(ST_ADR *, char*);
     void (*set_street)(ST_ADR *, char*);
     void (*set_city)(ST_ADR *, char*);
     void (*set_zip) (ST_ADR*, int);
     void (*st_test) (char*);
};

 

by: fridomPosted on 2004-05-07 at 08:27:19ID: 11015762

I suggest you check you marshalling/unmarshalling code. I suggest to putting them in their own structure and test them. If you know they work you can put them into the Database the lpVtbl stuff is totally unimportant my datastructure has pointers at the first positions. So you simply can drop the first without trouble. But what you can not drop is putting the data into the Database! You do not put anything into it, so you get out whatevef you find in the buffer. That is a bug in your code.

Friedrich

 

by: fridomPosted on 2004-05-07 at 08:33:28ID: 11015814

sorry, I see there is a put, so I bet the problem is here:
newStruct.myString = (char *)bufferPtr;
    bufferPtr += (strlen(newStruct.myString) + 1) * sizeof(char);

I'll have to check.

Friedrich

 

by: fridomPosted on 2004-05-07 at 09:13:25ID: 11016195

Well my problem is that the the get failed here. So it's impossible to tell where your problem is.

Friedrich

 

by: fridomPosted on 2004-05-07 at 09:39:34ID: 11016389

Ok, I cleaned up your code a bit and this works here:
include <db.h>
#include <string.h>
#include <stdlib.h>

#define MAXBUFFER 300
#define MAXSTRING 100

void getdata(void);
/* Declare our struct */
struct example_structure {
    float myFloat;
    int myInt;
    char *myString;
};
typedef struct example_structure EXAMPLE_STRUCTURE;

char SAMPLE_KEY[] = "eins";
char * Database = "./sample.db";
DBT sampleKEY;


/*
 * Program to illustrate marshalling and unmarshalling structures.
 *
 * Marshalling is the process of moving the contents of a structure's
 * fields into a single contiguous memory location. This is done so that
 * the structure can be stored in a Berkeley DB database.
 *
 * Unmarshalling is performed to take data retrieved from a Berkeley DB database
 * and place it back into the structure so that it can be used by the
 * application.
 */
int
main(void)
{
    DBT sampleDBT; /* The Berkeley DB data structure that we use to store data
                                     * in a database. Typically there are two of these for
                                     * every database record, one for a key and one for the
                                     * data. In this case, we need only one DBT for
                                     * illustration purposes.
                                     */

     DB *dbp;
     char *SerialNumber;

     int ret;

    EXAMPLE_STRUCTURE myStruct;  /* The structure we want to store */

    int buffer_length; /* The amount of data stored in our buffer */
    char buffer[MAXBUFFER];  /* The buffer itself */
    char *bufferPtr; /* A pointer into the buffer */



     memset(&sampleKEY, 0, sizeof(DBT));
     memset(&sampleDBT, 0, sizeof(DBT));



    /* First, we fill in our structure's data fields */
    myStruct.myFloat = 3.04;
    myStruct.myInt = 200;
    /* malloc space for the string */
    myStruct.myString = (char *)malloc(MAXSTRING * sizeof(char));
    /* Copy a string into that space. */
    strcpy(myStruct.myString, "My example string.");

    /*
     * In order to store the data for this structure, we must make sure that
     * all its data is lined up in a single contiguous block of memory -- that
     * is, in a single buffer. We also need to know how much data was put into
     * that buffer. To do this, we copy the structure's data into the buffer.
     * This is the actual marshalling process.
     *
     * Note that the order we use to copy the data is not important, except
     * that we have to make sure that we unmarshall in the same order. Here
     * we mix things up a bit in order to illustrate the concept.
     *
     * Notice that we keep track of how much data we've placed in the buffer as
     * we go. Also, take care to copy each new bit of data to the end of the
     * buffer, so as to not overwrite any data previously placed there.
     */

    /* Initialize the buffer */
    memset(&buffer, 0, MAXBUFFER);
    /* Copy the struct's int into the buffer */
    bufferPtr = &buffer[0];
    memcpy(bufferPtr, &(myStruct.myInt), sizeof(int));
    buffer_length = sizeof(int);

    /* Copy the struct's string into the buffer */
    bufferPtr = &buffer[buffer_length];
    memcpy(bufferPtr, myStruct.myString,
                strlen(myStruct.myString) + 1);
    buffer_length += (strlen(myStruct.myString) + 1);

    /* Copy the struct's float into the buffer */
    bufferPtr = &buffer[buffer_length];
    memcpy(bufferPtr, &(myStruct.myFloat), sizeof(float));
    buffer_length += sizeof(float);

    /*
     * We now have a buffer that contains all our data. We also have the size of
     * the data contained in that buffer. We can use this buffer with our DBT:
     */

    sampleDBT.data = buffer;
    sampleDBT.size = buffer_length;


    sampleKEY.data = SAMPLE_KEY;
    sampleKEY.size = sizeof(SAMPLE_KEY);




     if ((ret = db_create(&dbp, NULL, 0)) != 0)
     {
          fprintf(stderr, "db_create: %s\n", db_strerror(ret));
          return(ret);
     }


     if ((ret = dbp->open(dbp,
               NULL, Database, NULL, DB_BTREE, DB_CREATE, 0664)) != 0)
     {
          dbp->err(dbp, ret, "%s", Database);
          return(ret);

     }

     if ((ret = dbp->put(dbp, NULL, &sampleKEY, &sampleDBT, 0)) != 0)
     {
          dbp->err(dbp, ret, "%s", Database);
          fprintf(stderr, "db_create: %s\n", db_strerror(ret));
          return(ret);
     }

     //ret = dbp->close(dbp, 0);



    /*
     * We can now pass the data DBT to a DB->put() or DBC->c_put() call for
     * storage in the database. We won't show that here.
     */

    /*
     * Upon retrieval from the database (again, we don't show the actual
     * database get() activity), the DBT's data field is pointing to
     * a void * buffer that contains exactly the data that we marshalled into
     * our buffer above. We now need to only unmarshall that data. To do this,
     * we have to remember the order in which we originally marshalled the
     * data.
     */

    /*
     * Note that we're reusing the same DBT for unmarshalling process as we used
     * to marshall the data. In real-world usage, the two would be different
     * as they would almost certainly be declared in different scopes.
     */


    /*
     * Now we can print everything out to prove that the marshalling process
     * worked
     */

    printf("Original structure:\n");
    printf("\tmyInt: %i, \tmyFloat: %f\n", myStruct.myInt, myStruct.myFloat);
    printf("\tmyString: %s\n", myStruct.myString);
      ret = dbp->close(dbp, 0);

     getdata();

    return(0);
}



void getdata(void)
{
     char *bufferPtr; /* A pointer into the buffer */
     EXAMPLE_STRUCTURE newStruct; /* The structure we want to place data into */

     DBT sampleDBT;
     DB *dbp;

     int ret;

     memset(&sampleDBT, 0, sizeof(DBT));


     if ((ret = db_create(&dbp, NULL, 0)) != 0)
     {
          fprintf(stderr, "db_create: %s\n", db_strerror(ret));
     }


     if ((ret = dbp->open(dbp,
               NULL, Database, NULL, DB_BTREE, DB_CREATE, 0664)) != 0)
     {
          dbp->err(dbp, ret, "%s", Database);

     }



     if ((ret = dbp->get(dbp, NULL, &sampleKEY, &sampleDBT, 0)) != 0)
     {
          dbp->err(dbp, ret, "%s", Database);
              return;
     }


    bufferPtr = sampleDBT.data;

    /* First, find the int (the first bit of data that we stored) */
    newStruct.myInt = *((int *)bufferPtr);
    bufferPtr += sizeof(int);

    /* Next, the string */
    newStruct.myString = (char *)bufferPtr;
    bufferPtr += (strlen(newStruct.myString) + 1);

    /* And finally, the float */
    newStruct.myFloat = *((float *)bufferPtr);



    printf("\nNew structure (after marshalling and unmarshalling:\n");
    printf("\tmyInt: %i, \tmyFloat: %f\n", newStruct.myInt, newStruct.myFloat);

    printf("\tmyString: %s\n", newStruct.myString);

    /* Cleanup */

     ret = dbp->close(dbp, 0);


}
output:
Original structure:
        myInt: 200,     myFloat: 3.040000
        myString: My example string.

New structure (after marshalling and unmarshalling:
        myInt: 200,     myFloat: 3.040000
        myString: My example string.

Press enter to continue...
I did not understand why you would us a u_int32_t for the buffer, and of course you have to either flush the output or close the database connection otherwise nothing is written.

Regards
Friedrich

 

by: marcus_careyPosted on 2004-05-07 at 10:41:10ID: 11016853

Friedrich


Thanks a lot!

I changed the u_int32_t to char and it works. Steve from SleepyCat document support provided the example code which uses the u_int32_t data type.  I am not that familiar with SleepyCat Berkeley DB and I will have more questions in the future.  I have been using C/Database Toolchest from Mix Software which is not open source which is why I download the Berkeley DB software.  
 Thanks again, and I hope you will be available for more questions.  I have unlimited points.

Marcus

 

by: marcus_careyPosted on 2004-12-07 at 21:29:27ID: 12770798

Friedrich


You never explained your example.  


struct st_adr_lpVtbl {
     int (*save)(ST_ADR*);
     int (*clone)(ST_ADR*, ST_ADR*);
     int (*equal) (ST_ADR*, ST_ADR*);
     char * (*get_name) (ST_ADR*);
     char * (*get_first_name) (ST_ADR*);
     char * (*get_street) (ST_ADR *);
     char * (*get_city) (ST_ADR *);
     int  (*get_zip) (ST_ADR*);
     void * (*get_by_idx) (ST_ADR*, int);
     char * (*get_entry_by_idx) (ST_ADR*, int);
     void (*set_entry_by_idx) (ST_ADR*, int, char*);
     void (*set_by_idx) (ST_ADR*, int, void*);
     void (*set_name) (ST_ADR *, char*);
     void (*set_first_name)(ST_ADR *, char*);
     void (*set_street)(ST_ADR *, char*);
     void (*set_city)(ST_ADR *, char*);
     void (*set_zip) (ST_ADR*, int);
     void (*st_test) (char*);
};

 

by: fridomPosted on 2004-12-07 at 23:52:42ID: 12771248

Well it was an example on what I wrote to test the Berkeley DB. This example was not helpful to you and I rewrote a simplified example. The code you posted hier is Standard C code so what is unclear about it and what do you want to know?

struct st_adr_lpVtbl is a structure with function pointers. so you could write
ST_ADR *adr1, *adr2;

adr1->get_name(adr) -> gives out the name of the structure. if you would compar to instances of this structure you could write
adr1->equal(adr1, adr2);

It's a kind of "poor" man's OO progamming.

Regards
Friedrich




 

by: marcus_careyPosted on 2004-12-08 at 06:34:31ID: 12773552

The problem is I am assumming how you wrote each function.  


void set_name(ST_ADDR *Address, char *name)
{
         ST_ADDR *pAddress = Address;
       

         pAddress->data->name = name;
}

 

by: fridomPosted on 2004-12-08 at 09:09:49ID: 12775302

Well that's not important to understand how to use the Berkley DB I probably have written
void set_name (ST_ADR * adr, char *name){
     str(n)cpy (adr->data->name, name);
}

and I dropped it in the other example and simplified the whole problem.
Regards
Friedrich

20120131-EE-VQP-002

3 Ways to Join

30-Day Free Trial

The Experts

98% positive feedback on 31,087 answers since March 2000. angeliii is a Microsoft Most Valuable Professional for his work with MS SQL Server & Develoment.

He has also proven his knowledge of Visual Basic Programming, PHP Scripting and Oracle Databases.

The Experts

97% positive feedback on 10,752 answers since July 2000. lrmoore has more than 18 years experience in the networking industry.

The six-time Mircosoft MVPs specialties include firewalls, virtual private networking, and network management.

Testimonials

"...and excellent source for support... Kind of like having your very own IT dept." Electriciansnet

Testimonials

"I was apprehensive at signing up at first. However... it has already made my life as an IT administrator much easier." JaCrews

Testimonials

"WOW! You guys have great, active, and knowledgeable people on here." moore50

Business Clients

Business Clients

In the Press

"If you’ve got a question... Experts Exchange can supply an answer.”

In the Press

"...an invaluable aid for both IT professionals and those who require tech support."

In the Press

"where IT professionals provide quick answers on just about any topic"

Business Account Plans

Loading Advertisement...