Esempio n. 1
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}