Example #1
0
/*
 * Parse a seqset from the given string and append it to the chain
 * of seqsets at `*l'.
 */
HIDDEN void seqset_append(struct seqset **l, char *sequence, unsigned maxval)
{
    struct seqset **tail = l;

    while (*tail) {
	if (!maxval) maxval = (*tail)->maxval;
	tail = &(*tail)->nextseq;
    }

    *tail = seqset_parse(sequence, NULL, maxval);
}
Example #2
0
/*
 * Performs a STATUS command - note: state MAY be NULL here.
 */
int status_lookup(const char *mboxname, const char *userid,
		  unsigned statusitems, struct statusdata *sdata)
{
    struct mailbox *mailbox = NULL;
    unsigned numrecent = 0;
    unsigned numunseen = 0;
    unsigned c_statusitems;
    int r;

    /* Check status cache if possible */
    if (config_getswitch(IMAPOPT_STATUSCACHE)) {
	/* Do actual lookup of cache item. */
	r = statuscache_lookup(mboxname, userid, statusitems, sdata);

	/* Seen/recent status uses "push" invalidation events from
	 * seen_db.c.   This avoids needing to open cyrus.header to get
	 * the mailbox uniqueid to open the seen db and get the
	 * unseen_mtime and recentuid.
	 */

	if (!r) {
	    syslog(LOG_DEBUG, "statuscache, '%s', '%s', '0x%02x', 'yes'",
		   mboxname, userid, statusitems);
	    return 0;
	}

	syslog(LOG_DEBUG, "statuscache, '%s', '%s', '0x%02x', 'no'",
	       mboxname, userid, statusitems);
    }

    /* Missing or invalid cache entry */
    r = mailbox_open_irl(mboxname, &mailbox);
    if (r) return r;

    /* We always have message count, uidnext,
       uidvalidity, and highestmodseq for cache */
     c_statusitems = STATUS_MESSAGES | STATUS_UIDNEXT |
		     STATUS_UIDVALIDITY | STATUS_HIGHESTMODSEQ;

    if (!mailbox->i.exists) {
	/* no messages, so these two must also be zero */
	c_statusitems |= STATUS_RECENT | STATUS_UNSEEN;
    }
    else if (statusitems & (STATUS_RECENT | STATUS_UNSEEN)) {
	/* Read \Seen state */
	struct seqset *seq = NULL;
	uint32_t recno;
	struct index_record record;
	int internalseen = mailbox_internal_seen(mailbox, userid);
	unsigned recentuid;

	if (internalseen) {
	    recentuid = mailbox->i.recentuid;
	} else {
	    struct seen *seendb = NULL;
	    struct seendata sd = SEENDATA_INITIALIZER;

	    r = seen_open(userid, SEEN_CREATE, &seendb);
	    if (!r) r = seen_read(seendb, mailbox->uniqueid, &sd);
	    seen_close(&seendb);
	    if (r) goto done;

	    recentuid = sd.lastuid;
	    seq = seqset_parse(sd.seenuids, NULL, recentuid);
	    seen_freedata(&sd);
	}

	for (recno = 1; recno <= mailbox->i.num_records; recno++) {
	    if (mailbox_read_index_record(mailbox, recno, &record))
		continue;
	    if (record.system_flags & FLAG_EXPUNGED)
		continue;
	    if (record.uid > recentuid)
		numrecent++;
	    if (internalseen) {
		if (!(record.system_flags & FLAG_SEEN))
		    numunseen++;
	    }
	    else {
		if (!seqset_ismember(seq, record.uid))
		    numunseen++;
	    }
	}

	/* we've calculated the correct values for both */
	c_statusitems |= STATUS_RECENT | STATUS_UNSEEN;
    }

    statuscache_fill(sdata, userid, mailbox, c_statusitems,
		     numrecent, numunseen);

    /* cache the new value while unlocking */
    mailbox_unlock_index(mailbox, sdata);

  done:
    mailbox_close(&mailbox);
    return r;
}
Example #3
0
int main(int argc, char *argv[])
{
    const char *alt_config = NULL;
    unsigned maxval = 0;
    int flags = SEQ_MERGE;
    struct seqset *seq = NULL;
    int opt;
    unsigned num;
    char *res;
    const char *origlist = NULL;

    while ((opt = getopt(argc, argv, "C:m:o:s")) != EOF) {
	switch (opt) {
	case 'C': /* alt config file */
	    alt_config = optarg;
	    break;
	case 'm': /* maxval */
	    parseuint32(optarg, NULL, &maxval);
	    break;
	case 'o':
	    origlist = optarg;
	    break;
	case 's':
	    flags = SEQ_SPARSE;
	}
    }
	
    if ((argc - optind) < 1) usage(argv[0]);

    cyrus_init(alt_config, "cyr_sequence", 0);

    /* special case */
    if (!strcmp(argv[optind], "create")) {
	int i;
	seq = seqset_init(maxval, flags);
	for (i = optind + 1; i < argc; i++) {
	    char *ptr = argv[i];
	    int isadd = 1;
	    if (*ptr == '~') {
		isadd = 0;
		ptr++;
	    }
	    if (parseuint32(ptr, NULL, &num))
		printf("%s NAN\n", argv[i]);
	    else
		seqset_add(seq, num, isadd);
	}
	if (origlist) {
	    unsigned oldmax = seq_lastnum(origlist, NULL);
	    if (oldmax > maxval) {
		struct seqset *origseq = seqset_parse(origlist, NULL, oldmax);
		unsigned val;
		for (val = maxval + 1; val <= oldmax; val++)
		    seqset_add(seq, val, seqset_ismember(origseq, val));
		seqset_free(origseq);
	    }
	}
	res = seqset_cstring(seq);
	printf("%s\n", res);
	free(res);
    }
    else if (!strcmp(argv[optind], "parsed")) {
	unsigned i;
	seq = seqset_parse(argv[optind+1], NULL, maxval);
	printf("Sections: " SIZE_T_FMT "\n", seq->len);
	for (i = 0; i < seq->len; i++) {
	    if (seq->set[i].high == UINT_MAX)
		printf(" [%u, *]\n", seq->set[i].low);
	    else
		printf(" [%u, %u]\n", seq->set[i].low, seq->set[i].high);
	}
    }
    else if (!strcmp(argv[optind], "compress")) {
	seq = seqset_parse(argv[optind+1], NULL, maxval);
	res = seqset_cstring(seq);
	printf("%s\n", res);
	free(res);
    }
    else if (!strcmp(argv[optind], "members")) {
	seq = seqset_parse(argv[optind+1], NULL, maxval);
	while ((num = seqset_getnext(seq))) {
	    printf("%u\n", num);
	}
    }
    else if (!strcmp(argv[optind], "join")) {
	struct seqset *seq2;
	seq = seqset_parse(argv[optind+1], NULL, maxval);
	seq2 = seqset_parse(argv[optind+2], NULL, maxval);
	seqset_join(seq, seq2);
	res = seqset_cstring(seq);
	printf("%s\n", res);
	free(res);
    }
    else if (!strcmp(argv[optind], "ismember")) {
	int i;
	seq = seqset_parse(argv[optind+1], NULL, maxval);
	for (i = optind + 2; i < argc; i++) {
	    if (parseuint32(argv[i], NULL, &num))
		printf("%s NAN\n", argv[i]);
	    else
		printf("%d %s\n", num, seqset_ismember(seq, num) ? "Yes" : "No");
	}
    }
    else {
	printf("Unknown command %s", argv[optind]);
    }

    seqset_free(seq);

    cyrus_done();

    return 0;
}