Esempio n. 1
0
BOOL CDbxKV::MetaMergeHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub)
{
	DBEventSortingKey keyVal = { ccSub->contactID, 0, 0 }, insVal = { ccMeta->contactID, 0, 0 };
	ham_key_t key = { sizeof(keyVal), &keyVal }, key2 = { sizeof(insVal), &insVal };
	ham_record_t data = { 0 };

	cursor_ptr cursor(m_dbEventsSort);
	if (ham_cursor_find(cursor, &key, &data, HAM_FIND_GT_MATCH) != HAM_SUCCESS)
		return 0;
	 
	do {
		DBEventSortingKey *pKey = (DBEventSortingKey*)key.data;
		if (pKey->dwContactId != ccSub->contactID)
			break;

		insVal.ts = pKey->ts;
		insVal.dwEventId = pKey->dwEventId;
		ham_db_insert(m_dbEventsSort, NULL, &key2, &data, HAM_OVERWRITE);

		ccMeta->dbc.dwEventCount++;
	} while (ham_cursor_move(cursor, &key, &data, HAM_CURSOR_NEXT) == HAM_SUCCESS);

	// now update the number of events in a metacontact
	ham_key_t keyc = { sizeof(int), &ccMeta->contactID };
	ham_record_t datac = { sizeof(ccMeta->dbc), &ccMeta->dbc };
	ham_db_insert(m_dbContacts, NULL, &keyc, &datac, HAM_OVERWRITE);
	return 0;
}
Esempio n. 2
0
// will create the offset if it needs to
DWORD CDbxKV::GetModuleNameOfs(const char *szName)
{
	DWORD ofsExisting = FindExistingModuleNameOfs(szName);
	if (ofsExisting)
		return ofsExisting;

	if (m_bReadOnly)
		return 0;

	int nameLen = (int)strlen(szName);

	// need to create the module name
	int newIdx = ++m_maxModuleID;
	DBModuleName *pmod = (DBModuleName*)_alloca(sizeof(DBModuleName) + nameLen);
	pmod->dwSignature = DBMODULENAME_SIGNATURE;
	pmod->cbName = (char)nameLen;
	strcpy(pmod->name, szName);
	
	ham_key_t key = { sizeof(int), &newIdx };
	ham_record_t rec = { sizeof(DBModuleName) + nameLen, pmod };
	ham_db_insert(m_dbModules, NULL, &key, &rec, HAM_OVERWRITE);

	// add to cache
	char *mod = (char*)HeapAlloc(m_hModHeap, 0, nameLen + 1);
	strcpy(mod, szName);
	AddToList(mod, newIdx);

	// quit
	return -1;
}
Esempio n. 3
0
 /** Inserts a key/record pair. */
 void insert(txn *t, key *k, record *r, uint32_t flags = 0) {
   ham_status_t st = ham_db_insert(m_db,
             t ? t->get_handle() : 0,
             k ? k->get_handle() : 0,
             r ? r->get_handle() : 0, flags);
   if (st)
     throw error(st);
 }
Esempio n. 4
0
STDMETHODIMP_(MCONTACT) CDbxKV::AddContact()
{
	DWORD dwContactId;
	{
		mir_cslock lck(m_csDbAccess);
		dwContactId = m_dwMaxContactId++;

		DBCachedContact *cc = m_cache->AddContactToCache(dwContactId);
		cc->dbc.dwSignature = DBCONTACT_SIGNATURE;

		ham_key_t key = { sizeof(MCONTACT), &dwContactId };
		ham_record_t data = { sizeof(cc->dbc), &cc->dbc };
		ham_db_insert(m_dbContacts, NULL, &key, &data, HAM_OVERWRITE);
	}

	NotifyEventHooks(hContactAddedEvent, dwContactId, 0);
	return dwContactId;
}
Esempio n. 5
0
void
copy_db(ham_db_t *source, ham_db_t *dest) {
  ham_cursor_t *cursor;  /* hamsterdb cursor object */
  ham_status_t st;
  ham_key_t key;
  ham_record_t rec;

  memset(&key, 0, sizeof(key));
  memset(&rec, 0, sizeof(rec));

  /* create a new cursor */
  st = ham_cursor_create(&cursor, source, 0, 0);
  if (st)
    error("ham_cursor_create", st);

  /* get a cursor to the source database */
  st = ham_cursor_move(cursor, &key, &rec, HAM_CURSOR_FIRST);
  if (st == HAM_KEY_NOT_FOUND) {
    printf("database is empty!\n");
    return;
  }
  else if (st)
    error("ham_cursor_move", st);

  do {
    /* insert this element into the new database */
    st = ham_db_insert(dest, 0, &key, &rec, HAM_DUPLICATE);
    if (st)
      error("ham_db_insert", st);

    /* give some feedback to the user */
    printf(".");

    /* fetch the next item, and repeat till we've reached the end
     * of the database */
    st = ham_cursor_move(cursor, &key, &rec, HAM_CURSOR_NEXT);
    if (st && st != HAM_KEY_NOT_FOUND)
      error("ham_cursor_move", st);

  } while (st == 0);

  /* clean up and return */
  ham_cursor_close(cursor);
}
Esempio n. 6
0
STDMETHODIMP_(BOOL) CDbxKV::WriteContactSetting(MCONTACT contactID, DBCONTACTWRITESETTING *dbcws)
{
	if (dbcws == NULL || dbcws->szSetting == NULL || dbcws->szModule == NULL || m_bReadOnly)
		return 1;

	// the db format can't tolerate more than 255 bytes of space (incl. null) for settings+module name
	int settingNameLen = (int)strlen(dbcws->szSetting);
	int moduleNameLen = (int)strlen(dbcws->szModule);
	if (settingNameLen > 0xFE) {
#ifdef _DEBUG
		OutputDebugStringA("WriteContactSetting() got a > 255 setting name length. \n");
#endif
		return 1;
	}
	if (moduleNameLen > 0xFE) {
#ifdef _DEBUG
		OutputDebugStringA("WriteContactSetting() got a > 255 module name length. \n");
#endif
		return 1;
	}

	// used for notifications
	DBCONTACTWRITESETTING dbcwNotif = *dbcws;
	if (dbcwNotif.value.type == DBVT_WCHAR) {
		if (dbcwNotif.value.pszVal != NULL) {
			char* val = mir_utf8encodeW(dbcwNotif.value.pwszVal);
			if (val == NULL)
				return 1;

			dbcwNotif.value.pszVal = (char*)alloca(strlen(val) + 1);
			strcpy(dbcwNotif.value.pszVal, val);
			mir_free(val);
			dbcwNotif.value.type = DBVT_UTF8;
		}
		else return 1;
	}

	if (dbcwNotif.szModule == NULL || dbcwNotif.szSetting == NULL)
		return 1;

	DBCONTACTWRITESETTING dbcwWork = dbcwNotif;

	mir_ptr<BYTE> pEncoded(NULL);
	bool bIsEncrypted = false;
	switch (dbcwWork.value.type) {
	case DBVT_BYTE: case DBVT_WORD: case DBVT_DWORD:
		break;

	case DBVT_ASCIIZ: case DBVT_UTF8:
		bIsEncrypted = m_bEncrypted || IsSettingEncrypted(dbcws->szModule, dbcws->szSetting);
	LBL_WriteString:
		if (dbcwWork.value.pszVal == NULL)
			return 1;
		dbcwWork.value.cchVal = (WORD)strlen(dbcwWork.value.pszVal);
		if (bIsEncrypted) {
			size_t len;
			BYTE *pResult = m_crypto->encodeString(dbcwWork.value.pszVal, &len);
			if (pResult != NULL) {
				pEncoded = dbcwWork.value.pbVal = pResult;
				dbcwWork.value.cpbVal = (WORD)len;
				dbcwWork.value.type = DBVT_ENCRYPTED;
			}
		}
		break;

	case DBVT_UNENCRYPTED:
		dbcwNotif.value.type = dbcwWork.value.type = DBVT_UTF8;
		goto LBL_WriteString;

	case DBVT_BLOB: case DBVT_ENCRYPTED:
		if (dbcwWork.value.pbVal == NULL)
			return 1;
		break;
	default:
		return 1;
	}

	mir_cslockfull lck(m_csDbAccess);

	char *szCachedSettingName = m_cache->GetCachedSetting(dbcwWork.szModule, dbcwWork.szSetting, moduleNameLen, settingNameLen);

	// we don't cache blobs and passwords
	if (dbcwWork.value.type != DBVT_BLOB && dbcwWork.value.type != DBVT_ENCRYPTED && !bIsEncrypted) {
		DBVARIANT *pCachedValue = m_cache->GetCachedValuePtr(contactID, szCachedSettingName, 1);
		if (pCachedValue != NULL) {
			bool bIsIdentical = false;
			if (pCachedValue->type == dbcwWork.value.type) {
				switch (dbcwWork.value.type) {
				case DBVT_BYTE:   bIsIdentical = pCachedValue->bVal == dbcwWork.value.bVal;  break;
				case DBVT_WORD:   bIsIdentical = pCachedValue->wVal == dbcwWork.value.wVal;  break;
				case DBVT_DWORD:  bIsIdentical = pCachedValue->dVal == dbcwWork.value.dVal;  break;
				case DBVT_UTF8:
				case DBVT_ASCIIZ: bIsIdentical = strcmp(pCachedValue->pszVal, dbcwWork.value.pszVal) == 0; break;
				}
				if (bIsIdentical)
					return 0;
			}
			m_cache->SetCachedVariant(&dbcwWork.value, pCachedValue);
		}
		if (szCachedSettingName[-1] != 0) {
			lck.unlock();
			NotifyEventHooks(hSettingChangeEvent, contactID, (LPARAM)&dbcwWork);
			return 0;
		}
	}
	else m_cache->GetCachedValuePtr(contactID, szCachedSettingName, -1);

	DBSettingSortingKey keySearch;
	keySearch.dwContactID = contactID;
	keySearch.dwOfsModule = GetModuleNameOfs(dbcws->szModule);
	strncpy_s(keySearch.szSettingName, dbcws->szSetting, _TRUNCATE);

	ham_key_t key = { 2 * sizeof(DWORD) + settingNameLen, &keySearch };
	ham_record_t rec = { 0 };

	switch (dbcwWork.value.type) {
	case DBVT_BYTE:  rec.size = 2; break;
	case DBVT_WORD:  rec.size = 3; break;
	case DBVT_DWORD: rec.size = 5; break;
	
	case DBVT_ASCIIZ: 
	case DBVT_UTF8:
		rec.size = 3 + dbcwWork.value.cchVal; break;

	case DBVT_BLOB:
	case DBVT_ENCRYPTED:
		rec.size = 3 + dbcwWork.value.cpbVal; break;

	default:
		return 1;
	}

	rec.data = _alloca(rec.size);
	BYTE *pBlob = (BYTE*)rec.data;
	*pBlob++ = dbcwWork.value.type;
	switch (dbcwWork.value.type) {
	case DBVT_BYTE:  *pBlob = dbcwWork.value.bVal; break;
	case DBVT_WORD:  *(WORD*)pBlob = dbcwWork.value.wVal; break;
	case DBVT_DWORD: *(DWORD*)pBlob = dbcwWork.value.dVal; break;

	case DBVT_ASCIIZ:
	case DBVT_UTF8:
		*(WORD*)pBlob = dbcwWork.value.cchVal;
		memcpy(pBlob+2, dbcwWork.value.pszVal, dbcwWork.value.cchVal);
		break;

	case DBVT_BLOB:
	case DBVT_ENCRYPTED:
		*(WORD*)pBlob = dbcwWork.value.cpbVal;
		memcpy(pBlob+2, dbcwWork.value.pbVal, dbcwWork.value.cpbVal);
	}
	ham_db_insert(m_dbSettings, NULL, &key, &rec, HAM_OVERWRITE);
	lck.unlock();

	// notify
	NotifyEventHooks(hSettingChangeEvent, contactID, (LPARAM)&dbcwNotif);
	return 0;
}
Esempio n. 7
0
int
main(int argc, char **argv) {
  int i;
  ham_status_t st;      /* status variable */
  ham_env_t *env;       /* hamsterdb Environment object */
  ham_db_t *db;         /* hamsterdb Database object */
  ham_key_t key = {0};     /* the structure for a key */
  ham_record_t record = {0};   /* the structure for a record */

  /*
   * Connect to the server which should listen at 8080. The server is
   * implemented in server1.c.
   */
  st = ham_env_create(&env, "ham://localhost:8080/env1.db", 0, 0, 0);
  if (st != HAM_SUCCESS)
    error("ham_env_create", st);

  /* now open a Database in this Environment */
  st = ham_env_open_db(env, &db, 13, 0, 0);
  if (st != HAM_SUCCESS)
    error("ham_env_open_db", st);

  /* now we can insert, delete or lookup values in the database */
  for (i = 0; i < LOOP; i++) {
    key.data = &i;
    key.size = sizeof(i);

    record.size = key.size;
    record.data = key.data;

    st = ham_db_insert(db, 0, &key, &record, 0);
    if (st != HAM_SUCCESS)
      error("ham_db_insert", st);
  }

  /* now lookup all values */
  for (i = 0; i < LOOP; i++) {
    key.data = &i;
    key.size = sizeof(i);

    st = ham_db_find(db, 0, &key, &record, 0);
    if (st != HAM_SUCCESS)
      error("ham_db_find", st);

    /* check if the value is ok */
    if (*(int *)record.data != i) {
      printf("ham_db_find() ok, but returned bad value\n");
      return (-1);
    }
  }

  /* erase everything */
  for (i = 0; i < LOOP; i++) {
    key.data = &i;
    key.size = sizeof(i);

    st = ham_db_erase(db, 0, &key, 0);
    if (st != HAM_SUCCESS)
      error("ham_db_erase", st);
  }

  /* and make sure that the database is empty */
  for (i = 0; i < LOOP; i++) {
    key.data = &i;
    key.size = sizeof(i);

    st = ham_db_find(db, 0, &key, &record, 0);
    if (st != HAM_KEY_NOT_FOUND)
      error("ham_db_find", st);
  }

  /* close the database handle */
  st = ham_db_close(db, 0);
  if (st != HAM_SUCCESS)
    error("ham_db_close", st);

  /* close the environment handle */
  st = ham_env_close(env, 0);
  if (st != HAM_SUCCESS)
    error("ham_env_close", st);

  printf("success!\n");
  return (0);
}
Esempio n. 8
0
File: env1.c Progetto: ziposoft/ac1
int
main(int argc, char **argv) {
  int i;
  ham_status_t st;    /* status variable */
  ham_db_t *db[MAX_DBS];  /* hamsterdb database objects */
  ham_env_t *env;     /* hamsterdb environment */
  ham_cursor_t *cursor[MAX_DBS]; /* a cursor for each database */
  ham_key_t key, cust_key, ord_key;
  ham_record_t record, cust_record, ord_record;

  customer_t customers[MAX_CUSTOMERS] = {
    { 1, "Alan Antonov Corp." },
    { 2, "Barry Broke Inc." },
    { 3, "Carl Caesar Lat." },
    { 4, "Doris Dove Brd." }
  };

  order_t orders[MAX_ORDERS] = {
    { 1, 1, "Joe" },
    { 2, 1, "Tom" },
    { 3, 3, "Joe" },
    { 4, 4, "Tom" },
    { 5, 3, "Ben" },
    { 6, 3, "Ben" },
    { 7, 4, "Chris" },
    { 8, 1, "Ben" }
  };

  memset(&key, 0, sizeof(key));
  memset(&record, 0, sizeof(record));
  memset(&cust_key, 0, sizeof(cust_key));
  memset(&cust_record, 0, sizeof(cust_record));
  memset(&ord_key, 0, sizeof(ord_key));
  memset(&ord_record, 0, sizeof(ord_record));

  /* Now create a new hamsterdb Environment */
  st = ham_env_create(&env, "test.db", 0, 0664, 0);
  if (st != HAM_SUCCESS)
    error("ham_env_create", st);

  /*
   * Then create the two Databases in this Environment; each Database
   * has a name - the first is our "customer" Database, the second
   * is for the "orders"
   */
  st = ham_env_create_db(env, &db[0], DBNAME_CUSTOMER, 0, 0);
  if (st != HAM_SUCCESS)
    error("ham_env_create_db (customer)", st);
  st = ham_env_create_db(env, &db[1], DBNAME_ORDER, 0, 0);
  if (st != HAM_SUCCESS)
    error("ham_env_create_db (order)", st);

  /* Create a Cursor for each Database */
  for (i = 0; i < MAX_DBS; i++) {
    st = ham_cursor_create(&cursor[i], db[i], 0, 0);
    if (st != HAM_SUCCESS) {
      printf("ham_cursor_create() failed with error %d\n", st);
      return (-1);
    }
  }

  /* Insert a few customers in the first database */
  for (i = 0; i < MAX_CUSTOMERS; i++) {
    key.size = sizeof(int);
    key.data = &customers[i].id;

    record.size = sizeof(customer_t);
    record.data = &customers[i];

    st = ham_db_insert(db[0], 0, &key, &record, 0);
    if (st != HAM_SUCCESS)
      error("ham_db_insert (customer)", st);
  }

  /* And now the orders in the second database */
  for (i = 0; i < MAX_ORDERS; i++) {
    key.size = sizeof(int);
    key.data = &orders[i].id;

    record.size = sizeof(order_t);
    record.data = &orders[i];

    st = ham_db_insert(db[1], 0, &key, &record, 0);
    if (st != HAM_SUCCESS)
      error("ham_db_insert (order)", st);
  }

  /*
   * To demonstrate even more functions: close all objects, then
   * re-open the environment and the two databases.
   *
   * Note that ham_env_close automatically calls ham_db_close on all
   * databases.
   */
  for (i = 0; i < MAX_DBS; i++) {
    st = ham_cursor_close(cursor[i]);
    if (st != HAM_SUCCESS)
      error("ham_cursor_close", st);
  }
  st = ham_env_close(env, 0);
  if (st != HAM_SUCCESS)
    error("ham_env_close", st);

  /* Now reopen the environment and the databases */
  st = ham_env_open(&env, "test.db", 0, 0);
  if (st != HAM_SUCCESS)
    error("ham_env_open", st);
  st = ham_env_open_db(env, &db[0], DBNAME_CUSTOMER, 0, 0);
  if (st != HAM_SUCCESS)
    error("ham_env_open_db (customer)", st);
  st = ham_env_open_db(env, &db[1], DBNAME_ORDER, 0, 0);
  if (st != HAM_SUCCESS)
    error("ham_env_open_db (order)", st);

  /* Re-create a cursor for each database */
  for (i = 0; i < MAX_DBS; i++) {
    st = ham_cursor_create(&cursor[i], db[i], 0, 0);
    if (st != HAM_SUCCESS) {
      printf("ham_cursor_create() failed with error %d\n", st);
      return (-1);
    }
  }

  /*
   * Now start the query - we want to dump each customer with his
   * orders
   *
   * We have a loop with two cursors - the first cursor looping over
   * the database with customers, the second loops over the orders.
   */
  while (1) {
    customer_t *customer;

    st = ham_cursor_move(cursor[0], &cust_key, &cust_record,
            HAM_CURSOR_NEXT);
    if (st != HAM_SUCCESS) {
      /* reached end of the database? */
      if (st == HAM_KEY_NOT_FOUND)
        break;
      else
        error("ham_cursor_next(customer)", st);
    }

    customer = (customer_t *)cust_record.data;

    /* print the customer id and name */
    printf("customer %d ('%s')\n", customer->id, customer->name);

    /*
     * The inner loop prints all orders of this customer. Move the
     * cursor to the first entry.
     */
    st = ham_cursor_move(cursor[1], &ord_key, &ord_record,
            HAM_CURSOR_FIRST);
    if (st != HAM_SUCCESS) {
      /* reached end of the database? */
      if (st == HAM_KEY_NOT_FOUND)
        continue;
      else
        error("ham_cursor_next(order)", st);
    }

    do {
      order_t *order = (order_t *)ord_record.data;

      /* print this order, if it belongs to the current customer */
      if (order->customer_id == customer->id)
        printf("  order: %d (assigned to %s)\n",
            order->id, order->assignee);

      st = ham_cursor_move(cursor[1], &ord_key,
          &ord_record, HAM_CURSOR_NEXT);
      if (st != HAM_SUCCESS) {
        /* reached end of the database? */
        if (st == HAM_KEY_NOT_FOUND)
          break;
        else
          error("ham_cursor_next(order)", st);
      }
    } while (1);
  }

  /*
   * Now close the environment handle; the flag HAM_AUTO_CLEANUP will
   * automatically close all databases and cursors
   */
  st = ham_env_close(env, HAM_AUTO_CLEANUP);
  if (st != HAM_SUCCESS)
    error("ham_env_close", st);

  printf("success!\n");
  return (0);
}
Esempio n. 9
0
int
main(int argc, char **argv) {
  uint32_t i;
  ham_status_t st;             /* status variable */
  ham_env_t *env;              /* hamsterdb environment object */
  ham_db_t *db;                /* hamsterdb database object */
  ham_key_t key = {0};         /* the structure for a key */
  ham_record_t record = {0};   /* the structure for a record */
  ham_parameter_t params[] = { /* parameters for ham_env_create_db */
    {HAM_PARAM_KEY_TYPE, HAM_TYPE_UINT32},
    {HAM_PARAM_RECORD_SIZE, sizeof(uint32_t)},
    {0, }
  };

  /* First create a new hamsterdb Environment */
  st = ham_env_create(&env, "test.db", 0, 0664, 0);
  if (st != HAM_SUCCESS)
    error("ham_create", st);

  /* And in this Environment we create a new Database for uint32-keys
   * and uint32-records. */
  st = ham_env_create_db(env, &db, DATABASE_NAME, 0, &params[0]);
  if (st != HAM_SUCCESS)
    error("ham_create", st);

  /*
   * now we can insert, delete or lookup values in the database
   *
   * for our test program, we just insert a few values, then look them
   * up, then delete them and try to look them up again (which will fail).
   */
  for (i = 0; i < LOOP; i++) {
    key.data = &i;
    key.size = sizeof(i);

    record.size = key.size;
    record.data = key.data;

    st = ham_db_insert(db, 0, &key, &record, 0);
    if (st != HAM_SUCCESS)
      error("ham_db_insert", st);
  }

  /*
   * now lookup all values
   *
   * for ham_db_find(), we could use the flag HAM_RECORD_USER_ALLOC, if WE
   * allocate record.data (otherwise the memory is automatically allocated
   * by hamsterdb)
   */
  for (i = 0; i < LOOP; i++) {
    key.data = &i;
    key.size = sizeof(i);

    st = ham_db_find(db, 0, &key, &record, 0);
    if (st != HAM_SUCCESS)
      error("ham_db_find", st);

    /*
     * check if the value is ok
     */
    if (*(int *)record.data != i) {
      printf("ham_db_find() ok, but returned bad value\n");
      return (-1);
    }
  }

  /*
   * close the database handle, then re-open it (to demonstrate how to open
   * an Environment and a Database)
   */
  st = ham_db_close(db, 0);
  if (st != HAM_SUCCESS)
    error("ham_db_close", st);
  st = ham_env_close(env, 0);
  if (st != HAM_SUCCESS)
    error("ham_env_close", st);

  st = ham_env_open(&env, "test.db", 0, 0);
  if (st != HAM_SUCCESS)
    error("ham_env_open", st);
  st = ham_env_open_db(env, &db, DATABASE_NAME, 0, 0);
  if (st != HAM_SUCCESS)
    error("ham_env_open_db", st);

  /* now erase all values */
  for (i = 0; i < LOOP; i++) {
    key.size = sizeof(i);
    key.data = &i;

    st = ham_db_erase(db, 0, &key, 0);
    if (st != HAM_SUCCESS)
      error("ham_db_erase", st);
  }

  /*
   * once more we try to find all values... every ham_db_find() call must
   * now fail with HAM_KEY_NOT_FOUND
   */
  for (i = 0; i < LOOP; i++) {
    key.size = sizeof(i);
    key.data = &i;

    st = ham_db_find(db, 0, &key, &record, 0);
    if (st != HAM_KEY_NOT_FOUND)
      error("ham_db_find", st);
  }

  /* we're done! close the handles. HAM_AUTO_CLEANUP will also close the
   * 'db' handle */
  st = ham_env_close(env, HAM_AUTO_CLEANUP);
  if (st != HAM_SUCCESS)
    error("ham_env_close", st);

  printf("success!\n");
  return (0);
}
Esempio n. 10
0
File: env2.c Progetto: ziposoft/ac1
int
main(int argc, char **argv) {
  int i;
  ham_status_t st;    /* status variable */
  ham_db_t *db[MAX_DBS];  /* hamsterdb database objects */
  ham_env_t *env;     /* hamsterdb environment */
  ham_cursor_t *cursor[MAX_DBS]; /* a cursor for each database */
  ham_key_t key, cust_key, ord_key, c2o_key;
  ham_record_t record, cust_record, ord_record, c2o_record;

  customer_t customers[MAX_CUSTOMERS] = {
    { 1, "Alan Antonov Corp." },
    { 2, "Barry Broke Inc." },
    { 3, "Carl Caesar Lat." },
    { 4, "Doris Dove Brd." }
  };

  order_t orders[MAX_ORDERS] = {
    { 1, 1, "Joe" },
    { 2, 1, "Tom" },
    { 3, 3, "Joe" },
    { 4, 4, "Tom" },
    { 5, 3, "Ben" },
    { 6, 3, "Ben" },
    { 7, 4, "Chris" },
    { 8, 1, "Ben" }
  };

  memset(&key, 0, sizeof(key));
  memset(&record, 0, sizeof(record));
  memset(&cust_key, 0, sizeof(cust_key));
  memset(&cust_record, 0, sizeof(cust_record));
  memset(&ord_key, 0, sizeof(ord_key));
  memset(&ord_record, 0, sizeof(ord_record));
  memset(&c2o_key, 0, sizeof(c2o_key));
  memset(&c2o_record, 0, sizeof(c2o_record));

  /* Now create a new database file for the Environment */
  st = ham_env_create(&env, "test.db", 0, 0664, 0);
  if (st != HAM_SUCCESS)
    error("ham_env_create", st);

  /*
   * Then create the two Databases in this Environment; each Database
   * has a name - the first is our "customer" Database, the second
   * is for the "orders"; the third manages our 1:n relation and
   * therefore needs to enable duplicate keys
   */
  st = ham_env_create_db(env, &db[DBIDX_CUSTOMER], DBNAME_CUSTOMER, 0, 0);
  if (st != HAM_SUCCESS)
    error("ham_env_create_db(customer)", st);
  st = ham_env_create_db(env, &db[DBIDX_ORDER], DBNAME_ORDER, 0, 0);
  if (st != HAM_SUCCESS)
    error("ham_env_create_db(order)", st);
  st = ham_env_create_db(env, &db[DBIDX_C2O], DBNAME_C2O,
        HAM_ENABLE_DUPLICATES, 0);
  if (st != HAM_SUCCESS)
    error("ham_env_create_db(c2o)", st);

  /* Create a Cursor for each Database */
  for (i = 0; i < MAX_DBS; i++) {
    st = ham_cursor_create(&cursor[i], db[i], 0, 0);
    if (st != HAM_SUCCESS)
      error("ham_cursor_create" , st);
  }

  /*
   * Insert the customers in the customer table
   *
   * INSERT INTO customers VALUES (1, "Alan Antonov Corp.");
   * INSERT INTO customers VALUES (2, "Barry Broke Inc.");
   * etc
   */
  for (i = 0; i < MAX_CUSTOMERS; i++) {
    key.size = sizeof(int);
    key.data = &customers[i].id;

    record.size = sizeof(customer_t);
    record.data = &customers[i];

    st = ham_db_insert(db[0], 0, &key, &record, 0);
    if (st != HAM_SUCCESS)
      error("ham_db_insert (customer)", st);
  }

  /*
   * And now the orders in the second Database; contrary to env1,
   * we only store the assignee, not the whole structure
   *
   * INSERT INTO orders VALUES (1, "Joe");
   * INSERT INTO orders VALUES (2, "Tom");
   */
  for (i = 0; i < MAX_ORDERS; i++) {
    key.size = sizeof(int);
    key.data = &orders[i].id;

    record.size = sizeof(orders[i].assignee);
    record.data = orders[i].assignee;

    st = ham_db_insert(db[1], 0, &key, &record, 0);
    if (st != HAM_SUCCESS)
      error("ham_db_insert (order)", st);
  }

  /*
   * And now the 1:n relationships; the flag HAM_DUPLICATE creates
   * a duplicate key, if the key already exists
   *
   * INSERT INTO c2o VALUES (1, 1);
   * INSERT INTO c2o VALUES (2, 1);
   * etc
   */
  for (i = 0; i < MAX_ORDERS; i++) {
    key.size = sizeof(int);
    key.data = &orders[i].customer_id;

    record.size = sizeof(int);
    record.data = &orders[i].id;

    st = ham_db_insert(db[2], 0, &key, &record, HAM_DUPLICATE);
    if (st != HAM_SUCCESS)
      error("ham_db_insert(c2o)", st);
  }

  /*
   * Now start the query - we want to dump each customer with his
   * orders
   *
   * loop over the customer; for each customer, loop over the 1:n table
   * and pick those orders with the customer id. then load the order
   * and print it
   *
   * the outer loop is similar to:
   *  SELECT * FROM customers WHERE 1;
   */
  while (1) {
    customer_t *customer;

    st = ham_cursor_move(cursor[0], &cust_key, &cust_record, HAM_CURSOR_NEXT);
    if (st != HAM_SUCCESS) {
      /* reached end of the database? */
      if (st == HAM_KEY_NOT_FOUND)
        break;
      else
        error("ham_cursor_next(customer)", st);
    }

    customer = (customer_t *)cust_record.data;

    /* print the customer id and name */
    printf("customer %d ('%s')\n", customer->id, customer->name);

    /*
     * loop over the 1:n table
     *
     * before we start the loop, we move the cursor to the
     * first duplicate key
     *
     * SELECT * FROM customers, orders, c2o
     *   WHERE c2o.customer_id=customers.id AND
     *    c2o.order_id=orders.id;
     */
    c2o_key.data = &customer->id;
    c2o_key.size = sizeof(int);
    st = ham_cursor_find(cursor[2], &c2o_key, 0, 0);
    if (st != HAM_SUCCESS) {
      if (st == HAM_KEY_NOT_FOUND)
        continue;
      error("ham_cursor_find(c2o)", st);
    }
    st = ham_cursor_move(cursor[2], 0, &c2o_record, 0);
    if (st != HAM_SUCCESS)
      error("ham_cursor_move(c2o)", st);

    do {
      int order_id;

      order_id = *(int *)c2o_record.data;
      ord_key.data = &order_id;
      ord_key.size = sizeof(int);

      /*
       * load the order
       * SELECT * FROM orders WHERE id = order_id;
       */
      st = ham_db_find(db[1], 0, &ord_key, &ord_record, 0);
      if (st != HAM_SUCCESS)
        error("ham_db_find(order)", st);

      printf("  order: %d (assigned to %s)\n",
          order_id, (char *)ord_record.data);

      /*
       * The flag HAM_ONLY_DUPLICATES restricts the cursor
       * movement to the duplicate list.
       */
      st = ham_cursor_move(cursor[2], &c2o_key,
          &c2o_record, HAM_CURSOR_NEXT|HAM_ONLY_DUPLICATES);
      if (st != HAM_SUCCESS) {
        /* reached end of the database? */
        if (st == HAM_KEY_NOT_FOUND)
          break;
        else
          error("ham_cursor_next(c2o)", st);
      }
    } while (1);
  }

  /*
   * Now close the Environment handle; the flag
   * HAM_AUTO_CLEANUP will automatically close all Databases and
   * Cursors
   */
  st = ham_env_close(env, HAM_AUTO_CLEANUP);
  if (st != HAM_SUCCESS)
    error("ham_env_close", st);

  printf("success!\n");
  return (0);
}
Esempio n. 11
0
File: db3.c Progetto: ziposoft/ac1
int
main(int argc, char **argv) {
  ham_status_t st;    /* status variable */
  ham_env_t *env;     /* hamsterdb environment object */
  ham_db_t *db;     /* hamsterdb database object */
  ham_cursor_t *cursor; /* a database cursor */
  char line[1024 * 4];  /* a buffer for reading lines */
  ham_key_t key;
  ham_record_t record;

  memset(&key, 0, sizeof(key));
  memset(&record, 0, sizeof(record));

  printf("This sample uses hamsterdb to sort data.\n");
  printf("Reading from stdin...\n");

  /*
   * Create a new hamsterdb Environment.
   * We could create an In-Memory-Environment to speed up the sorting.
   */
  st = ham_env_create(&env, "test.db", 0, 0664, 0);
  if (st != HAM_SUCCESS) {
    printf("ham_env_create() failed with error %d\n", st);
    return (-1);
  }

  st = ham_env_create_db(env, &db, DATABASE_NAME,
          HAM_ENABLE_EXTENDED_KEYS | HAM_ENABLE_DUPLICATES, 0);
  if (st != HAM_SUCCESS) {
    printf("ham_env_create_db() failed with error %d\n", st);
    return (-1);
  }

  /*
   * Since we use strings as our database keys we use our own comparison
   * function based on strcmp instead of the default memcmp function.
   */
  st = ham_db_set_compare_func(db, my_string_compare);
  if (st) {
    printf("ham_set_compare_func() failed with error %d\n", st);
    return (-1);
  }

  /*
   * Now read each line from stdin and split it in words; then each
   * word is inserted into the database
   */
  while (fgets(line, sizeof(line), stdin)) {
    char *start = line, *p;

    /*
     * strtok is not the best function because it's not threadsafe
     * and not flexible, but it's good enough for this example.
     */
    while ((p = strtok(start, " \t\r\n"))) {
      key.data = p;
      key.size = (ham_size_t)strlen(p) + 1; /* also store the terminating
                           * 0-byte */

      st = ham_db_insert(db, 0, &key, &record, 0);
      if (st != HAM_SUCCESS && st!=HAM_DUPLICATE_KEY) {
        printf("ham_db_insert() failed with error %d\n", st);
        return (-1);
      }
      printf(".");

      start = 0;
    }
  }

  /* create a cursor */
  st = ham_cursor_create(&cursor, db, 0, 0);
  if (st != HAM_SUCCESS) {
    printf("ham_cursor_create() failed with error %d\n", st);
    return (-1);
  }

  /* iterate over all items with HAM_CURSOR_NEXT, and print the words */
  while (1) {
    st = ham_cursor_move(cursor, &key, &record, HAM_CURSOR_NEXT);
    if (st != HAM_SUCCESS) {
      /* reached end of the database? */
      if (st == HAM_KEY_NOT_FOUND)
        break;
      else {
        printf("ham_cursor_next() failed with error %d\n", st);
        return (-1);
      }
    }

    /* print the word */
    printf("%s\n", (const char *)key.data);
  }

  /*
   * Then close the handles; the flag HAM_AUTO_CLEANUP will automatically
   * close all database and cursors, and we do not need to call
   * ham_cursor_close and ham_db_close
   */
  st = ham_env_close(env, HAM_AUTO_CLEANUP);
  if (st != HAM_SUCCESS) {
    printf("ham_env_close() failed with error %d\n", st);
    return (-1);
  }

  /* success! */
  return (0);
}