/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.aliyun.odps.graph; import java.io.BufferedInputStream; import java.io.IOException; import com.aliyun.odps.conf.Configuration; import com.aliyun.odps.counter.Counter; import com.aliyun.odps.data.TableInfo; import com.aliyun.odps.io.Writable; import com.aliyun.odps.io.WritableComparable; import com.aliyun.odps.io.WritableRecord; /** * Worker 上下文对象,封装了框架提供的核心功能. * * @param <VERTEX_ID> * Vertex ID 类型 * @param <VERTEX_VALUE> * Vertex Value 类型 * @param <EDGE_VALUE> * Edge Value 类型 * @param <MESSAGE> * Message 类型 */ @SuppressWarnings("rawtypes") public abstract class WorkerContext<VERTEX_ID extends WritableComparable, VERTEX_VALUE extends Writable, EDGE_VALUE extends Writable, MESSAGE extends Writable> { /** * 获取作业配置. * * 在 {@link GraphJob} 设置的配置参数可以从作业配置中读取 * * <p> * 注意:这里只能get配置参数,而不能set配置参数 * </p> * * @return ODPS Graph 作业配置 */ public abstract Configuration getConfiguration(); /** * 获取当前 Worker 的共享对象. * * @return 当前 Worker 的共享对象. * @see {@link WorkerComputer} */ public abstract Writable getWorkerValue(); /** * 获取当前 Worker 的编号,从 0 开始计数. * * @return 当前 Worker 的编号,从 0 开始计数. */ public abstract int getWorkerId(); /** * 获取 Worker 数目. * * @return Worker 数目 */ public abstract int getNumWorkers(); /** * 获取当前超步,即第几次迭代,从 0 开始计数. * * @return 当前超步 */ public abstract long getSuperstep(); /** * 获取最大迭代次数,默认 -1,小于或等于 0 时表示最大迭代次数不作为作业终止条件. * * @return 最大迭代次数 * @see JobConf#setMaxIteration(int) */ public abstract long getMaxIteration(); /** * 获取当前 Worker 负责的点数量. * * @return 当前 Worker 负责的点数量 */ public abstract long getWorkerNumVertices(); /** * 获取当前 Worker 负责的边数量. * * @return 当前 Worker 负责的边数量 */ public abstract long getWorkerNumEdges(); /** * 获取所有点数量,所有 Worker 负责的点数之和. * * @return 所有点数量 */ public abstract long getTotalNumVertices(); /** * 获取所有边数量,所有 Worker 负责的边数之和. * * @return 所有边数量 */ public abstract long getTotalNumEdges(); /** * 获取给定名称的Counter对象,name为{@link Enum} * * @param name * Counter名称 * @return */ public abstract Counter getCounter(Enum<?> name); /** * 获取给定组名和名称的 Counter 对象. * * @param group * Counter 组名 * @param name * Counter 名 * @return */ public abstract Counter getCounter(String group, String name); /** * 获取上一轮迭代结束时给定编号 Aggregator 的结果. * * <p> * 对于第一轮迭代(超步为0),调用本方法返回 {@link Aggregator#createStartupValue(WorkerContext)} * 创建的值, {@link Aggregator#createStartupValue(WorkerContext)} 默认返回 null,用户可以 * override. * * @param <VALUE> * Aggregator 值类型 * @param aggregatorIndex * Aggregator编号,起始为 0 * @return * @see Aggregator#aggregate(Writable, Object) * @see GraphJob#setAggregatorClass(Class...) */ public abstract <VALUE extends Writable> VALUE getLastAggregatedValue( int aggregatorIndex); /** * 默认获取上一轮迭代结束时编号0的 Aggregator 的结果. * * <p> * 对于第一轮迭代(超步为0),调用本方法返回 {@link Aggregator#createStartupValue(WorkerContext)} * 创建的值, {@link Aggregator#createStartupValue(WorkerContext)} 默认返回 null,用户可以 * override. * * @param <VALUE> * Aggregator 值类型 * @return * @see Aggregator#aggregate(Writable, Object) * @see GraphJob#setAggregatorClass(Class...) */ public <VALUE extends Writable> VALUE getLastAggregatedValue() { return getLastAggregatedValue(0); } /** * 获取默认输出的表信息. * * @return 默认输出的表信息 * @throws IOException */ public abstract TableInfo getOutputTable() throws IOException; /** * 获取给定输出标签的表信息. * * @param label * 输出标签 * @return 给定输出标签的表信息 * @throws IOException */ public abstract TableInfo getOutputTable(String label) throws IOException; /** * 写记录到默认输出. * * @param fieldVals * 待写出的记录值 * @throws IOException * @see GraphJob#addOutput(TableInfo) */ public abstract void write(Writable... fieldVals) throws IOException; /** * 写记录到给定标签输出. * * @param label * 输出标签 * @param fieldVals * 待写出的记录值 * @throws IOException * @see GraphJob#addOutput(TableInfo, String) */ public abstract void write(String label, Writable... fieldVals) throws IOException; /** * 读取文件类型资源,一次全部读取到内存,返回 byte[]. * * <p> * 如果资源文件比较大,应该使用{@link #readCacheFileAsStream(String)} * 获得一个带缓存的输入流,支持边读边处理,防止Java内存溢出 * </p> * * <p> * 使用文件类型资源步骤:<br/> * <ol> * <li>上传资源文件: console < add file res_file.txt; * <li>运行 ODPS Graph 作业命令: console < jar -resources res_file.txt ...,或者使用API( * {@link JobConf#addCacheResources(String)}) * <li>ODPS Graph 作业里读取资源:context.readCacheFile("res_file.txt"); * </ol> * </p> * * <p> * 资源文件在运行时会下载到所在的节点机器上并缓存,类似于Hadoop的<a href= * "http://hadoop.apache.org/common/docs/r0.19.2/cn/mapred_tutorial.html#DistributedCache" * >DistributedCache</a> * </p> * * @param resourceName * 资源名称 * @return 资源内容 * @throws IOException * 资源未声明、资源类型不匹配以及其他读取错误抛异常 * @see #readCacheFileAsStream(String) */ public abstract byte[] readCacheFile(String resourceName) throws IOException; /** * 读取文件类型资源,返回一个带缓存的输入流. * * <p> * readCacheFileAsStream * 支持边读边处理(常见的场景是读取一行处理一行),适合读取比较大的文件资源,防止Java内存溢出,如果文件资源比较小,也可以直接使用 * {@link #readCacheFile(String)} 方法一次性读取到内存。 * </p> * * <p> * 使用文件类型资源步骤类似{@link #readCacheFile(String)} * </p> * * @param resourceName * 资源名称 * @return 资源内容的BufferedInputStream * @throws IOException * 资源未声明、资源类型不匹配以及其他读取错误抛异常 * @see #readCacheFile(String) */ public abstract BufferedInputStream readCacheFileAsStream(String resourceName) throws IOException; /** * 读取压缩档案类型资源,返回解压后的所有文件内容的迭代器. * * <p> * 如果文件内容比较大,应该使用 {@link #readCacheArchiveAsStream(String)} * ,支持边读边处理,防止Java内存溢出。 * </p> * * <p> * 使用压缩档案类型资源步骤:<br/> * <ol> * <li>上传资源压缩包: console < add archive ref_archive.tar.gz; * <li>运行 ODPS Graph 作业命令: console < jar -resources ref_archive.tar.gz * ...,或者使用API( {@link JobConf#addCacheResources(String)}) * <li>ODPS Graph 里读取资源:context.readCacheArchive("ref_archive.tar.gz"); * </ol> * </p> * * <p> * 资源压缩包在Worker运行时会下载到所在的节点机器上并缓存,类似于Hadoop的<a href= * "http://hadoop.apache.org/common/docs/r0.19.2/cn/mapred_tutorial.html#DistributedCache" * >DistributedCache</a> * </p> * * @param resourceName * 资源名称 * @return 压缩包解压后的所有文件内容迭代器 * @throws IOException * 资源未声明、资源类型不匹配以及其他读取错误抛异常 * @see #readCacheArchiveAsStream(String) */ public abstract Iterable<byte[]> readCacheArchive(String resourceName) throws IOException; /** * 读取压缩档案类型资源,可以传入一个相对路径读取部分文件. * * <p> * 与{@link #readCacheArchive(String)} 不同的是可以传入一个相对路径,用于读取压缩包里的部分文件的内容,更多说明见 * {@link #readCacheArchive(String)}方法 * </p> * * <p> * 读取压缩包内子目录的代码示例: * * <pre> * Iterable<byte[]> iter = context.readCacheArchiveAsStream(RESOURCE_ARCHIVE, * "subdir/*"); * for (byte[] content : iter) { * } * </pre> * * </p> * * @param resourceName * 资源名称 * @param relativePath * 读取资源的相对路径 * @return 文件内容迭代器 * @throws IOException * 资源未声明、资源类型不匹配以及其他读取错误抛异常 * @see #readCacheArchiveAsStream(String) */ public abstract Iterable<byte[]> readCacheArchive(String resourceName, String relativePath) throws IOException; /** * 读取压缩档案类型资源,返回 BufferedInputStream 的迭代器. * * @param resourceName * 资源名称 * @return BufferedInputStream的迭代器 * @throws IOException * 资源未声明、资源类型不匹配以及其他读取错误抛异常 * @see #readCacheArchive(String) */ public abstract Iterable<BufferedInputStream> readCacheArchiveAsStream( String resourceName) throws IOException; /** * 读取压缩档案类型资源,返回 BufferedInputStream 的迭代器. * * @param resourceName * 资源名称 * @param relativePath * 读取资源的相对路径 * @return BufferedInputStream的迭代器 * @throws IOException * 资源未声明、资源类型不匹配以及其他读取错误抛异常 * @see #readCacheArchive(String, String) */ public abstract Iterable<BufferedInputStream> readCacheArchiveAsStream( String resourceName, String relativePath) throws IOException; /** * 读取表类型资源,ODPS的小表(Table)也可以作为资源,大小限制参见ODPS的相关文档. * * <p> * 使用表类型资源步骤:<br/> * <ol> * <li>增加资源表: console < add table my_table partition(ds='1') as res_table; * <li>运行 ODPS Graph 作业命令: console < jar -resources res_table ...,或者使用API( * {@link JobConf#addCacheResources(String)}) * <li>ODPS Graph 里读取资源:context.readResourceTable("res_table"); * </ol> * </p> * * <p> * 代码示例: * * <pre> * Iterable<WritableRecord> iter = context.readResourceTable("res_table"); * for (WritableRecord record : iter) { * // handle record * } * </pre> * * @param resourceName * 表类型资源名称 * @return 记录迭代器 * @throws IOException * 资源未声明、资源类型不匹配以及其他错误抛异常 */ public abstract Iterable<WritableRecord> readResourceTable(String resourceName) throws IOException; /** * 获取表类型资源对应的表信息,包括Project、表名称、分区等信息. * * @param resourceName * 表类型资源名称 * @return 表信息 * @throws IOException * 资源未声明、资源类型不匹配以及其他错误抛异常 */ public abstract TableInfo getResourceTable(String resourceName) throws IOException; /** * 向 ODPS Graph 框架报告进度. * * 如果用户方法处理时间很长,且中间没有调用框架,可以调用这个方法避免worker超时,框架默认600秒超时. */ public abstract void progress(); /** * 获取当前 Worker 的计算对象,每轮开始时初始化,结束时发送给 Master。 * 在 {@link MasterComputer} 中能获取到各个 Worker 的 ComputeValue. * * @return 返回当前 Worker 的计算对象 */ public abstract Writable getComputeValue(); }