Example #1
0
static struct VirtualContainer *recursive_parse(FILE *const in,
                                                uint64_t start_bit,
                                                struct DB *const db) {
    char buf[128];
    fgets(buf, 120, in);
    assert(buf[0] == '[');
    if (buf[1] == ']') {
        return NULL;
    }
    struct VirtualContainer *vc = vc_create(start_bit);
    fgets(buf, 28, in);
    assert(buf[0] == '<');
    // '<!' : bloomcontainer
    // '<'  : bloomtable
    const bool load_bf = (buf[1] != '!');
    for (uint64_t j = 0; j < DB_CONTAINER_NR; j++) {
        fgets(buf, 28, in);
        if (buf[0] == '>')
            break;

        const uint64_t mtid = strtoull(buf, NULL, 16);
        assert(db->cms[start_bit / 3]);
        const int raw_fd = db->cms[start_bit / 3]->raw_fd;
        struct MetaTable *const mt =
            db_load_metatable(db, mtid, raw_fd, load_bf);
        assert(mt);
        vc->cc.count++;
        vc->cc.metatables[j] = mt;
    }
    if (buf[0] != '>') {  // read 8 in loop, eat '>'
        fgets(buf, 28, in);
        assert(buf[0] == '>');
    }
    if (!load_bf) {  // no bf, load bc
        assert(buf[1] == '!');
        // load bloomcontainer
        assert(buf[2] != '\0');
        const uint64_t mtid_bc = strtoull(buf + 2, NULL, 16);
        struct BloomContainer *const bc =
            db_load_bloomcontainer_meta(db, mtid_bc);
        vc->cc.bc = bc;
    }
    for (uint64_t i = 0; i < 8; i++) {
        vc->sub_vc[i] = recursive_parse(in, start_bit + 3, db);
    }
    fgets(buf, 28, in);
    assert(buf[0] == ']');
    return vc;
}
Example #2
0
static void compaction_initial(struct Compaction *const comp,
                               struct DB *const db,
                               struct VirtualContainer *const vc,
                               uint64_t nr_feed) {
    bzero(comp, sizeof(*comp));
    comp->start_bit = vc->start_bit;
    comp->sub_bit = vc->start_bit + 3;
    comp->gen_bc = (comp->sub_bit >= BC_START_BIT);
    assert(nr_feed <= vc->cc.count);
    assert(vc->cc.count <= DB_CONTAINER_NR);
    comp->nr_feed = nr_feed;
    comp->db = db;
    comp->vc = vc;
    comp->cm_to = db->cms[comp->sub_bit / 3];

    // alloc arenas
    uint8_t *const arena = huge_alloc(TABLE_ALIGN);
    assert(arena);
    comp->arena = arena;
    // old mts & mtids
    for (uint64_t i = 0; i < nr_feed; i++) {
        struct MetaTable *const mt = vc->cc.metatables[i];
        assert(mt);
        comp->mts_old[i] = mt;
        comp->mtids_old[i] = mt->mtid;
    }

    // new tables
    for (uint64_t i = 0; i < 8u; i++) {
        struct Table *const table = table_alloc_default(1.8);
        assert(table);
        comp->tables[i] = table;
    }

    // mbcs_old (if exists else NULL)
    for (uint64_t i = 0; i < 8u; i++) {
        if (!vc->sub_vc[i]) {
            vc->sub_vc[i] = vc_create(comp->sub_bit);
        }
        comp->mbcs_old[i] = vc->sub_vc[i]->cc.bc;
    }
}
Example #3
0
// create empty db
static struct DB *db_create(const char *const meta_dir,
                            struct ContainerMapConf *const cm_conf) {
    const double sec0 = debug_time_sec();
    if (!db_touch_dir(meta_dir, ""))
        return NULL;
    if (!db_touch_dir(meta_dir, DB_META_BACKUP_DIR))
        return NULL;

    // pre make 256 sub-dirs
    char sub_dir[16];
    for (uint64_t i = 0; i < 256; i++) {
        sprintf(sub_dir, "%02" PRIx64, i);
        if (!db_touch_dir(meta_dir, sub_dir))
            return NULL;
    }

    struct DB *const db = (typeof(db))malloc(sizeof(*db));
    bzero(db, sizeof(*db));

    for (int i = 0; (i < 6) && cm_conf->raw_fn[i]; i++) {
        struct ContainerMap *const cm =
            containermap_create(cm_conf->raw_fn[i], cm_conf->hints[i]);
        assert(cm);
        db->cms_dump[i] = cm;
    }

    db_initial(db, meta_dir, cm_conf);

    // empty vc
    db->vcroot = vc_create(0);
    assert(db->vcroot);

    // mtid start from 1
    db->next_mtid = 1;

    // initial anything
    db_log_diff(db, sec0, "Initialized Metadata");
    return db;
}
Example #4
0
int main(int argc, char** argv) {
    // NOTE: devmgr has getenv_bool. when more options are added, consider
    // sharing that.
    bool keep_log = false;
    const char* value = getenv("virtcon.keep-log-visible");
    if (value == NULL ||
        ((strcmp(value, "0") == 0) ||
         (strcmp(value, "false") == 0) ||
         (strcmp(value, "off") == 0))) {
        keep_log = false;
    } else {
        keep_log = true;
    }

    const char* cmd = NULL;
    int shells = 0;
    while (argc > 1) {
        if (!strcmp(argv[1], "--run")) {
            if (argc > 2) {
                argc--;
                argv++;
                cmd = argv[1];
                if (shells < 1)
                    shells = 1;
                printf("CMD: %s\n", cmd);
            }
        } else if (!strcmp(argv[1], "--shells")) {
            if (argc > 2) {
                argc--;
                argv++;
                shells = atoi(argv[1]);
            }
        }
        argc--;
        argv++;
    }

    if (port_init(&port) < 0) {
        return -1;
    }

    // create initial console for debug log
    if (vc_create(&log_vc, false) != ZX_OK) {
        return -1;
    }
    snprintf(log_vc->title, sizeof(log_vc->title), "debuglog");

    // Get our process koid so the log reader can
    // filter out our own debug messages from the log
    zx_info_handle_basic_t info;
    if (zx_object_get_info(zx_process_self(), ZX_INFO_HANDLE_BASIC, &info,
                           sizeof(info), NULL, NULL) == ZX_OK) {
        proc_koid = info.koid;
    }

    log_ph.handle = zx_take_startup_handle(PA_HND(PA_USER0, 1));
    if (log_ph.handle == ZX_HANDLE_INVALID) {
        printf("vc log listener: did not receive log startup handle\n");
        return -1;
    }

    log_ph.func = log_reader_cb;
    log_ph.waitfor = ZX_LOG_READABLE;

    if ((new_vc_ph.handle = zx_take_startup_handle(PA_HND(PA_USER0, 0))) != ZX_HANDLE_INVALID) {
        new_vc_ph.func = new_vc_cb;
        new_vc_ph.waitfor = ZX_CHANNEL_READABLE;
        port_wait(&port, &new_vc_ph);
    }

    setup_dir_watcher("/dev/class/input", input_cb, &input_ph, &input_dir_fd);

    if (!vc_display_init()) {
        return -1;
    }

    setenv("TERM", "xterm", 1);

    for (int i = 0; i < shells; ++i) {
        if (i == 0)
            start_shell(!keep_log, cmd);
        else
            start_shell(false, NULL);
    }

    zx_status_t r = port_dispatch(&port, ZX_TIME_INFINITE, false);
    printf("vc: port failure: %d\n", r);
    return -1;
}
Example #5
0
static zx_status_t session_create(vc_t** out, int* out_fd, bool make_active, bool special) {
    int fd;

    // The ptmx device can start later than these threads
    int retry = 30;
    while ((fd = open("/dev/misc/ptmx", O_RDWR | O_NONBLOCK)) < 0) {
        if (--retry == 0) {
            return ZX_ERR_IO;
        }
        usleep(100000);
    }

    int client_fd = openat(fd, "0", O_RDWR);
    if (client_fd < 0) {
        close(fd);
        return ZX_ERR_IO;
    }

    vc_t* vc;
    if (vc_create(&vc, special)) {
        close(fd);
        close(client_fd);
        return ZX_ERR_INTERNAL;
    }
    zx_status_t r;
    if ((r = port_fd_handler_init(&vc->fh, fd, POLLIN | POLLRDHUP | POLLHUP)) < 0) {
        vc_destroy(vc);
        close(fd);
        close(client_fd);
        return r;
    }
    vc->fd = fd;

    if (make_active) {
        vc_set_active(-1, vc);
    }

    pty_window_size_t wsz = {
        .width = vc->columns,
        .height = vc->rows,
    };
    ioctl_pty_set_window_size(fd, &wsz);

    vc->fh.func = session_io_cb;

    *out = vc;
    *out_fd = client_fd;
    return ZX_OK;
}

static void start_shell(bool make_active, const char* cmd) {
    vc_t* vc;
    int fd;

    if (session_create(&vc, &fd, make_active, cmd != NULL) < 0) {
        return;
    }

    vc->is_shell = true;

    if (launch_shell(vc, fd, cmd) < 0) {
        session_destroy(vc);
    } else {
        port_wait(&port, &vc->fh.ph);
    }
}