1
0
Fork 0

added _dropDatabase()

This commit is contained in:
Jan Steemann 2013-09-02 18:04:19 +02:00
parent 05a88d3477
commit bae9f097fc
12 changed files with 424 additions and 92 deletions

View File

@ -1346,7 +1346,7 @@ void ArangoServer::openDatabases () {
void ArangoServer::closeDatabases () {
TRI_CleanupActions();
TRI_DestroyVocBase(_vocbase);
TRI_DestroyVocBase(_vocbase, 0);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, _vocbase);
_vocbase = 0;

View File

@ -138,8 +138,9 @@ void VocbaseManager::closeUserVocbases () {
std::map<std::string, TRI_vocbase_t*>::iterator i = _vocbases.begin();
for (; i != _vocbases.end(); ++i) {
TRI_vocbase_t* vocbase = i->second;
TRI_DestroyVocBase(vocbase);
TRI_vocbase_t* vocbase = (*i).second;
TRI_DestroyVocBase(vocbase, 0);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, vocbase);
}
@ -147,7 +148,7 @@ void VocbaseManager::closeUserVocbases () {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief look vocbase by name
/// @brief look up vocbase by name
////////////////////////////////////////////////////////////////////////////////
TRI_vocbase_t* VocbaseManager::lookupVocbaseByName (string const& name) {
@ -219,6 +220,53 @@ bool VocbaseManager::isValidName (std::string const& name) const {
return TRI_IsAllowedCollectionName(false, name.c_str());
}
////////////////////////////////////////////////////////////////////////////////
/// @brief remove a vocbase by name
////////////////////////////////////////////////////////////////////////////////
int VocbaseManager::deleteVocbase (string const& name) {
if (name == TRI_VOC_SYSTEM_DATABASE) {
// cannot delete _system database
return TRI_ERROR_FORBIDDEN;
}
TRI_vocbase_t* vocbase = 0;
{
WRITE_LOCKER(_rwLock);
map<string, TRI_vocbase_s*>::iterator find = _vocbases.find(name);
if (find == _vocbases.end()) {
// database does not exist
return TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND;
}
// ok, we found it
vocbase = (*find).second;
// remove from the list
_vocbases.erase(name);
}
assert(vocbase != 0);
const string path = string(vocbase->_path);
LOGGER_INFO("removing database '" << name << "', path '" << path << "'");
// destroy the vocbase, but not its collections
// there might be JavaScript objects referencing the collections somehow,
// so we must not free them yet
// putting the collections in this vector will allow us freeing them later
TRI_DestroyVocBase(vocbase, _freeCollections);
// same for the vocbase
_freeVocbases.push_back(vocbase);
// ok, now delete the data in the file system
int res = TRI_RemoveDirectory(path.c_str());
return res;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief run version check
/// @return bool returns false if the version check fails

View File

@ -40,9 +40,12 @@
#include "VocBase/vocbase.h"
#include <map>
#include <string>
#include <vector>
#include "v8.h"
struct TRI_vector_pointer_s;
namespace triagens {
namespace rest {
class ApplicationEndpointServer;
@ -79,9 +82,31 @@ namespace triagens {
_rwLock(),
_authCache(),
_startupLoader(0),
_endpointServer(0) {
_endpointServer(0),
_freeCollections(0),
_freeVocbases() {
// allocate some space for collection pointers that we need to remove later
_freeCollections = (TRI_vector_pointer_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_vector_pointer_t), false);
if (_freeCollections != 0) {
TRI_InitVectorPointer(_freeCollections, TRI_UNKNOWN_MEM_ZONE);
}
};
~VocbaseManager () {
// if we have buffered some collections, we must now free them
if (_freeCollections != 0) {
TRI_FreeCollectionsVocBase(_freeCollections);
TRI_FreeVectorPointer(TRI_UNKNOWN_MEM_ZONE, _freeCollections);
}
// on shutdown, we'll free all vocbases we had collected
for (size_t i = 0; i < _freeVocbases.size(); ++i) {
TRI_Free(TRI_UNKNOWN_MEM_ZONE, _freeVocbases[i]);
}
}
VocbaseManager (const VocbaseManager&);
VocbaseManager& operator= (const VocbaseManager&);
@ -158,6 +183,12 @@ namespace triagens {
bool isValidName (std::string const&) const;
////////////////////////////////////////////////////////////////////////////////
/// @brief remove a vocbase by name
////////////////////////////////////////////////////////////////////////////////
int deleteVocbase (string const&);
////////////////////////////////////////////////////////////////////////////////
/// @brief add the startup loader
////////////////////////////////////////////////////////////////////////////////
@ -310,6 +341,18 @@ namespace triagens {
////////////////////////////////////////////////////////////////////////////////
triagens::rest::ApplicationEndpointServer* _endpointServer;
////////////////////////////////////////////////////////////////////////////////
/// @brief a vector of collections that we own and must free at the end
////////////////////////////////////////////////////////////////////////////////
struct TRI_vector_pointer_s* _freeCollections;
////////////////////////////////////////////////////////////////////////////////
/// @brief a vector of vocbases that we own and must free at the end
////////////////////////////////////////////////////////////////////////////////
std::vector<TRI_vocbase_s*> _freeVocbases;
};
}

View File

@ -843,19 +843,6 @@ static v8::Handle<v8::Value> EnsureFulltextIndex (v8::Arguments const& argv,
return scope.Close(index);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief extracts a vocbase from a javascript object
////////////////////////////////////////////////////////////////////////////////
static TRI_vocbase_t* UnwrapVocBase (v8::Handle<v8::Object> vocbaseObject) {
if (false) {
return TRI_UnwrapClass<TRI_vocbase_t>(vocbaseObject, WRP_VOCBASE_TYPE);
}
else {
return GetContextVocBase();
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief looks up a document and returns it
////////////////////////////////////////////////////////////////////////////////
@ -888,7 +875,7 @@ static v8::Handle<v8::Value> DocumentVocbaseCol (const bool useCollection,
}
else {
// called as db._document()
vocbase = UnwrapVocBase(argv.Holder());
vocbase = GetContextVocBase();
}
assert(vocbase);
@ -994,7 +981,7 @@ static v8::Handle<v8::Value> ExistsVocbaseCol (const bool useCollection,
}
else {
// called as db._exists()
vocbase = UnwrapVocBase(argv.Holder());
vocbase = GetContextVocBase();
}
assert(vocbase);
@ -1097,8 +1084,7 @@ static v8::Handle<v8::Value> ReplaceVocbaseCol (const bool useCollection,
}
else {
// called as db._replace()
//vocbase = TRI_UnwrapClass<TRI_vocbase_t>(argv.Holder(), WRP_VOCBASE_TYPE);
vocbase = UnwrapVocBase(argv.Holder());
vocbase = GetContextVocBase();
}
assert(vocbase);
@ -1396,8 +1382,7 @@ static v8::Handle<v8::Value> UpdateVocbaseCol (const bool useCollection,
}
else {
// called as db._update()
//vocbase = TRI_UnwrapClass<TRI_vocbase_t>(argv.Holder(), WRP_VOCBASE_TYPE);
vocbase = UnwrapVocBase(argv.Holder());
vocbase = GetContextVocBase();
}
assert(vocbase);
@ -1517,7 +1502,7 @@ static v8::Handle<v8::Value> RemoveVocbaseCol (const bool useCollection,
}
else {
// called as db._remove()
vocbase = UnwrapVocBase(argv.Holder());
vocbase = GetContextVocBase();
}
assert(vocbase);
@ -1565,8 +1550,7 @@ static v8::Handle<v8::Value> RemoveVocbaseCol (const bool useCollection,
static v8::Handle<v8::Value> CreateVocBase (v8::Arguments const& argv, TRI_col_type_e collectionType) {
v8::HandleScope scope;
//TRI_vocbase_t* vocbase = TRI_UnwrapClass<TRI_vocbase_t>(argv.Holder(), WRP_VOCBASE_TYPE);
TRI_vocbase_t* vocbase = UnwrapVocBase(argv.Holder());
TRI_vocbase_t* vocbase = GetContextVocBase();
if (vocbase == 0) {
TRI_V8_EXCEPTION_INTERNAL(scope, "cannot extract vocbase");
@ -4555,7 +4539,7 @@ static v8::Handle<v8::Value> JS_CountVocbaseCol (v8::Arguments const& argv) {
int res = trx.begin();
if (res != TRI_ERROR_NO_ERROR) {
TRI_V8_EXCEPTION_MESSAGE(scope, res, "cannot count documents");
TRI_V8_EXCEPTION(scope, res);
}
TRI_primary_collection_t* primary = trx.primaryCollection();
@ -5895,6 +5879,7 @@ static v8::Handle<v8::Value> JS_NameVocbaseCol (v8::Arguments const& argv) {
// if we wouldn't do this, we would risk other threads modifying the name while
// we're reading it
char* name = TRI_GetCollectionNameByIdVocBase(collection->_vocbase, collection->_cid);
if (name == 0) {
return scope.Close(v8::Undefined());
}
@ -6919,8 +6904,7 @@ static v8::Handle<v8::Value> MapGetVocBase (v8::Local<v8::String> name,
v8::HandleScope scope;
v8::Handle<v8::Object> holder = info.Holder()->ToObject();
//TRI_vocbase_t* vocbase = TRI_UnwrapClass<TRI_vocbase_t>(holder, WRP_VOCBASE_TYPE);
TRI_vocbase_t* vocbase = UnwrapVocBase(holder);
TRI_vocbase_t* vocbase = GetContextVocBase();
if (vocbase == 0) {
TRI_V8_EXCEPTION_INTERNAL(scope, "cannot extract vocbase");
@ -7027,7 +7011,7 @@ static v8::Handle<v8::Value> MapGetVocBase (v8::Local<v8::String> name,
static v8::Handle<v8::Value> JS_CollectionVocbase (v8::Arguments const& argv) {
v8::HandleScope scope;
TRI_vocbase_t* vocbase = UnwrapVocBase(argv.Holder());
TRI_vocbase_t* vocbase = GetContextVocBase();
if (vocbase == 0) {
TRI_V8_EXCEPTION_INTERNAL(scope, "cannot extract vocbase");
@ -7081,8 +7065,7 @@ static v8::Handle<v8::Value> JS_CollectionVocbase (v8::Arguments const& argv) {
static v8::Handle<v8::Value> JS_CollectionsVocbase (v8::Arguments const& argv) {
v8::HandleScope scope;
//TRI_vocbase_t* vocbase = TRI_UnwrapClass<TRI_vocbase_t>(argv.Holder(), WRP_VOCBASE_TYPE);
TRI_vocbase_t* vocbase = UnwrapVocBase(argv.Holder());
TRI_vocbase_t* vocbase = GetContextVocBase();
if (vocbase == 0) {
TRI_V8_EXCEPTION_INTERNAL(scope, "cannot extract vocbase");
@ -7091,10 +7074,10 @@ static v8::Handle<v8::Value> JS_CollectionsVocbase (v8::Arguments const& argv) {
TRI_vector_pointer_t colls = TRI_CollectionsVocBase(vocbase);
bool error = false;
uint32_t n = (uint32_t) colls._length;
// already create an array of the correct size
v8::Handle<v8::Array> result = v8::Array::New(n);
v8::Handle<v8::Array> result = v8::Array::New();
uint32_t n = (uint32_t) colls._length;
for (uint32_t i = 0; i < n; ++i) {
TRI_vocbase_col_t const* collection = (TRI_vocbase_col_t const*) colls._buffer[i];
@ -7104,7 +7087,7 @@ static v8::Handle<v8::Value> JS_CollectionsVocbase (v8::Arguments const& argv) {
error = true;
break;
}
result->Set(i, c);
}
@ -7124,8 +7107,7 @@ static v8::Handle<v8::Value> JS_CollectionsVocbase (v8::Arguments const& argv) {
static v8::Handle<v8::Value> JS_CompletionsVocbase (v8::Arguments const& argv) {
v8::HandleScope scope;
// TRI_vocbase_t* vocbase = TRI_UnwrapClass<TRI_vocbase_t>(argv.Holder(), WRP_VOCBASE_TYPE);
TRI_vocbase_t* vocbase = UnwrapVocBase(argv.Holder());
TRI_vocbase_t* vocbase = GetContextVocBase();
if (vocbase == 0) {
return scope.Close(v8::Array::New());
@ -7158,20 +7140,24 @@ static v8::Handle<v8::Value> JS_CompletionsVocbase (v8::Arguments const& argv) {
result->Set(j++, v8::String::New("_collection()"));
result->Set(j++, v8::String::New("_collections()"));
result->Set(j++, v8::String::New("_create()"));
result->Set(j++, v8::String::New("_createDatabase()"));
result->Set(j++, v8::String::New("_createDocumentCollection()"));
result->Set(j++, v8::String::New("_createEdgeCollection()"));
result->Set(j++, v8::String::New("_createStatement()"));
result->Set(j++, v8::String::New("_document()"));
result->Set(j++, v8::String::New("_drop()"));
result->Set(j++, v8::String::New("_dropDatabase()"));
result->Set(j++, v8::String::New("_executeTransaction()"));
result->Set(j++, v8::String::New("_exists()"));
result->Set(j++, v8::String::New("_isSystem()"));
result->Set(j++, v8::String::New("_listDatabases()"));
result->Set(j++, v8::String::New("_name()"));
result->Set(j++, v8::String::New("_path()"));
result->Set(j++, v8::String::New("_query()"));
result->Set(j++, v8::String::New("_remove()"));
result->Set(j++, v8::String::New("_replace()"));
result->Set(j++, v8::String::New("_update()"));
result->Set(j++, v8::String::New("_useDatabase()"));
result->Set(j++, v8::String::New("_version()"));
return scope.Close(result);
@ -7552,7 +7538,7 @@ static v8::Handle<v8::Value> JS_VersionVocbase (v8::Arguments const& argv) {
static v8::Handle<v8::Value> JS_PathVocbase (v8::Arguments const& argv) {
v8::HandleScope scope;
TRI_vocbase_t* vocbase = UnwrapVocBase(argv.Holder());
TRI_vocbase_t* vocbase = GetContextVocBase();
return scope.Close(v8::String::New(vocbase->_path));
}
@ -7568,7 +7554,7 @@ static v8::Handle<v8::Value> JS_PathVocbase (v8::Arguments const& argv) {
static v8::Handle<v8::Value> JS_NameVocbase (v8::Arguments const& argv) {
v8::HandleScope scope;
TRI_vocbase_t* vocbase = UnwrapVocBase(argv.Holder());
TRI_vocbase_t* vocbase = GetContextVocBase();
return scope.Close(v8::String::New(vocbase->_name));
}
@ -7584,7 +7570,7 @@ static v8::Handle<v8::Value> JS_NameVocbase (v8::Arguments const& argv) {
static v8::Handle<v8::Value> JS_IsSystemVocbase (v8::Arguments const& argv) {
v8::HandleScope scope;
TRI_vocbase_t* vocbase = UnwrapVocBase(argv.Holder());
TRI_vocbase_t* vocbase = GetContextVocBase();
return scope.Close(v8::Boolean::New(vocbase->_isSystem));
}
@ -7708,14 +7694,14 @@ static v8::Handle<v8::Value> saveToCollection (TRI_vocbase_t* vocbase,
res = trx.finish(res);
if (res != TRI_ERROR_NO_ERROR) {
TRI_V8_EXCEPTION_MESSAGE(scope, res, "cannot save document");
TRI_V8_EXCEPTION(scope, res);
}
// return OK
return scope.Close(result);
}
TRI_V8_EXCEPTION_MESSAGE(scope, res, "cannot save document into collection");
TRI_V8_EXCEPTION(scope, res);
}
////////////////////////////////////////////////////////////////////////////////
@ -7733,7 +7719,11 @@ static v8::Handle<v8::Value> JS_CreateUserVocbase (v8::Arguments const& argv) {
TRI_V8_EXCEPTION_USAGE(scope, "CREATE_DATABASE(<name>, <path>, <options>)");
}
TRI_vocbase_t* vocbase = UnwrapVocBase(argv.Holder());
TRI_vocbase_t* vocbase = GetContextVocBase();
if (vocbase == 0) {
TRI_V8_EXCEPTION_INTERNAL(scope, "cannot extract vocbase");
}
if (! vocbase->_isSystem) {
TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_USE_SYSTEM_DATABASE);
@ -7827,7 +7817,7 @@ static v8::Handle<v8::Value> JS_CreateUserVocbase (v8::Arguments const& argv) {
if (! vocbaseOk) {
VocbaseManager::manager.unlockCreation();
// unload vocbase
TRI_DestroyVocBase(userVocbase);
TRI_DestroyVocBase(userVocbase, 0);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, userVocbase);
userVocbase = 0;
@ -7869,7 +7859,7 @@ static v8::Handle<v8::Value> JS_CreateUserVocbase (v8::Arguments const& argv) {
VocbaseManager::manager.unlockCreation();
// unload vocbase
TRI_DestroyVocBase(userVocbase);
TRI_DestroyVocBase(userVocbase, 0);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, userVocbase);
userVocbase = 0;
@ -7882,6 +7872,73 @@ static v8::Handle<v8::Value> JS_CreateUserVocbase (v8::Arguments const& argv) {
return scope.Close(result);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief delete an existing database
///
/// @FUN{DELETE_DATABASE}
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_DeleteUserVocbase (v8::Arguments const& argv) {
v8::HandleScope scope;
if (argv.Length() != 1) {
TRI_V8_EXCEPTION_USAGE(scope, "DELETE_DATABASE(<name>)");
}
TRI_vocbase_t* vocbase = GetContextVocBase();
if (vocbase == 0) {
TRI_V8_EXCEPTION_INTERNAL(scope, "cannot extract vocbase");
}
if (! vocbase->_isSystem) {
TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_USE_SYSTEM_DATABASE);
}
const string name = TRI_ObjectToString(argv[0]);
// exclusive lock start
// ---------------------------------------------------------
VocbaseManager::manager.lockCreation();
int res = VocbaseManager::manager.deleteVocbase(name);
if (res == TRI_ERROR_NO_ERROR) {
TRI_vocbase_col_t* col = TRI_LookupCollectionByNameVocBase(vocbase, TRI_COL_NAME_DATABASES);
if (col == 0) {
VocbaseManager::manager.unlockCreation();
TRI_V8_EXCEPTION_INTERNAL(scope, "cannot extract collection");
}
CollectionNameResolver resolver(col->_vocbase);
SingleCollectionWriteTransaction<EmbeddableTransaction<V8TransactionContext>, 1> trx(col->_vocbase, resolver, col->_cid);
res = trx.begin();
if (res != TRI_ERROR_NO_ERROR) {
VocbaseManager::manager.unlockCreation();
TRI_V8_EXCEPTION(scope, res);
}
trx.deleteDocument(name.c_str(), TRI_DOC_UPDATE_LAST_WRITE, false, 0, 0);
res = trx.finish(res);
}
VocbaseManager::manager.unlockCreation();
// exclusive lock end
// ---------------------------------------------------------
if (res != TRI_ERROR_NO_ERROR) {
TRI_V8_EXCEPTION(scope, res);
}
return scope.Close(v8::True());
}
////////////////////////////////////////////////////////////////////////////////
/// @brief add a new endpoint
///
@ -7897,7 +7954,11 @@ static v8::Handle<v8::Value> JS_AddEndpoint (v8::Arguments const& argv) {
TRI_V8_EXCEPTION_USAGE(scope, "ADD_ENDPOINT(<endpoint>, <names>)");
}
TRI_vocbase_t* vocbase = UnwrapVocBase(argv.Holder());
TRI_vocbase_t* vocbase = GetContextVocBase();
if (vocbase == 0) {
TRI_V8_EXCEPTION_INTERNAL(scope, "cannot extract vocbase");
}
if (! vocbase->_isSystem) {
TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_USE_SYSTEM_DATABASE);
@ -8765,13 +8826,14 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context,
TRI_AddGlobalFunctionVocbase(context, "FORMAT_DATETIME", JS_formatDatetime);
TRI_AddGlobalFunctionVocbase(context, "PARSE_DATETIME", JS_parseDatetime);
TRI_AddGlobalFunctionVocbase(context, "RELOAD_AUTH", JS_ReloadAuth);
TRI_AddGlobalFunctionVocbase(context, "TRANSACTION", JS_Transaction);
TRI_AddGlobalFunctionVocbase(context, "RELOAD_AUTH", JS_ReloadAuth, true);
TRI_AddGlobalFunctionVocbase(context, "TRANSACTION", JS_Transaction, true);
TRI_AddGlobalFunctionVocbase(context, "USE_DATABASE", JS_UseVocbase);
TRI_AddGlobalFunctionVocbase(context, "USE_DATABASE", JS_UseVocbase, true);
TRI_AddGlobalFunctionVocbase(context, "LIST_DATABASES", JS_ListVocbases, true);
TRI_AddGlobalFunctionVocbase(context, "CREATE_DATABASE", JS_CreateUserVocbase, true);
TRI_AddGlobalFunctionVocbase(context, "ADD_ENDPOINT", JS_AddEndpoint);
TRI_AddGlobalFunctionVocbase(context, "DELETE_DATABASE", JS_DeleteUserVocbase, true);
TRI_AddGlobalFunctionVocbase(context, "ADD_ENDPOINT", JS_AddEndpoint, true);
// .............................................................................
// create global variables

View File

@ -445,16 +445,6 @@ static int WriteShutdownInfo (char const* filename) {
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief free the memory associated with a collection
////////////////////////////////////////////////////////////////////////////////
static void FreeCollection (TRI_vocbase_t* vocbase, TRI_vocbase_col_t* collection) {
TRI_DestroyReadWriteLock(&collection->_lock);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, collection);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief removes a collection name from the global list of collections
///
@ -488,16 +478,20 @@ static bool UnregisterCollection (TRI_vocbase_t* vocbase,
static bool UnloadCollectionCallback (TRI_collection_t* col, void* data) {
TRI_vocbase_col_t* collection;
#if 0
TRI_vocbase_t* vocbase;
TRI_voc_cid_t cid;
#endif
TRI_document_collection_t* document;
int res;
collection = data;
TRI_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
#if 0
cid = collection->_cid;
vocbase = collection->_vocbase;
#endif
if (collection->_status != TRI_VOC_COL_STATUS_UNLOADING) {
TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(collection);
@ -550,9 +544,11 @@ static bool UnloadCollectionCallback (TRI_collection_t* col, void* data) {
collection->_status = TRI_VOC_COL_STATUS_UNLOADED;
collection->_collection = NULL;
#if 0
if (cid > 0) {
TRI_RemoveCollectionTransactionContext(vocbase->_transactionContext, cid);
}
#endif
TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(collection);
return true;
@ -562,18 +558,23 @@ static bool UnloadCollectionCallback (TRI_collection_t* col, void* data) {
/// @brief drops a collection
////////////////////////////////////////////////////////////////////////////////
static bool DropCollectionCallback (TRI_collection_t* col, void* data) {
static bool DropCollectionCallback (TRI_collection_t* col,
void* data) {
TRI_document_collection_t* document;
TRI_vocbase_col_t* collection;
TRI_vocbase_t* vocbase;
#if 0
TRI_voc_cid_t cid;
#endif
regmatch_t matches[3];
regex_t re;
int res;
size_t i;
collection = data;
#if 0
cid = 0;
#endif
#ifdef _WIN32
// .........................................................................
@ -618,7 +619,9 @@ static bool DropCollectionCallback (TRI_collection_t* col, void* data) {
return false;
}
#if 0
cid = collection->_cid;
#endif
document = (TRI_document_collection_t*) collection->_collection;
@ -737,9 +740,11 @@ static bool DropCollectionCallback (TRI_collection_t* col, void* data) {
regfree(&re);
#if 0
if (cid > 0) {
TRI_RemoveCollectionTransactionContext(vocbase->_transactionContext, cid);
}
#endif
return true;
}
@ -1137,6 +1142,10 @@ static int ScanPath (TRI_vocbase_t* vocbase,
static int LoadCollectionVocBase (TRI_vocbase_t* vocbase,
TRI_vocbase_col_t* collection) {
TRI_col_type_e type;
if (! TRI_CanUseVocBase(vocbase)) {
return TRI_ERROR_ARANGO_DATABASE_NOT_FOUND;
}
// .............................................................................
// read lock
@ -1337,6 +1346,46 @@ size_t PageSize;
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief free the memory associated with a collection
////////////////////////////////////////////////////////////////////////////////
void TRI_FreeCollectionVocBase (TRI_vocbase_col_t* collection) {
TRI_DestroyReadWriteLock(&collection->_lock);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, collection);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief free the memory associated with all collections in a vector
////////////////////////////////////////////////////////////////////////////////
void TRI_FreeCollectionsVocBase (TRI_vector_pointer_t* collections) {
size_t i, n;
n = TRI_LengthVectorPointer(collections);
for (i = 0; i < n; ++i) {
TRI_vocbase_col_t* c = TRI_AtVectorPointer(collections, i);
TRI_FreeCollectionVocBase(c);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns whether or not the vocbase can be used
////////////////////////////////////////////////////////////////////////////////
bool TRI_CanUseVocBase (TRI_vocbase_t* vocbase) {
bool canUse;
TRI_READ_LOCK_COLLECTIONS_VOCBASE(vocbase);
canUse = vocbase->_canUse;
TRI_READ_UNLOCK_COLLECTIONS_VOCBASE(vocbase);
return canUse;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks if a collection name is allowed
///
@ -1734,6 +1783,8 @@ TRI_vocbase_t* TRI_OpenVocBase (char const* path,
}
}
}
vocbase->_canUse = true;
// we are done
return vocbase;
@ -1743,14 +1794,20 @@ TRI_vocbase_t* TRI_OpenVocBase (char const* path,
/// @brief closes a database and all collections
////////////////////////////////////////////////////////////////////////////////
void TRI_DestroyVocBase (TRI_vocbase_t* vocbase) {
void TRI_DestroyVocBase (TRI_vocbase_t* vocbase,
TRI_vector_pointer_t* reuseCollections) {
TRI_vector_pointer_t collections;
size_t i;
TRI_InitVectorPointer(&collections, TRI_UNKNOWN_MEM_ZONE);
TRI_READ_LOCK_COLLECTIONS_VOCBASE(vocbase);
TRI_WRITE_LOCK_COLLECTIONS_VOCBASE(vocbase);
// cannot use this vocbase from now on
vocbase->_canUse = false;
TRI_CopyDataVectorPointer(&collections, &vocbase->_collections);
TRI_READ_UNLOCK_COLLECTIONS_VOCBASE(vocbase);
TRI_WRITE_UNLOCK_COLLECTIONS_VOCBASE(vocbase);
// from here on, the vocbase is unusable, i.e. no collections can be created/loaded etc.
// starts unloading of collections
for (i = 0; i < collections._length; ++i) {
@ -1791,14 +1848,15 @@ void TRI_DestroyVocBase (TRI_vocbase_t* vocbase) {
vocbase->_replicationLogger = NULL;
// free dead collections (already dropped but pointers still around)
for (i = 0; i < vocbase->_deadCollections._length; ++i) {
TRI_vocbase_col_t* collection;
collection = (TRI_vocbase_col_t*) vocbase->_deadCollections._buffer[i];
TRI_RemoveCollectionTransactionContext(vocbase->_transactionContext, collection->_cid);
FreeCollection(vocbase, collection);
if (vocbase->_isSystem) {
TRI_FreeCollectionVocBase(collection);
}
}
// free collections
@ -1806,8 +1864,19 @@ void TRI_DestroyVocBase (TRI_vocbase_t* vocbase) {
TRI_vocbase_col_t* collection;
collection = (TRI_vocbase_col_t*) vocbase->_collections._buffer[i];
#if 0
TRI_RemoveCollectionTransactionContext(vocbase->_transactionContext, collection->_cid);
FreeCollection(vocbase, collection);
#endif
if (reuseCollections != 0) {
// the pointer to the collection is transferred to the other vector,
// which is then responsible to free the collection later
TRI_PushBackVectorPointer(reuseCollections, collection);
}
else {
// instantly free the collection
TRI_FreeCollectionVocBase(collection);
}
}
// we are just before terminating the server. we can now write out a file with the
@ -2006,7 +2075,6 @@ TRI_json_t* TRI_InventoryCollectionsVocBase (TRI_vocbase_t* vocbase,
return json;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief gets a collection name by a collection id
///
@ -2022,6 +2090,11 @@ char* TRI_GetCollectionNameByIdVocBase (TRI_vocbase_t* vocbase,
TRI_READ_LOCK_COLLECTIONS_VOCBASE(vocbase);
if (! vocbase->_canUse) {
TRI_READ_UNLOCK_COLLECTIONS_VOCBASE(vocbase);
return NULL;
}
found = CONST_CAST(TRI_LookupByKeyAssociativePointer(&vocbase->_collectionsById, &id));
if (found == NULL) {
@ -2040,10 +2113,11 @@ char* TRI_GetCollectionNameByIdVocBase (TRI_vocbase_t* vocbase,
/// @brief looks up a (document) collection by name
////////////////////////////////////////////////////////////////////////////////
TRI_vocbase_col_t* TRI_LookupCollectionByNameVocBase (TRI_vocbase_t* vocbase, char const* name) {
TRI_vocbase_col_t* TRI_LookupCollectionByNameVocBase (TRI_vocbase_t* vocbase,
char const* name) {
TRI_vocbase_col_t* found;
const char c = *name;
// if collection name is passed as a stringified id, we'll use the lookupbyid function
// this is safe because collection names must not start with a digit
if (c >= '0' && c <= '9') {
@ -2052,7 +2126,12 @@ TRI_vocbase_col_t* TRI_LookupCollectionByNameVocBase (TRI_vocbase_t* vocbase, ch
// otherwise we'll look up the collection by name
TRI_READ_LOCK_COLLECTIONS_VOCBASE(vocbase);
found = CONST_CAST(TRI_LookupByKeyAssociativePointer(&vocbase->_collectionsByName, name));
if (vocbase->_canUse) {
found = CONST_CAST(TRI_LookupByKeyAssociativePointer(&vocbase->_collectionsByName, name));
}
else {
found = NULL;
}
TRI_READ_UNLOCK_COLLECTIONS_VOCBASE(vocbase);
return found;
@ -2064,9 +2143,14 @@ TRI_vocbase_col_t* TRI_LookupCollectionByNameVocBase (TRI_vocbase_t* vocbase, ch
TRI_vocbase_col_t* TRI_LookupCollectionByIdVocBase (TRI_vocbase_t* vocbase, TRI_voc_cid_t id) {
TRI_vocbase_col_t* found;
TRI_READ_LOCK_COLLECTIONS_VOCBASE(vocbase);
found = CONST_CAST(TRI_LookupByKeyAssociativePointer(&vocbase->_collectionsById, &id));
if (vocbase->_canUse) {
found = CONST_CAST(TRI_LookupByKeyAssociativePointer(&vocbase->_collectionsById, &id));
}
else {
found = NULL;
}
TRI_READ_UNLOCK_COLLECTIONS_VOCBASE(vocbase);
return found;
@ -2081,9 +2165,14 @@ TRI_vocbase_col_t* TRI_FindCollectionByNameOrCreateVocBase (TRI_vocbase_t* vocba
const TRI_col_type_t type,
TRI_server_id_t generatingServer) {
TRI_vocbase_col_t* found;
TRI_READ_LOCK_COLLECTIONS_VOCBASE(vocbase);
found = CONST_CAST(TRI_LookupByKeyAssociativePointer(&vocbase->_collectionsByName, name));
if (vocbase->_canUse) {
found = CONST_CAST(TRI_LookupByKeyAssociativePointer(&vocbase->_collectionsByName, name));
}
else {
found = NULL;
}
TRI_READ_UNLOCK_COLLECTIONS_VOCBASE(vocbase);
if (found != NULL) {
@ -2139,6 +2228,11 @@ TRI_vocbase_col_t* TRI_CreateCollectionVocBase (TRI_vocbase_t* vocbase,
return NULL;
}
if (! TRI_CanUseVocBase(vocbase)) {
TRI_set_errno(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
return NULL;
}
type = (TRI_col_type_e) parameter->_type;
if (! TRI_IS_DOCUMENT_COLLECTION(type)) {
@ -2307,10 +2401,14 @@ int TRI_DropCollectionVocBase (TRI_vocbase_t* vocbase,
TRI_server_id_t generatingServer) {
int res;
if (! TRI_CanUseVocBase(vocbase)) {
return TRI_set_errno(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
}
if (! collection->_canDrop) {
return TRI_set_errno(TRI_ERROR_FORBIDDEN);
}
TRI_ReadLockReadWriteLock(&vocbase->_inventoryLock);
// mark collection as deleted
@ -2451,6 +2549,10 @@ int TRI_RenameCollectionVocBase (TRI_vocbase_t* vocbase,
bool isSystem;
int res;
if (! TRI_CanUseVocBase(vocbase)) {
return TRI_set_errno(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
}
if (! collection->_canRename) {
return TRI_set_errno(TRI_ERROR_FORBIDDEN);
}

View File

@ -52,6 +52,7 @@ struct TRI_replication_applier_s;
struct TRI_replication_logger_s;
struct TRI_shadow_store_s;
struct TRI_transaction_context_s;
struct TRI_vector_pointer_s;
// -----------------------------------------------------------------------------
// --SECTION-- public macros
@ -333,6 +334,8 @@ typedef struct TRI_vocbase_s {
bool _isSystem;
bool _requireAuthentication;
bool _authenticateSystemOnly;
bool _canUse; // this is set to false during deletion of a database
char* _name; // database name
@ -460,11 +463,30 @@ TRI_vocbase_defaults_t;
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief free the memory associated with a collection
////////////////////////////////////////////////////////////////////////////////
void TRI_FreeCollectionVocBase (TRI_vocbase_col_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief free the memory associated with all collections in a vector
////////////////////////////////////////////////////////////////////////////////
void TRI_FreeCollectionsVocBase (struct TRI_vector_pointer_s*);
////////////////////////////////////////////////////////////////////////////////
/// @brief returns whether or not the vocbase can be used
////////////////////////////////////////////////////////////////////////////////
bool TRI_CanUseVocBase (TRI_vocbase_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief checks if a collection is allowed
////////////////////////////////////////////////////////////////////////////////
bool TRI_IsAllowedCollectionName (bool, char const*);
bool TRI_IsAllowedCollectionName (bool,
char const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create a new tick
@ -525,7 +547,8 @@ TRI_vocbase_t* TRI_OpenVocBase (char const*,
/// @brief closes a database and all collections
////////////////////////////////////////////////////////////////////////////////
void TRI_DestroyVocBase (TRI_vocbase_t*);
void TRI_DestroyVocBase (TRI_vocbase_t*,
struct TRI_vector_pointer_s*);
////////////////////////////////////////////////////////////////////////////////
/// @brief set the system defaults

View File

@ -82,6 +82,17 @@ function post_api_database (req, res) {
actions.resultOk(req, res, actions.HTTP_OK, { result : result });
}
function delete_api_database (req, res) {
if (req.suffix.length !== 1) {
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
return;
}
var result = arangodb.db._deleteDatabase(req.suffix[0]);
actions.resultOk(req, res, actions.HTTP_OK, { result : result });
}
////////////////////////////////////////////////////////////////////////////////
/// @brief handles a database request
////////////////////////////////////////////////////////////////////////////////
@ -98,6 +109,9 @@ actions.defineHttp({
else if (req.requestType === actions.POST) {
post_api_database(req, res);
}
else if (req.requestType === actions.DELETE) {
delete_api_database(req, res);
}
else {
actions.resultUnsupported(req, res);
}

View File

@ -130,6 +130,7 @@ ArangoCollection.TYPE_EDGE = 3;
ArangoCollection.prototype._PRINT = function (context) {
var status = "unknown";
var type = "unknown";
var name = this.name();
switch (this.status()) {
case ArangoCollection.STATUS_NEW_BORN: status = "new born"; break;
@ -154,7 +155,7 @@ ArangoCollection.prototype._PRINT = function (context) {
if (useColor) { context.output += colors.COLOR_RESET; }
context.output += ", \"";
if (useColor) { context.output += colors.COLOR_STRING; }
context.output += this.name();
context.output += name ? name : "unknown";
if (useColor) { context.output += colors.COLOR_RESET; }
context.output += "\" (type " + type + ", status " + status + ")]";
};

View File

@ -243,7 +243,7 @@ ArangoDatabase.prototype._help = function () {
////////////////////////////////////////////////////////////////////////////////
ArangoDatabase.prototype.toString = function () {
return "[object ArangoDatabase '" + this._name() + "']";
return "[object ArangoDatabase \"" + this._name() + "\"]";
};
////////////////////////////////////////////////////////////////////////////////
@ -263,9 +263,8 @@ ArangoDatabase.prototype.toString = function () {
/// @brief return all collections from the database
////////////////////////////////////////////////////////////////////////////////
ArangoDatabase.prototype._collections = function (excludeSystem) {
var append = (excludeSystem ? "?excludeSystem=true" : "");
var requestResult = this._connection.GET(this._collectionurl() + append);
ArangoDatabase.prototype._collections = function () {
var requestResult = this._connection.GET(this._collectionurl());
arangosh.checkRequestResult(requestResult);
@ -829,6 +828,22 @@ ArangoDatabase.prototype._createDatabase = function (name, path, options) {
return requestResult.result;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief drop an existing database
////////////////////////////////////////////////////////////////////////////////
ArangoDatabase.prototype._dropDatabase = function (name) {
var requestResult = this._connection.DELETE("/_api/database/" + encodeURIComponent(name));
if (requestResult !== null && requestResult.error === true) {
throw new ArangoError(requestResult);
}
arangosh.checkRequestResult(requestResult);
return requestResult.result;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief list all existing databases
////////////////////////////////////////////////////////////////////////////////

View File

@ -242,7 +242,7 @@ ArangoDatabase.prototype._help = function () {
////////////////////////////////////////////////////////////////////////////////
ArangoDatabase.prototype.toString = function () {
return "[object ArangoDatabase '" + this._name() + "']";
return "[object ArangoDatabase \"" + this._name() + "\"]";
};
////////////////////////////////////////////////////////////////////////////////
@ -262,9 +262,8 @@ ArangoDatabase.prototype.toString = function () {
/// @brief return all collections from the database
////////////////////////////////////////////////////////////////////////////////
ArangoDatabase.prototype._collections = function (excludeSystem) {
var append = (excludeSystem ? "?excludeSystem=true" : "");
var requestResult = this._connection.GET(this._collectionurl() + append);
ArangoDatabase.prototype._collections = function () {
var requestResult = this._connection.GET(this._collectionurl());
arangosh.checkRequestResult(requestResult);
@ -828,6 +827,22 @@ ArangoDatabase.prototype._createDatabase = function (name, path, options) {
return requestResult.result;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief drop an existing database
////////////////////////////////////////////////////////////////////////////////
ArangoDatabase.prototype._dropDatabase = function (name) {
var requestResult = this._connection.DELETE("/_api/database/" + encodeURIComponent(name));
if (requestResult !== null && requestResult.error === true) {
throw new ArangoError(requestResult);
}
arangosh.checkRequestResult(requestResult);
return requestResult.result;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief list all existing databases
////////////////////////////////////////////////////////////////////////////////

View File

@ -129,6 +129,7 @@ ArangoCollection.TYPE_EDGE = 3;
ArangoCollection.prototype._PRINT = function (context) {
var status = "unknown";
var type = "unknown";
var name = this.name();
switch (this.status()) {
case ArangoCollection.STATUS_NEW_BORN: status = "new born"; break;
@ -153,7 +154,7 @@ ArangoCollection.prototype._PRINT = function (context) {
if (useColor) { context.output += colors.COLOR_RESET; }
context.output += ", \"";
if (useColor) { context.output += colors.COLOR_STRING; }
context.output += this.name();
context.output += name ? name : "unknown";
if (useColor) { context.output += colors.COLOR_RESET; }
context.output += "\" (type " + type + ", status " + status + ")]";
};

View File

@ -83,7 +83,7 @@ ArangoDatabase.prototype._PRINT = function (context) {
////////////////////////////////////////////////////////////////////////////////
ArangoDatabase.prototype.toString = function(seen, path, names, level) {
return "[ArangoDatabase \"" + this._path() + "\"]";
return "[ArangoDatabase \"" + this._name() + "\"]";
};
////////////////////////////////////////////////////////////////////////////////
@ -143,6 +143,14 @@ ArangoDatabase.prototype._createDatabase = function (name, path, options) {
return CREATE_DATABASE(name, path, options);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief delete an existing database
////////////////////////////////////////////////////////////////////////////////
ArangoDatabase.prototype._dropDatabase = function (name) {
return DELETE_DATABASE(name);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief lists all existing databases
////////////////////////////////////////////////////////////////////////////////
@ -156,7 +164,7 @@ ArangoDatabase.prototype._listDatabases = function () {
////////////////////////////////////////////////////////////////////////////////
ArangoDatabase.prototype._useDatabase = function (name) {
return USE_DATABASES(name);
return USE_DATABASE(name);
}
////////////////////////////////////////////////////////////////////////////////