nsresult
DOMStorageDBThread::PendingOperations::Execute(DOMStorageDBThread* aThread)
{
    // Called outside the lock

    mozStorageTransaction transaction(aThread->mWorkerConnection, false);

    nsresult rv;

    for (uint32_t i = 0; i < mExecList.Length(); ++i) {
        DOMStorageDBThread::DBOperation* task = mExecList[i];
        rv = task->Perform(aThread);
        if (NS_FAILED(rv)) {
            return rv;
        }
    }

    rv = transaction.Commit();
    if (NS_FAILED(rv)) {
        return rv;
    }

    return NS_OK;
}
void 
perform_keystate_export(int sockfd, engineconfig_type *config, const char *zone,
                        int bds)
{
	#define LOG_AND_RETURN(errmsg) do { ods_log_error_and_printf(\
		sockfd,module_str,errmsg); return; } while (0)
	#define LOG_AND_RETURN_1(errmsg,param) do { ods_log_error_and_printf(\
		sockfd,module_str,errmsg,param); return; } while (0)

	GOOGLE_PROTOBUF_VERIFY_VERSION;
    
	OrmConnRef conn;
	if (!ods_orm_connect(sockfd, config, conn))
		return; // error already reported.
	
	{	OrmTransactionRW transaction(conn);
		if (!transaction.started())
			LOG_AND_RETURN("transaction not started");

		std::string qzone;
		if (!OrmQuoteStringValue(conn, std::string(zone), qzone))
			LOG_AND_RETURN("quoting string value failed");
		
		{	OrmResultRef rows;
			::ods::keystate::EnforcerZone enfzone;
			if (!OrmMessageEnumWhere(conn,enfzone.descriptor(),
									 rows,"name = %s",qzone.c_str()))
				LOG_AND_RETURN("zone enumeration failed");
			
			if (!OrmFirst(rows)) {
				ods_printf(sockfd,"zone %s not found\n",zone);
				return;
			}
			
			OrmContextRef context;
			if (!OrmGetMessage(rows, enfzone, /*zones + keys*/true, context))
				LOG_AND_RETURN("retrieving zone from database failed");
			
			// we no longer need the query result, so release it.
			rows.release();

			// Retrieve the dnskey ttl from the policy associated with the zone.
			::ods::kasp::Policy policy;
			if (!load_kasp_policy(conn, enfzone.policy(), policy))
				LOG_AND_RETURN_1("policy %s not found",enfzone.policy().c_str());
			uint32_t dnskey_ttl = policy.keys().ttl();

			bool bSubmitChanged = false;
			bool bRetractChanged = false;
			bool bKeytagChanged = false;
			
			for (int k=0; k<enfzone.keys_size(); ++k) {
				const ::ods::keystate::KeyData &key = enfzone.keys(k);
				if (key.role()==::ods::keystate::ZSK)
					continue;
				
				if (key.ds_at_parent()!=::ods::keystate::submit
					&& key.ds_at_parent()!=::ods::keystate::submitted
					&& key.ds_at_parent()!=::ods::keystate::retract
					&& key.ds_at_parent()!=::ods::keystate::retracted
					)
					continue;
				
				std::string dnskey;
				uint16_t keytag = dnskey_from_id(dnskey,key.locator().c_str(),
												 key.role(),
												 enfzone.name().c_str(),
												 key.algorithm(),bds,
												 dnskey_ttl);
				if (keytag) {
					ods_writen(sockfd, dnskey.c_str(), dnskey.size());
					bSubmitChanged = key.ds_at_parent()==::ods::keystate::submit;
					bRetractChanged = key.ds_at_parent()==::ods::keystate::retract;
					bKeytagChanged = key.keytag()!=keytag;
					if (bSubmitChanged) {
						::ods::keystate::KeyData *kd = enfzone.mutable_keys(k);
						kd->set_ds_at_parent(::ods::keystate::submitted);
					}
					if (bRetractChanged) {
						::ods::keystate::KeyData *kd = enfzone.mutable_keys(k);
						kd->set_ds_at_parent(::ods::keystate::retracted);
					}
					if (bKeytagChanged) {
						::ods::keystate::KeyData *kd = enfzone.mutable_keys(k);
						kd->set_keytag(keytag);
					}
				} else
					LOG_AND_RETURN_1("unable to find key with id %s",
									 key.locator().c_str());
			}
    
			if (bSubmitChanged || bRetractChanged || bKeytagChanged) {
				// Update the zone recursively in the database as keystates
				// have been changed because of the export
				
				if (!OrmMessageUpdate(context))
					LOG_AND_RETURN("updating zone in the database failed");
				
				
				if (!transaction.commit())
					LOG_AND_RETURN("committing zone to the database failed");
			}
		}
	}
}
Esempio n. 3
0
    virtual bool run(OperationContext* txn,
                     const string& dbname,
                     BSONObj& cmdObj,
                     int options,
                     string& errmsg,
                     BSONObjBuilder& result,
                     bool fromRepl) {
        const std::string ns = parseNsCollectionRequired(dbname, cmdObj);
        Status allowedWriteStatus = userAllowedWriteNS(ns);
        if (!allowedWriteStatus.isOK()) {
            return appendCommandStatus(result, allowedWriteStatus);
        }

        const BSONObj query = cmdObj.getObjectField("query");
        const BSONObj fields = cmdObj.getObjectField("fields");
        const BSONObj update = cmdObj.getObjectField("update");
        const BSONObj sort = cmdObj.getObjectField("sort");

        bool upsert = cmdObj["upsert"].trueValue();
        bool returnNew = cmdObj["new"].trueValue();
        bool remove = cmdObj["remove"].trueValue();

        if (remove) {
            if (upsert) {
                errmsg = "remove and upsert can't co-exist";
                return false;
            }
            if (!update.isEmpty()) {
                errmsg = "remove and update can't co-exist";
                return false;
            }
            if (returnNew) {
                errmsg = "remove and returnNew can't co-exist";
                return false;
            }
        } else if (!cmdObj.hasField("update")) {
            errmsg = "need remove or update";
            return false;
        }

        bool ok = false;
        MONGO_WRITE_CONFLICT_RETRY_LOOP_BEGIN {
            errmsg = "";

            // We can always retry because we only ever modify one document
            ok = runImpl(txn,
                         dbname,
                         ns,
                         query,
                         fields,
                         update,
                         sort,
                         upsert,
                         returnNew,
                         remove,
                         result,
                         errmsg);
        }
        MONGO_WRITE_CONFLICT_RETRY_LOOP_END(txn, "findAndModify", ns);

        if (!ok && errmsg == "no-collection") {
            // Take X lock so we can create collection, then re-run operation.
            ScopedTransaction transaction(txn, MODE_IX);
            Lock::DBLock lk(txn->lockState(), dbname, MODE_X);
            Client::Context ctx(txn, ns, false /* don't check version */);
            if (!fromRepl &&
                !repl::getGlobalReplicationCoordinator()->canAcceptWritesForDatabase(dbname)) {
                return appendCommandStatus(result,
                                           Status(ErrorCodes::NotMaster,
                                                  str::stream()
                                                      << "Not primary while creating collection "
                                                      << ns << " during findAndModify"));
            }
            Database* db = ctx.db();
            if (db->getCollection(ns)) {
                // someone else beat us to it, that's ok
                // we might race while we unlock if someone drops
                // but that's ok, we'll just do nothing and error out
            } else {
                MONGO_WRITE_CONFLICT_RETRY_LOOP_BEGIN {
                    WriteUnitOfWork wuow(txn);
                    uassertStatusOK(userCreateNS(txn, db, ns, BSONObj(), !fromRepl));
                    wuow.commit();
                }
                MONGO_WRITE_CONFLICT_RETRY_LOOP_END(txn, "findAndModify", ns);
            }

            errmsg = "";
            ok = runImpl(txn,
                         dbname,
                         ns,
                         query,
                         fields,
                         update,
                         sort,
                         upsert,
                         returnNew,
                         remove,
                         result,
                         errmsg);
        }
Esempio n. 4
0
void FlipCommand::onExecute(Context* context)
{
  ContextWriter writer(context);
  Document* document = writer.document();
  Sprite* sprite = writer.sprite();

  {
    Transaction transaction(writer.context(),
      m_flipMask ?
      (m_flipType == doc::algorithm::FlipHorizontal ?
        "Flip Horizontal":
        "Flip Vertical"):
      (m_flipType == doc::algorithm::FlipHorizontal ?
        "Flip Canvas Horizontal":
        "Flip Canvas Vertical"));
    DocumentApi api = document->getApi(transaction);

    CelList cels;
    if (m_flipMask) {
      auto range = App::instance()->timeline()->range();
      if (range.enabled())
        cels = get_unique_cels(sprite, range);
      else if (writer.cel())
        cels.push_back(writer.cel());
    }
    else {
      for (Cel* cel : sprite->uniqueCels())
        cels.push_back(cel);
    }

    Mask* mask = document->mask();
    if (m_flipMask && document->isMaskVisible()) {
      Site site = *writer.site();

      for (Cel* cel : cels) {
        site.frame(cel->frame());
        site.layer(cel->layer());

        int x, y;
        Image* image = site.image(&x, &y);
        if (!image)
          continue;

        // When the mask is inside the cel, we can try to flip the
        // pixels inside the image.
        if (cel->bounds().contains(mask->bounds())) {
          gfx::Rect flipBounds = mask->bounds();
          flipBounds.offset(-x, -y);
          flipBounds &= image->bounds();
          if (flipBounds.isEmpty())
            continue;

          if (mask->bitmap() && !mask->isRectangular())
            transaction.execute(new cmd::FlipMaskedCel(cel, m_flipType));
          else
            api.flipImage(image, flipBounds, m_flipType);

          if (cel->layer()->isTransparent())
            transaction.execute(new cmd::TrimCel(cel));
        }
        // When the mask is bigger than the cel bounds, we have to
        // expand the cel, make the flip, and shrink it again.
        else {
          gfx::Rect flipBounds = (sprite->bounds() & mask->bounds());
          if (flipBounds.isEmpty())
            continue;

          ExpandCelCanvas expand(
            site, cel->layer(),
            TiledMode::NONE, transaction,
            ExpandCelCanvas::None);

          expand.validateDestCanvas(gfx::Region(flipBounds));

          if (mask->bitmap() && !mask->isRectangular())
            doc::algorithm::flip_image_with_mask(
              expand.getDestCanvas(), mask, m_flipType,
              document->bgColor(cel->layer()));
          else
            doc::algorithm::flip_image(
              expand.getDestCanvas(),
              flipBounds, m_flipType);

          expand.commit();
        }
      }
    }
    else {
      for (Cel* cel : cels) {
        Image* image = cel->image();

        api.setCelPosition
          (sprite, cel,
            (m_flipType == doc::algorithm::FlipHorizontal ?
              sprite->width() - image->width() - cel->x():
              cel->x()),
            (m_flipType == doc::algorithm::FlipVertical ?
              sprite->height() - image->height() - cel->y():
              cel->y()));

        api.flipImage(image, image->bounds(), m_flipType);
      }
    }

    // Flip the mask.
    Image* maskBitmap = mask->bitmap();
    if (maskBitmap) {
      transaction.execute(new cmd::FlipMask(document, m_flipType));

      // Flip the mask position because the
      if (!m_flipMask)
        transaction.execute(
          new cmd::SetMaskPosition(
            document,
            gfx::Point(
              (m_flipType == doc::algorithm::FlipHorizontal ?
               sprite->width() - mask->bounds().x2():
               mask->bounds().x),
              (m_flipType == doc::algorithm::FlipVertical ?
               sprite->height() - mask->bounds().y2():
               mask->bounds().y))));

      document->generateMaskBoundaries();
    }

    transaction.commit();
  }

  update_screen_for_document(document);
}
Esempio n. 5
0
ExitCode _initAndListen(int listenPort) {
    Client::initThread("initandlisten");

    _initWireSpec();
    auto globalServiceContext = getGlobalServiceContext();

    globalServiceContext->setFastClockSource(FastClockSourceFactory::create(Milliseconds(10)));
    globalServiceContext->setOpObserver(stdx::make_unique<OpObserver>());

    DBDirectClientFactory::get(globalServiceContext)
        .registerImplementation([](OperationContext* txn) {
            return std::unique_ptr<DBClientBase>(new DBDirectClient(txn));
        });

    const repl::ReplSettings& replSettings = repl::getGlobalReplicationCoordinator()->getSettings();

    {
        ProcessId pid = ProcessId::getCurrent();
        LogstreamBuilder l = log(LogComponent::kControl);
        l << "MongoDB starting : pid=" << pid << " port=" << serverGlobalParams.port
          << " dbpath=" << storageGlobalParams.dbpath;
        if (replSettings.isMaster())
            l << " master=" << replSettings.isMaster();
        if (replSettings.isSlave())
            l << " slave=" << (int)replSettings.isSlave();

        const bool is32bit = sizeof(int*) == 4;
        l << (is32bit ? " 32" : " 64") << "-bit host=" << getHostNameCached() << endl;
    }

    DEV log(LogComponent::kControl) << "DEBUG build (which is slower)" << endl;

#if defined(_WIN32)
    VersionInfoInterface::instance().logTargetMinOS();
#endif

    logProcessDetails();

    checked_cast<ServiceContextMongoD*>(getGlobalServiceContext())->createLockFile();

    transport::TransportLayerLegacy::Options options;
    options.port = listenPort;
    options.ipList = serverGlobalParams.bind_ip;

    auto sep =
        stdx::make_unique<ServiceEntryPointMongod>(getGlobalServiceContext()->getTransportLayer());
    auto sepPtr = sep.get();

    getGlobalServiceContext()->setServiceEntryPoint(std::move(sep));

    // Create, start, and attach the TL
    auto transportLayer = stdx::make_unique<transport::TransportLayerLegacy>(options, sepPtr);
    auto res = transportLayer->setup();
    if (!res.isOK()) {
        error() << "Failed to set up listener: " << res;
        return EXIT_NET_ERROR;
    }

    std::shared_ptr<DbWebServer> dbWebServer;
    if (serverGlobalParams.isHttpInterfaceEnabled) {
        dbWebServer.reset(new DbWebServer(serverGlobalParams.bind_ip,
                                          serverGlobalParams.port + 1000,
                                          getGlobalServiceContext(),
                                          new RestAdminAccess()));
        if (!dbWebServer->setupSockets()) {
            error() << "Failed to set up sockets for HTTP interface during startup.";
            return EXIT_NET_ERROR;
        }
    }

    getGlobalServiceContext()->initializeGlobalStorageEngine();

#ifdef MONGO_CONFIG_WIREDTIGER_ENABLED
    if (WiredTigerCustomizationHooks::get(getGlobalServiceContext())->restartRequired()) {
        exitCleanly(EXIT_CLEAN);
    }
#endif

    // Warn if we detect configurations for multiple registered storage engines in
    // the same configuration file/environment.
    if (serverGlobalParams.parsedOpts.hasField("storage")) {
        BSONElement storageElement = serverGlobalParams.parsedOpts.getField("storage");
        invariant(storageElement.isABSONObj());
        BSONObj storageParamsObj = storageElement.Obj();
        BSONObjIterator i = storageParamsObj.begin();
        while (i.more()) {
            BSONElement e = i.next();
            // Ignore if field name under "storage" matches current storage engine.
            if (storageGlobalParams.engine == e.fieldName()) {
                continue;
            }

            // Warn if field name matches non-active registered storage engine.
            if (getGlobalServiceContext()->isRegisteredStorageEngine(e.fieldName())) {
                warning() << "Detected configuration for non-active storage engine "
                          << e.fieldName() << " when current storage engine is "
                          << storageGlobalParams.engine;
            }
        }
    }

    if (!getGlobalServiceContext()->getGlobalStorageEngine()->getSnapshotManager()) {
        if (moe::startupOptionsParsed.count("replication.enableMajorityReadConcern") &&
            moe::startupOptionsParsed["replication.enableMajorityReadConcern"].as<bool>()) {
            // Note: we are intentionally only erroring if the user explicitly requested that we
            // enable majority read concern. We do not error if the they are implicitly enabled for
            // CSRS because a required step in the upgrade procedure can involve an mmapv1 node in
            // the CSRS in the REMOVED state. This is handled by the TopologyCoordinator.
            invariant(replSettings.isMajorityReadConcernEnabled());
            severe() << "Majority read concern requires a storage engine that supports"
                     << " snapshots, such as wiredTiger. " << storageGlobalParams.engine
                     << " does not support snapshots.";
            exitCleanly(EXIT_BADOPTIONS);
        }
    }

    logMongodStartupWarnings(storageGlobalParams, serverGlobalParams);

    {
        stringstream ss;
        ss << endl;
        ss << "*********************************************************************" << endl;
        ss << " ERROR: dbpath (" << storageGlobalParams.dbpath << ") does not exist." << endl;
        ss << " Create this directory or give existing directory in --dbpath." << endl;
        ss << " See http://dochub.mongodb.org/core/startingandstoppingmongo" << endl;
        ss << "*********************************************************************" << endl;
        uassert(10296, ss.str().c_str(), boost::filesystem::exists(storageGlobalParams.dbpath));
    }

    {
        stringstream ss;
        ss << "repairpath (" << storageGlobalParams.repairpath << ") does not exist";
        uassert(12590, ss.str().c_str(), boost::filesystem::exists(storageGlobalParams.repairpath));
    }

    // TODO:  This should go into a MONGO_INITIALIZER once we have figured out the correct
    // dependencies.
    if (snmpInit) {
        snmpInit();
    }

    if (!storageGlobalParams.readOnly) {
        boost::filesystem::remove_all(storageGlobalParams.dbpath + "/_tmp/");
    }

    if (mmapv1GlobalOptions.journalOptions & MMAPV1Options::JournalRecoverOnly)
        return EXIT_NET_ERROR;

    if (mongodGlobalParams.scriptingEnabled) {
        ScriptEngine::setup();
    }

    auto startupOpCtx = getGlobalServiceContext()->makeOperationContext(&cc());

    repairDatabasesAndCheckVersion(startupOpCtx.get());

    if (storageGlobalParams.upgrade) {
        log() << "finished checking dbs";
        exitCleanly(EXIT_CLEAN);
    }

    uassertStatusOK(getGlobalAuthorizationManager()->initialize(startupOpCtx.get()));

    /* this is for security on certain platforms (nonce generation) */
    srand((unsigned)(curTimeMicros64() ^ startupSrandTimer.micros()));

    // The snapshot thread provides historical collection level and lock statistics for use
    // by the web interface. Only needed when HTTP is enabled.
    if (serverGlobalParams.isHttpInterfaceEnabled) {
        statsSnapshotThread.go();

        invariant(dbWebServer);
        stdx::thread web(stdx::bind(&webServerListenThread, dbWebServer));
        web.detach();
    }

#ifndef _WIN32
    mongo::signalForkSuccess();
#endif
    AuthorizationManager* globalAuthzManager = getGlobalAuthorizationManager();
    if (globalAuthzManager->shouldValidateAuthSchemaOnStartup()) {
        Status status = authindex::verifySystemIndexes(startupOpCtx.get());
        if (!status.isOK()) {
            log() << redact(status);
            exitCleanly(EXIT_NEED_UPGRADE);
        }

        // SERVER-14090: Verify that auth schema version is schemaVersion26Final.
        int foundSchemaVersion;
        status =
            globalAuthzManager->getAuthorizationVersion(startupOpCtx.get(), &foundSchemaVersion);
        if (!status.isOK()) {
            log() << "Auth schema version is incompatible: "
                  << "User and role management commands require auth data to have "
                  << "at least schema version " << AuthorizationManager::schemaVersion26Final
                  << " but startup could not verify schema version: " << status;
            exitCleanly(EXIT_NEED_UPGRADE);
        }
        if (foundSchemaVersion < AuthorizationManager::schemaVersion26Final) {
            log() << "Auth schema version is incompatible: "
                  << "User and role management commands require auth data to have "
                  << "at least schema version " << AuthorizationManager::schemaVersion26Final
                  << " but found " << foundSchemaVersion << ". In order to upgrade "
                  << "the auth schema, first downgrade MongoDB binaries to version "
                  << "2.6 and then run the authSchemaUpgrade command.";
            exitCleanly(EXIT_NEED_UPGRADE);
        }
    } else if (globalAuthzManager->isAuthEnabled()) {
        error() << "Auth must be disabled when starting without auth schema validation";
        exitCleanly(EXIT_BADOPTIONS);
    } else {
        // If authSchemaValidation is disabled and server is running without auth,
        // warn the user and continue startup without authSchema metadata checks.
        log() << startupWarningsLog;
        log() << "** WARNING: Startup auth schema validation checks are disabled for the "
                 "database."
              << startupWarningsLog;
        log() << "**          This mode should only be used to manually repair corrupted auth "
                 "data."
              << startupWarningsLog;
    }

    auto shardingInitialized =
        uassertStatusOK(ShardingState::get(startupOpCtx.get())
                            ->initializeShardingAwarenessIfNeeded(startupOpCtx.get()));
    if (shardingInitialized) {
        reloadShardRegistryUntilSuccess(startupOpCtx.get());
    }

    if (!storageGlobalParams.readOnly) {
        logStartup(startupOpCtx.get());

        startFTDC();

        getDeleter()->startWorkers();

        restartInProgressIndexesFromLastShutdown(startupOpCtx.get());

        if (serverGlobalParams.clusterRole == ClusterRole::ShardServer) {
            // Note: For replica sets, ShardingStateRecovery happens on transition to primary.
            if (!repl::getGlobalReplicationCoordinator()->isReplEnabled()) {
                uassertStatusOK(ShardingStateRecovery::recover(startupOpCtx.get()));
            }
        } else if (serverGlobalParams.clusterRole == ClusterRole::ConfigServer) {
            uassertStatusOK(
                initializeGlobalShardingStateForMongod(startupOpCtx.get(),
                                                       ConnectionString::forLocal(),
                                                       kDistLockProcessIdForConfigServer));
            Balancer::create(startupOpCtx->getServiceContext());
        }

        repl::getGlobalReplicationCoordinator()->startup(startupOpCtx.get());

        const unsigned long long missingRepl =
            checkIfReplMissingFromCommandLine(startupOpCtx.get());
        if (missingRepl) {
            log() << startupWarningsLog;
            log() << "** WARNING: mongod started without --replSet yet " << missingRepl
                  << " documents are present in local.system.replset" << startupWarningsLog;
            log() << "**          Restart with --replSet unless you are doing maintenance and "
                  << " no other clients are connected." << startupWarningsLog;
            log() << "**          The TTL collection monitor will not start because of this."
                  << startupWarningsLog;
            log() << "**         ";
            log() << " For more info see http://dochub.mongodb.org/core/ttlcollections";
            log() << startupWarningsLog;
        } else {
            startTTLBackgroundJob();
        }

        if (!replSettings.usingReplSets() && !replSettings.isSlave() &&
            storageGlobalParams.engine != "devnull") {
            ScopedTransaction transaction(startupOpCtx.get(), MODE_X);
            Lock::GlobalWrite lk(startupOpCtx.get()->lockState());
            FeatureCompatibilityVersion::setIfCleanStartup(
                startupOpCtx.get(), repl::StorageInterface::get(getGlobalServiceContext()));
        }
    }

    startClientCursorMonitor();

    PeriodicTask::startRunningPeriodicTasks();

    // MessageServer::run will return when exit code closes its socket and we don't need the
    // operation context anymore
    startupOpCtx.reset();

    auto start = getGlobalServiceContext()->addAndStartTransportLayer(std::move(transportLayer));
    if (!start.isOK()) {
        error() << "Failed to start the listener: " << start.toString();
        return EXIT_NET_ERROR;
    }

    return waitForShutdown();
}
Esempio n. 6
0
void KVStore::clear()
{
    Transaction transaction(*this);
    mConn.exec("DELETE FROM data");
    transaction.commit();
}
Esempio n. 7
0
File: delete.cpp Progetto: aox/aox
void Delete::execute()
{
    if ( state() != Executing || !ok() )
        return;

    if ( d->first ) {
        d->first = false;

        // We should really require DeleteMessages and Expunge only if
        // we know the mailbox isn't empty; but we'll know that inside
        // the transaction, and permitted() won't let us clean that up
        // if we don't have permission. So it'll have to wait until we
        // query permissions ourselves.

        requireRight( d->m, Permissions::DeleteMailbox );
        requireRight( d->m, Permissions::DeleteMessages );
        requireRight( d->m, Permissions::Expunge );
    }

    if ( !permitted() )
        return;

    if ( !transaction() ) {
        setTransaction( new Transaction( this ) );
        Query * lock = new Query( "select * from mailboxes "
                                  "where id=$1 for update", 0 );
        lock->bind( 1, d->m->id() );
        transaction()->enqueue( lock );

        d->messages = new Query( "select count(mm.uid)::bigint as messages "
                                 "from mailbox_messages mm "
                                 "join messages m on (mm.message=m.id) "
                                 "join mailboxes mb on (mm.mailbox=mb.id) "
                                 "where mm.mailbox=$1 and not mm.seen and "
                                 "(mm.uid>=mb.first_recent or m.idate>$2)",
                                 this );
        d->messages->bind( 1, d->m->id() );
        Date now;
        now.setCurrentTime();
        d->messages->bind( 2, now.unixTime() - 20 );
        transaction()->enqueue( d->messages );
        transaction()->execute();
    }

    if ( d->messages ) {
        if ( !d->messages->done() )
            return;

        int64 messages = 0;

        Row * r = d->messages->nextRow();
        if ( d->messages->failed() || !r )
            error( No, "Could not determine if any messages exist" );
        else
            messages = r->getBigint( "messages" );

        if ( messages )
            error( No, "Cannot delete mailbox: " + fn( messages ) +
                   " messages exist" );
        d->messages = 0;

        if ( ok() && d->m->remove( transaction() ) == 0 )
            error( No, "Cannot delete mailbox " + d->m->name().ascii() );

        Mailbox::refreshMailboxes( transaction() );
        transaction()->commit();
    }

    if ( !transaction()->done() )
        return;

    if ( transaction()->failed() ) {
        error( No, "Database error: " + transaction()->error() );
        return;
    }

    finish();
}
Esempio n. 8
0
/// Opens a transaction.
///
/// \return A new transaction.
store::transaction
store::backend::start(void)
{
    return transaction(*this);
}
IDBIndex* IDBObjectStore::createIndex(ScriptState* scriptState, const String& name, const IDBKeyPath& keyPath, const IDBIndexParameters& options, ExceptionState& exceptionState)
{
    IDB_TRACE("IDBObjectStore::createIndex");
    if (!m_transaction->isVersionChange()) {
        exceptionState.throwDOMException(InvalidStateError, IDBDatabase::notVersionChangeTransactionErrorMessage);
        return nullptr;
    }
    if (isDeleted()) {
        exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectStoreDeletedErrorMessage);
        return nullptr;
    }
    if (m_transaction->isFinished() || m_transaction->isFinishing()) {
        exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage);
        return nullptr;
    }
    if (!m_transaction->isActive()) {
        exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage);
        return nullptr;
    }
    if (!keyPath.isValid()) {
        exceptionState.throwDOMException(SyntaxError, "The keyPath argument contains an invalid key path.");
        return nullptr;
    }
    if (containsIndex(name)) {
        exceptionState.throwDOMException(ConstraintError, "An index with the specified name already exists.");
        return nullptr;
    }

    if (keyPath.type() == IDBKeyPath::ArrayType && options.multiEntry()) {
        exceptionState.throwDOMException(InvalidAccessError, "The keyPath argument was an array and the multiEntry option is true.");
        return nullptr;
    }
    if (!backendDB()) {
        exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage);
        return nullptr;
    }

    int64_t indexId = m_metadata.maxIndexId + 1;
    backendDB()->createIndex(m_transaction->id(), id(), indexId, name, keyPath, options.unique(), options.multiEntry());

    ++m_metadata.maxIndexId;

    IDBIndexMetadata metadata(name, indexId, keyPath, options.unique(), options.multiEntry());
    IDBIndex* index = IDBIndex::create(metadata, this, m_transaction.get());
    m_indexMap.set(name, index);
    m_metadata.indexes.set(indexId, metadata);
    m_transaction->db()->indexCreated(id(), metadata);

    ASSERT(!exceptionState.hadException());
    if (exceptionState.hadException())
        return nullptr;

    IDBRequest* indexRequest = openCursor(scriptState, nullptr, WebIDBCursorDirectionNext, WebIDBTaskTypePreemptive);
    indexRequest->preventPropagation();

    // This is kept alive by being the success handler of the request, which is in turn kept alive by the owning transaction.
    RefPtrWillBeRawPtr<IndexPopulator> indexPopulator = IndexPopulator::create(scriptState, transaction()->db(), m_transaction->id(), id(), metadata);
    indexRequest->setOnsuccess(indexPopulator);
    return index;
}
Esempio n. 10
0
RefPtr<IDBTransaction> LegacyDatabase::transaction(ScriptExecutionContext* context, const String& storeName, const String& mode, ExceptionCode& ec)
{
    RefPtr<DOMStringList> storeNames = DOMStringList::create();
    storeNames->append(storeName);
    return transaction(context, storeNames, mode, ec);
}
Esempio n. 11
0
void reverse_frames(Doc* doc, const DocRange& range)
{
  const app::Context* context = static_cast<app::Context*>(doc->context());
  const ContextReader reader(context);
  ContextWriter writer(reader, 500);
  Transaction transaction(writer.context(), "Reverse Frames");
  DocApi api = doc->getApi(transaction);
  Sprite* sprite = doc->sprite();
  LayerList layers;
  frame_t frameBegin, frameEnd;
  bool moveFrames = false;
  bool swapCels = false;

  switch (range.type()) {
    case DocRange::kCels:
      frameBegin = range.firstFrame();
      frameEnd = range.lastFrame();
      layers = range.selectedLayers().toLayerList();
      swapCels = true;
      break;
    case DocRange::kFrames:
      frameBegin = range.firstFrame();
      frameEnd = range.lastFrame();
      layers = sprite->allLayers();
      moveFrames = true;
      break;
    case DocRange::kLayers:
      frameBegin = frame_t(0);
      frameEnd = sprite->totalFrames()-1;
      layers = range.selectedLayers().toLayerList();
      swapCels = true;
      break;
  }

  if (moveFrames) {
    for (frame_t frameRev = frameEnd+1;
         frameRev > frameBegin;
         --frameRev) {
      api.moveFrame(sprite, frameBegin, frameRev,
                    kDropBeforeFrame,
                    kDontAdjustTags);
    }
  }
  else if (swapCels) {
    for (Layer* layer : layers) {
      if (!layer->isImage())
        continue;

      for (frame_t frame = frameBegin,
             frameRev = frameEnd;
           frame != (frameBegin+frameEnd)/2+1;
           ++frame, --frameRev) {
        if (frame == frameRev)
          continue;

        LayerImage* imageLayer = static_cast<LayerImage*>(layer);
        api.swapCel(imageLayer, frame, frameRev);
      }
    }
  }

  transaction.setNewDocRange(range);
  transaction.commit();
}
Esempio n. 12
0
static DocRange drop_range_op(
  Doc* doc,
  const Op op,
  const DocRange& from,
  DocRangePlace place,
  const TagsHandling tagsHandling,
  DocRange to)
{
  // Convert "first child" operation into a insert after last child.
  LayerGroup* parent = nullptr;
  if (to.type() == DocRange::kLayers &&
      !to.selectedLayers().empty()) {
    if (place == kDocRangeFirstChild &&
        (*to.selectedLayers().begin())->isGroup()) {
      place = kDocRangeAfter;
      parent = static_cast<LayerGroup*>((*to.selectedLayers().begin()));

      to.clearRange();
      to.startRange(parent->lastLayer(), -1, DocRange::kLayers);
      to.endRange(parent->lastLayer(), -1);
    }
    else {
      parent = (*to.selectedLayers().begin())->parent();
    }

    // Check that we're not moving a group inside itself
    for (auto moveThis : from.selectedLayers()) {
      if (moveThis == parent ||
          (moveThis->isGroup() &&
           has_child(static_cast<LayerGroup*>(moveThis), parent)))
        return from;
    }
  }

  if (place != kDocRangeBefore &&
      place != kDocRangeAfter) {
    ASSERT(false);
    throw std::invalid_argument("Invalid 'place' argument");
  }

  Sprite* sprite = doc->sprite();

  // Check noop/trivial/do nothing cases, i.e., move a range to the same place.
  // Also check invalid cases, like moving a Background layer.
  switch (from.type()) {

    case DocRange::kCels:
      if (from == to)
        return from;
      break;

    case DocRange::kFrames:
      if (op == Move) {
        // Simple cases with one continuos range of frames that are a
        // no-op.
        if ((from.selectedFrames().ranges() == 1) &&
            ((to.firstFrame() >= from.firstFrame() &&
              to.lastFrame() <= from.lastFrame()) ||
             (place == kDocRangeBefore && to.firstFrame() == from.lastFrame()+1) ||
             (place == kDocRangeAfter && to.lastFrame() == from.firstFrame()-1)) &&
            // If there are tags, this might not be a no-op
            (sprite->frameTags().empty() ||
             tagsHandling == kDontAdjustTags)) {
          return from;
        }
      }
      break;

    case DocRange::kLayers:
      if (op == Move) {
        SelectedLayers srcSelLayers = from.selectedLayers();
        SelectedLayers dstSelLayers = to.selectedLayers();
        LayerList srcLayers = srcSelLayers.toLayerList();
        LayerList dstLayers = dstSelLayers.toLayerList();
        ASSERT(!srcLayers.empty());
        if (srcLayers.empty())
          return from;

        // dstLayers can be nullptr when we insert the first child in
        // a group.

        // Check no-ops when we move layers at the same level (all
        // layers with the same parent), all adjacents, and which are
        // moved to the same place.
        if (!dstSelLayers.empty() &&
            srcSelLayers.hasSameParent() &&
            dstSelLayers.hasSameParent() &&
            are_layers_adjacent(srcLayers) &&
            are_layers_adjacent(dstLayers)) {
          for (Layer* srcLayer : srcLayers)
            if (dstSelLayers.contains(srcLayer))
              return from;

          if ((place == kDocRangeBefore
               && dstLayers.front() == srcLayers.back()->getNext()) ||
              (place == kDocRangeAfter
               && dstLayers.back() == srcLayers.front()->getPrevious()))
            return from;
        }

        // We cannot move the background
        for (Layer* layer : srcSelLayers)
          if (layer->isBackground())
            throw std::runtime_error("The background layer cannot be moved");
      }

      // Before background
      if (place == kDocRangeBefore) {
        for (Layer* background : to.selectedLayers()) {
          if (background && background->isBackground())
            throw std::runtime_error("You cannot move or copy something below the background layer");
        }
      }
      break;
  }

  const char* undoLabel = NULL;
  switch (op) {
    case Move: undoLabel = "Move Range"; break;
    case Copy: undoLabel = "Copy Range"; break;
    default:
      ASSERT(false);
      throw std::invalid_argument("Invalid 'op' argument");
  }
  DocRange resultRange;

  {
    const app::Context* context = static_cast<app::Context*>(doc->context());
    const ContextReader reader(context);
    ContextWriter writer(reader, 500);
    Transaction transaction(writer.context(), undoLabel, ModifyDocument);
    DocApi api = doc->getApi(transaction);

    // TODO Try to add the range with just one call to DocApi
    // methods, to avoid generating a lot of cmd::SetCelFrame (see
    // DocApi::setCelFramePosition() function).

    switch (from.type()) {

      case DocRange::kCels: {
        LayerList allLayers = sprite->allBrowsableLayers();
        if (allLayers.empty())
          break;

        LayerList srcLayers = from.selectedLayers().toLayerList();
        LayerList dstLayers = to.selectedLayers().toLayerList();
        if (srcLayers.empty() ||
            dstLayers.empty())
          throw std::invalid_argument("You need to specify a non-empty cels range");

        if (find_layer_index(allLayers, srcLayers.front()) <
            find_layer_index(allLayers, dstLayers.front())) {
          std::reverse(srcLayers.begin(), srcLayers.end());
          std::reverse(dstLayers.begin(), dstLayers.end());
        }

        if (from.firstFrame() < to.firstFrame()) {
          auto srcFrames = from.selectedFrames().makeReverse();
          auto dstFrames = to.selectedFrames().makeReverse();

          move_or_copy_cels(api, op, srcLayers, dstLayers, srcFrames, dstFrames);
        }
        else {
          const auto& srcFrames = from.selectedFrames();
          const auto& dstFrames = to.selectedFrames();

          move_or_copy_cels(api, op, srcLayers, dstLayers, srcFrames, dstFrames);
        }

        resultRange = to;
        break;
      }

      case DocRange::kFrames: {
        frame_t dstFrame;
        if (place == kDocRangeBefore)
          dstFrame = to.firstFrame();
        else
          dstFrame = to.lastFrame();

        resultRange = move_or_copy_frames(api, op, sprite,
                                          from, dstFrame,
                                          place, tagsHandling);
        break;
      }

      case DocRange::kLayers: {
        LayerList allLayers = sprite->allBrowsableLayers();
        if (allLayers.empty())
          break;

        LayerList srcLayers = from.selectedLayers().toLayerList();
        LayerList dstLayers = to.selectedLayers().toLayerList();
        ASSERT(!srcLayers.empty());

        switch (op) {

          case Move:
            if (place == kDocRangeBefore) {
              Layer* beforeThis = (!dstLayers.empty() ? dstLayers.front(): nullptr);
              Layer* afterThis  = nullptr;

              for (Layer* srcLayer : srcLayers) {
                if (afterThis)
                  api.restackLayerAfter(srcLayer, parent, afterThis);
                else
                  api.restackLayerBefore(srcLayer, parent, beforeThis);

                afterThis = srcLayer;
              }
            }
            else if (place == kDocRangeAfter) {
              Layer* afterThis = (!dstLayers.empty() ? dstLayers.back(): nullptr);
              for (Layer* srcLayer : srcLayers) {
                api.restackLayerAfter(srcLayer, parent, afterThis);
                afterThis = srcLayer;
              }
            }

            // Same set of layers than the "from" range
            resultRange = from;
            break;

          case Copy: {
            if (place == kDocRangeBefore) {
              Layer* beforeThis = (!dstLayers.empty() ? dstLayers.front(): nullptr);
              for (Layer* srcLayer :  srcLayers) {
                Layer* copiedLayer = api.duplicateLayerBefore(
                  srcLayer, parent, beforeThis);

                resultRange.startRange(copiedLayer, -1, DocRange::kLayers);
                resultRange.endRange(copiedLayer, -1);
              }
            }
            else if (place == kDocRangeAfter) {
              std::reverse(srcLayers.begin(), srcLayers.end());

              Layer* afterThis = (!dstLayers.empty() ? dstLayers.back(): nullptr);
              for (Layer* srcLayer :  srcLayers) {
                Layer* copiedLayer = api.duplicateLayerAfter(
                  srcLayer, parent, afterThis);

                resultRange.startRange(copiedLayer, -1, DocRange::kLayers);
                resultRange.endRange(copiedLayer, -1);
              }
            }
            break;
          }
        }
        break;
      }
    }

    if (resultRange.type() != DocRange::kNone)
      transaction.setNewDocRange(resultRange);

    transaction.commit();
  }

  return resultRange;
}
Esempio n. 13
0
void StorageAreaSync::sync(bool clearItems, const HashMap<String, String>& items)
{
    ASSERT(!isMainThread());

    if (items.isEmpty() && !clearItems && !m_syncCloseDatabase)
        return;
    if (m_databaseOpenFailed)
        return;

    if (!m_database.isOpen() && m_syncCloseDatabase) {
        m_syncCloseDatabase = false;
        return;
    }

    if (!m_database.isOpen())
        openDatabase(CreateIfNonExistent);
    if (!m_database.isOpen())
        return;

    // Closing this db because it is about to be deleted by StorageTracker.
    // The delete will be cancelled if StorageAreaSync needs to reopen the db
    // to write new items created after the request to delete the db.
    if (m_syncCloseDatabase) {
        m_syncCloseDatabase = false;
        m_database.close();
        return;
    }
    
    SQLiteTransactionInProgressAutoCounter transactionCounter;

    // If the clear flag is set, then we clear all items out before we write any new ones in.
    if (clearItems) {
        SQLiteStatement clear(m_database, "DELETE FROM ItemTable");
        if (clear.prepare() != SQLITE_OK) {
            LOG_ERROR("Failed to prepare clear statement - cannot write to local storage database");
            return;
        }

        int result = clear.step();
        if (result != SQLITE_DONE) {
            LOG_ERROR("Failed to clear all items in the local storage database - %i", result);
            return;
        }
    }

    SQLiteStatement insert(m_database, "INSERT INTO ItemTable VALUES (?, ?)");
    if (insert.prepare() != SQLITE_OK) {
        LOG_ERROR("Failed to prepare insert statement - cannot write to local storage database");
        return;
    }

    SQLiteStatement remove(m_database, "DELETE FROM ItemTable WHERE key=?");
    if (remove.prepare() != SQLITE_OK) {
        LOG_ERROR("Failed to prepare delete statement - cannot write to local storage database");
        return;
    }

    HashMap<String, String>::const_iterator end = items.end();

    SQLiteTransaction transaction(m_database);
    transaction.begin();
    for (HashMap<String, String>::const_iterator it = items.begin(); it != end; ++it) {
        // Based on the null-ness of the second argument, decide whether this is an insert or a delete.
        SQLiteStatement& query = it->value.isNull() ? remove : insert;

        query.bindText(1, it->key);

        // If the second argument is non-null, we're doing an insert, so bind it as the value.
        if (!it->value.isNull())
            query.bindBlob(2, it->value);

        int result = query.step();
        if (result != SQLITE_DONE) {
            LOG_ERROR("Failed to update item in the local storage database - %i", result);
            break;
        }

        query.reset();
    }
    transaction.commit();
}
Esempio n. 14
0
nsresult
FileManager::Init(nsIFile* aDirectory,
                  mozIStorageConnection* aConnection)
{
  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");

  mFileInfos.Init();

  bool exists;
  nsresult rv = aDirectory->Exists(&exists);
  NS_ENSURE_SUCCESS(rv, rv);

  if (exists) {
    bool isDirectory;
    rv = aDirectory->IsDirectory(&isDirectory);
    NS_ENSURE_SUCCESS(rv, rv);
    NS_ENSURE_TRUE(isDirectory, NS_ERROR_FAILURE);
  }
  else {
    rv = aDirectory->Create(nsIFile::DIRECTORY_TYPE, 0755);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  mozStorageTransaction transaction(aConnection, false);

  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
    "CREATE VIRTUAL TABLE fs USING filesystem;"
  ));
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<mozIStorageStatement> stmt;
  rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
    "SELECT name, (name IN (SELECT id FROM file)) FROM fs "
    "WHERE path = :path"
  ), getter_AddRefs(stmt));
  NS_ENSURE_SUCCESS(rv, rv);

  nsString path;
  rv = aDirectory->GetPath(path);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = stmt->BindStringByName(NS_LITERAL_CSTRING("path"), path);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<mozIStorageServiceQuotaManagement> ss =
    do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
  NS_ENSURE_TRUE(ss, NS_ERROR_FAILURE);

  bool hasResult;
  while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
    nsString name;
    rv = stmt->GetString(0, name);
    NS_ENSURE_SUCCESS(rv, rv);

    PRInt32 flag = stmt->AsInt32(1);

    nsCOMPtr<nsIFile> file;
    rv = aDirectory->Clone(getter_AddRefs(file));
    NS_ENSURE_SUCCESS(rv, rv);

    rv = file->Append(name);
    NS_ENSURE_SUCCESS(rv, rv);

    if (flag) {
      rv = ss->UpdateQuotaInformationForFile(file);
      NS_ENSURE_SUCCESS(rv, rv);
    }
    else {
      rv = file->Remove(false);
      if (NS_FAILED(rv)) {
        NS_WARNING("Failed to remove orphaned file!");
      }
    }
  }

  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
    "DROP TABLE fs;"
  ));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = aDirectory->GetPath(mDirectoryPath);
  NS_ENSURE_SUCCESS(rv, rv);

  transaction.Commit();
  return NS_OK;
}
Esempio n. 15
0
bool AbstractDatabase::performOpenAndVerify(bool shouldSetVersionInNewDatabase, ExceptionCode& ec)
{
    const int maxSqliteBusyWaitTime = 30000;

    if (!m_sqliteDatabase.open(m_filename, true)) {
        LOG_ERROR("Unable to open database at path %s", m_filename.ascii().data());
        ec = INVALID_STATE_ERR;
        return false;
    }
    if (!m_sqliteDatabase.turnOnIncrementalAutoVacuum())
        LOG_ERROR("Unable to turn on incremental auto-vacuum for database %s", m_filename.ascii().data());

    m_sqliteDatabase.setBusyTimeout(maxSqliteBusyWaitTime);

    String currentVersion;
    {
        MutexLocker locker(guidMutex());

        GuidVersionMap::iterator entry = guidToVersionMap().find(m_guid);
        if (entry != guidToVersionMap().end()) {
            // Map null string to empty string (see updateGuidVersionMap()).
            currentVersion = entry->second.isNull() ? String("") : entry->second.threadsafeCopy();
            LOG(StorageAPI, "Current cached version for guid %i is %s", m_guid, currentVersion.ascii().data());

#if PLATFORM(CHROMIUM)
            // Note: In multi-process browsers the cached value may be inaccurate, but
            // we cannot read the actual version from the database without potentially
            // inducing a form of deadlock, a busytimeout error when trying to
            // access the database. So we'll use the cached value if we're unable to read
            // the value from the database file without waiting.
            // FIXME: Add an async openDatabase method to the DatabaseAPI.
            const int noSqliteBusyWaitTime = 0;
            m_sqliteDatabase.setBusyTimeout(noSqliteBusyWaitTime);
            String versionFromDatabase;
            if (getVersionFromDatabase(versionFromDatabase, false)) {
                currentVersion = versionFromDatabase;
                updateGuidVersionMap(m_guid, currentVersion);
            }
            m_sqliteDatabase.setBusyTimeout(maxSqliteBusyWaitTime);
#endif
        } else {
            LOG(StorageAPI, "No cached version for guid %i", m_guid);

            SQLiteTransaction transaction(m_sqliteDatabase);
            transaction.begin();
            if (!transaction.inProgress()) {
                LOG_ERROR("Unable to begin transaction while opening %s", databaseDebugName().ascii().data());
                ec = INVALID_STATE_ERR;
                m_sqliteDatabase.close();
                return false;
            }

            String tableName(infoTableName);
            if (!m_sqliteDatabase.tableExists(tableName)) {
                m_new = true;

                if (!m_sqliteDatabase.executeCommand("CREATE TABLE " + tableName + " (key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,value TEXT NOT NULL ON CONFLICT FAIL);")) {
                    LOG_ERROR("Unable to create table %s in database %s", infoTableName, databaseDebugName().ascii().data());
                    ec = INVALID_STATE_ERR;
                    transaction.rollback();
                    m_sqliteDatabase.close();
                    return false;
                }
            } else if (!getVersionFromDatabase(currentVersion, false)) {
                LOG_ERROR("Failed to get current version from database %s", databaseDebugName().ascii().data());
                ec = INVALID_STATE_ERR;
                transaction.rollback();
                m_sqliteDatabase.close();
                return false;
            }

            if (currentVersion.length()) {
                LOG(StorageAPI, "Retrieved current version %s from database %s", currentVersion.ascii().data(), databaseDebugName().ascii().data());
            } else if (!m_new || shouldSetVersionInNewDatabase) {
                LOG(StorageAPI, "Setting version %s in database %s that was just created", m_expectedVersion.ascii().data(), databaseDebugName().ascii().data());
                if (!setVersionInDatabase(m_expectedVersion, false)) {
                    LOG_ERROR("Failed to set version %s in database %s", m_expectedVersion.ascii().data(), databaseDebugName().ascii().data());
                    ec = INVALID_STATE_ERR;
                    transaction.rollback();
                    m_sqliteDatabase.close();
                    return false;
                }
                currentVersion = m_expectedVersion;
            }
            updateGuidVersionMap(m_guid, currentVersion);
            transaction.commit();
        }
    }

    if (currentVersion.isNull()) {
        LOG(StorageAPI, "Database %s does not have its version set", databaseDebugName().ascii().data());
        currentVersion = "";
    }

    // If the expected version isn't the empty string, ensure that the current database version we have matches that version. Otherwise, set an exception.
    // If the expected version is the empty string, then we always return with whatever version of the database we have.
    if ((!m_new || shouldSetVersionInNewDatabase) && m_expectedVersion.length() && m_expectedVersion != currentVersion) {
        LOG(StorageAPI, "page expects version %s from database %s, which actually has version name %s - openDatabase() call will fail", m_expectedVersion.ascii().data(),
            databaseDebugName().ascii().data(), currentVersion.ascii().data());
        ec = INVALID_STATE_ERR;
        m_sqliteDatabase.close();
        return false;
    }

    ASSERT(m_databaseAuthorizer);
    m_sqliteDatabase.setAuthorizer(m_databaseAuthorizer);

    m_opened = true;

    if (m_new && !shouldSetVersionInNewDatabase)
        m_expectedVersion = ""; // The caller provided a creationCallback which will set the expected version.

    return true;
}
Esempio n. 16
0
/* Create a new key with the specified number of bits (or retrieve it 
 from a pre-generated keypool)  */
bool HsmKeyFactoryPB::CreateNewKey(int bits, const std::string &repository,
                                   const std::string &policy, int algorithm,
                                   KeyRole role,
                                   HsmKey **ppKey)
{
#if 0
	// perform retrieval and update of a hsm key inside a single transaction.
	OrmTransactionRW transaction(_conn);
	if (!transaction.started())
		return false;
#endif
	
    // Find keys that are available and match exactly with the given parameters.
	{	OrmResultRef rows;
		if (!OrmMessageEnumWhere(_conn, ::ods::hsmkey::HsmKey::descriptor(),
								 rows, "inception IS NULL"))
			return false;

		::ods::hsmkey::HsmKey *pbkey = new ::ods::hsmkey::HsmKey;
		
		for (bool next=OrmFirst(rows); next; next=OrmNext(rows)) {
			OrmContextRef context;
			if (OrmGetMessage(rows, *pbkey, true, context)) {
				if (!pbkey->has_inception() 
					&& pbkey->bits() == bits
					&& pbkey->repository() == repository
					&& pbkey->policy() == policy
					&& pbkey->algorithm() == algorithm
					&& pbkey->role() == (::ods::hsmkey::keyrole)role
					)
				{
					// found a candidate, so we no longer need the rows
					rows.release();

					pbkey->set_inception(time_now());
					HsmKeyPB pbkey_ref(pbkey);
					
					// Fixate unset attributes that returned their default value.
					// Otherwise when we list the keys those values will show 
					// up as 'not set'
					if (!pbkey->has_policy())
						pbkey_ref.setPolicy(policy);
					if (!pbkey->has_algorithm())
						pbkey_ref.setAlgorithm(algorithm);
					if (!pbkey->has_role())
						pbkey_ref.setKeyRole(role);
					
					pbkey = NULL;

					// We have modified the key and need to update it.
					if (!OrmMessageUpdate(context)) 
						return false;
#if 0
					if (!transaction.commit())
						return false;
#endif
					std::pair<std::map<std::string,HsmKeyPB>::iterator,bool> ret;
					ret = _keys.insert(std::pair<std::string,HsmKeyPB>(
										pbkey_ref.locator(),pbkey_ref));
					*ppKey = &ret.first->second;
					return true;
				}
			}
		}

		delete pbkey;
    }

#if 0
	// explicit rollback not strictly needed as it's the default action.
	// but we want to be sure to leave the transaction before we start calling 
	// callbacks on our delegate.
	transaction.rollback(); 
#endif
	
    // We were not able to find any suitable key, give up.
    if (_delegate)
        _delegate->OnKeyShortage(bits,repository,policy,algorithm,role);
    return false;
}
Esempio n. 17
0
nsresult
DOMStorageDBThread::InitDatabase()
{
  Telemetry::AutoTimer<Telemetry::LOCALDOMSTORAGE_INIT_DATABASE_MS> timer;

  nsresult rv;

  // Here we are on the worker thread. This opens the worker connection.
  MOZ_ASSERT(!NS_IsMainThread());

  rv = OpenDatabaseConnection();
  NS_ENSURE_SUCCESS(rv, rv);

  rv = TryJournalMode();
  NS_ENSURE_SUCCESS(rv, rv);

  // Create a read-only clone
  (void)mWorkerConnection->Clone(true, getter_AddRefs(mReaderConnection));
  NS_ENSURE_TRUE(mReaderConnection, NS_ERROR_FAILURE);

  mozStorageTransaction transaction(mWorkerConnection, false);

  // Ensure Goanna 1.9.1 storage table
  rv = mWorkerConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         "CREATE TABLE IF NOT EXISTS webappsstore2 ("
         "scope TEXT, "
         "key TEXT, "
         "value TEXT, "
         "secure INTEGER, "
         "owner TEXT)"));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = mWorkerConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        "CREATE UNIQUE INDEX IF NOT EXISTS scope_key_index"
        " ON webappsstore2(scope, key)"));
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<mozIStorageFunction> function1(new nsReverseStringSQLFunction());
  NS_ENSURE_TRUE(function1, NS_ERROR_OUT_OF_MEMORY);

  rv = mWorkerConnection->CreateFunction(NS_LITERAL_CSTRING("REVERSESTRING"), 1, function1);
  NS_ENSURE_SUCCESS(rv, rv);

  bool exists;

  // Check if there is storage of Goanna 1.9.0 and if so, upgrade that storage
  // to actual webappsstore2 table and drop the obsolete table. First process
  // this newer table upgrade to priority potential duplicates from older
  // storage table.
  rv = mWorkerConnection->TableExists(NS_LITERAL_CSTRING("webappsstore"),
                                &exists);
  NS_ENSURE_SUCCESS(rv, rv);

  if (exists) {
    rv = mWorkerConnection->ExecuteSimpleSQL(
      NS_LITERAL_CSTRING("INSERT OR IGNORE INTO "
                         "webappsstore2(scope, key, value, secure, owner) "
                         "SELECT REVERSESTRING(domain) || '.:', key, value, secure, owner "
                         "FROM webappsstore"));
    NS_ENSURE_SUCCESS(rv, rv);

    rv = mWorkerConnection->ExecuteSimpleSQL(
      NS_LITERAL_CSTRING("DROP TABLE webappsstore"));
    NS_ENSURE_SUCCESS(rv, rv);
  }

  // Check if there is storage of Goanna 1.8 and if so, upgrade that storage
  // to actual webappsstore2 table and drop the obsolete table. Potential
  // duplicates will be ignored.
  rv = mWorkerConnection->TableExists(NS_LITERAL_CSTRING("moz_webappsstore"),
                                &exists);
  NS_ENSURE_SUCCESS(rv, rv);

  if (exists) {
    rv = mWorkerConnection->ExecuteSimpleSQL(
      NS_LITERAL_CSTRING("INSERT OR IGNORE INTO "
                         "webappsstore2(scope, key, value, secure, owner) "
                         "SELECT REVERSESTRING(domain) || '.:', key, value, secure, domain "
                         "FROM moz_webappsstore"));
    NS_ENSURE_SUCCESS(rv, rv);

    rv = mWorkerConnection->ExecuteSimpleSQL(
      NS_LITERAL_CSTRING("DROP TABLE moz_webappsstore"));
    NS_ENSURE_SUCCESS(rv, rv);
  }

  rv = transaction.Commit();
  NS_ENSURE_SUCCESS(rv, rv);

  // Database open and all initiation operation are done.  Switching this flag
  // to true allow main thread to read directly from the database.
  // If we would allow this sooner, we would have opened a window where main thread
  // read might operate on a totaly broken and incosistent database.
  mDBReady = true;

  // List scopes having any stored data
  nsCOMPtr<mozIStorageStatement> stmt;
  rv = mWorkerConnection->CreateStatement(NS_LITERAL_CSTRING("SELECT DISTINCT scope FROM webappsstore2"),
                                    getter_AddRefs(stmt));
  NS_ENSURE_SUCCESS(rv, rv);
  mozStorageStatementScoper scope(stmt);

  while (NS_SUCCEEDED(rv = stmt->ExecuteStep(&exists)) && exists) {
    nsAutoCString foundScope;
    rv = stmt->GetUTF8String(0, foundScope);
    NS_ENSURE_SUCCESS(rv, rv);

    MonitorAutoLock monitor(mThreadObserver->GetMonitor());
    mScopesHavingData.PutEntry(foundScope);
  }

  return NS_OK;
}
nsresult
nsDOMStoragePersistentDB::Init(const nsString& aDatabaseName)
{
  nsresult rv;

  nsCOMPtr<nsIFile> storageFile;
  rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
                              getter_AddRefs(storageFile));
  NS_ENSURE_SUCCESS(rv, rv);
  rv = storageFile->Append(aDatabaseName);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<mozIStorageService> service;

  service = do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID, &rv);
  NS_ENSURE_SUCCESS(rv, rv);
  rv = service->OpenDatabase(storageFile, getter_AddRefs(mConnection));
  if (rv == NS_ERROR_FILE_CORRUPTED) {
    // delete the db and try opening again
    rv = storageFile->Remove(PR_FALSE);
    NS_ENSURE_SUCCESS(rv, rv);
    rv = service->OpenDatabase(storageFile, getter_AddRefs(mConnection));
  }
  NS_ENSURE_SUCCESS(rv, rv);

  rv = mConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        "PRAGMA temp_store = MEMORY"));
  NS_ENSURE_SUCCESS(rv, rv);

  mozStorageTransaction transaction(mConnection, PR_FALSE);

  // Ensure Gecko 1.9.1 storage table
  rv = mConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         "CREATE TABLE IF NOT EXISTS webappsstore2 ("
         "scope TEXT, "
         "key TEXT, "
         "value TEXT, "
         "secure INTEGER, "
         "owner TEXT)"));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = mConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        "CREATE UNIQUE INDEX IF NOT EXISTS scope_key_index"
        " ON webappsstore2(scope, key)"));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = mConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         "CREATE TEMPORARY TABLE webappsstore2_temp ("
         "scope TEXT, "
         "key TEXT, "
         "value TEXT, "
         "secure INTEGER, "
         "owner TEXT)"));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = mConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        "CREATE UNIQUE INDEX scope_key_index_temp"
        " ON webappsstore2_temp(scope, key)"));
  NS_ENSURE_SUCCESS(rv, rv);


  rv = mConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        "CREATE TEMPORARY VIEW webappsstore2_view AS "
        "SELECT * FROM webappsstore2_temp "
        "UNION ALL "
        "SELECT * FROM webappsstore2 "
          "WHERE NOT EXISTS ("
            "SELECT scope, key FROM webappsstore2_temp "
            "WHERE scope = webappsstore2.scope AND key = webappsstore2.key)"));
  NS_ENSURE_SUCCESS(rv, rv);

  // carry deletion to both the temporary table and the disk table
  rv = mConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        "CREATE TEMPORARY TRIGGER webappsstore2_view_delete_trigger "
        "INSTEAD OF DELETE ON webappsstore2_view "
        "BEGIN "
          "DELETE FROM webappsstore2_temp "
          "WHERE scope = OLD.scope AND key = OLD.key; "
          "DELETE FROM webappsstore2 "
          "WHERE scope = OLD.scope AND key = OLD.key; "
        "END"));
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<mozIStorageFunction> function1(new nsReverseStringSQLFunction());
  NS_ENSURE_TRUE(function1, NS_ERROR_OUT_OF_MEMORY);

  rv = mConnection->CreateFunction(NS_LITERAL_CSTRING("REVERSESTRING"), 1, function1);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<mozIStorageFunction> function2(new nsIsOfflineSQLFunction());
  NS_ENSURE_TRUE(function2, NS_ERROR_OUT_OF_MEMORY);

  rv = mConnection->CreateFunction(NS_LITERAL_CSTRING("ISOFFLINE"), 1, function2);
  NS_ENSURE_SUCCESS(rv, rv);

  PRBool exists;

  // Check if there is storage of Gecko 1.9.0 and if so, upgrade that storage
  // to actual webappsstore2 table and drop the obsolete table. First process
  // this newer table upgrade to priority potential duplicates from older
  // storage table.
  rv = mConnection->TableExists(NS_LITERAL_CSTRING("webappsstore"),
                                &exists);
  NS_ENSURE_SUCCESS(rv, rv);

  if (exists) {
      rv = mConnection->ExecuteSimpleSQL(
             NS_LITERAL_CSTRING("INSERT OR IGNORE INTO "
                                "webappsstore2(scope, key, value, secure, owner) "
                                "SELECT REVERSESTRING(domain) || '.:', key, value, secure, owner "
                                "FROM webappsstore"));
      NS_ENSURE_SUCCESS(rv, rv);

      rv = mConnection->ExecuteSimpleSQL(
             NS_LITERAL_CSTRING("DROP TABLE webappsstore"));
      NS_ENSURE_SUCCESS(rv, rv);
  }

  // Check if there is storage of Gecko 1.8 and if so, upgrade that storage
  // to actual webappsstore2 table and drop the obsolete table. Potential
  // duplicates will be ignored.
  rv = mConnection->TableExists(NS_LITERAL_CSTRING("moz_webappsstore"),
                                &exists);
  NS_ENSURE_SUCCESS(rv, rv);

  if (exists) {
      rv = mConnection->ExecuteSimpleSQL(
             NS_LITERAL_CSTRING("INSERT OR IGNORE INTO "
                                "webappsstore2(scope, key, value, secure, owner) "
                                "SELECT REVERSESTRING(domain) || '.:', key, value, secure, domain "
                                "FROM moz_webappsstore"));
      NS_ENSURE_SUCCESS(rv, rv);

      rv = mConnection->ExecuteSimpleSQL(
             NS_LITERAL_CSTRING("DROP TABLE moz_webappsstore"));
      NS_ENSURE_SUCCESS(rv, rv);
  }

  // temporary - disk synchronization statements
  rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
         "INSERT INTO webappsstore2_temp"
         " SELECT * FROM webappsstore2"
         " WHERE scope = :scope AND NOT EXISTS ("
            "SELECT scope, key FROM webappsstore2_temp "
            "WHERE scope = webappsstore2.scope AND key = webappsstore2.key)"),
         getter_AddRefs(mCopyToTempTableStatement));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
         "INSERT OR REPLACE INTO webappsstore2"
         " SELECT * FROM webappsstore2_temp"
         " WHERE scope = :scope;"),
         getter_AddRefs(mCopyBackToDiskStatement));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
         "DELETE FROM webappsstore2_temp"
         " WHERE scope = :scope;"),
         getter_AddRefs(mDeleteTemporaryTableStatement));
  NS_ENSURE_SUCCESS(rv, rv);

  // retrieve all keys associated with a domain
  rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
         "SELECT key, value, secure FROM webappsstore2_temp "
         "WHERE scope = :scope"),
         getter_AddRefs(mGetAllKeysStatement));
  NS_ENSURE_SUCCESS(rv, rv);

  // retrieve a value given a domain and a key
  rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
         "SELECT value, secure FROM webappsstore2_temp "
         "WHERE scope = :scope "
         "AND key = :key"),
         getter_AddRefs(mGetKeyValueStatement));
  NS_ENSURE_SUCCESS(rv, rv);

  // insert a new key
  rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
         "INSERT OR REPLACE INTO "
         "webappsstore2_temp(scope, key, value, secure) "
         "VALUES (:scope, :key, :value, :secure)"),
         getter_AddRefs(mInsertKeyStatement));
  NS_ENSURE_SUCCESS(rv, rv);

  // update the secure status of an existing key
  rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
         "UPDATE webappsstore2_temp "
         "SET secure = :secure "
         "WHERE scope = :scope "
         "AND key = :key "),
         getter_AddRefs(mSetSecureStatement));
  NS_ENSURE_SUCCESS(rv, rv);

  // remove a key
  rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
         "DELETE FROM webappsstore2_view "
         "WHERE scope = :scope "
         "AND key = :key"),
         getter_AddRefs(mRemoveKeyStatement));
  NS_ENSURE_SUCCESS(rv, rv);

  // remove keys owned by a specific domain
  rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
         "DELETE FROM webappsstore2_view "
         "WHERE scope GLOB :scope"),
         getter_AddRefs(mRemoveOwnerStatement));
  NS_ENSURE_SUCCESS(rv, rv);

  // remove keys belonging exactly only to a specific domain
  rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
         "DELETE FROM webappsstore2_view "
         "WHERE scope = :scope"),
         getter_AddRefs(mRemoveStorageStatement));
  NS_ENSURE_SUCCESS(rv, rv);

  // remove all keys
  rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
         "DELETE FROM webappsstore2_view"),
         getter_AddRefs(mRemoveAllStatement));
  NS_ENSURE_SUCCESS(rv, rv);

  // check the usage for a given owner that is an offline-app allowed domain
  rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
         "SELECT SUM(LENGTH(key) + LENGTH(value)) "
         "FROM ("
           "SELECT key,value FROM webappsstore2_temp "
           "WHERE scope GLOB :scope "
           "UNION ALL "
           "SELECT key,value FROM webappsstore2 "
           "WHERE scope GLOB :scope "
           "AND NOT EXISTS ("
             "SELECT scope, key "
             "FROM webappsstore2_temp "
             "WHERE scope = webappsstore2.scope "
             "AND key = webappsstore2.key"
           ")"
         ")"),
         getter_AddRefs(mGetFullUsageStatement));
  NS_ENSURE_SUCCESS(rv, rv);

  // check the usage for a given owner that is not an offline-app allowed domain
  rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
         "SELECT SUM(LENGTH(key) + LENGTH(value)) "
         "FROM ("
           "SELECT key, value FROM webappsstore2_temp "
           "WHERE scope GLOB :scope "
           "AND NOT ISOFFLINE(scope) "
           "UNION ALL "
           "SELECT key, value FROM webappsstore2 "
           "WHERE scope GLOB :scope "
           "AND NOT ISOFFLINE(scope) "
           "AND NOT EXISTS ("
             "SELECT scope, key "
             "FROM webappsstore2_temp "
             "WHERE scope = webappsstore2.scope "
             "AND key = webappsstore2.key"
           ")"
         ")"),
         getter_AddRefs(mGetOfflineExcludedUsageStatement));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = transaction.Commit();
  NS_ENSURE_SUCCESS(rv, rv);

  return NS_OK;
}
Esempio n. 19
0
        virtual bool run(OperationContext* txn,  const string& dbname, BSONObj& cmdObj, int options,
                          string& errmsg, BSONObjBuilder& result,
                          bool fromRepl = false ) {

            // ---  parse

            NamespaceString ns( dbname, cmdObj[name].String() );
            Status status = userAllowedWriteNS( ns );
            if ( !status.isOK() )
                return appendCommandStatus( result, status );

            if ( cmdObj["indexes"].type() != Array ) {
                errmsg = "indexes has to be an array";
                result.append( "cmdObj", cmdObj );
                return false;
            }

            std::vector<BSONObj> specs;
            {
                BSONObjIterator i( cmdObj["indexes"].Obj() );
                while ( i.more() ) {
                    BSONElement e = i.next();
                    if ( e.type() != Object ) {
                        errmsg = "everything in indexes has to be an Object";
                        result.append( "cmdObj", cmdObj );
                        return false;
                    }
                    specs.push_back( e.Obj() );
                }
            }

            if ( specs.size() == 0 ) {
                errmsg = "no indexes to add";
                return false;
            }

            // check specs
            for ( size_t i = 0; i < specs.size(); i++ ) {
                BSONObj spec = specs[i];
                if ( spec["ns"].eoo() ) {
                    spec = _addNsToSpec( ns, spec );
                    specs[i] = spec;
                }

                if ( spec["ns"].type() != String ) {
                    errmsg = "spec has no ns";
                    result.append( "spec", spec );
                    return false;
                }
                if ( ns != spec["ns"].String() ) {
                    errmsg = "namespace mismatch";
                    result.append( "spec", spec );
                    return false;
                }
            }

            // now we know we have to create index(es)
            // Note: createIndexes command does not currently respect shard versioning.
            ScopedTransaction transaction(txn, MODE_IX);
            Lock::DBLock dbLock(txn->lockState(), ns.db(), MODE_X);
            if (!fromRepl &&
                !repl::getGlobalReplicationCoordinator()->canAcceptWritesForDatabase(dbname)) {
                return appendCommandStatus(result, Status(ErrorCodes::NotMaster, str::stream()
                    << "Not primary while creating indexes in " << ns.ns()));
            }

            Database* db = dbHolder().get(txn, ns.db());
            if (!db) {
                db = dbHolder().openDb(txn, ns.db());
            }

            Collection* collection = db->getCollection( ns.ns() );
            result.appendBool( "createdCollectionAutomatically", collection == NULL );
            if ( !collection ) {
                MONGO_WRITE_CONFLICT_RETRY_LOOP_BEGIN {
                    WriteUnitOfWork wunit(txn);
                    collection = db->createCollection( txn, ns.ns() );
                    invariant( collection );
                    if (!fromRepl) {
                        getGlobalEnvironment()->getOpObserver()->onCreateCollection(
                                txn,
                                ns,
                                CollectionOptions());
                    }
                    wunit.commit();
                } MONGO_WRITE_CONFLICT_RETRY_LOOP_END(txn, "createIndexes", ns.ns());
            }
Esempio n. 20
0
void run()
{
  /*****
   * Dbo tutorial section 3. A first session
   *****/

  /*
   * Setup a session, would typically be done once at application startup.
   *
   * For testing, we'll be using Sqlite3's special :memory: database. You
   * can replace this with an actual filename for actual persistence.
   */
  dbo::backend::Sqlite3 sqlite3(":memory:");
  sqlite3.setProperty("show-queries", "true");
  dbo::Session session;
  session.setConnection(sqlite3);

  session.mapClass<User>("user");

  /*
   * Try to create the schema (will fail if already exists).
   */
  session.createTables();

  {
    dbo::Transaction transaction(session);

    User *user = new User();
    user->name = "Joe";
    user->password = "******";
    user->role = User::Visitor;
    user->karma = 13;

    dbo::ptr<User> userPtr = session.add(user);
  }

  /*****
   * Dbo tutorial section 4. Querying objects
   *****/

  {
    dbo::Transaction transaction(session);

    dbo::ptr<User> joe = session.find<User>().where("name = ?").bind("Joe");

    std::cerr << "Joe has karma: " << joe->karma << std::endl;

    dbo::ptr<User> joe2 = session.query< dbo::ptr<User> >
      ("select u from user u").where("name = ?").bind("Joe");
  }

  {
    dbo::Transaction transaction(session);

    typedef dbo::collection< dbo::ptr<User> > Users;

    Users users = session.find<User>();

    std::cerr << "We have " << users.size() << " users:" << std::endl;

    for (Users::const_iterator i = users.begin(); i != users.end(); ++i)
      std::cerr << " user " << (*i)->name
		<< " with karma of " << (*i)->karma << std::endl;
  }

  /*****
   * Dbo tutorial section 5. Updating objects
   *****/

  {
    dbo::Transaction transaction(session);

    dbo::ptr<User> joe = session.find<User>().where("name = ?").bind("Joe");

    joe.modify()->karma++;
    joe.modify()->password = "******";
  }

  {
    dbo::Transaction transaction(session);
    dbo::ptr<User> joe = session.find<User>().where("name = ?").bind("Joe");
    if (joe)
      joe.remove();
  }

  {
    dbo::Transaction transaction(session);

    dbo::ptr<User> silly = session.add(new User());
    silly.modify()->name = "Silly";
    silly.remove();
  }

}
Esempio n. 21
0
    virtual bool run(OperationContext* txn,
                     const string& dbname,
                     BSONObj& cmdObj,
                     int options,
                     string& errmsg,
                     BSONObjBuilder& result) {
        const NamespaceString ns(parseNs(dbname, cmdObj));

        Status status = userAllowedWriteNS(ns);
        if (!status.isOK())
            return appendCommandStatus(result, status);

        if (cmdObj["indexes"].type() != Array) {
            errmsg = "indexes has to be an array";
            result.append("cmdObj", cmdObj);
            return false;
        }

        std::vector<BSONObj> specs;
        {
            BSONObjIterator i(cmdObj["indexes"].Obj());
            while (i.more()) {
                BSONElement e = i.next();
                if (e.type() != Object) {
                    errmsg = "everything in indexes has to be an Object";
                    result.append("cmdObj", cmdObj);
                    return false;
                }
                specs.push_back(e.Obj());
            }
        }

        if (specs.size() == 0) {
            errmsg = "no indexes to add";
            return false;
        }

        // check specs
        for (size_t i = 0; i < specs.size(); i++) {
            BSONObj spec = specs[i];
            if (spec["ns"].eoo()) {
                spec = _addNsToSpec(ns, spec);
                specs[i] = spec;
            }

            if (spec["ns"].type() != String) {
                errmsg = "ns field must be a string";
                result.append("spec", spec);
                return false;
            }

            std::string nsFromUser = spec["ns"].String();
            if (nsFromUser.empty()) {
                errmsg = "ns field cannot be an empty string";
                result.append("spec", spec);
                return false;
            }

            if (ns != nsFromUser) {
                errmsg = str::stream() << "value of ns field '" << nsFromUser
                                       << "' doesn't match namespace " << ns.ns();
                result.append("spec", spec);
                return false;
            }
        }

        // now we know we have to create index(es)
        // Note: createIndexes command does not currently respect shard versioning.
        ScopedTransaction transaction(txn, MODE_IX);
        Lock::DBLock dbLock(txn->lockState(), ns.db(), MODE_X);
        if (!repl::getGlobalReplicationCoordinator()->canAcceptWritesFor(ns)) {
            return appendCommandStatus(
                result,
                Status(ErrorCodes::NotMaster,
                       str::stream() << "Not primary while creating indexes in " << ns.ns()));
        }

        Database* db = dbHolder().get(txn, ns.db());
        if (!db) {
            db = dbHolder().openDb(txn, ns.db());
        }

        Collection* collection = db->getCollection(ns.ns());
        if (collection) {
            result.appendBool("createdCollectionAutomatically", false);
        } else {
            MONGO_WRITE_CONFLICT_RETRY_LOOP_BEGIN {
                WriteUnitOfWork wunit(txn);
                collection = db->createCollection(txn, ns.ns(), CollectionOptions());
                invariant(collection);
                wunit.commit();
            }
            MONGO_WRITE_CONFLICT_RETRY_LOOP_END(txn, "createIndexes", ns.ns());
            result.appendBool("createdCollectionAutomatically", true);
        }

        const int numIndexesBefore = collection->getIndexCatalog()->numIndexesTotal(txn);
        result.append("numIndexesBefore", numIndexesBefore);

        auto client = txn->getClient();
        ScopeGuard lastOpSetterGuard =
            MakeObjGuard(repl::ReplClientInfo::forClient(client),
                         &repl::ReplClientInfo::setLastOpToSystemLastOpTime,
                         txn);

        MultiIndexBlock indexer(txn, collection);
        indexer.allowBackgroundBuilding();
        indexer.allowInterruption();

        const size_t origSpecsSize = specs.size();
        indexer.removeExistingIndexes(&specs);

        if (specs.size() == 0) {
            result.append("numIndexesAfter", numIndexesBefore);
            result.append("note", "all indexes already exist");
            return true;
        }

        if (specs.size() != origSpecsSize) {
            result.append("note", "index already exists");
        }

        for (size_t i = 0; i < specs.size(); i++) {
            const BSONObj& spec = specs[i];
            if (spec["unique"].trueValue()) {
                status = checkUniqueIndexConstraints(txn, ns.ns(), spec["key"].Obj());

                if (!status.isOK()) {
                    return appendCommandStatus(result, status);
                }
            }
            if (spec["v"].isNumber() && spec["v"].numberInt() == 0) {
                return appendCommandStatus(
                    result,
                    Status(ErrorCodes::CannotCreateIndex,
                           str::stream() << "illegal index specification: " << spec << ". "
                                         << "The option v:0 cannot be passed explicitly"));
            }
        }

        MONGO_WRITE_CONFLICT_RETRY_LOOP_BEGIN {
            uassertStatusOK(indexer.init(specs));
        }
        MONGO_WRITE_CONFLICT_RETRY_LOOP_END(txn, "createIndexes", ns.ns());

        // If we're a background index, replace exclusive db lock with an intent lock, so that
        // other readers and writers can proceed during this phase.
        if (indexer.getBuildInBackground()) {
            txn->recoveryUnit()->abandonSnapshot();
            dbLock.relockWithMode(MODE_IX);
            if (!repl::getGlobalReplicationCoordinator()->canAcceptWritesFor(ns)) {
                return appendCommandStatus(
                    result,
                    Status(ErrorCodes::NotMaster,
                           str::stream() << "Not primary while creating background indexes in "
                                         << ns.ns()));
            }
        }

        try {
            Lock::CollectionLock colLock(txn->lockState(), ns.ns(), MODE_IX);
            uassertStatusOK(indexer.insertAllDocumentsInCollection());
        } catch (const DBException& e) {
            invariant(e.getCode() != ErrorCodes::WriteConflict);
            // Must have exclusive DB lock before we clean up the index build via the
            // destructor of 'indexer'.
            if (indexer.getBuildInBackground()) {
                try {
                    // This function cannot throw today, but we will preemptively prepare for
                    // that day, to avoid data corruption due to lack of index cleanup.
                    txn->recoveryUnit()->abandonSnapshot();
                    dbLock.relockWithMode(MODE_X);
                    if (!repl::getGlobalReplicationCoordinator()->canAcceptWritesFor(ns)) {
                        return appendCommandStatus(
                            result,
                            Status(ErrorCodes::NotMaster,
                                   str::stream()
                                       << "Not primary while creating background indexes in "
                                       << ns.ns() << ": cleaning up index build failure due to "
                                       << e.toString()));
                    }
                } catch (...) {
                    std::terminate();
                }
            }
            throw;
        }
        // Need to return db lock back to exclusive, to complete the index build.
        if (indexer.getBuildInBackground()) {
            txn->recoveryUnit()->abandonSnapshot();
            dbLock.relockWithMode(MODE_X);
            uassert(ErrorCodes::NotMaster,
                    str::stream() << "Not primary while completing index build in " << dbname,
                    repl::getGlobalReplicationCoordinator()->canAcceptWritesFor(ns));

            Database* db = dbHolder().get(txn, ns.db());
            uassert(28551, "database dropped during index build", db);
            uassert(28552, "collection dropped during index build", db->getCollection(ns.ns()));
        }

        MONGO_WRITE_CONFLICT_RETRY_LOOP_BEGIN {
            WriteUnitOfWork wunit(txn);

            indexer.commit();

            for (size_t i = 0; i < specs.size(); i++) {
                std::string systemIndexes = ns.getSystemIndexesCollection();
                getGlobalServiceContext()->getOpObserver()->onCreateIndex(
                    txn, systemIndexes, specs[i]);
            }

            wunit.commit();
        }
        MONGO_WRITE_CONFLICT_RETRY_LOOP_END(txn, "createIndexes", ns.ns());

        result.append("numIndexesAfter", collection->getIndexCatalog()->numIndexesTotal(txn));

        lastOpSetterGuard.Dismiss();

        return true;
    }
Esempio n. 22
0
void Database::scheduleTransaction()
{
    ASSERT(!m_transactionInProgressMutex.tryLock()); // Locked by caller.
    RefPtr<SQLTransactionBackend> transaction;

    if (m_isTransactionQueueEnabled && !m_transactionQueue.isEmpty())
        transaction = m_transactionQueue.takeFirst();

    if (transaction && databaseContext()->databaseThread()) {
        auto task = DatabaseTransactionTask::create(transaction);
        LOG(StorageAPI, "Scheduling DatabaseTransactionTask %p for transaction %p\n", task.get(), task->transaction());
        m_transactionInProgress = true;
        databaseContext()->databaseThread()->scheduleTask(WTF::move(task));
    } else
        m_transactionInProgress = false;
}
Esempio n. 23
0
void repairDatabasesAndCheckVersion(OperationContext* txn) {
    LOG(1) << "enter repairDatabases (to check pdfile version #)";

    ScopedTransaction transaction(txn, MODE_X);
    Lock::GlobalWrite lk(txn->lockState());

    vector<string> dbNames;

    StorageEngine* storageEngine = txn->getServiceContext()->getGlobalStorageEngine();
    storageEngine->listDatabases(&dbNames);

    // Repair all databases first, so that we do not try to open them if they are in bad shape
    if (storageGlobalParams.repair) {
        invariant(!storageGlobalParams.readOnly);
        for (vector<string>::const_iterator i = dbNames.begin(); i != dbNames.end(); ++i) {
            const string dbName = *i;
            LOG(1) << "    Repairing database: " << dbName;

            fassert(18506, repairDatabase(txn, storageEngine, dbName));
        }
    }

    const repl::ReplSettings& replSettings = repl::getGlobalReplicationCoordinator()->getSettings();

    // On replica set members we only clear temp collections on DBs other than "local" during
    // promotion to primary. On pure slaves, they are only cleared when the oplog tells them
    // to. The local DB is special because it is not replicated.  See SERVER-10927 for more
    // details.
    const bool shouldClearNonLocalTmpCollections =
        !(checkIfReplMissingFromCommandLine(txn) || replSettings.usingReplSets() ||
          replSettings.isSlave());

    const bool shouldDoCleanupForSERVER23299 = isSubjectToSERVER23299(txn);

    for (vector<string>::const_iterator i = dbNames.begin(); i != dbNames.end(); ++i) {
        const string dbName = *i;
        LOG(1) << "    Recovering database: " << dbName;

        Database* db = dbHolder().openDb(txn, dbName);
        invariant(db);

        // First thing after opening the database is to check for file compatibility,
        // otherwise we might crash if this is a deprecated format.
        auto status = db->getDatabaseCatalogEntry()->currentFilesCompatible(txn);
        if (!status.isOK()) {
            if (status.code() == ErrorCodes::CanRepairToDowngrade) {
                // Convert CanRepairToDowngrade statuses to MustUpgrade statuses to avoid logging a
                // potentially confusing and inaccurate message.
                //
                // TODO SERVER-24097: Log a message informing the user that they can start the
                // current version of mongod with --repair and then proceed with normal startup.
                status = {ErrorCodes::MustUpgrade, status.reason()};
            }
            severe() << "Unable to start mongod due to an incompatibility with the data files and"
                        " this version of mongod: "
                     << redact(status);
            severe() << "Please consult our documentation when trying to downgrade to a previous"
                        " major release";
            quickExit(EXIT_NEED_UPGRADE);
            return;
        }

        // Check if admin.system.version contains an invalid featureCompatibilityVersion.
        // If a valid featureCompatibilityVersion is present, cache it as a server parameter.
        if (dbName == "admin") {
            if (Collection* versionColl =
                    db->getCollection(FeatureCompatibilityVersion::kCollection)) {
                BSONObj featureCompatibilityVersion;
                if (Helpers::findOne(txn,
                                     versionColl,
                                     BSON("_id" << FeatureCompatibilityVersion::kParameterName),
                                     featureCompatibilityVersion)) {
                    auto version = FeatureCompatibilityVersion::parse(featureCompatibilityVersion);
                    if (!version.isOK()) {
                        severe() << version.getStatus();
                        fassertFailedNoTrace(40283);
                    }
                    serverGlobalParams.featureCompatibilityVersion.store(version.getValue());
                }
            }
        }

        // Major versions match, check indexes
        const string systemIndexes = db->name() + ".system.indexes";

        Collection* coll = db->getCollection(systemIndexes);
        unique_ptr<PlanExecutor> exec(
            InternalPlanner::collectionScan(txn, systemIndexes, coll, PlanExecutor::YIELD_MANUAL));

        BSONObj index;
        PlanExecutor::ExecState state;
        while (PlanExecutor::ADVANCED == (state = exec->getNext(&index, NULL))) {
            const BSONObj key = index.getObjectField("key");
            const string plugin = IndexNames::findPluginName(key);

            if (db->getDatabaseCatalogEntry()->isOlderThan24(txn)) {
                if (IndexNames::existedBefore24(plugin)) {
                    continue;
                }

                log() << "Index " << index << " claims to be of type '" << plugin << "', "
                      << "which is either invalid or did not exist before v2.4. "
                      << "See the upgrade section: "
                      << "http://dochub.mongodb.org/core/upgrade-2.4" << startupWarningsLog;
            }

            const Status keyStatus = validateKeyPattern(key);
            if (!keyStatus.isOK()) {
                log() << "Problem with index " << index << ": " << redact(keyStatus)
                      << " This index can still be used however it cannot be rebuilt."
                      << " For more info see"
                      << " http://dochub.mongodb.org/core/index-validation" << startupWarningsLog;
            }

            if (index["v"].isNumber() && index["v"].numberInt() == 0) {
                log() << "WARNING: The index: " << index << " was created with the deprecated"
                      << " v:0 format.  This format will not be supported in a future release."
                      << startupWarningsLog;
                log() << "\t To fix this, you need to rebuild this index."
                      << " For instructions, see http://dochub.mongodb.org/core/rebuild-v0-indexes"
                      << startupWarningsLog;
            }
        }

        // Non-yielding collection scans from InternalPlanner will never error.
        invariant(PlanExecutor::IS_EOF == state);

        if (replSettings.usingReplSets()) {
            // We only care about the _id index if we are in a replset
            checkForIdIndexes(txn, db);
            // Ensure oplog is capped (mmap does not guarantee order of inserts on noncapped
            // collections)
            if (db->name() == "local") {
                checkForCappedOplog(txn, db);
            }
        }

        if (shouldDoCleanupForSERVER23299) {
            handleSERVER23299ForDb(txn, db);
        }

        if (!storageGlobalParams.readOnly &&
            (shouldClearNonLocalTmpCollections || dbName == "local")) {
            db->clearTmpCollections(txn);
        }
    }

    LOG(1) << "done repairDatabases";
}
void LocalStorageDatabase::updateDatabaseWithChangedItems(const HashMap<String, String>& changedItems)
{
    if (!m_database.isOpen())
        openDatabase(CreateIfNonExistent);
    if (!m_database.isOpen())
        return;

    if (m_shouldClearItems) {
        m_shouldClearItems = false;

        SQLiteStatement clearStatement(m_database, "DELETE FROM ItemTable");
        if (clearStatement.prepare() != SQLResultOk) {
            LOG_ERROR("Failed to prepare clear statement - cannot write to local storage database");
            return;
        }

        int result = clearStatement.step();
        if (result != SQLResultDone) {
            LOG_ERROR("Failed to clear all items in the local storage database - %i", result);
            return;
        }
    }

    SQLiteStatement insertStatement(m_database, "INSERT INTO ItemTable VALUES (?, ?)");
    if (insertStatement.prepare() != SQLResultOk) {
        LOG_ERROR("Failed to prepare insert statement - cannot write to local storage database");
        return;
    }

    SQLiteStatement deleteStatement(m_database, "DELETE FROM ItemTable WHERE key=?");
    if (deleteStatement.prepare() != SQLResultOk) {
        LOG_ERROR("Failed to prepare delete statement - cannot write to local storage database");
        return;
    }

    SQLiteTransaction transaction(m_database);
    transaction.begin();

    HashMap<String, String>::const_iterator it = changedItems.begin();
    const HashMap<String, String>::const_iterator end = changedItems.end();
    for (; it != end; ++it) {
        // A null value means that the key/value pair should be deleted.
        SQLiteStatement& statement = it->value.isNull() ? deleteStatement : insertStatement;

        statement.bindText(1, it->key);

        // If we're inserting a key/value pair, bind the value as well.
        if (!it->value.isNull())
            statement.bindBlob(2, it->value);

        int result = statement.step();
        if (result != SQLResultDone) {
            LOG_ERROR("Failed to update item in the local storage database - %i", result);
            break;
        }

        statement.reset();
    }

    transaction.commit();
}
Esempio n. 25
0
void KisTransactionTest::testUndoWithUnswitchedFrames()
{
    KisSurrogateUndoAdapter undoAdapter;
    const QRect imageRect(0,0,100,100);


    const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();
    KisPaintDeviceSP dev = new KisPaintDevice(cs);

    TestUtil::TestingTimedDefaultBounds *bounds = new TestUtil::TestingTimedDefaultBounds();
    dev->setDefaultBounds(bounds);

    KisRasterKeyframeChannel *channel = dev->createKeyframeChannel(KisKeyframeChannel::Content);
    QVERIFY(channel);

    KisPaintDeviceFramesInterface *i = dev->framesInterface();
    QVERIFY(i);

    QCOMPARE(i->frames().size(), 1);


    dev->fill(QRect(10,10,20,20), KoColor(Qt::white, cs));

    KIS_DUMP_DEVICE_2(dev, imageRect, "00_f0_w20", "dd");
    QCOMPARE(dev->exactBounds(), QRect(10,10,20,20));


    // add keyframe at position 10
    channel->addKeyframe(10);

    // add keyframe at position 11
    channel->addKeyframe(11);

    // add keyframe at position 12
    channel->addKeyframe(12);

    KIS_DUMP_DEVICE_2(dev, imageRect, "01_f0_b20", "dd");
    QCOMPARE(dev->exactBounds(), QRect(10,10,20,20));

    {
        KisTransaction transaction(kundo2_noi18n("first_stroke"), dev, 0);

        dev->clear();
        dev->fill(QRect(40,40,21,21), KoColor(Qt::red, cs));

        transaction.commit(&undoAdapter);

        KIS_DUMP_DEVICE_2(dev, imageRect, "02_f0_b21_stroke", "dd");
        QCOMPARE(dev->exactBounds(), QRect(40,40,21,21));
    }

    // switch to frame 10
    bounds->testingSetTime(10);

    KIS_DUMP_DEVICE_2(dev, imageRect, "03_f10_b0_switched", "dd");
    QVERIFY(dev->exactBounds().isEmpty());

    {
        KisTransaction transaction(kundo2_noi18n("second_stroke"), dev, 0);

        dev->fill(QRect(60,60,22,22), KoColor(Qt::green, cs));

        transaction.commit(&undoAdapter);

        KIS_DUMP_DEVICE_2(dev, imageRect, "04_f10_b22_stroke", "dd");
        QCOMPARE(dev->exactBounds(), QRect(60,60,22,22));
    }

    undoAdapter.undo();

    KIS_DUMP_DEVICE_2(dev, imageRect, "05_f10_b0_undone", "dd");
    QVERIFY(dev->exactBounds().isEmpty());

    bounds->testingSetTime(0);
    KIS_DUMP_DEVICE_2(dev, imageRect, "06_f0_b21_undone", "dd");
    QCOMPARE(dev->exactBounds(), QRect(40,40,21,21));

    bounds->testingSetTime(10);
    QVERIFY(dev->exactBounds().isEmpty());

    undoAdapter.undo();

    KIS_DUMP_DEVICE_2(dev, imageRect, "07_f10_b0_undone_x2", "dd");
    QVERIFY(dev->exactBounds().isEmpty());

    bounds->testingSetTime(0);
    KIS_DUMP_DEVICE_2(dev, imageRect, "08_f0_b20_undone_x2", "dd");
    QCOMPARE(dev->exactBounds(), QRect(10,10,20,20));

    {
        KisTransaction transaction(kundo2_noi18n("third_move"), dev, 0);

        dev->moveTo(17,17);

        transaction.commit(&undoAdapter);

        KIS_DUMP_DEVICE_2(dev, imageRect, "09_f0_o27_move", "dd");
        QCOMPARE(dev->exactBounds(), QRect(27,27,20,20));
    }

    bounds->testingSetTime(10);
    QVERIFY(dev->exactBounds().isEmpty());

    undoAdapter.undo();

    KIS_DUMP_DEVICE_2(dev, imageRect, "10_f10_b0_undone_x3", "dd");
    QVERIFY(dev->exactBounds().isEmpty());

    bounds->testingSetTime(0);
    KIS_DUMP_DEVICE_2(dev, imageRect, "11_f0_b20_undone_x3", "dd");
    QCOMPARE(dev->exactBounds(), QRect(10,10,20,20));
}
Esempio n. 26
0
TreeItem* TraktorFeature::importLibrary(QString file) {
    //Give thread a low priority
    QThread* thisThread = QThread::currentThread();
    thisThread->setPriority(QThread::LowestPriority);
    //Invisible root item of Traktor's child model
    TreeItem* root = NULL;
    //Delete all table entries of Traktor feature
    ScopedTransaction transaction(m_database);
    clearTable("traktor_playlist_tracks");
    clearTable("traktor_library");
    clearTable("traktor_playlists");
    transaction.commit();

    transaction.transaction();
    QSqlQuery query(m_database);
    query.prepare("INSERT INTO traktor_library (artist, title, album, year,"
                  "genre,comment,tracknumber,bpm, bitrate,duration, location,"
                  "rating,key) VALUES (:artist, :title, :album, :year,:genre,"
                  ":comment, :tracknumber,:bpm, :bitrate,:duration, :location,"
                  ":rating,:key)");

    //Parse Trakor XML file using SAX (for performance)
    QFile traktor_file(file);
    if (!traktor_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "Cannot open Traktor music collection";
        return NULL;
    }
    QXmlStreamReader xml(&traktor_file);
    bool inCollectionTag = false;
    //TODO(XXX) is this still needed to parse the library correctly?
    bool inEntryTag = false;
    bool inPlaylistsTag = false;
    bool isRootFolderParsed = false;
    int nAudioFiles = 0;

    while (!xml.atEnd() && !m_cancelImport) {
        xml.readNext();
        if (xml.isStartElement()) {
            if (xml.name() == "COLLECTION") {
                inCollectionTag = true;
            }
            // Each "ENTRY" tag in <COLLECTION> represents a track
            if (inCollectionTag && xml.name() == "ENTRY" ) {
                inEntryTag = true;
                //parse track
                parseTrack(xml, query);
                ++nAudioFiles; //increment number of files in the music collection
            }
            if (xml.name() == "PLAYLISTS") {
                inPlaylistsTag = true;
            } if (inPlaylistsTag && !isRootFolderParsed && xml.name() == "NODE") {
                QXmlStreamAttributes attr = xml.attributes();
                QString nodetype = attr.value("TYPE").toString();
                QString name = attr.value("NAME").toString();

                if (nodetype == "FOLDER" && name == "$ROOT") {
                    //process all playlists
                    root = parsePlaylists(xml);
                    isRootFolderParsed = true;
                }
            }
        }
        if (xml.isEndElement()) {
            if (xml.name() == "COLLECTION") {
                inCollectionTag = false;
            }
            if (xml.name() == "ENTRY" && inCollectionTag) {
                inEntryTag = false;
            }
            if (xml.name() == "PLAYLISTS" && inPlaylistsTag) {
                inPlaylistsTag = false;
            }
        }
    }
    if (xml.hasError()) {
         // do error handling
         qDebug() << "Cannot process Traktor music collection";
         if (root)
             delete root;
         return NULL;
    }

    qDebug() << "Found: " << nAudioFiles << " audio files in Traktor";
    //initialize TraktorTableModel
    transaction.commit();

    return root;
}
Esempio n. 27
0
///////////////////////////////////////////////////////////////////////////////
/// \brief  Saves a set of WindowSettings to a bed.
///
/// \details The bed and Id that are saved to are determined by the id field
///         of the WindowSettings object passed in.  If the WindowSettings 
///         already exist in the bed, a new history index will be created.
///
///         If there is a problem saving the WindowSettings, a warning will
///         be emitted, and false will be returned.
///
/// \param  window_settings The WindowSettings to save.
/// \return \c true if the WindowSettings were saved successfully.
///
/// \ingroup loading
bool saveWindowSettings(const WindowSettings& window_settings)
{
   try
   {
      std::shared_ptr<bed::Bed> bed = bed::openWritable(window_settings.id.bed);
      if (!bed)
         throw std::runtime_error("Could not open bed for writing!");

      bed::Db& db = bed->getDb();

      bed::Transaction transaction(db, bed::Transaction::Immediate);

      int history_index = 0;
   
      if (db.getInt(BE_WND_WINDOW_SETTINGS_SQL_TABLE_EXISTS, 0) == 0)
      {
         db.exec(BE_WND_WINDOW_SETTINGS_SQL_CREATE_TABLE);
      }
      else
      {
         bed::Stmt latest(db, Id(BE_WND_WINDOW_SETTINGS_SQLID_LATEST_INDEX), BE_WND_WINDOW_SETTINGS_SQL_LATEST_INDEX);
         latest.bind(1, window_settings.id.asset.value());
         if (latest.step())
            history_index = latest.getInt(0);
      }

      bed::Stmt save(db, Id(BE_WND_WINDOW_SETTINGS_SQLID_SAVE), BE_WND_WINDOW_SETTINGS_SQL_SAVE);
      save.bind(1, window_settings.id.asset.value());
      save.bind(2, history_index + 1);
      save.bind(3, static_cast<int>(window_settings.mode));
      save.bind(4, window_settings.system_positioned);
      save.bind(5, window_settings.save_position_on_close);
      save.bind(6, window_settings.position.x);
      save.bind(7, window_settings.position.y);
      save.bind(8, window_settings.size.x);
      save.bind(9, window_settings.size.y);
      save.bind(10, window_settings.monitor_index);
      save.bind(11, window_settings.refresh_rate);
      save.bind(12, static_cast<int>(window_settings.v_sync));
      save.bind(13, window_settings.msaa_level);
      save.bind(14, window_settings.red_bits);
      save.bind(15, window_settings.green_bits);
      save.bind(16, window_settings.blue_bits);
      save.bind(17, window_settings.alpha_bits);
      save.bind(18, window_settings.depth_bits);
      save.bind(19, window_settings.stencil_bits);
      save.bind(20, window_settings.srgb_capable);
      save.bind(21, window_settings.use_custom_gamma);
      save.bind(22, window_settings.custom_gamma);
      save.bind(23, window_settings.context_version_major);
      save.bind(24, window_settings.context_version_minor);
      save.bind(25, window_settings.forward_compatible_context ? 1 : 0);
      save.bind(26, window_settings.debug_context ? 1 : 0);
      save.bind(27, static_cast<int>(window_settings.context_profile_type));
      
      save.step();
      transaction.commit();
      return true;
   }
   catch (const bed::Db::error& err)
   {
      BE_LOG(VWarning) << "Database error while saving window settings!" << BE_LOG_NL
                       << "              Bed: " << window_settings.id.bed << BE_LOG_NL
                       << "WindowSettings ID: " << window_settings.id.asset << BE_LOG_NL
                       << "        Exception: " << err.what() << BE_LOG_NL
                       << "              SQL: " << err.sql() << BE_LOG_END;
   }
   catch (const std::runtime_error& err)
   {
      BE_LOG(VWarning) << "Exception while saving window settings!" << BE_LOG_NL
                       << "              Bed: " << window_settings.id.bed << BE_LOG_NL
                       << "WindowSettings ID: " << window_settings.id.asset << BE_LOG_NL
                       << "        Exception: " << err.what() << BE_LOG_END;
   }

   return false;
}
Esempio n. 28
0
QSet<int> DirectoryDAO::relocateDirectory(const QString& oldFolder,
                                          const QString& newFolder) {
    // TODO(rryan): This method could use error reporting. It can fail in
    // mysterious ways for example if a track in the oldFolder also has a zombie
    // track location in newFolder then the replace query will fail because the
    // location column becomes non-unique.
    ScopedTransaction transaction(m_database);
    QSqlQuery query(m_database);
    query.prepare("UPDATE " % DIRECTORYDAO_TABLE % " SET " % DIRECTORYDAO_DIR % "="
                  ":newFolder WHERE " % DIRECTORYDAO_DIR % " = :oldFolder");
    query.bindValue(":newFolder", newFolder);
    query.bindValue(":oldFolder", oldFolder);
    if (!query.exec()) {
        LOG_FAILED_QUERY(query) << "coud not relocate directory"
                                << oldFolder << "to" << newFolder;
        return QSet<int>();
    }

    FieldEscaper escaper(m_database);
    QString startsWithOldFolder =
            escaper.escapeString(escaper.escapeStringForLike(oldFolder % '/', '%') + '%');
    // Also update information in the track_locations table. This is where mixxx
    // gets the location information for a track.
    query.prepare(QString("SELECT library.id, track_locations.id, track_locations.location "
                          "FROM library INNER JOIN track_locations ON "
                          "track_locations.id = library.location WHERE "
                          "track_locations.location LIKE %1 ESCAPE '%'")
                  .arg(startsWithOldFolder));
    if (!query.exec()) {
        LOG_FAILED_QUERY(query) << "coud not relocate path of tracks";
        return QSet<int>();
    }

    QSet<int> ids;
    QList<int> loc_ids;
    QStringList old_locs;
    while (query.next()) {
        ids.insert(query.value(0).toInt());
        loc_ids.append(query.value(1).toInt());
        old_locs.append(query.value(2).toString());
    }

    QString replacement("UPDATE track_locations SET location = :newloc "
                        "WHERE id = :id");
    query.prepare(replacement);
    for (int i = 0; i < loc_ids.size(); ++i) {
        QString newloc = old_locs.at(i);
        newloc.replace(0, oldFolder.size(), newFolder);
        query.bindValue("newloc", newloc);
        query.bindValue("id", loc_ids.at(i));
        if (!query.exec()) {
            LOG_FAILED_QUERY(query) << "coud not relocate path of tracks";
            return QSet<int>();
        }
    }

    qDebug() << "Relocated tracks:" << ids.size();

    transaction.commit();
    return ids;
}
Esempio n. 29
0
void LibraryScanner::slotStartScan() {
    qDebug() << "LibraryScanner::slotStartScan";
    QSet<QString> trackLocations = m_trackDao.getTrackLocations();
    QHash<QString, int> directoryHashes = m_libraryHashDao.getDirectoryHashes();
    QRegExp extensionFilter =
            QRegExp(SoundSourceProxy::supportedFileExtensionsRegex(),
                    Qt::CaseInsensitive);
    QRegExp coverExtensionFilter =
            QRegExp(CoverArtUtils::supportedCoverArtExtensionsRegex(),
                    Qt::CaseInsensitive);
    QStringList directoryBlacklist = ScannerUtil::getDirectoryBlacklist();

    m_scannerGlobal = ScannerGlobalPointer(
        new ScannerGlobal(trackLocations, directoryHashes, extensionFilter,
                          coverExtensionFilter, directoryBlacklist));
    m_scannerGlobal->startTimer();

    emit(scanStarted());

    // Try to upgrade the library from 1.7 (XML) to 1.8+ (DB) if needed. If the
    // upgrade_filename already exists, then do not try to upgrade since we have
    // already done it.
    // TODO(XXX) SETTINGS_PATH may change in new Mixxx Versions. Here we need
    // the SETTINGS_PATH from Mixxx V <= 1.7
    QString upgrade_filename = QDir::homePath().append("/").append(SETTINGS_PATH).append("DBUPGRADED");
    qDebug() << "upgrade filename is " << upgrade_filename;
    QFile upgradefile(upgrade_filename);
    if (!upgradefile.exists()) {
        QTime t2;
        t2.start();
        LegacyLibraryImporter libImport(m_trackDao, m_playlistDao);
        connect(&libImport, SIGNAL(progress(QString)),
                this, SIGNAL(progressLoading(QString)));
        ScopedTransaction transaction(m_database);
        libImport.import();
        transaction.commit();
        qDebug("Legacy importer took %d ms", t2.elapsed());
    }

    // First, we're going to mark all the directories that we've previously
    // hashed as needing verification. As we search through the directory tree
    // when we rescan, we'll mark any directory that does still exist as
    // verified.
    m_libraryHashDao.invalidateAllDirectories();

    // Mark all the tracks in the library as needing verification of their
    // existence. (ie. we want to check they're still on your hard drive where
    // we think they are)
    m_trackDao.invalidateTrackLocationsInLibrary();

    qDebug() << "Recursively scanning library.";

    // Start scanning the library. This prepares insertion queries in TrackDAO
    // (must be called before calling addTracksAdd) and begins a transaction.
    m_trackDao.addTracksPrepare();

    // Recursivly scan each directory in the directories table.
    QStringList dirs = m_directoryDao.getDirs();

    // If there are no directories then we have nothing to do. Cleanup and
    // finish the scan immediately.
    if (dirs.isEmpty()) {
        slotFinishScan();
        return;
    }

    // Queue up recursive scan tasks for every directory. When all tasks are
    // done, TaskWatcher will signal slotFinishScan.
    TaskWatcher* pWatcher = &m_scannerGlobal->getTaskWatcher();
    connect(pWatcher, SIGNAL(allTasksDone()),
            this, SLOT(slotFinishScan()));

    foreach (const QString& dirPath, dirs) {
        // Acquire a security bookmark for this directory if we are in a
        // sandbox. For speed we avoid opening security bookmarks when recursive
        // scanning so that relies on having an open bookmark for the containing
        // directory.
        MDir dir(dirPath);

        queueTask(new RecursiveScanDirectoryTask(this, m_scannerGlobal, dir.dir(),
                                                 dir.token()));
    }
void SetLoopSectionCommand::onExecute(Context* ctx)
{
  doc::Document* doc = ctx->activeDocument();
  if (!doc)
    return;

  doc::Sprite* sprite = doc->sprite();
  doc::frame_t begin = m_begin;
  doc::frame_t end = m_end;
  bool on = false;

  switch (m_action) {

    case Action::Auto: {
      auto range = App::instance()->timeline()->range();
      if (range.enabled() && (range.frames() > 1)) {
        begin = range.selectedFrames().firstFrame();
        end = range.selectedFrames().lastFrame();
        on = true;
      }
      else {
        on = false;
      }
      break;
    }

    case Action::On:
      on = true;
      break;

    case Action::Off:
      on = false;
      break;

  }

  doc::FrameTag* loopTag = get_loop_tag(sprite);
  if (on) {
    if (!loopTag) {
      loopTag = create_loop_tag(begin, end);

      ContextWriter writer(ctx);
      Transaction transaction(writer.context(), "Add Loop");
      transaction.execute(new cmd::AddFrameTag(sprite, loopTag));
      transaction.commit();
    }
    else if (loopTag->fromFrame() != begin ||
             loopTag->toFrame() != end) {
      ContextWriter writer(ctx);
      Transaction transaction(writer.context(), "Set Loop Range");
      transaction.execute(new cmd::SetFrameTagRange(loopTag, begin, end));
      transaction.commit();
    }
    else {
      Command* cmd = CommandsModule::instance()->getCommandByName(CommandId::FrameTagProperties);
      ctx->executeCommand(cmd);
    }
  }
  else {
    if (loopTag) {
      ContextWriter writer(ctx);
      Transaction transaction(writer.context(), "Remove Loop");
      transaction.execute(new cmd::RemoveFrameTag(sprite, loopTag));
      transaction.commit();
    }
  }

  App::instance()->timeline()->invalidate();
}