Exemplo n.º 1
0
static inline int
si_trackdir(sitrack *track, sr *r, si *i)
{
	DIR *dir = opendir(i->scheme->path);
	if (ssunlikely(dir == NULL)) {
		sr_malfunction(r->e, "directory '%s' open error: %s",
		               i->scheme->path, strerror(errno));
		return -1;
	}
	struct dirent *de;
	while ((de = readdir(dir))) {
		if (ssunlikely(de->d_name[0] == '.'))
			continue;
		uint64_t id_parent = 0;
		uint64_t id = 0;
		int rc = si_process(de->d_name, &id, &id_parent);
		if (ssunlikely(rc == -1))
			continue; /* skip unknown file */
		si_tracknsn(track, id_parent);
		si_tracknsn(track, id);

		sinode *head, *node;
		sspath path;
		switch (rc) {
		case SI_RDB_DBI:
		case SI_RDB_DBSEAL: {
			/* find parent node and mark it as having
			 * incomplete compaction process */
			head = si_trackget(track, id_parent);
			if (sslikely(head == NULL)) {
				head = si_nodenew(r);
				if (ssunlikely(head == NULL))
					goto error;
				head->self.id.id = id_parent;
				head->recover = SI_RDB_UNDEF;
				si_trackset(track, head);
			}
			head->recover |= rc;
			/* remove any incomplete file made during compaction */
			if (rc == SI_RDB_DBI) {
				ss_pathcompound(&path, i->scheme->path, id_parent, id,
				                ".db.incomplete");
				rc = ss_vfsunlink(r->vfs, path.path);
				if (ssunlikely(rc == -1)) {
					sr_malfunction(r->e, "db file '%s' unlink error: %s",
					               path.path, strerror(errno));
					goto error;
				}
				continue;
			}
			assert(rc == SI_RDB_DBSEAL);
			/* recover 'sealed' node */
			node = si_nodenew(r);
			if (ssunlikely(node == NULL))
				goto error;
			node->recover = SI_RDB_DBSEAL;
			ss_pathcompound(&path, i->scheme->path, id_parent, id,
			                ".db.seal");
			rc = si_nodeopen(node, r, i->scheme, &path, NULL);
			if (ssunlikely(rc == -1)) {
				si_nodefree(node, r, 0);
				goto error;
			}
			si_trackset(track, node);
			si_trackmetrics(track, node);
			continue;
		}
		}
		assert(rc == SI_RDB);

		head = si_trackget(track, id);
		if (head != NULL && (head->recover & SI_RDB)) {
			/* loaded by snapshot */
			continue;
		}

		/* recover node */
		node = si_nodenew(r);
		if (ssunlikely(node == NULL))
			goto error;
		node->recover = SI_RDB;
		ss_path(&path, i->scheme->path, id, ".db");
		rc = si_nodeopen(node, r, i->scheme, &path, NULL);
		if (ssunlikely(rc == -1)) {
			si_nodefree(node, r, 0);
			goto error;
		}
		si_trackmetrics(track, node);

		/* track node */
		if (sslikely(head == NULL)) {
			si_trackset(track, node);
		} else {
			/* replace a node previously created by a
			 * incomplete compaction */
			si_trackreplace(track, head, node);
			head->recover &= ~SI_RDB_UNDEF;
			node->recover |= head->recover;
			si_nodefree(head, r, 0);
		}
	}
	closedir(dir);
	return 0;
error:
	closedir(dir);
	return -1;
}
Exemplo n.º 2
0
/* Program start. */
int main (int argc, char *argv[]) {
	int crc_dvb = 1, crc_internal = 1, dvb_adapter = 0, dvb_demux = 0, dvb_loop = 1, loop_time = 10;
	int ch, dvb_demux_fd, dvb_bytes, retval, dvb_data_length = 0, processed_bytes = 0, done = 0, show_bouquet_list = 0, show_sdt_list = 0, show_filtered_list = 0;
	int filter_bouquet_id = 0, dvbs = 1, hd = 0, filter_user_number = 0;
        unsigned char filter_region_count = 0;
        unsigned char filter_region[10];
	time_t dvb_loop_start;
	char dvb_buffer[DVB_BUFFER_SIZE];
	char *dvb_data = NULL, *dvb_temp = NULL;
	Network *network;
	Transport *transport;
	Bouquet *bouquet;
	Service *service;
	OpenTVChannel *channel;

	/* Process command line options. */
	while ((ch = getopt(argc, argv, "c:C:a:d:l:ib:BSFhvr:s:HU:")) != -1) {
		switch (ch) {
			case 'c':
				crc_dvb = atoi(optarg);
				slowlane_log(3, "crc_dvb set to %i.", crc_dvb);
				break;
			
				crc_internal = atoi(optarg);
				slowlane_log(3, "crc_internal set to %i.", crc_internal);
				break;
			case 'a':
				dvb_adapter = atoi(optarg);
				slowlane_log(3, "dvb_adapter set to %i.", dvb_adapter);
				break;
			case 'd':
				dvb_demux = atoi(optarg);
				slowlane_log(3, "dvb_demux set to %i.", dvb_demux);
				break;
			case 'v':
				verbose++;
				slowlane_log(0, "verbose set to %i.", verbose);
				break;
			case 'l':
                                loop_time = atoi(optarg);
                                slowlane_log(3, "loop_time set to %i.", loop_time);
                                break;
			case 'B':
				show_bouquet_list = 1;
				slowlane_log(3, "show_bouquet_list set to %i.", show_bouquet_list);
				break;
			case 'S':
				show_sdt_list = 1;
				slowlane_log(3, "show_sdt_list set to %i.", show_sdt_list);
				break;
			case 'b':
				filter_bouquet_id = atoi(optarg);
				slowlane_log(3, "filter_bouquet_id to %i.", filter_bouquet_id);
				break;
			case 'r':
				if (filter_region_count == 10) {
					slowlane_log(1, "filter_region table is full at %i.", filter_region_count);
				} else {
					filter_region[filter_region_count] = atoi(optarg);
					slowlane_log(1, "filter_region table added %i to pos %i.", filter_region[filter_region_count], filter_region_count);
					filter_region_count++;
				}
				
				break;
			case 's':
				dvbs = atoi(optarg);
				slowlane_log(1, "DVB-S%i and below transports enabled.", dvbs);
				break;
			case 'H':
				hd = 1;
				slowlane_log(1, "HD transports enabled (%i).", hd);
				break;
			case 'F':
				show_filtered_list = 1;
				slowlane_log(3, "show_filtered_list set to %i.", show_filtered_list);
				break;
			case 'U':
				filter_user_number = atoi(optarg);
				slowlane_log(1, "Filtering user numbers above %i.", filter_user_number);
				break;
			case 'h':
			default:
				usage();
				return EXIT_FAILURE;
				break;
		}
	}

	/* Fetch fd for DVB card. */
	if ((dvb_demux_fd = dvb_open(dvb_adapter, dvb_demux)) < 1) {
		slowlane_log(0, "dvb_open failed and returned %i.", dvb_demux_fd);
		return EXIT_FAILURE;
	}

	/* Set filter for NIT. */
	if ((retval = dvb_set_filter(dvb_demux_fd, 0x0010, 0x40, 0xf0, crc_dvb)) < 0) {
		slowlane_log(0, "NIT dvb_set_filter failed and returned %i.", retval);
		return EXIT_FAILURE;
	}

	/* Record when we start this loop.*/
	dvb_loop_start = time(NULL);

	/* Loop obtaining packets until we have enough. */
	while (dvb_loop) {
		/* Read DVB card. */
		if ((dvb_bytes = dvb_read(dvb_demux_fd, dvb_buffer, DVB_BUFFER_SIZE)) <= 0) {
			slowlane_log(0, "dvb_read failed and returned %i.", dvb_bytes);
			dvb_close(dvb_demux_fd);
			return EXIT_FAILURE;
		}

		/* Copy data into dvb_data. */
		if (dvb_data == NULL) {
			slowlane_log(3, "dvb_read read in %i, mallocing memory.", dvb_bytes);
			dvb_data_length = dvb_bytes;
			dvb_data = (char *) malloc (dvb_data_length);
			memcpy(dvb_data, dvb_buffer, dvb_data_length);		
		} else {
			slowlane_log(3, "dvb_read read in %i, already %i here, reallocing memory.", dvb_bytes, dvb_data_length);
			dvb_data = (char *) realloc (dvb_data, dvb_data_length + dvb_bytes);
			memcpy(dvb_data + dvb_data_length, dvb_buffer, dvb_bytes);
                        dvb_data_length += dvb_bytes;
		}

		/* Loop while processing function is reporting success, this is needed for some dvb cards or sasc-ng virtual cards which
		 * don't obey the one packet per read rule. */
		do {
			/* Process SI received. */
			if ((processed_bytes = si_process((unsigned char *)dvb_data, dvb_data_length, crc_internal)) < 0) {
				slowlane_log(0, "si_process failed and returned %i.", processed_bytes);

				/* Dump data and flush buffer. */
				free(dvb_data);
				dvb_data = NULL;
				dvb_data_length = 0;
			} else {
				if (processed_bytes > 0) {
					if (processed_bytes == dvb_data_length) {
						slowlane_log(3, "si_process processed whole data of size %i.", processed_bytes);
						dvb_data_length = 0;
						free(dvb_data);
						dvb_data = NULL;
					} else {
						slowlane_log(3, "si_process processed less then whole data of size %i out of %i.", processed_bytes, dvb_data_length);
						dvb_temp = (char *) malloc (dvb_data_length - processed_bytes);
						memcpy(dvb_temp, dvb_data + processed_bytes, dvb_data_length - processed_bytes);
						free(dvb_data);
						dvb_data = dvb_temp;
						dvb_data_length -= processed_bytes;
					}
				}
			}
		} while (processed_bytes < dvb_data_length && processed_bytes > 0);

		if (dvb_loop == 1) {
			/* Verify if timeout has expired. */
			if (time(NULL) > dvb_loop_start + loop_time) {
				/* Verify if all present networks are complete. */
				done = 1;

				for (network = network_list; network != NULL; network = network->next) {
					if (!section_tracking_check(&network->sections)) {
						done = 0;
					}
				}

				if (done) {
					/* Inform the user. */
					slowlane_log(2, "NIT tables complete (%i), moving to BAT and DST tables.", dvb_loop);

					/* Set filter for BAT and SDT. */
					if ((retval = dvb_set_filter(dvb_demux_fd, 0x0011, 0x40, 0xf0, crc_dvb)) < 0) {
						slowlane_log(0, "BAT/DST dvb_set_filter failed and returned %i.", retval);
						return EXIT_FAILURE;
					}

					/* Essentially starting the loop again. */
				        dvb_loop_start = time(NULL);
					dvb_loop = 2;
				}
			}
		} else {
			/* Verify if timeout has expired. */
			if (time(NULL) > dvb_loop_start + loop_time) {
				/* Verify if all present networks are complete. */
				done = 1;

				for (network = network_list; network != NULL; network = network->next) {
					for (transport = network->transports; transport != NULL; transport = transport->next) {
						if (transport->sections.populated == 0 || !section_tracking_check(&transport->sections)) {
							done = 0;
						}
					}
				}

				for (bouquet = bouquet_list; bouquet != NULL; bouquet = bouquet->next) {
					if (!section_tracking_check(&bouquet->sections)) {
						done = 0;
					}
				}

				if (done) {
					/* Inform the user. */
					slowlane_log(2, "BAT and DST tables complete (%i).", dvb_loop);

					dvb_loop = 0;
					break;
				}
			}
		}
	}

	/* Close fd now we're done. */
	dvb_close(dvb_demux_fd);

	/* Print Bouquet List if requested. */
	if (show_bouquet_list) {
		printf("# Bouquet List\n");
		for (bouquet = bouquet_list; bouquet != NULL; bouquet = bouquet->next) {
			printf("%i,%s\n", bouquet->bouquet_id, bouquet->name);
		}
	}

	/* Print Network, Transponder and Service List if requested. */
	if (show_sdt_list) {
		printf("# Satellite Network, Transponder and Service List.\n");
		for (network = network_list; network != NULL; network = network->next) {
			printf("N %i - %s\n", network->network_id, network->name);
			for (transport = network->transports; transport != NULL; transport = transport->next) {
				printf("T %i - ON: %i ModSys: %i Freq: %i Sym: %i Pol: %i ModType: %i FEC: %i RollOff: %i Orb: %i West: %i\n", transport->transport_id, transport->original_network_id, transport->modulation_system, transport->frequency, transport->symbol_rate, transport->polarization, transport->modulation_type, transport->fec, transport->roll_off, transport->orbital_position, transport->west_east_flag);
				for (service = transport->services; service != NULL; service = service->next) {
					printf("S %i - Running: %i FreeCA: %i Type: %i Name: %s AltName: %s Provider: %s\n", service->service_id, service->running, service->free_ca, service->type, service->name, service->alt_name, service->provider);
				}
			}
		}
	}

	/* If we did either of the above, abort. */
	if (show_bouquet_list || show_sdt_list) {
		return EXIT_SUCCESS;
	}

	/* Process BAT/SMT data to form channnel list. */
	bouquet = filter_data (filter_bouquet_id, filter_region_count, filter_region, dvbs, hd, filter_user_number);

	/* Exit if we're displaying the list. */
	if (show_filtered_list) {
		/* Cycle through channels. */
		for (channel = bouquet->channels; channel != NULL; channel = channel->next) {
			printf("O (%i:%i) %i %s (%s)\n", channel->transport->transport_id, channel->service->service_id, channel->user_number, channel->service->name, channel->service->alt_name);
		}

		return EXIT_SUCCESS;
	}

	/* XXX - Update MySQL database with it. */
	for (channel = bouquet->channels; channel != NULL; channel = channel->next) {
		printf("%i,%i,%i,%i,%i,%i,%i,%i,%i,%s\n", 
				channel->transport->transport_id,
				channel->transport->original_network_id,
				channel->transport->frequency,
				channel->transport->symbol_rate,
				channel->transport->polarization,
				channel->transport->modulation_system,
				channel->transport->roll_off,
				channel->service->service_id,
				channel->user_number,
				channel->service->name
		 );
	}

	/* XXX - Somehow handle xmltv overrides. */

	return EXIT_SUCCESS;
}