Example #1
0
void cmd_drop(int id){
	snapshot* snapshot = getSnapshot(id);
	if(snapshot != NULL){
		deleteSnapshot(snapshot);
		printf("ok\n");
		return;
	}
	printf("no such snapshot\n");
}
Example #2
0
void cmd_rollback(int id){
	snapshot* rollbackSnapshot = getSnapshot(id);
	if(rollbackSnapshot != NULL){
		snapshot* currentSnapshot = snapshot_head;
		while(currentSnapshot != rollbackSnapshot){
			snapshot* nextSnapshot = currentSnapshot->next;
			deleteSnapshot(currentSnapshot);
			currentSnapshot = nextSnapshot;
		}
		cmd_checkout(id);
	}else{
		printf("no such snapshot\n");
	}
}
Example #3
0
int syncInit(int cfd, long long *tbytes) {
    char errmsg[ERRMSG_MAX] = {0};
    SyncInit *syncinit;
    SyncInitResponse response = SYNC_INIT_RESPONSE__INIT;

    syncinit = (SyncInit *) recvMessage(cfd, SyncInitType, tbytes);
    if (syncinit == NULL) {
        errMsg(LOG_ERR, "Could not read initialization message from client.");
        return -1;
    }

    // initial checks
    // check resource (must match)
    if (strcmp(syncinit->resource, config.resource) != 0) {
        snprintf(errmsg, ERRMSG_MAX, "Received resource %s does not match."
                "local resource %s", syncinit->resource, config.resource);
        response.continue_ = 0;
        response.error_message = errmsg;
        sendMessage(cfd, SyncInitResponseType, &response);
        return -1;
    }

    // check sync-id
    char lastsyncid[SYNCID_MAX];
    char lastsyncidpath[PATH_MAX];
    char syncid[SYNCID_MAX];
    char syncidpath[PATH_MAX];

    // if we receive syncid, we already marked as successfully done
    // only sending confirmation has failed last time
    snprintf(lastsyncidpath, PATH_MAX, "%s/%s.syncid.last", config.logdir,
            config.resource);
    if (fileExists(lastsyncidpath) &&
            (readSyncId(lastsyncid, lastsyncidpath, SYNCID_MAX) == 0)) {
        if (lastsyncid == syncinit->sync_id) {
            // send the confirmation, don't sync
            response.continue_ = 0;
            response.has_already_synced = 1;
            response.already_synced = 1;
            sendMessage(cfd, SyncInitResponseType, &response);
            return 0; // no files to be synchronized
        }
    }

    int errflag = 0;
    // if we can read syncid file, last sync did not finish properly
    // revert snapshot
    snprintf(syncidpath, PATH_MAX, "%s/%s.syncid", config.logdir,
            config.resource);
    if (fileExists(syncidpath) &&
            (readSyncId(syncid, syncidpath, SYNCID_MAX) == 0)) {
        if (syncid == syncinit->sync_id) {
            // TODO: here we should support resume
        }

        // revert last snapshot, check for its existence is necessary, but
        // is done nevertheless
        if (fileExists(config.snapshot) == 1) {
            // do as one block, this should not fail, if yes, we are in trouble
            errMsg(LOG_INFO, "Reverting snapshot.");
            int ret = 0;

            ret = deleteSnapshot(config.rootdir);
            ret |= createSnapshot(config.snapshot, config.rootdir, 0);
            ret |= deleteSnapshot(config.snapshot);

            if (ret != 0) {
                errflag = 1;
                snprintf(errmsg, ERRMSG_MAX, "Reverting to last snapshot"
                        "has failed.");
            }
        }
    }

    // create snapshot
    // snapshot might exists (if last time program crash before sync-id was
    // written or before it was deleted), but in this case we don't need to
    // revert it
    if (!errflag && fileExists(config.snapshot)) {
        errMsg(LOG_INFO, "Snapshot %s unexpectedly exists, deleting.",
                config.snapshot);
        if (deleteSnapshot(config.snapshot) == -1) {
            errMsg(LOG_ERR, "Could not delete snapshot %s", config.snapshot);
            errflag = 1;
        }
    }
    if (!errflag &&
            (createSnapshot(config.rootdir, config.snapshot, 1) != 0)) {
        errMsg(LOG_ERR, "Could not create snapshot %s", config.snapshot);
        errflag = 1;
    }

    // write syncid
    if (!errflag && (writeSyncId(syncinit->sync_id, syncidpath) != 0)) {
        errMsg(LOG_ERR, "Could not write sync-id. Stopping.");
        errflag = 1;
    }

    // send response
    int ret;
    if (errflag) {
        response.continue_ = 0;
        snprintf(errmsg, ERRMSG_MAX, "Error in snapshot operation.");
        response.error_message = errmsg;
        ret = -1;
    } else {
        response.continue_ = 1;
        ret = syncinit->number_files;
    }
    sync_init__free_unpacked(syncinit, NULL);

    if (sendMessage(cfd, SyncInitResponseType, &response) == 0)
        return ret;
    else
        return -1;
}
Example #4
0
int handleClient(int cfd, struct sockaddr *claddr, socklen_t *addrlen) {
    long long tbytes = 0; // total number of transfered bytes
    char addrstr[IS_ADDR_STR_LEN];

    errMsg(LOG_INFO, "Connection from %s", inetAddressStr(claddr, *addrlen,
            addrstr, IS_ADDR_STR_LEN));

    // sync-init, return value is number of files
    int32_t nfiles;
    nfiles = syncInit(cfd, &tbytes);
    if (nfiles == -1)
        return -1;
    
    errMsg(LOG_INFO, "Number of files to synchronize: %d", nfiles);
    // outer loop: files, inner loop: chunks
    for (int i = 0; i < nfiles; i++) {
        FileChunk *chunk;
        int fd = -1;

        // we are guaranteed to get at least one chunk for each file
        chunk = (FileChunk *) recvMessage(cfd, FileChunkType, &tbytes);
        if (chunk == NULL) {
            errMsg(LOG_ERR, "Could not read message from client.");
            return -1;
        }

        for (;;) {
            for (int k = 0; k < chunk->n_ops; k++) {
                // TODO
                // in case of a failure inform client to do an rsync based sync
                handleGenericOperation(&fd, chunk->relative_path, chunk->ops[k]);
            }

            if (chunk->last_chunk == 1) {
                file_chunk__free_unpacked(chunk, NULL);
                break;
            } else {
                file_chunk__free_unpacked(chunk, NULL);
                chunk = (FileChunk *) recvMessage(cfd, FileChunkType, &tbytes);
                if (chunk == NULL) {
                    errMsg(LOG_ERR, "Could not read message from client.");
                    return -1;
                }
            }
        }

        if (fd != -1) {
            if (close(fd) == -1)
                errMsg(LOG_WARNING, "Could not close file.");
        }

    }

    errMsg(LOG_INFO, "Received bytes: %lld", tbytes);

    // transfer was successful, we can delete snapshot (created in syncInit())
    if (deleteSnapshot(config.snapshot) == -1) {
        errMsg(LOG_ERR, "Could not delete snapshot %s", config.snapshot);
        close(cfd);
        return -1;
    }

    // rename resource.syncid to resource.syncid.last
    char lastsyncidpath[PATH_MAX];
    char syncidpath[PATH_MAX];
    snprintf(lastsyncidpath, PATH_MAX, "%s/%s.syncid.last", config.logdir,
            config.resource);
    snprintf(syncidpath, PATH_MAX, "%s/%s.syncid", config.logdir,
            config.resource);

    if (rename(syncidpath, lastsyncidpath) == -1) {
        errnoMsg(LOG_CRIT, "Could not rename sync-id file to sync-id.last.");
        close(cfd);
        return -1;
    }

    // and finally send confirmation to client
    SyncFinish conf = SYNC_FINISH__INIT;
    conf.has_transferred_bytes = 1;
    conf.transferred_bytes = (uint64_t) tbytes;
    if (sendMessage(cfd, SyncFinishType, &conf) != 0) {
        close(cfd);
        return -1;
    }

    if (close(cfd) == -1)
        errMsg(LOG_WARNING, "Could not close socket.");
    
    return 0;
}
Example #5
0
int synchronize(void) {
    int pidfd;
    char pidpath[PATH_MAX];
    int logfd;
    char logpath[PATH_MAX];
    int newsync = 0;

    // make sure, that there isn't another client process for this resource
    // already running
    snprintf(pidpath, PATH_MAX, "/var/run/syncedfs/client/%s.pid",
            config.resource);
    pidfd = createPidFile(config.ident, pidpath, 0);
    if (pidfd == -1) {
        errMsg(LOG_ERR, "Could not create pid file %s, Exiting sync.", pidpath);
        return -1;
    }

    // if sync log does not exist, switch log
    snprintf(logpath, PATH_MAX, "%s/%s.sync", config.logdir, config.resource);
    errMsg(LOG_INFO, "logpath: %s", logpath);
    logfd = open(logpath, O_RDONLY);
    if (logfd == -1) {
        if (switchLog() != 0) {
            errMsg(LOG_ERR, "Could not switch log file. Stopping.");
            return -1;
        }

        logfd = open(logpath, O_RDONLY);
        if (logfd == -1) {
            errnoMsg(LOG_ERR, "Could not open log file %s", logpath);
            return -1;
        }
        newsync = 1;
    }


    // sync-id
    char id[SYNCID_MAX];
    char idpath[PATH_MAX];
    snprintf(idpath, PATH_MAX, "%s/%s.id", config.logdir, config.resource);

    // second part of the condition covers weird states after crash etc.
    if (newsync == 1 || readSyncId(id, idpath, SYNCID_MAX) != 0) {
        if (generateSyncId(id, SYNCID_MAX) != 0) {
            errMsg(LOG_ERR, "Could not get sync-id. Stopping.");
            return -1;
        }
        if (writeSyncId(id, idpath) != 0) {
            errMsg(LOG_ERR, "Could not write sync-id. Stopping.");
            return -1;
        }
    }

    // create snapshot
    if (newsync || !fileExists(config.snapshot)) {
        if (createSnapshot(config.rootdir, config.snapshot, 1) == -1) {
            errMsg(LOG_ERR, "Could not create snapshot of %s to %s Stopping.",
                    config.rootdir, config.snapshot);
            return -1;
        }
    }

    // load log
    if (loadLog(logfd) != 0) {
        errMsg(LOG_ERR, "Could not load log %s", logpath);
        return -1;
    }

    // transfer changes
    if (transfer(config.host, config.port) == -1) {
        errMsg(LOG_ERR, "Error in transfer. Exiting sync.");

        // in case of failure only delete pid file
        if (deletePidFile(pidfd, pidpath) == -1)
            errExit(LOG_ERR, "Deleting PID file '%s'", pidpath);

        return -1;
    }

    // delete snapshot
    if (deleteSnapshot(config.snapshot) == -1)
        errMsg(LOG_ERR, "Could not delete snapshot %s", config.snapshot);

    // delete syncid
    if (unlink(idpath) == -1)
        errExit(LOG_ERR, "Deleting sync-id file '%s'", idpath);

    // delete sync log
    close(logfd);
    if (unlink(logpath) == -1)
        errExit(LOG_ERR, "Deleting log file '%s'", logpath);

    // delete pid file
    if (deletePidFile(pidfd, pidpath) == -1)
        errExit(LOG_ERR, "Deleting PID file '%s'", pidpath);

    return 0;
}