void SftpChannelPrivate::handleStatus() { const SftpStatusResponse &response = m_incomingPacket.asStatusResponse(); #ifdef CREATOR_SSH_DEBUG qDebug("%s: status = %d", Q_FUNC_INFO, response.status); #endif JobMap::Iterator it = lookupJob(response.requestId); switch (it.value()->type()) { case AbstractSftpOperation::ListDir: handleLsStatus(it, response); break; case AbstractSftpOperation::Download: handleGetStatus(it, response); break; case AbstractSftpOperation::UploadFile: handlePutStatus(it, response); break; case AbstractSftpOperation::MakeDir: handleMkdirStatus(it, response); break; case AbstractSftpOperation::StatFile: case AbstractSftpOperation::RmDir: case AbstractSftpOperation::Rm: case AbstractSftpOperation::Rename: case AbstractSftpOperation::CreateFile: case AbstractSftpOperation::CreateLink: handleStatusGeneric(it, response); break; } }
void SftpChannelPrivate::handleHandle() { const SftpHandleResponse &response = m_incomingPacket.asHandleResponse(); JobMap::Iterator it = lookupJob(response.requestId); const QSharedPointer<AbstractSftpOperationWithHandle> job = it.value().dynamicCast<AbstractSftpOperationWithHandle>(); if (job.isNull()) { throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR, "Unexpected SSH_FXP_HANDLE packet."); } if (job->state != AbstractSftpOperationWithHandle::OpenRequested) { throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR, "Unexpected SSH_FXP_HANDLE packet."); } job->remoteHandle = response.handle; job->state = AbstractSftpOperationWithHandle::Open; switch (it.value()->type()) { case AbstractSftpOperation::ListDir: handleLsHandle(it); break; case AbstractSftpOperation::CreateFile: handleCreateFileHandle(it); break; case AbstractSftpOperation::Download: handleGetHandle(it); break; case AbstractSftpOperation::UploadFile: handlePutHandle(it); break; default: Q_ASSERT(!"Oh no, I forgot to handle an SFTP operation type!"); } }
/* ACKJOB jobid_1 jobid_2 ... jobid_N * * Set job state as acknowledged, if the job does not exist creates a * fake job just to hold the acknowledge. * * As a result of a job being acknowledged, the system tries to garbage * collect it, that is, to remove the job from every node of the system * in order to both avoid multiple deliveries of the same job, and to * release resources. * * If a job was already acknowledged, the ACKJOB command still has the * effect of forcing a GC attempt ASAP. * * The command returns the number of jobs already known and that were * already not in the ACKED state. */ void ackjobCommand(client *c) { int j, known = 0; if (validateJobIDs(c,c->argv+1,c->argc-1) == C_ERR) return; /* Perform the appropriate action for each job. */ for (j = 1; j < c->argc; j++) { job *job = lookupJob(c->argv[j]->ptr); /* Case 1: No such job. Create one just to hold the ACK. However * if the cluster is composed by a single node we are sure the job * does not exist in the whole cluster, so do this only if the * cluster size is greater than one. */ if (job == NULL && server.cluster->size > 1 && !myselfLeaving()) { char *id = c->argv[j]->ptr; int ttl = getRawTTLFromJobID(id); /* TTL is even for "at most once" jobs. In this case we * don't need to create a dummy hack. */ if (ttl & 1) { job = createJob(id,JOB_STATE_ACKED,0,0); setJobTTLFromID(job); serverAssert(registerJob(job) == C_OK); } } /* Case 2: Job exists and is not acknowledged. Change state. */ else if (job && job->state != JOB_STATE_ACKED) { dequeueJob(job); /* Safe to call if job is not queued. */ acknowledgeJob(job); known++; } /* Anyway... start a GC attempt on the acked job. */ if (job) tryJobGC(job); } addReplyLongLong(c,known); }
/* FASTACK jobid_1 jobid_2 ... jobid_N * * Performs a fast acknowledge of the specified jobs. * A fast acknowledge does not really attempt to make sure all the nodes * that may have a copy recive the ack. The job is just discarded and * a best-effort DELJOB is sent to all the nodes that may have a copy * without caring if they receive or not the message. * * This command will more likely result in duplicated messages delivery * during network partiitons, but uses less messages compared to ACKJOB. * * If a job is not known, a cluster-wide DELJOB is broadcasted. * * The command returns the number of jobs that are deleted from the local * node as a result of receiving the command. */ void fastackCommand(client *c) { int j, known = 0; if (validateJobIDs(c,c->argv+1,c->argc-1) == C_ERR) return; /* Perform the appropriate action for each job. */ for (j = 1; j < c->argc; j++) { job *job = lookupJob(c->argv[j]->ptr); if (job == NULL) { /* Job not known, just broadcast the DELJOB message to everybody. */ clusterBroadcastJobIDMessage(server.cluster->nodes,c->argv[j]->ptr, CLUSTERMSG_TYPE_DELJOB,0, CLUSTERMSG_NOFLAGS); } else { clusterBroadcastDelJob(job); unregisterJob(job); freeJob(job); known++; } } addReplyLongLong(c,known); }