버클리DB를 사용해서 개발시에..

rokmn3309의 이미지

테스트로 main()함수 안에서 cursor를 열어서 데이터 읽기했을때는 문제가 없었으나 함수로 빼서 cursor를 열어서 읽기를 시도 했을때에 DB_NEXT 옵션사용시 데이터가 없다거나, DB_SET 옵션사용시 메모리 할당을 할수 없다는 메세지가 나옵니다..
cursor생성시에는 에러나 오류등은 없었습니다. DB4-4.0.x,4.1에서 나타나는 현상은 동일했습니다.

main에서 하는거와 함수로 빼서 하는거랑 어떤 차이가 있는지 알수가 없군요.
아래는 대충적인 소스입니다.

다만 함수로 뺐을때에 다음과 같은 cursor를 사용안했을때에는 정상적으로 동작합니다.

ret = dbp->get(dbp, NULL, &key, &data,0);
ret = dbp->put(dbp, NULL,&key, &data, DB_NOOVERWRITE); 
ret = dbp->del(dbp, NULL,&key,0); 


DB *dbp;
DBC *dbcp;
DBT key, data;

typedef struct imi_struct {
   char seq[32];
   char name[64];
   unsigned long age;
   unsigned int sex;
   char addr[128];
} StructDef;

int open_database(char *dbname){
  //DB 오픈
}
int close_database(){
  //DB 종료
}
int execute_database(StructDef *dstr,char *dbname,int act){
    int ret = 0;
    if(open_database(dbname)==0){
        memset(&key, 0, sizeof(DBT));
        memset(&data, 0, sizeof(DBT));

        ret = dbp->cursor(dbp, NULL, &dbcp, 0);
        if (ret != 0) {
            printf("Create cursor failed : %s\n",db_strerror(ret));
            goto err2;
        }
        data.data = dstr;
        data.size = sizeof(StructDef);
        data.flags = DB_DBT_USERMEM;

        while( (ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0 ){
             printf("seq: %s", dstr->seq);
             printf("\tname: %s", dstr->name);
             printf("\tage: %d", dstr->age);
             printf("\tsex: %d", dstr->sex);
             printf("\taddr: %s\n", dstr->addr);
        }
       
        if (ret != DB_NOTFOUND) {
             printf("data is not exist\n");
        }

        if (dbcp != NULL) 
            dbcp->c_close(dbcp); 
	
        if(close_database()!=0)
             goto err;
        }
   }
   return 0;

err:	(void)dbp->close(dbp, 0);
		return -1;
err2:	(void)dbcp->c_close(dbcp); 
		goto err;
}
int main(int argc, char *argv[]){
   StructDef mydata;
   memset(&mydata, 0, sizeof(StructDef));
   
   if(execute_database(&mydata,"my_sample.db",5)==0){
      printf("select all succeed\n");
   }
   return 0;
}

cpulpul의 이미지

함수에서 레코드를 불러오든 main()에서 불러오든 전혀 관계 없습니다.
더우기 전역변수로 선언 되었기어 더욱 그렇지요..

get()함수에서 레코드 불러오기가 안된다고 하셨는데..

"DB_NEXT", "DB_SET" 등은 c_get() 함수의 매개 변수 입니다.
c_get()함수의 매개변수로 DB_NEXT를 사용하여 while()문으로 반복을 하면 첫레코드부터 마지막 레코드 까지 순회합니다.

하지만 get()함수는 다른 용도로 사용을 합니다.
key값을 설정한후 해당레코드에 직접 접근을 하는 경우등으로 사용을 하지요..

자세한 사항은 버클리 API 레퍼런스를 참고 하세요..

rokmn3309의 이미지

m.m

위에서 처음에 글 쓸때에.. get(),put(),del()은 이상없이 되고..
커서를 사용할때 안된다고 했는데 .. 제가 올린 내용을 잘못 읽으신듯하네요.

cpulpul의 이미지

그럼 위의 코드 에서 문제가 발생한단 말입니까? :D

그럼 음.. key2, data2의 초기화는 어디서 하는가요?
DBT 초기화가 되지 않으면 에러가 발생합니다.

rokmn3309의 이미지

key2, data2는 여러가지로 테스트하다가 보니 잘못들어갓군요.. 수정했습니다.
첨 글에서

읽기를 시도 했을때에 DB_NEXT 옵션사용시 데이터가 없다거나, DB_SET 옵션사용시 메모리 할당을 할수 없다는 메세지가 나옵니다

이런 메세지가 나왔습니다. 컴파일시에 에러도 아니고 커서 생성시에 반환값도 정상으로 나옵니다. 하지만 위 소스 코드처럼
while문에 c_get을 했을시에 데이터가 있음에도 불구하고 데이터가 없다는(DB_NOTFOUND) 메세지를 반환하는게
문제입니다. 아니면은 c_get에서 DB_SET나 DB_SET_RANGE옵션으로
데이터를 가져 올려고 하면은 "Cannot allocate memory"메세지를 출력합니다.

하지만 동일 소스를 그대로 main으로 가져가서 테스트 하면은 문제없이 데이터를 출력합니다.

cpulpul의 이미지

Quote:
data.data = dstr;
        data.size = sizeof(StructDef);
        data.flags = DB_DBT_USERMEM;

        while( (ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0 ){
             printf("seq: %s", dstr->seq);
             printf("\tname: %s", dstr->name);
             printf("\tage: %d", dstr->age);
             printf("\tsex: %d", dstr->sex);
             printf("\taddr: %s\n", dstr->addr);
        }

위의 코드를 이렇게 한번 테스트 해보세요.

data.data = dstr;
        data.size = sizeof(StructDef);
        data.flags = DB_DBT_USERMEM;

        while( (ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0 ){
             printf("seq: %s", dstr->seq);
             printf("\tname: %s", dstr->name);
             printf("\tage: %d", dstr->age);
             printf("\tsex: %d", dstr->sex);
             printf("\taddr: %s\n", dstr->addr);

        data.data = dstr;
        data.size = sizeof(StructDef);
        data.flags = DB_DBT_USERMEM;
        }

제가 업무중이라 테스트 는 안해봤습니다.

사용자 메모리 할당에서 최초 한번만 할당하고..
다음 레코드에서는 할당되지 않은 공간에다 기록할려고 시도하면서 에러가
발생한것 같습니다.

rokmn3309의 이미지

계속 봐주어서 고맙게 생각합니다...
말씀하신데로 테스트는 해봤는데 출력메세지는 동일하였습니다.

c_get에서 DB_NEXT 플래그를 줬을때는 데이터가 하나도 없다고 나오고..
DB_SET이나 DB_SET_RANGE 플래그로 c_get사용시에는 Cannot allocate memory 였습니다..

cpulpul의 이미지

이런 글이 있네요..

Quote:
DB_DBT_USERMEM
The data field of the key or data structure must refer to memory that is at least ulen bytes in length. If the length of the requested item is less than or equal to that number of bytes, the item is copied into the memory to which the data field refers. Otherwise, the size field is set to the length needed for the requested item, and the error ENOMEM is returned.

이걸 추가 시켜 실행하여 보시죠..
data.ulen = sizeof(StructDef);

rokmn3309의 이미지

...
key,data가 사용되는곳에 .data, .size, .ulen, .flags 옵션을 다주고 커서 여는곳과 닫는곳을 한군데로 해서 하니 문제 없이 잘 동작합니다...

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.