// returns index of player who takes trick void DBConverter::addPassoutTurn(Suit moveSuit, vector<CardsSet>& hands, int& firstPlayer, const vector<Card>& moves, int turnNumber, vector<DBSet>& dbCandidates, CardsSet& utilizedCards) { int nextFirstPlayer = firstPlayer; Card currentMax = moves[firstPlayer]; for( int i = 0; i < NumOfPlayers; i++ ) { // Hand index of move #i int handIndex = (firstPlayer + i) % NumOfPlayers; // Adding move information to set CheckError(IsSetContainsCard(hands[handIndex], moves[handIndex]), "Wrong layout"); GetLog() << "Move suit: " << GetCardSuit(moves[firstPlayer+i]) << endl; dbCandidates.push_back(DBSet(utilizedCards, hands[handIndex], moves[firstPlayer], moves[(firstPlayer + 1) % NumOfPlayers], moves[(firstPlayer + 2) % NumOfPlayers], i)); // Updating current game state. hands[handIndex] = RemoveCardFromSet(hands[handIndex], moves[handIndex]); utilizedCards = AddCardToSet(utilizedCards, moves[handIndex]); if( IsGreaterCard(moves[handIndex], currentMax, moveSuit, SuitNoTrump) ) { currentMax = moves[handIndex]; nextFirstPlayer = handIndex; } } // According to Sochi and Leningrad rules first hand is first player until all widow cards opened if( turnNumber <= 2 ) { firstPlayer = nextFirstPlayer; } }
uint8_t XTDBInsert(XTDBHandle* handle,bson* newVal) { _S_FN(insert); handle->gen++; bson_oid_t oid; bson_oid_gen(&oid); BinaryStr key,val; uint8_t ret; bson copyObj; handle->lastOp = XTDB_OP_INSERT; key.data = oid.bytes; key.len = sizeof(oid.bytes); if (bson_copy(©Obj,newVal)) { handle->error = XTDB_INVALID_BSON; return False; } bson_unfinish_object(©Obj); if (bson_append_oid(©Obj,"_id",&oid)) { handle->error = XTDB_NO_MEM; bson_destroy(©Obj); return False; } if (bson_finish(©Obj)) { handle->error = XTDB_NO_MEM; bson_destroy(©Obj); return False; } //bson_print(©Obj); BsonToBStr(©Obj,&val); if (XTDBInsertToIndex(handle,&key,&val) == False) { assert(0); return False; } ret = DBSet(handle->mainDB,&key,&val,False); _E_FN(insert); if (!ret) { handle->error = DBGetLastError(handle->mainDB); } else { memcpy(&handle->status.insertStatus.newOid,&oid,sizeof(oid)); } return ret; }
// XXX revisit after DB eror uint8_t XTDBCreateIndex(XTDBHandle* handle,char* fieldName) { String idxDBName; String descKey; bson idxDesc; BinaryStr key,value,data; DataBaseBE* db; int rc; StrInit(&descKey); if(StrAppendFmt(&descKey,"index.value.%s",fieldName)) { handle->error = XTDB_NO_MEM; return False; } StrToBStr(descKey.ptr,&key); if (DBGet(handle->descDB,&key,&value)) { // Index already exists printf("Index already exists.\n"); StrFree(&descKey); BinaryStrFree(&value); handle->error= XTDB_INDEX_EXISTS; return False; } bson_init(&idxDesc); if (bson_append_string(&idxDesc,"name",fieldName)) { handle->error = XTDB_NO_MEM; bson_destroy(&idxDesc); StrFree(&descKey); return False; } if (bson_finish(&idxDesc)) { handle->error = XTDB_NO_MEM; bson_destroy(&idxDesc); StrFree(&descKey); return False; } BsonToBStr(&idxDesc,&value); if (!DBSet(handle->descDB,&key,&value,False)) { printf("Error Adding to index names list\n"); handle->error = DBGetLastError(handle->descDB); bson_destroy(&idxDesc); StrFree(&descKey); return False; } StrFree(&descKey); StrToBStr(IDXFIELDNAME,&key); StrToBStr(fieldName,&value); if (!DBSet(handle->descDB,&key,&value,True)) { //printf("Error Adding to index names list\n"); handle->error = DBGetLastError(handle->descDB); //handle->error = XTDB_IO_ERR; bson_destroy(&idxDesc); return False; } bson_destroy(&idxDesc); if (GetIndexDBName(handle,fieldName,&idxDBName)) { handle->error = XTDB_NO_MEM; return False; } db = DBInit(STR(&idxDBName),BDBOWRITER | BDBOCREAT); StrFree(&idxDBName); if (!db) { handle->error = XTDB_NO_MEM; return False; } rc = DBOpen(db,BDBOCREAT|BDBOWRITER); if (!rc) { handle->error = DBGetLastError(db); DBFree(db); return False; } DBClose(db); DBFree(db); if (!XTDBAddIndex(handle,fieldName)) { // AddIndex failed return printf("Error Adding to index names list\n"); return False; } assert(XTDBGetIndex(handle,fieldName)); void* iter = DBIter(handle->mainDB); while (DBIterCur(handle->mainDB,iter,&key,&data)) { //printf("Adding value to index\n"); bson obj; BStrToBson(&data,&obj); if (!XTDBInsertToIndex(handle,&key,&data)) { return False; } BinaryStrFree(&key); BinaryStrFree(&data); DBIterNext(handle->mainDB,iter); } DBIterFree(handle->mainDB,iter); return True; }
// XXX revisit after db return values uint8_t XTDBUpdateIndexIter(XTDBHandle* handle,const char* indexName,DataBaseBE* db,void* voidArgs) { XTDBUpdateIndexArgs * args = voidArgs; bson_type oldType, newType; bson oldBsonVal,newBsonVal; BinaryStr out1,out2; BSONElem qVal; uint8_t ret; handle->error = XTDB_OK; oldType = bson_find(&args->oldItr,&args->oldBson,indexName); newType = bson_find(&args->newItr,&args->newBson,indexName); if (!oldType && !newType) { // nothing to update return True; } if (!newType && oldType) { // new bson value does not have indexed field remove and return BSONElemInitFromItr(&qVal,&args->newItr); if (ConvertToBStr(&qVal,&newBsonVal)) { handle->error = XTDB_NO_MEM; } BsonToBStr(&newBsonVal,&out1); // XXX what are the reasons db delete can fail ? ret = DBDeleteKeyVal(db,&out1,&args->key); bson_destroy(&newBsonVal); if (ret) { return True; } handle->error = DBGetLastError(db); return False; } // Both old and new values have this field BSONElemInitFromItr(&qVal,&args->oldItr); if (ConvertToBStr(&qVal,&oldBsonVal)) { handle->error = XTDB_NO_MEM; } BsonToBStr(&oldBsonVal,&out1); BSONElemInitFromItr(&qVal,&args->newItr); if (ConvertToBStr(&qVal,&newBsonVal)) { handle->error = XTDB_NO_MEM; } BsonToBStr(&newBsonVal,&out2); if (BStrEqual(&out1,&out2)) { ret = True; goto freeBson; } ret = DBDeleteKeyVal(db,&out1,&args->key); if (!ret) { handle->error = DBGetLastError(db); goto freeBson; } ret = DBSet(db,&out2,&args->key,True); if (!ret) { handle->error = DBGetLastError(db); goto freeBson; } freeBson: bson_destroy(&oldBsonVal); bson_destroy(&newBsonVal); return ret; }
// Checked uint8_t XTDBInsertToIndex(XTDBHandle* handle,BinaryStr* key,BinaryStr* data) { bson_oid_t oid; bson_iterator q; bson_type qType; uint8_t ret = True; _S_FN(indexInsert); if (!tcmaprnum(handle->indexes)) { _E_FN(indexInsert); return True; } bson_iterator_from_buffer(&q, data->data); while((qType = bson_iterator_next(&q))) { const char* keyVal = bson_iterator_key(&q); //printf("keyval %s\n",keyVal); DataBaseBE* db; BSONElem qVal; BSONElemInitFromItr(&qVal,&q); db = XTDBGetIndex(handle,keyVal); if (db) { bson outBson; BinaryStr out; if (qType == BSON_ARRAY) { assert(0); bson_iterator si; bson_type t; bson_iterator_subiterator(&q,&si); while ((t=bson_iterator_next(&si))) { if (ConvertToBStr(&qVal,&outBson)) { handle->error = XTDB_NO_MEM; return False; } BsonToBStr(&outBson,&out); ret = DBSet(db,&out,key,True); bson_destroy(&outBson); if (ret) { handle->error = XTDB_IO_ERR; goto error; } } } else { if (ConvertToBStr(&qVal,&outBson)) { handle->error = XTDB_NO_MEM; return False; } BsonToBStr(&outBson,&out); ret = DBSet(db,&out,key,True); bson_destroy(&outBson); if (!ret) { handle->error = XTDB_IO_ERR; goto error; } } } } _E_FN(indexInsert); return ret; error: // roll back is required? // can simply return error unnecessarily inserted elements will be eventually corrected when index is accessed return ret; //return DBSet(handle->mainDB,&key,&val,False); }
uint8_t XTDBUpdate(XTDBHandle* handle,bson* query,bson* newVal,uint8_t upsert) { XTDBCursor* cur ; BinaryStr key,value,newValueStr; uint8_t updated = False,ret=True; int nUpdated = 0; bson_oid_t oid; bson withOid; int isMod; XTDBUpdateStatus status; status.upserted = False; _S_FN(update); handle->lastOp = XTDB_OP_UPDATE; if (!(cur = XTDBFind(handle,query))) { return False; } BsonToBStr(newVal,&newValueStr); if ((handle->error = ObjModValidateValBson(newVal,&isMod))) { return False; } while (XTDBCursorNextBStr(cur,&key,&value)) { handle->gen++; //updated = True; // retain the oid with new object if (!isMod) { memcpy(oid.bytes,key.data,sizeof(oid.bytes)); if(!XTDBBsonAppendOid(handle,newVal,&withOid,&oid)) { return False; } } else { bson obj; bson error; bson outObj; BStrToBson(&value,&obj); handle->error = ObjModifyBson(&obj,newVal,&withOid,&error); if (handle->error) { bson_iterator itr; bson_iterator_init(&itr,&error); bson_find(&itr,&error,"error"); strncpy(handle->errorString,bson_iterator_string(&itr),sizeof(handle->errorString)); bson_destroy(&error); return False; } } BsonToBStr(&withOid,&newValueStr); // Remove entry from index and re-insert if (!XTDBUpdateIndex(handle,&key,&newValueStr,&value)) { XTDBCursorFree(cur); BinaryStrFree(&key); BinaryStrFree(&value); bson_destroy(&withOid); return False; } //XTDBInsertToIndex(handle,&key,&newValueStr); //XTDBRemoveFromIndex(handle,&key,&value); if (!DBSet(handle->mainDB,&key,&newValueStr,False)) { XTDBCursorFree(cur); BinaryStrFree(&key); BinaryStrFree(&value); bson_destroy(&withOid); handle->error = DBGetLastError(handle->mainDB); return False; } BinaryStrFree(&key); BinaryStrFree(&value); bson_destroy(&withOid); nUpdated++; } if (cur->error != XTDB_OK) { handle->error = cur->error; return False; } if ( !nUpdated && upsert) { ret = XTDBInsert(handle,newVal); memcpy(&status.newOid,&handle->status.insertStatus.newOid,sizeof(status.newOid)); status.upserted = True; nUpdated = 1; } status.nUpdated = nUpdated; handle->lastOp = XTDB_OP_UPDATE; handle->status.updateStatus = status; XTDBCursorFree(cur); _E_FN(update); return ret; }