Exemple #1
0
static int
write_log_page(struct file *file, struct log_param *lp)
{
  struct file_header hdr;
  uint16_t region;
  coffee_page_t log_page;
  int16_t log_record;
  uint16_t log_record_size;
  uint16_t log_records;
  cfs_offset_t offset;
  struct log_param lp_out;

  read_header(&hdr, file->page);

  adjust_log_config(&hdr, &log_record_size, &log_records);
  region = modify_log_buffer(log_record_size, &lp->offset, &lp->size);

  log_page = 0;
  if(HDR_MODIFIED(hdr)) {
    /* A log structure has already been created. */
    log_page = hdr.log_page;
    log_record = find_next_record(file, log_page, log_records);
    if(log_record >= log_records) {
      /* The log is full; merge the log. */
      PRINTF(("Coffee: Merging the file %s with its log\n", hdr.name));
      return merge_log(file->page, 0);
    }
  } else {
    /* Create a log structure. */
    log_page = create_log(file, &hdr);
    if(log_page == INVALID_PAGE) {
      return -1;
    }
    PRINTF(("Coffee: Created a log structure for file %s at page %u\n",
    	hdr.name, (unsigned)log_page));
    hdr.log_page = log_page;
    log_record = 0;
  }

  {
    char copy_buf[log_record_size];

    lp_out.offset = offset = region * log_record_size;
    lp_out.buf = copy_buf;
    lp_out.size = log_record_size;

    if((lp->offset > 0 || lp->size != log_record_size) &&
	read_log_page(&hdr, log_record, &lp_out) < 0) {
      COFFEE_READ(copy_buf, sizeof(copy_buf),
	  absolute_offset(file->page, offset));
    }

    memcpy(&copy_buf[lp->offset], lp->buf, lp->size);

    /*
     * Write the region number in the region index table.
     * The region number is incremented to avoid values of zero.
     */
    offset = absolute_offset(log_page, 0);
    ++region;
    COFFEE_WRITE(&region, sizeof(region),
		 offset + log_record * sizeof(region));

    offset += log_records * sizeof(region);
    COFFEE_WRITE(copy_buf, sizeof(copy_buf),
		 offset + log_record * log_record_size);
    file->record_count = log_record + 1;
  }

  return lp->size;
}
Exemple #2
0
bool resolver::parse_message(msg& msg)
{
	if ((size_t) (msg.end - msg.data) <= sizeof(header)) {
		return false;
	}

	if (!parse_header(msg)) {
		return false;
	}

	if (msg.h->ancount == 0) {
		return false;
	}

	if (!find_first_record(msg)) {
		return false;
	}

	dns_entry entry;
	entry.name = msg.name;
	entry.namelen = msg.namelen;

	red_black_tree<dns_entry>::iterator it;
	if (!_M_cache.find(entry, it)) {
		// Name not found in the cache.
		return false;
	}

	dns_entry* e = it.data;

	msg.narecords = 0;
	msg.cnamelen = 0;

	for (unsigned short i = msg.h->ancount; (msg.ptr < msg.end) && (i > 0); i--) {
		rr rr;
		if (!find_next_record(msg, rr)) {
			return false;
		}

		if (!process_record(msg, rr)) {
			return false;
		}
	}

	time_t now = time(NULL);

	if (msg.narecords == 1) {
		// If not the original request...
		if (e->cnamelen > 0) {
			// The domain name of the original request is in e->cname.
			red_black_tree<dns_entry>::iterator itcname;
			if (!find(e->cname, e->cnamelen, itcname)) {
				_M_cache.erase(it);
				return false;
			}

			_M_cache.erase(it);

			e = itcname.data;
		}

		struct address* addr = msg.arecords;

		e->address.addr = addr->addr;
		e->address.expire = now + addr->expire;
		e->address.preference = addr->preference;

		e->addresses = &e->address;
		e->naddresses = 1;

		e->status = STATUS_VALID;

		return true;
	} else if (msg.narecords > 1) {
		// If not the original request...
		if (e->cnamelen > 0) {
			// The domain name of the original request is in e->cname.
			red_black_tree<dns_entry>::iterator itcname;
			if (!find(e->cname, e->cnamelen, itcname)) {
				_M_cache.erase(it);
				return false;
			}

			_M_cache.erase(it);

			e = itcname.data;
		}

		if ((e->addresses = (struct address*) malloc(msg.narecords * sizeof(struct address))) == NULL) {
			_M_cache.erase(it);
			return false;
		}

		struct address* addr = msg.arecords;
		for (unsigned short i = 0; i < msg.narecords; i++, addr++) {
			e->addresses[i].addr = addr->addr;
			e->addresses[i].expire = now + addr->expire;
			e->addresses[i].preference = addr->preference;
		}

		e->naddresses = msg.narecords;

		e->status = STATUS_VALID;

		return true;
	} else if (msg.cnamelen > 0) {
		dns_entry* ecname;

		// If not the original request...
		if (e->cnamelen > 0) {
			// The domain name of the original request is in e->cname.
			char* cname = e->cname;
			unsigned short cnamelen = e->cnamelen;

			red_black_tree<dns_entry>::iterator itcname;
			if (!find(cname, cnamelen, itcname)) {
				_M_cache.erase(it);
				return false;
			}

			e->cnamelen = 0;

			_M_cache.erase(it);

			if (++itcname.data->recursion > MAX_RECURSION) {
				_M_cache.erase(itcname);
				free(cname);
				return false;
			}

			if (!add_to_cache(msg.cname, msg.cnamelen, (rr_type) msg.type, &itcname)) {
				_M_cache.erase(itcname);
				free(cname);
				return false;
			}

			ecname = itcname.data;
			ecname->cname = cname;
			ecname->cnamelen = cnamelen;
		} else {
			red_black_tree<dns_entry>::iterator itcname;
			if (!add_to_cache(msg.cname, msg.cnamelen, (rr_type) msg.type, &itcname)) {
				_M_cache.erase(it);
				return false;
			}

			ecname = itcname.data;
			if ((ecname->cname = (char*) malloc(msg.namelen)) == NULL) {
				_M_cache.erase(itcname);
				_M_cache.erase(it);
				return false;
			}

			memcpy(ecname->cname, msg.name, msg.namelen);
			ecname->cnamelen = msg.namelen;
		}

		return make_request(ecname->name, ecname->namelen, (rr_type) ecname->type, true);
	} else {
		return false;
	}
}