int Keyspace_AddStr(ClientObj client_, const std::string& key_, const std::string& num_) { Keyspace::Client* client = (Keyspace::Client *) client_; ByteString key(key_.length(), key_.length(), key_.c_str()); int64_t result; unsigned read; int64_t num; num = strntoint64(num_.c_str(), num_.length(), &read); if (read != num_.length()) return KEYSPACE_API_ERROR; return client->Add(key, num, result); }
bool ReplicatedKeyspaceDB::Execute( Transaction* transaction, uint64_t paxosID, uint64_t commandID) { #define CHECK_CMD() \ if (storedPaxosID > paxosID || \ (storedPaxosID == paxosID && storedCommandID >= commandID)) \ return true; bool ret; unsigned nread; int64_t num; uint64_t storedPaxosID, storedCommandID; ByteString userValue; ValBuffer tmp; ByteString key; ret = true; switch (msg.type) { case KEYSPACE_SET: WriteValue(wdata, paxosID, commandID, msg.value); ret &= table->Set(transaction, msg.key, wdata); wdata.Set(msg.value); break; case KEYSPACE_TEST_AND_SET: ret &= table->Get(transaction, msg.key, wdata); if (!ret) break; ReadValue(wdata, storedPaxosID, storedCommandID, userValue); CHECK_CMD(); wdata.Set(userValue); if (wdata == msg.test) { WriteValue(wdata, paxosID, commandID, msg.value); ret &= table->Set(transaction, msg.key, wdata); if (ret) wdata.Set(msg.value); } break; case KEYSPACE_ADD: // read number: ret &= table->Get(transaction, msg.key, wdata); if (!ret) break; ReadValue(wdata, storedPaxosID, storedCommandID, userValue); CHECK_CMD(); // parse number: num = strntoint64(userValue.buffer, userValue.length, &nread); if (nread == (unsigned) userValue.length) { num = num + msg.num; // print number: wdata.length = snwritef(wdata.buffer, wdata.size, "%U:%U:%I", paxosID, commandID, num); // write number: ret &= table->Set(transaction, msg.key, wdata); // data is returned to the user wdata.length = snwritef(wdata.buffer, wdata.size, "%I", num); } else ret = false; break; case KEYSPACE_RENAME: ret &= table->Get(transaction, msg.key, wdata); if (!ret) break; ReadValue(wdata, storedPaxosID, storedCommandID, userValue); CHECK_CMD(); tmp.Set(userValue); WriteValue(wdata, paxosID, commandID, tmp); ret &= table->Set(transaction, msg.newKey, wdata); if (!ret) break; ret &= table->Delete(transaction, msg.key); break; case KEYSPACE_DELETE: ret &= table->Delete(transaction, msg.key); break; case KEYSPACE_REMOVE: ret &= table->Get(transaction, msg.key, tmp); if (!ret) break; ReadValue(tmp, storedPaxosID, storedCommandID, userValue); CHECK_CMD(); wdata.Set(userValue); ret &= table->Delete(transaction, msg.key); break; case KEYSPACE_PRUNE: ret &= table->Prune(transaction, msg.prefix); break; case KEYSPACE_SET_EXPIRY: Log_Trace("Setting expiry for key: %.*s", msg.key.length, msg.key.buffer); // remove old expiry if (msg.prevExpiryTime > 0) { WriteExpiryTime(kdata, msg.prevExpiryTime, msg.key); table->Delete(transaction, kdata); } // write !!t:<expirytime>:<key> => NULL WriteExpiryTime(kdata, msg.nextExpiryTime, msg.key); rdata.Clear(); table->Set(transaction, kdata, rdata); // write !!k:<key> => <expiryTime> WriteExpiryKey(kdata, msg.key); table->Set(transaction, kdata, msg.nextExpiryTime); ret = true; break; case KEYSPACE_EXPIRE: Log_Trace("Expiring key: %.*s", msg.key.length, msg.key.buffer); // delete !!k:<key> => <expiryTime> WriteExpiryKey(kdata, msg.key); table->Delete(transaction, kdata); // delete !!t:<expirytime>:<key> => NULL WriteExpiryTime(kdata, msg.prevExpiryTime, msg.key); table->Delete(transaction, kdata); // delete actual key table->Delete(transaction, msg.key); // (*) expiryAdded = false; ret = true; break; case KEYSPACE_REMOVE_EXPIRY: // same as above except (*) is missing Log_Trace("Removing expiry for key: %.*s", msg.key.length, msg.key.buffer); // delete !!k:<key> => <expiryTime> WriteExpiryKey(kdata, msg.key); table->Delete(transaction, kdata); // delete !!t:<expirytime>:<key> => NULL WriteExpiryTime(kdata, msg.prevExpiryTime, msg.key); table->Delete(transaction, kdata); ret = true; break; case KEYSPACE_CLEAR_EXPIRIES: Log_Trace("Clearing all expiries"); kdata.Writef("!!"); table->Prune(transaction, kdata, true); ret = true; break; default: ASSERT_FAIL(); } return ret; }
bool SingleKeyspaceDB::Add(KeyspaceOp* op) { // Log_Trace(); bool isWrite; int64_t num; unsigned nread; uint64_t storedPaxosID, storedCommandID, expiryTime; ByteString userValue; isWrite = op->IsWrite(); if (isWrite && !transaction.IsActive()) { transaction.Set(table); transaction.Begin(); } op->status = true; if (op->IsWrite() && writePaxosID) { if (table->Set(&transaction, "@@paxosID", "1")) writePaxosID = false; } if (op->IsGet()) { op->value.Allocate(KEYSPACE_VAL_SIZE); op->status &= table->Get(NULL, op->key, vdata); if (op->status) { ReadValue(vdata, storedPaxosID, storedCommandID, userValue); op->value.Set(userValue); } op->service->OnComplete(op); } else if (op->IsList() || op->IsCount()) { AsyncListVisitor *alv = new AsyncListVisitor(op); MultiDatabaseOp* mdbop = new AsyncMultiDatabaseOp(); mdbop->Visit(table, *alv); dbReader.Add(mdbop); } else if (op->type == KeyspaceOp::SET) { WriteValue(vdata, 1, 0, op->value); op->status &= table->Set(&transaction, op->key, vdata); op->service->OnComplete(op); } else if (op->type == KeyspaceOp::TEST_AND_SET) { op->status &= table->Get(&transaction, op->key, vdata); if (op->status) { ReadValue(vdata, storedPaxosID, storedCommandID, userValue); if (userValue == op->test) { WriteValue(vdata, 1, 0, op->value); op->status &= table->Set(&transaction, op->key, vdata); } else op->value.Set(userValue); } op->service->OnComplete(op); } else if (op->type == KeyspaceOp::ADD) { // read number: op->status = table->Get(&transaction, op->key, vdata); if (op->status) { ReadValue(vdata, storedPaxosID, storedCommandID, userValue); // parse number: num = strntoint64(userValue.buffer, userValue.length, &nread); if (nread == (unsigned) userValue.length) { num = num + op->num; // print number: vdata.length = snwritef(vdata.buffer, vdata.size, "1:0:%I", num); // write number: op->status &= table->Set(&transaction, op->key, vdata); // returned to the user: vdata.length = snwritef(vdata.buffer, vdata.size, "%I", num); op->value.Allocate(vdata.length); op->value.Set(vdata); } else op->status = false; } op->service->OnComplete(op); } else if (op->type == KeyspaceOp::RENAME) { op->status &= table->Get(&transaction, op->key, vdata); if (op->status) { // value doesn't change op->status &= table->Set(&transaction, op->newKey, vdata); if (op->status) op->status &= table->Delete(&transaction, op->key); } op->service->OnComplete(op); } else if (op->type == KeyspaceOp::DELETE) { op->status &= table->Delete(&transaction, op->key); op->service->OnComplete(op); } else if (op->type == KeyspaceOp::REMOVE) { op->value.Allocate(KEYSPACE_VAL_SIZE); op->status &= table->Get(&transaction, op->key, vdata); if (op->status) { ReadValue(vdata, storedPaxosID, storedCommandID, userValue); op->value.Set(userValue); op->status &= table->Delete(&transaction, op->key); } op->service->OnComplete(op); } else if (op->type == KeyspaceOp::PRUNE) { op->status &= table->Prune(&transaction, op->prefix); op->service->OnComplete(op); } else if (op->type == KeyspaceOp::SET_EXPIRY) { Log_Trace("Setting expiry for key: %.*s", op->key.length, op->key.buffer); // check old expiry WriteExpiryKey(kdata, op->key); if (table->Get(&transaction, kdata, vdata)) { // this key already had an expiry expiryTime = strntouint64(vdata.buffer, vdata.length, &nread); if (nread < 1) ASSERT_FAIL(); // delete old value WriteExpiryTime(kdata, expiryTime, op->key); table->Delete(&transaction, kdata); } // write !!t:<expirytime>:<key> => NULL WriteExpiryTime(kdata, op->nextExpiryTime, op->key); op->value.Clear(); table->Set(&transaction, kdata, op->value); // write !!k:<key> => <expiryTime> WriteExpiryKey(kdata, op->key); table->Set(&transaction, kdata, op->nextExpiryTime); InitExpiryTimer(); op->status = true; op->service->OnComplete(op); } else if (op->type == KeyspaceOp::REMOVE_EXPIRY) { Log_Trace("Removing expiry for key: %.*s", op->key.length, op->key.buffer); // check old expiry WriteExpiryKey(kdata, op->key); if (table->Get(&transaction, kdata, vdata)) { // this key already had an expiry expiryTime = strntouint64(vdata.buffer, vdata.length, &nread); if (nread < 1) ASSERT_FAIL(); // delete old value WriteExpiryTime(kdata, expiryTime, op->key); table->Delete(&transaction, kdata); } WriteExpiryKey(kdata, op->key); table->Delete(&transaction, kdata); InitExpiryTimer(); op->status = true; op->service->OnComplete(op); } else if (op->type == KeyspaceOp::CLEAR_EXPIRIES) { Log_Trace("Clearing all expiries"); kdata.Writef("!!"); table->Prune(&transaction, kdata, true); InitExpiryTimer(); op->status = true; op->service->OnComplete(op); } else ASSERT_FAIL(); return true; }
bool SingleKeyspaceDB::Add(KeyspaceOp* op) { // Log_Trace(); bool isWrite; int64_t num; unsigned nread; uint64_t storedPaxosID; uint64_t storedCommandID; ByteString userValue; isWrite = op->IsWrite(); if (isWrite && !transaction.IsActive()) { transaction.Set(table); transaction.Begin(); } op->status = true; if (op->IsWrite() && writePaxosID) { if (table->Set(&transaction, "@@paxosID", "1")) writePaxosID = false; } if (op->IsGet()) { op->value.Allocate(KEYSPACE_VAL_SIZE); op->status &= table->Get(NULL, op->key, data); if (op->status) { ReadValue(data, storedPaxosID, storedCommandID, userValue); op->value.Set(userValue); } op->service->OnComplete(op); } else if (op->IsList() || op->IsCount()) { AsyncListVisitor *alv = new AsyncListVisitor(op); MultiDatabaseOp* mdbop = new AsyncMultiDatabaseOp(); mdbop->Visit(table, *alv); dbReader.Add(mdbop); } else if (op->type == KeyspaceOp::SET) { WriteValue(data, 1, 0, op->value); op->status &= table->Set(&transaction, op->key, data); op->service->OnComplete(op); } else if (op->type == KeyspaceOp::TEST_AND_SET) { op->status &= table->Get(&transaction, op->key, data); if (op->status) { ReadValue(data, storedPaxosID, storedCommandID, userValue); if (userValue == op->test) { WriteValue(data, 1, 0, op->value); op->status &= table->Set(&transaction, op->key, data); } else op->value.Set(userValue); } op->service->OnComplete(op); } else if (op->type == KeyspaceOp::ADD) { // read number: op->status = table->Get(&transaction, op->key, data); if (op->status) { ReadValue(data, storedPaxosID, storedCommandID, userValue); // parse number: num = strntoint64(userValue.buffer, userValue.length, &nread); if (nread == (unsigned) userValue.length) { num = num + op->num; // print number: data.length = snwritef(data.buffer, data.size, "1:0:%I", num); // write number: op->status &= table->Set(&transaction, op->key, data); // returned to the user: data.length = snwritef(data.buffer, data.size, "%I", num); op->value.Allocate(data.length); op->value.Set(data); } else op->status = false; } op->service->OnComplete(op); } else if (op->type == KeyspaceOp::RENAME) { op->status &= table->Get(&transaction, op->key, data); if (op->status) { // value doesn't change op->status &= table->Set(&transaction, op->newKey, data); if (op->status) op->status &= table->Delete(&transaction, op->key); } op->service->OnComplete(op); } else if (op->type == KeyspaceOp::DELETE) { op->status &= table->Delete(&transaction, op->key); op->service->OnComplete(op); } else if (op->type == KeyspaceOp::REMOVE) { op->value.Allocate(KEYSPACE_VAL_SIZE); op->status &= table->Get(&transaction, op->key, data); if (op->status) { ReadValue(data, storedPaxosID, storedCommandID, userValue); op->value.Set(userValue); op->status &= table->Delete(&transaction, op->key); } op->service->OnComplete(op); } else if (op->type == KeyspaceOp::PRUNE) { op->status &= table->Prune(&transaction, op->prefix); op->service->OnComplete(op); } else ASSERT_FAIL(); return true; }